Nektar++
Loading...
Searching...
No Matches
Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | List of all members
Nektar::MultiRegions::DisContField Class Reference

This class is the abstractio n of a global discontinuous two- dimensional spectral/hp element expansion which approximates the solution of a set of partial differential equations. More...

#include <DisContField.h>

Inheritance diagram for Nektar::MultiRegions::DisContField:
[legend]

Public Member Functions

 DisContField ()
 Default constructor.
 
 DisContField (const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &graph, const std::string &variable, const bool SetUpJustDG=true, const bool DeclareCoeffPhysArrays=true, const Collections::ImplementationType ImpType=Collections::eNoImpType, const std::string bcvariable="NotSet")
 Constructs a 1D discontinuous field based on a mesh and boundary conditions.
 
 DisContField (const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &graph1D, const SpatialDomains::CompositeMap &domain, const SpatialDomains::BoundaryConditions &Allbcs, const std::string &variable, const LibUtilities::CommSharedPtr &comm, bool SetToOneSpaceDimensions=false, const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Constructor for a DisContField from a List of subdomains New Constructor for arterial network.
 
 DisContField (const DisContField &In, const bool DeclareCoeffPhysArrays=true)
 Constructs a 1D discontinuous field based on an existing field.
 
 DisContField (const DisContField &In, const SpatialDomains::MeshGraphSharedPtr &graph, const std::string &variable, const bool SetUpJustDG=true, const bool DeclareCoeffPhysArrays=true)
 
 DisContField (const ExpList &In)
 Constructs a 1D discontinuous field based on an existing field. (needed in order to use ContField( const ExpList &In) constructor.
 
 ~DisContField () override
 Destructor.
 
GlobalLinSysSharedPtr GetGlobalBndLinSys (const GlobalLinSysKey &mkey)
 For a given key, returns the associated global linear system.
 
bool SameTypeOfBoundaryConditions (const DisContField &In)
 Check to see if expansion has the same BCs as In.
 
std::vector< bool > & GetNegatedFluxNormal (void)
 
NekDouble L2_DGDeriv (const int dir, const Array< OneD, const NekDouble > &coeffs, const Array< OneD, const NekDouble > &soln)
 Calculate the \( L^2 \) error of the \( Q_{\rm dir} \) derivative using the consistent DG evaluation of \( Q_{\rm dir} \).
 
void EvaluateHDGPostProcessing (const Array< OneD, const NekDouble > &coeffs, Array< OneD, NekDouble > &outarray)
 Evaluate HDG post-processing to increase polynomial order of solution.
 
void GetLocTraceToTraceMap (LocTraceToTraceMapSharedPtr &LocTraceToTraceMap)
 
void GetFwdBwdTracePhys (const Array< OneD, const NekDouble > &field, Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > &bndCond, const Array< OneD, const ExpListSharedPtr > &BndCondExp)
 This method extracts the "forward" and "backward" trace data from the array field and puts the data into output vectors Fwd and Bwd.
 
ExpListSharedPtrGetLocElmtTrace ()
 
- Public Member Functions inherited from Nektar::MultiRegions::ExpList
 ExpList (const ExpansionType Type=eNoType)
 The default constructor using a type.
 
 ExpList (const ExpList &in, const bool DeclareCoeffPhysArrays=true)
 The copy constructor.
 
 ExpList (const ExpList &in, const std::vector< unsigned int > &eIDs, const bool DeclareCoeffPhysArrays=true, const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Constructor copying only elements defined in eIds.
 
 ExpList (const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &graph, const bool DeclareCoeffPhysArrays=true, const std::string &var="DefaultVar", const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Generate an ExpList from a meshgraph graph and session file.
 
 ExpList (const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::ExpansionInfoMap &expansions, const bool DeclareCoeffPhysArrays=true, const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Sets up a list of local expansions based on an expansion Map.
 
 ExpList (SpatialDomains::PointGeom *geom)
 Specialised constructors for 0D Expansions Wrapper around LocalRegion::PointExp - used in PrePacing.cpp.
 
 ExpList (const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, const ExpListSharedPtr > &bndConstraint, const Array< OneD, const SpatialDomains ::BoundaryConditionShPtr > &bndCond, const LocalRegions::ExpansionVector &locexp, const SpatialDomains::MeshGraphSharedPtr &graph, const LibUtilities::CommSharedPtr &comm, const bool DeclareCoeffPhysArrays=true, const std::string variable="DefaultVar", const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Generate expansions for the trace space expansions used in DisContField.
 
 ExpList (const LibUtilities::SessionReaderSharedPtr &pSession, const LocalRegions::ExpansionVector &locexp, const SpatialDomains::MeshGraphSharedPtr &graph, const bool DeclareCoeffPhysArrays, const std::string variable, const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Generate an trace ExpList from a meshgraph graph and session file.
 
 ExpList (const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::CompositeMap &domain, const SpatialDomains::MeshGraphSharedPtr &graph, const bool DeclareCoeffPhysArrays=true, const std::string variable="DefaultVar", bool SetToOneSpaceDimension=false, const LibUtilities::CommSharedPtr comm=LibUtilities::CommSharedPtr(), const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Constructor based on domain information only for 1D & 2D boundary conditions.
 
virtual ~ExpList ()
 The default destructor.
 
int GetNcoeffs (void) const
 Returns the total number of local degrees of freedom \(N_{\mathrm{eof}}=\sum_{e=1}^{{N_{\mathrm{el}}}}N^{e}_m\).
 
int GetNcoeffs (const int eid) const
 Returns the total number of local degrees of freedom for element eid.
 
ExpansionType GetExpType (void)
 Returns the type of the expansion.
 
void SetExpType (ExpansionType Type)
 Returns the type of the expansion.
 
int EvalBasisNumModesMax (void) const
 Evaulates the maximum number of modes in the elemental basis order over all elements.
 
const Array< OneD, int > EvalBasisNumModesMaxPerExp (void) const
 Returns the vector of the number of modes in the elemental basis order over all elements.
 
int GetTotPoints (void) const
 Returns the total number of quadrature points m_npoints \(=Q_{\mathrm{tot}}\).
 
int GetTotPoints (const int eid) const
 Returns the total number of quadrature points for eid's element \(=Q_{\mathrm{tot}}\).
 
int GetNpoints (void) const
 Returns the total number of quadrature points m_npoints \(=Q_{\mathrm{tot}}\).
 
int Get1DScaledTotPoints (const NekDouble scale) const
 Returns the total number of qudature points scaled by the factor scale on each 1D direction.
 
void SetWaveSpace (const bool wavespace)
 Sets the wave space to the one of the possible configuration true or false.
 
void SetModifiedBasis (const bool modbasis)
 Set Modified Basis for the stability analysis.
 
bool GetWaveSpace (void) const
 This function returns the third direction expansion condition, which can be in wave space (coefficient) or not It is stored in the variable m_WaveSpace.
 
void SetPhys (int i, NekDouble val)
 Set the i th value of m_phys to value val.
 
void SetPhys (const Array< OneD, const NekDouble > &inarray)
 Fills the array m_phys.
 
void SetPhysArray (Array< OneD, NekDouble > &inarray)
 Sets the array m_phys.
 
void SetPhysState (const bool physState)
 This function manually sets whether the array of physical values \(\boldsymbol{u}_l\) (implemented as m_phys) is filled or not.
 
bool GetPhysState (void) const
 This function indicates whether the array of physical values \(\boldsymbol{u}_l\) (implemented as m_phys) is filled or not.
 
void MultiplyByQuadratureMetric (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 multiply the metric jacobi and quadrature weights
 
void DivideByQuadratureMetric (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 Divided by the metric jacobi and quadrature weights.
 
void IProductWRTBase (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function calculates the inner product of a function \(f(\boldsymbol{x})\) with respect to all local expansion modes \(\phi_n^e(\boldsymbol{x})\).
 
void IProductWRTDerivBase (const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function calculates the inner product of a function \(f(\boldsymbol{x})\) with respect to the derivative (in direction.
 
void IProductWRTDirectionalDerivBase (const Array< OneD, const NekDouble > &direction, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
void IProductWRTDerivBase (const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, NekDouble > &outarray)
 This function calculates the inner product of a function \(f(\boldsymbol{x})\) with respect to the derivative of all local expansion modes \(\phi_n^e(\boldsymbol{x})\).
 
void FwdTransLocalElmt (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function elementally evaluates the forward transformation of a function \(u(\boldsymbol{x})\) onto the global spectral/hp expansion.
 
void FwdTrans (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
void ExponentialFilter (Array< OneD, NekDouble > &array, const NekDouble alpha, const NekDouble exponent, const NekDouble cutoff)
 
void MultiplyByElmtInvMass (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function elementally mulplies the coefficient space of Sin my the elemental inverse of the mass matrix.
 
void MultiplyByInvMassMatrix (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
void MultiplyByMassMatrix (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
void SmoothField (Array< OneD, NekDouble > &field)
 Smooth a field across elements.
 
GlobalLinSysKey HelmSolve (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff=StdRegions::NullVarCoeffMap, const MultiRegions::VarFactorsMap &varfactors=MultiRegions::NullVarFactorsMap, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray, const bool PhysSpaceForcing=true)
 Solve helmholtz problem.
 
GlobalLinSysKey LinearAdvectionDiffusionReactionSolve (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff=StdRegions::NullVarCoeffMap, const MultiRegions::VarFactorsMap &varfactors=MultiRegions::NullVarFactorsMap, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray, const bool PhysSpaceForcing=true)
 Solve Advection Diffusion Reaction.
 
GlobalLinSysKey LinearAdvectionReactionSolve (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff=StdRegions::NullVarCoeffMap, const MultiRegions::VarFactorsMap &varfactors=MultiRegions::NullVarFactorsMap, const Array< OneD, const NekDouble > &dirForcing=NullNekDouble1DArray, const bool PhysSpaceForcing=true)
 Solve Advection Diffusion Reaction.
 
void FwdTransBndConstrained (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
void BwdTrans (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function elementally evaluates the backward transformation of the global spectral/hp element expansion.
 
void GetCoords (Array< OneD, NekDouble > &coord_0, Array< OneD, NekDouble > &coord_1=NullNekDouble1DArray, Array< OneD, NekDouble > &coord_2=NullNekDouble1DArray)
 This function calculates the coordinates of all the elemental quadrature points \(\boldsymbol{x}_i\).
 
void GetCoords (const int eid, Array< OneD, NekDouble > &coord_0, Array< OneD, NekDouble > &coord_1=NullNekDouble1DArray, Array< OneD, NekDouble > &coord_2=NullNekDouble1DArray)
 
void HomogeneousFwdTrans (const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool Shuff=true, bool UnShuff=true)
 
void HomogeneousBwdTrans (const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool Shuff=true, bool UnShuff=true)
 
void DealiasedProd (const int num_dofs, const Array< OneD, NekDouble > &inarray1, const Array< OneD, NekDouble > &inarray2, Array< OneD, NekDouble > &outarray)
 
void DealiasedDotProd (const int num_dofs, const Array< OneD, Array< OneD, NekDouble > > &inarray1, const Array< OneD, Array< OneD, NekDouble > > &inarray2, Array< OneD, Array< OneD, NekDouble > > &outarray)
 
void GetBCValues (Array< OneD, NekDouble > &BndVals, const Array< OneD, NekDouble > &TotField, int BndID)
 
void NormVectorIProductWRTBase (Array< OneD, const NekDouble > &V1, Array< OneD, const NekDouble > &V2, Array< OneD, NekDouble > &outarray, int BndID)
 
void NormVectorIProductWRTBase (Array< OneD, Array< OneD, NekDouble > > &V, Array< OneD, NekDouble > &outarray)
 
void ApplyGeomInfo ()
 Apply geometry information to each expansion.
 
void Reset ()
 Reset geometry information and reset matrices.
 
void ResetMatrices ()
 Reset matrices.
 
void WriteTecplotHeader (std::ostream &outfile, std::string var="")
 
void WriteTecplotZone (std::ostream &outfile, int expansion=-1)
 
void WriteTecplotField (std::ostream &outfile, int expansion=-1)
 
void WriteTecplotConnectivity (std::ostream &outfile, int expansion=-1)
 
void WriteVtkHeader (std::ostream &outfile)
 
void WriteVtkFooter (std::ostream &outfile)
 
void WriteVtkPieceHeader (std::ostream &outfile, int expansion, int istrip=0)
 
void WriteVtkPieceFooter (std::ostream &outfile, int expansion)
 
void WriteVtkPieceData (std::ostream &outfile, int expansion, std::string var="v")
 
int GetCoordim (int eid)
 This function returns the dimension of the coordinates of the element eid.
 
void SetCoeff (int i, NekDouble val)
 Set the i th coefficiient in m_coeffs to value val.
 
void SetCoeffs (int i, NekDouble val)
 Set the i th coefficiient in m_coeffs to value val.
 
void SetCoeffsArray (Array< OneD, NekDouble > &inarray)
 Set the m_coeffs array to inarray.
 
int GetShapeDimension ()
 This function returns the dimension of the shape of the element eid.
 
const Array< OneD, const NekDouble > & GetCoeffs () const
 This function returns (a reference to) the array \(\boldsymbol{\hat{u}}_l\) (implemented as m_coeffs) containing all local expansion coefficients.
 
void ImposeDirichletConditions (Array< OneD, NekDouble > &outarray)
 Impose Dirichlet Boundary Conditions onto Array.
 
void ImposeNeumannConditions (Array< OneD, NekDouble > &outarray)
 Add Neumann Boundary Condition forcing to Array.
 
void ImposeRobinConditions (Array< OneD, NekDouble > &outarray)
 Add Robin Boundary Condition forcing to Array.
 
void FillBndCondFromField (const Array< OneD, NekDouble > coeffs)
 Fill Bnd Condition expansion from the values stored in expansion.
 
void FillBndCondFromField (const int nreg, const Array< OneD, NekDouble > coeffs)
 Fill Bnd Condition expansion in nreg from the values stored in expansion.
 
void LocalToGlobal (bool useComm=true)
 Gathers the global coefficients \(\boldsymbol{\hat{u}}_g\) from the local coefficients \(\boldsymbol{\hat{u}}_l\).
 
void LocalToGlobal (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool useComm=true)
 
void GlobalToLocal (void)
 Scatters from the global coefficients \(\boldsymbol{\hat{u}}_g\) to the local coefficients \(\boldsymbol{\hat{u}}_l\).
 
void GlobalToLocal (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
NekDouble GetCoeff (int i)
 Get the i th value (coefficient) of m_coeffs.
 
NekDouble GetCoeffs (int i)
 Get the i th value (coefficient) of m_coeffs.
 
const Array< OneD, const NekDouble > & GetPhys () const
 This function returns (a reference to) the array \(\boldsymbol{u}_l\) (implemented as m_phys) containing the function \(u^{\delta}(\boldsymbol{x})\) evaluated at the quadrature points.
 
NekDouble Linf (const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
 This function calculates the \(L_\infty\) error of the global spectral/hp element approximation.
 
NekDouble L2 (const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
 This function calculates the \(L_\infty\) error of the global This function calculates the \(L_2\) error with respect to soln of the global spectral/hp element approximation.
 
NekDouble H1 (const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
 Calculates the \(H^1\) error of the global spectral/hp element approximation.
 
NekDouble Integral ()
 Calculates the \(H^1\) error of the global spectral/hp element approximation.
 
NekDouble Integral (const Array< OneD, const NekDouble > &inarray)
 
NekDouble VectorFlux (const Array< OneD, Array< OneD, NekDouble > > &inarray)
 
Array< OneD, const NekDoubleHomogeneousEnergy (void)
 This function calculates the energy associated with each one of the modesof a 3D homogeneous nD expansion.
 
void SetHomo1DSpecVanVisc (Array< OneD, NekDouble > visc)
 This function sets the Spectral Vanishing Viscosity in homogeneous1D expansion.
 
Array< OneD, const unsigned int > GetZIDs (void)
 This function returns a vector containing the wave numbers in z-direction associated with the 3D homogenous expansion. Required if a parellelisation is applied in the Fourier direction.
 
LibUtilities::TranspositionSharedPtr GetTransposition (void)
 This function returns the transposition class associated with the homogeneous expansion.
 
NekDouble GetHomoLen (void)
 This function returns the Width of homogeneous direction associated with the homogeneous expansion.
 
void SetHomoLen (const NekDouble lhom)
 This function sets the Width of homogeneous direction associated with the homogeneous expansion.
 
Array< OneD, const unsigned int > GetYIDs (void)
 This function returns a vector containing the wave numbers in y-direction associated with the 3D homogenous expansion. Required if a parellelisation is applied in the Fourier direction.
 
void PhysInterp1DScaled (const NekDouble scale, const Array< OneD, NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function interpolates the physical space points in inarray to outarray using the same points defined in the expansion but where the number of points are rescaled by 1DScale.
 
void PhysGalerkinProjection1DScaled (const NekDouble scale, const Array< OneD, NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function Galerkin projects the physical space points in inarray to outarray where inarray is assumed to be defined in the expansion but where the number of points are rescaled by 1DScale.
 
int GetExpSize (void)
 This function returns the number of elements in the expansion.
 
size_t GetNumElmts (void)
 This function returns the number of elements in the expansion which may be different for a homogeoenous extended expansionp.
 
const std::shared_ptr< LocalRegions::ExpansionVectorGetExp () const
 This function returns the vector of elements in the expansion.
 
LocalRegions::ExpansionSharedPtrGetExp (int n) const
 This function returns (a shared pointer to) the local elemental expansion of the \(n^{\mathrm{th}}\) element.
 
LocalRegions::ExpansionSharedPtrGetExpFromGeomId (int n)
 This function returns (a shared pointer to) the local elemental expansion of the \(n^{\mathrm{th}}\) element given a global geometry ID.
 
LocalRegions::ExpansionSharedPtrGetExp (const Array< OneD, const NekDouble > &gloCoord)
 This function returns (a shared pointer to) the local elemental expansion containing the arbitrary point given by gloCoord.
 
int GetExpIndex (const Array< OneD, const NekDouble > &gloCoord, NekDouble tol=0.0, bool returnNearestElmt=false, int cachedId=-1, NekDouble maxDistance=1e6)
 This function returns the index of the local elemental expansion containing the arbitrary point given by gloCoord, within a distance tolerance of tol.
 
int GetExpIndex (const Array< OneD, const NekDouble > &gloCoords, Array< OneD, NekDouble > &locCoords, NekDouble tol=0.0, bool returnNearestElmt=false, int cachedId=-1, NekDouble maxDistance=1e6)
 
NekDouble PhysEvaluate (const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &phys)
 
int GetCoeff_Offset (int n) const
 Get the start offset position for a local contiguous list of coeffs correspoinding to element n.
 
int GetPhys_Offset (int n) const
 Get the start offset position for a local contiguous list of quadrature points in a full array correspoinding to element n.
 
Array< OneD, NekDouble > & UpdateCoeffs ()
 This function returns (a reference to) the array \(\boldsymbol{\hat{u}}_l\) (implemented as m_coeffs) containing all local expansion coefficients.
 
Array< OneD, NekDouble > & UpdatePhys ()
 This function returns (a reference to) the array \(\boldsymbol{u}_l\) (implemented as m_phys) containing the function \(u^{\delta}(\boldsymbol{x})\) evaluated at the quadrature points.
 
void PhysDeriv (Direction edir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d)
 
void PhysDeriv (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1=NullNekDouble1DArray, Array< OneD, NekDouble > &out_d2=NullNekDouble1DArray)
 This function discretely evaluates the derivative of a function \(f(\boldsymbol{x})\) on the domain consisting of all elements of the expansion.
 
void PhysDeriv (const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d)
 
void CurlCurl (Array< OneD, Array< OneD, NekDouble > > &Vel, Array< OneD, Array< OneD, NekDouble > > &Q)
 
void PhysDirectionalDeriv (const Array< OneD, const NekDouble > &direction, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
void GetMovingFrames (const SpatialDomains::GeomMMF MMFdir, const Array< OneD, const NekDouble > &CircCentre, Array< OneD, Array< OneD, NekDouble > > &outarray)
 
const Array< OneD, const std::shared_ptr< ExpList > > & GetBndCondExpansions ()
 
const Array< OneD, const NekDouble > & GetBndCondBwdWeight ()
 Get the weight value for boundary conditions.
 
void SetBndCondBwdWeight (const int index, const NekDouble value)
 Set the weight value for boundary conditions.
 
std::shared_ptr< ExpList > & UpdateBndCondExpansion (int i)
 
void Upwind (const Array< OneD, const NekDouble > &Vn, const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &Upwind)
 
void Upwind (const Array< OneD, const Array< OneD, NekDouble > > &Vec, const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &Upwind)
 
std::shared_ptr< ExpList > & GetTrace ()
 
std::shared_ptr< AssemblyMapDG > & GetTraceMap (void)
 
std::shared_ptr< InterfaceMapDG > & GetInterfaceMap (void)
 
const Array< OneD, const int > & GetTraceBndMap (void)
 
void GetNormals (Array< OneD, Array< OneD, NekDouble > > &normals)
 
void GetElmtNormalLength (Array< OneD, NekDouble > &lengthsFwd, Array< OneD, NekDouble > &lengthsBwd)
 Get the length of elements in boundary normal direction.
 
void GetBwdWeight (Array< OneD, NekDouble > &weightAver, Array< OneD, NekDouble > &weightJump)
 Get the weight value for boundary conditions for boundary average and jump calculations.
 
void AddTraceIntegral (const Array< OneD, const NekDouble > &Fn, Array< OneD, NekDouble > &outarray)
 
void AddFwdBwdTraceIntegral (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &outarray)
 
void GetFwdBwdTracePhys (Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd)
 
void GetFwdBwdTracePhys (const Array< OneD, const NekDouble > &field, Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, bool FillBnd=true, bool PutFwdInBwdOnBCs=false, bool DoExchange=true)
 
void FillBwdWithBoundCond (const Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, bool PutFwdInBwdOnBCs=false)
 
void AddTraceQuadPhysToField (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &field)
 Add Fwd and Bwd value to field, a reverse procedure of GetFwdBwdTracePhys.
 
void AddTraceQuadPhysToOffDiag (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &field)
 
void GetLocTraceFromTracePts (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &locTraceFwd, Array< OneD, NekDouble > &locTraceBwd)
 
void FillBwdWithBwdWeight (Array< OneD, NekDouble > &weightave, Array< OneD, NekDouble > &weightjmp)
 Fill Bwd with boundary conditions.
 
void PeriodicBwdCopy (const Array< OneD, const NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd)
 Copy and fill the Periodic boundaries.
 
void PeriodicBwdRot (Array< OneD, Array< OneD, NekDouble > > &Bwd)
 Rotate Bwd trace for rotational periodicity boundaries when the flow is perpendicular to the rotation axis.
 
void PeriodicDeriveBwdRot (TensorOfArray3D< NekDouble > &Bwd)
 Rotate Bwd trace derivative for rotational periodicity boundaries when the flow is perpendicular to the rotation axis.
 
void RotLocalBwdTrace (Array< OneD, Array< OneD, NekDouble > > &Bwd)
 Rotate local Bwd trace across a rotational interface when the flow is perpendicular to the rotation axis.
 
void RotLocalBwdDeriveTrace (TensorOfArray3D< NekDouble > &Bwd)
 Rotate local Bwd trace derivatives across a rotational interface when the flow is perpendicular to the rotation axis.
 
const std::vector< bool > & GetLeftAdjacentFaces (void) const
 
void ExtractTracePhys (Array< OneD, NekDouble > &outarray)
 
void ExtractTracePhys (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool gridVelocity=false)
 
const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > & GetBndConditions ()
 
Array< OneD, SpatialDomains::BoundaryConditionShPtr > & UpdateBndConditions ()
 
void EvaluateBoundaryConditions (const NekDouble time=0.0, const std::string varName="", const NekDouble=NekConstants::kNekUnsetDouble, const NekDouble=NekConstants::kNekUnsetDouble)
 
void GeneralMatrixOp (const GlobalMatrixKey &gkey, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 This function calculates the result of the multiplication of a matrix of type specified by mkey with a vector given by inarray.
 
void SetUpPhysNormals ()
 
void GetBoundaryToElmtMap (Array< OneD, int > &ElmtID, Array< OneD, int > &EdgeID)
 
virtual void GetBndElmtExpansion (int i, std::shared_ptr< ExpList > &result, const bool DeclareCoeffPhysArrays=true)
 
void ExtractElmtToBndPhys (int i, const Array< OneD, NekDouble > &elmt, Array< OneD, NekDouble > &boundary)
 
void ExtractPhysToBndElmt (int i, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &bndElmt)
 
void ExtractPhysToBnd (int i, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &bnd)
 
void GetBoundaryNormals (int i, Array< OneD, Array< OneD, NekDouble > > &normals)
 
void GeneralGetFieldDefinitions (std::vector< LibUtilities::FieldDefinitionsSharedPtr > &fielddef, int NumHomoDir=0, Array< OneD, LibUtilities::BasisSharedPtr > &HomoBasis=LibUtilities::NullBasisSharedPtr1DArray, std::vector< NekDouble > &HomoLen=LibUtilities::NullNekDoubleVector, bool homoStrips=false, std::vector< unsigned int > &HomoSIDs=LibUtilities::NullUnsignedIntVector, std::vector< unsigned int > &HomoZIDs=LibUtilities::NullUnsignedIntVector, std::vector< unsigned int > &HomoYIDs=LibUtilities::NullUnsignedIntVector)
 
std::map< int, RobinBCInfoSharedPtrGetRobinBCInfo ()
 
void GetPeriodicEntities (PeriodicMap &periodicVerts, PeriodicMap &periodicEdges, PeriodicMap &periodicFaces=NullPeriodicMap)
 
std::vector< LibUtilities::FieldDefinitionsSharedPtrGetFieldDefinitions ()
 
void GetFieldDefinitions (std::vector< LibUtilities::FieldDefinitionsSharedPtr > &fielddef)
 
void AppendFieldData (LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata)
 Append the element data listed in elements fielddef->m_ElementIDs onto fielddata.
 
void AppendFieldData (LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata, Array< OneD, NekDouble > &coeffs)
 Append the data in coeffs listed in elements fielddef->m_ElementIDs onto fielddata.
 
void ExtractElmtDataToCoeffs (LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata, std::string &field, Array< OneD, NekDouble > &coeffs)
 Extract the data in fielddata into the coeffs using the basic ExpList Elemental expansions rather than planes in homogeneous case.
 
void ExtractCoeffsToCoeffs (const std::shared_ptr< ExpList > &fromExpList, const Array< OneD, const NekDouble > &fromCoeffs, Array< OneD, NekDouble > &toCoeffs)
 Extract the data from fromField using fromExpList the coeffs using the basic ExpList Elemental expansions rather than planes in homogeneous case.
 
void ExtractDataToCoeffs (LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata, std::string &field, Array< OneD, NekDouble > &coeffs, std::unordered_map< int, int > zIdToPlane=std::unordered_map< int, int >())
 
void ExtractCoeffsFromFile (const std::string &fileName, LibUtilities::CommSharedPtr comm, const std::string &varName, Array< OneD, NekDouble > &coeffs)
 
void GenerateElementVector (const int ElementID, const NekDouble scalar1, const NekDouble scalar2, Array< OneD, NekDouble > &outarray)
 
std::shared_ptr< ExpListGetSharedThisPtr ()
 Returns a shared pointer to the current object.
 
std::shared_ptr< LibUtilities::SessionReaderGetSession () const
 Returns the session object.
 
std::shared_ptr< LibUtilities::CommGetComm () const
 Returns the comm object.
 
SpatialDomains::MeshGraphSharedPtr GetGraph ()
 
LibUtilities::BasisSharedPtr GetHomogeneousBasis (void)
 
std::shared_ptr< ExpList > & GetPlane (int n)
 
void CreateCollections (Collections::ImplementationType ImpType=Collections::eNoImpType)
 
void ClearGlobalLinSysManager (void)
 
int GetPoolCount (std::string)
 
void UnsetGlobalLinSys (GlobalLinSysKey, bool)
 
LibUtilities::NekManager< GlobalLinSysKey, GlobalLinSys > & GetGlobalLinSysManager (void)
 
const Array< OneD, const std::pair< int, int > > & GetCoeffsToElmt () const
 Get m_coeffs to elemental value map.
 
void AddTraceJacToElmtJac (const Array< OneD, const DNekMatSharedPtr > &FwdMat, const Array< OneD, const DNekMatSharedPtr > &BwdMat, Array< OneD, DNekMatSharedPtr > &fieldMat)
 
void GetMatIpwrtDeriveBase (const Array< OneD, const Array< OneD, NekDouble > > &inarray, const int nDirctn, Array< OneD, DNekMatSharedPtr > &mtxPerVar)
 
void GetMatIpwrtDeriveBase (const TensorOfArray3D< NekDouble > &inarray, Array< OneD, DNekMatSharedPtr > &mtxPerVar)
 
void GetDiagMatIpwrtBase (const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, DNekMatSharedPtr > &mtxPerVar)
 
void AddTraceIntegralToOffDiag (const Array< OneD, const NekDouble > &FwdFlux, const Array< OneD, const NekDouble > &BwdFlux, Array< OneD, NekDouble > &outarray)
 
void AddRightIPTPhysDerivBase (const int dir, const Array< OneD, const DNekMatSharedPtr > ElmtJacQuad, Array< OneD, DNekMatSharedPtr > ElmtJacCoef)
 
void AddRightIPTBaseMatrix (const Array< OneD, const DNekMatSharedPtr > ElmtJacQuad, Array< OneD, DNekMatSharedPtr > ElmtJacCoef)
 
const LocTraceToTraceMapSharedPtrGetLocTraceToTraceMap () const
 
std::vector< bool > & GetLeftAdjacentTraces (void)
 
const std::unordered_map< int, int > & GetElmtToExpId (void)
 This function returns the map of index inside m_exp to geom id.
 
int GetElmtToExpId (int elmtId)
 This function returns the index inside m_exp for a given geom id.
 
const Collections::CollectionVectorGetCollections () const
 This function returns collections.
 
int Get_coll_coeff_offset (int n) const
 
int Get_coll_phys_offset (int n) const
 
const Array< OneD, const Array< OneD, NekDouble > > & GetGridVelocity ()
 

Public Attributes

Array< OneD, int > m_BCtoElmMap
 
Array< OneD, int > m_BCtoTraceMap
 

Protected Member Functions

void GenerateBoundaryConditionExpansion (const SpatialDomains::MeshGraphSharedPtr &graph1D, const SpatialDomains::BoundaryConditions &bcs, const std::string variable, const bool DeclareCoeffPhysArrays=true, const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Discretises the boundary conditions.
 
void GenerateBoundaryConditionExpansion (const Array< OneD, const MultiRegions::ExpListSharedPtr > &In, const SpatialDomains::BoundaryConditions &bcs, const std::string variable, const bool DeclareCoeffPhysArrays=true, const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Make copy of boundary conditions.
 
void FindPeriodicTraces (const SpatialDomains::BoundaryConditions &bcs, const std::string variable)
 Generate a associative map of periodic vertices in a mesh.
 
void SetUpDG (const std::string="DefaultVar", const Collections::ImplementationType ImpType=Collections::eNoImpType)
 Set up all DG member variables and maps.
 
bool IsLeftAdjacentTrace (const int n, const int e)
 This routine determines if an element is to the "left" of the adjacent trace, which arises from the idea there is a local normal direction between two elements (i.e. on the trace) and one elements would then be the left.
 
ExpListSharedPtrv_GetTrace () override
 
AssemblyMapDGSharedPtrv_GetTraceMap (void) override
 
InterfaceMapDGSharedPtrv_GetInterfaceMap (void) override
 
const LocTraceToTraceMapSharedPtrv_GetLocTraceToTraceMap (void) const override
 
std::vector< bool > & v_GetLeftAdjacentTraces (void) override
 
void v_AddTraceIntegral (const Array< OneD, const NekDouble > &Fn, Array< OneD, NekDouble > &outarray) override
 Add trace contributions into elemental coefficient spaces.
 
void v_AddFwdBwdTraceIntegral (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &outarray) override
 Add trace contributions into elemental coefficient spaces.
 
void v_AddTraceQuadPhysToField (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &field) override
 
void v_ExtractTracePhys (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool gridVelocity=false) override
 This method extracts the trace (verts in 1D) from the field inarray and puts the values in outarray.
 
void v_ExtractTracePhys (Array< OneD, NekDouble > &outarray) override
 
void v_GetLocTraceFromTracePts (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &locTraceFwd, Array< OneD, NekDouble > &locTraceBwd) override
 
void GenerateFieldBnd1D (SpatialDomains::BoundaryConditions &bcs, const std::string variable)
 
std::map< int, RobinBCInfoSharedPtrv_GetRobinBCInfo () override
 
const Array< OneD, const MultiRegions::ExpListSharedPtr > & v_GetBndCondExpansions () override
 
const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > & v_GetBndConditions () override
 
MultiRegions::ExpListSharedPtrv_UpdateBndCondExpansion (int i) override
 
Array< OneD, SpatialDomains::BoundaryConditionShPtr > & v_UpdateBndConditions () override
 
void v_GetBoundaryToElmtMap (Array< OneD, int > &ElmtID, Array< OneD, int > &TraceID) override
 
void v_GetBndElmtExpansion (int i, std::shared_ptr< ExpList > &result, const bool DeclareCoeffPhysArrays) override
 
void v_Reset () override
 Reset this field, so that geometry information can be updated.
 
void v_EvaluateBoundaryConditions (const NekDouble time=0.0, const std::string varName="", const NekDouble x2_in=NekConstants::kNekUnsetDouble, const NekDouble x3_in=NekConstants::kNekUnsetDouble) override
 Evaluate all boundary conditions at a given time..
 
GlobalLinSysKey v_HelmSolve (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const MultiRegions::VarFactorsMap &varfactors, const Array< OneD, const NekDouble > &dirForcing, const bool PhysSpaceForcing) override
 Solve the Helmholtz equation.
 
void v_PeriodicBwdCopy (const Array< OneD, const NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd) override
 
void v_PeriodicBwdRot (Array< OneD, Array< OneD, NekDouble > > &Bwd) override
 
void v_PeriodicDeriveBwdRot (TensorOfArray3D< NekDouble > &Bwd) override
 
void v_RotLocalBwdTrace (Array< OneD, Array< OneD, NekDouble > > &Bwd) override
 
void v_RotLocalBwdDeriveTrace (TensorOfArray3D< NekDouble > &Bwd) override
 
void v_FillBwdWithBwdWeight (Array< OneD, NekDouble > &weightave, Array< OneD, NekDouble > &weightjmp) override
 Fill the weight with m_bndCondBndWeight.
 
void v_GetFwdBwdTracePhys (Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd) override
 
void v_GetFwdBwdTracePhys (const Array< OneD, const NekDouble > &field, Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, bool FillBnd=true, bool PutFwdInBwdOnBCs=false, bool DoExchange=true) override
 
void v_FillBwdWithBoundCond (const Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, bool PutFwdInBwdOnBCs) override
 
void FillBwdWithBoundCond (const Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > &bndConditions, const Array< OneD, const ExpListSharedPtr > &BndCondExpansions, bool PutFwdInBwdOnBCs)
 
const Array< OneD, const NekDouble > & v_GetBndCondBwdWeight () override
 
void v_SetBndCondBwdWeight (const int index, const NekDouble value) override
 
void v_GetPeriodicEntities (PeriodicMap &periodicVerts, PeriodicMap &periodicEdges, PeriodicMap &periodicFaces) override
 Obtain a copy of the periodic edges and vertices for this field.
 
void v_AddTraceIntegralToOffDiag (const Array< OneD, const NekDouble > &FwdFlux, const Array< OneD, const NekDouble > &BwdFlux, Array< OneD, NekDouble > &outarray) override
 
void Rotate (Array< OneD, Array< OneD, NekDouble > > &Bwd, const int dir, const NekDouble angle, const int offset, const int npts)
 Rotate the slice [offset, offset + npts) of the 3D vector field in Bwd around the axis 'dir' by 'angle'.
 
void DeriveRotate (TensorOfArray3D< NekDouble > &Bwd, const int dir, const NekDouble angle, const int offset, const int npts)
 Rotate the slice [offset, offset + npts) of the 3D vector field in Bwd around the axis 'dir' by 'angle'.
 
- Protected Member Functions inherited from Nektar::MultiRegions::ExpList
std::shared_ptr< DNekMatGenGlobalMatrixFull (const GlobalLinSysKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
 
const DNekScalBlkMatSharedPtr GenBlockMatrix (const GlobalMatrixKey &gkey)
 This function assembles the block diagonal matrix of local matrices of the type mtype.
 
const DNekScalBlkMatSharedPtrGetBlockMatrix (const GlobalMatrixKey &gkey)
 
void MultiplyByBlockMatrix (const GlobalMatrixKey &gkey, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
std::shared_ptr< GlobalMatrixGenGlobalMatrix (const GlobalMatrixKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
 Generates a global matrix from the given key and map.
 
void GlobalEigenSystem (const std::shared_ptr< DNekMat > &Gmat, Array< OneD, NekDouble > &EigValsReal, Array< OneD, NekDouble > &EigValsImag, Array< OneD, NekDouble > &EigVecs=NullNekDouble1DArray)
 
std::shared_ptr< GlobalLinSysGenGlobalLinSys (const GlobalLinSysKey &mkey, const std::shared_ptr< AssemblyMapCG > &locToGloMap)
 This operation constructs the global linear system of type mkey.
 
std::shared_ptr< GlobalLinSysGenGlobalBndLinSys (const GlobalLinSysKey &mkey, const AssemblyMapSharedPtr &locToGloMap)
 Generate a GlobalLinSys from information provided by the key "mkey" and the mapping provided in LocToGloBaseMap.
 
virtual size_t v_GetNumElmts (void)
 
virtual void v_Upwind (const Array< OneD, const Array< OneD, NekDouble > > &Vec, const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &Upwind)
 
virtual void v_Upwind (const Array< OneD, const NekDouble > &Vn, const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &Upwind)
 
virtual const Array< OneD, const int > & v_GetTraceBndMap ()
 
virtual void v_GetNormals (Array< OneD, Array< OneD, NekDouble > > &normals)
 Populate normals with the normals of all expansions.
 
virtual void v_AddTraceQuadPhysToOffDiag (const Array< OneD, const NekDouble > &Fwd, const Array< OneD, const NekDouble > &Bwd, Array< OneD, NekDouble > &field)
 
virtual const std::vector< bool > & v_GetLeftAdjacentFaces (void) const
 
virtual void v_MultiplyByInvMassMatrix (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual GlobalLinSysKey v_LinearAdvectionDiffusionReactionSolve (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const MultiRegions::VarFactorsMap &varfactors, const Array< OneD, const NekDouble > &dirForcing, const bool PhysSpaceForcing)
 
virtual GlobalLinSysKey v_LinearAdvectionReactionSolve (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const MultiRegions::VarFactorsMap &varfactors, const Array< OneD, const NekDouble > &dirForcing, const bool PhysSpaceForcing)
 
virtual void v_ImposeDirichletConditions (Array< OneD, NekDouble > &outarray)
 
virtual void v_ImposeNeumannConditions (Array< OneD, NekDouble > &outarray)
 
virtual void v_ImposeRobinConditions (Array< OneD, NekDouble > &outarray)
 
virtual void v_FillBndCondFromField (const Array< OneD, NekDouble > coeffs)
 
virtual void v_FillBndCondFromField (const int nreg, const Array< OneD, NekDouble > coeffs)
 
virtual void v_LocalToGlobal (bool UseComm)
 
virtual void v_LocalToGlobal (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseComm)
 
virtual void v_GlobalToLocal (void)
 
virtual void v_GlobalToLocal (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_BwdTrans (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_FwdTrans (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_FwdTransLocalElmt (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_FwdTransBndConstrained (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_SmoothField (Array< OneD, NekDouble > &field)
 
virtual void v_IProductWRTBase (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_IProductWRTDerivBase (const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_IProductWRTDerivBase (const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_GetCoords (Array< OneD, NekDouble > &coord_0, Array< OneD, NekDouble > &coord_1=NullNekDouble1DArray, Array< OneD, NekDouble > &coord_2=NullNekDouble1DArray)
 
virtual void v_GetCoords (const int eid, Array< OneD, NekDouble > &xc0, Array< OneD, NekDouble > &xc1, Array< OneD, NekDouble > &xc2)
 
virtual void v_PhysDeriv (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2)
 
virtual void v_PhysDeriv (const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d)
 
virtual void v_PhysDeriv (Direction edir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d)
 
virtual void v_Curl (Array< OneD, Array< OneD, NekDouble > > &Vel, Array< OneD, Array< OneD, NekDouble > > &Q)
 
virtual void v_CurlCurl (Array< OneD, Array< OneD, NekDouble > > &Vel, Array< OneD, Array< OneD, NekDouble > > &Q)
 
virtual void v_PhysDirectionalDeriv (const Array< OneD, const NekDouble > &direction, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_GetMovingFrames (const SpatialDomains::GeomMMF MMFdir, const Array< OneD, const NekDouble > &CircCentre, Array< OneD, Array< OneD, NekDouble > > &outarray)
 
virtual void v_HomogeneousFwdTrans (const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool Shuff=true, bool UnShuff=true)
 
virtual void v_HomogeneousBwdTrans (const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool Shuff=true, bool UnShuff=true)
 
virtual void v_DealiasedProd (const int num_dofs, const Array< OneD, NekDouble > &inarray1, const Array< OneD, NekDouble > &inarray2, Array< OneD, NekDouble > &outarray)
 
virtual void v_DealiasedDotProd (const int num_dofs, const Array< OneD, Array< OneD, NekDouble > > &inarray1, const Array< OneD, Array< OneD, NekDouble > > &inarray2, Array< OneD, Array< OneD, NekDouble > > &outarray)
 
virtual void v_GetBCValues (Array< OneD, NekDouble > &BndVals, const Array< OneD, NekDouble > &TotField, int BndID)
 
virtual void v_NormVectorIProductWRTBase (Array< OneD, const NekDouble > &V1, Array< OneD, const NekDouble > &V2, Array< OneD, NekDouble > &outarray, int BndID)
 
virtual void v_NormVectorIProductWRTBase (Array< OneD, Array< OneD, NekDouble > > &V, Array< OneD, NekDouble > &outarray)
 
virtual void v_SetUpPhysNormals ()
 
virtual void v_ExtractElmtToBndPhys (const int i, const Array< OneD, NekDouble > &elmt, Array< OneD, NekDouble > &boundary)
 
virtual void v_ExtractPhysToBndElmt (const int i, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &bndElmt)
 
virtual void v_ExtractPhysToBnd (const int i, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &bnd)
 
virtual void v_GetBoundaryNormals (int i, Array< OneD, Array< OneD, NekDouble > > &normals)
 
virtual std::vector< LibUtilities::FieldDefinitionsSharedPtrv_GetFieldDefinitions (void)
 
virtual void v_GetFieldDefinitions (std::vector< LibUtilities::FieldDefinitionsSharedPtr > &fielddef)
 
virtual void v_AppendFieldData (LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata)
 
virtual void v_AppendFieldData (LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata, Array< OneD, NekDouble > &coeffs)
 
virtual void v_ExtractDataToCoeffs (LibUtilities::FieldDefinitionsSharedPtr &fielddef, std::vector< NekDouble > &fielddata, std::string &field, Array< OneD, NekDouble > &coeffs, std::unordered_map< int, int > zIdToPlane)
 
virtual void v_ExtractCoeffsToCoeffs (const std::shared_ptr< ExpList > &fromExpList, const Array< OneD, const NekDouble > &fromCoeffs, Array< OneD, NekDouble > &toCoeffs)
 
virtual void v_WriteTecplotHeader (std::ostream &outfile, std::string var="")
 
virtual void v_WriteTecplotZone (std::ostream &outfile, int expansion)
 
virtual void v_WriteTecplotField (std::ostream &outfile, int expansion)
 
virtual void v_WriteTecplotConnectivity (std::ostream &outfile, int expansion)
 
virtual void v_WriteVtkPieceData (std::ostream &outfile, int expansion, std::string var)
 
virtual void v_WriteVtkPieceHeader (std::ostream &outfile, int expansion, int istrip)
 
virtual NekDouble v_L2 (const Array< OneD, const NekDouble > &phys, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
 
virtual NekDouble v_Integral (const Array< OneD, const NekDouble > &inarray)
 
virtual NekDouble v_VectorFlux (const Array< OneD, Array< OneD, NekDouble > > &inarray)
 
virtual Array< OneD, const NekDoublev_HomogeneousEnergy (void)
 
virtual LibUtilities::TranspositionSharedPtr v_GetTransposition (void)
 
virtual NekDouble v_GetHomoLen (void)
 
virtual void v_SetHomoLen (const NekDouble lhom)
 
virtual Array< OneD, const unsigned int > v_GetZIDs (void)
 
virtual Array< OneD, const unsigned int > v_GetYIDs (void)
 
virtual void v_PhysInterp1DScaled (const NekDouble scale, const Array< OneD, NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_PhysGalerkinProjection1DScaled (const NekDouble scale, const Array< OneD, NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
 
virtual void v_ClearGlobalLinSysManager (void)
 
virtual int v_GetPoolCount (std::string)
 
virtual void v_UnsetGlobalLinSys (GlobalLinSysKey, bool)
 
virtual LibUtilities::NekManager< GlobalLinSysKey, GlobalLinSys > & v_GetGlobalLinSysManager (void)
 
void ExtractFileBCs (const std::string &fileName, LibUtilities::CommSharedPtr comm, const std::string &varName, const std::shared_ptr< ExpList > locExpList)
 
virtual LibUtilities::BasisSharedPtr v_GetHomogeneousBasis (void)
 
virtual void v_SetHomo1DSpecVanVisc (Array< OneD, NekDouble > visc)
 
virtual std::shared_ptr< ExpList > & v_GetPlane (int n)
 

Protected Attributes

Array< OneD, SpatialDomains::BoundaryConditionShPtrm_bndConditions
 An array which contains the information about the boundary condition structure definition on the different boundary regions.
 
Array< OneD, MultiRegions::ExpListSharedPtrm_bndCondExpansions
 An object which contains the discretised boundary conditions.
 
Array< OneD, NekDoublem_bndCondBndWeight
 
InterfaceMapDGSharedPtr m_interfaceMap
 Interfaces mapping for trace space.
 
GlobalLinSysMapShPtr m_globalBndMat
 Global boundary matrix.
 
ExpListSharedPtr m_trace
 Trace space storage for points between elements.
 
MultiRegions::ExpListSharedPtr m_locElmtTrace
 Local Elemental trace expansions.
 
AssemblyMapDGSharedPtr m_traceMap
 Local to global DG mapping for trace space.
 
std::set< int > m_boundaryTraces
 A set storing the global IDs of any boundary Verts.
 
PeriodicMap m_periodicVerts
 A map which identifies groups of periodic vertices.
 
PeriodicMap m_periodicEdges
 A map which identifies pairs of periodic edges.
 
PeriodicMap m_periodicFaces
 A map which identifies pairs of periodic faces.
 
std::vector< int > m_periodicFwdCopy
 A vector indicating degress of freedom which need to be copied from forwards to backwards space in case of a periodic boundary condition.
 
std::vector< int > m_periodicBwdCopy
 
std::vector< bool > m_leftAdjacentTraces
 
LocTraceToTraceMapSharedPtr m_locTraceToTraceMap
 
- Protected Attributes inherited from Nektar::MultiRegions::ExpList
SpatialDomains::EntityHolder1D m_holder
 Pointer holder for PulseWaveSolver.
 
ExpansionType m_expType
 Expansion type.
 
LibUtilities::CommSharedPtr m_comm
 Communicator.
 
LibUtilities::SessionReaderSharedPtr m_session
 Session.
 
SpatialDomains::MeshGraphSharedPtr m_graph
 Mesh associated with this expansion list.
 
int m_ncoeffs
 The total number of local degrees of freedom. m_ncoeffs \(=N_{\mathrm{eof}}=\sum_{e=1}^{{N_{\mathrm{el}}}}N^{e}_l\).
 
int m_npoints
 
Array< OneD, NekDoublem_coeffs
 Concatenation of all local expansion coefficients.
 
Array< OneD, NekDoublem_phys
 The global expansion evaluated at the quadrature points.
 
bool m_physState
 The state of the array m_phys.
 
std::shared_ptr< LocalRegions::ExpansionVectorm_exp
 The list of local expansions.
 
Collections::CollectionVector m_collections
 
std::vector< bool > m_collectionsDoInit
 Vector of bools to act as an initialise on first call flag.
 
std::vector< int > m_coll_coeff_offset
 Offset of elemental data into the array m_coeffs.
 
std::vector< int > m_coll_phys_offset
 Offset of elemental data into the array m_phys.
 
Array< OneD, int > m_coeff_offset
 Offset of elemental data into the array m_coeffs.
 
Array< OneD, int > m_phys_offset
 Offset of elemental data into the array m_phys.
 
Array< OneD, std::pair< int, int > > m_coeffsToElmt
 m_coeffs to elemental value map
 
BlockMatrixMapShPtr m_blockMat
 
bool m_WaveSpace
 
std::unordered_map< int, int > m_elmtToExpId
 Mapping from geometry ID of element to index inside m_exp.
 
Array< OneD, Array< OneD, NekDouble > > m_gridVelocity
 Grid velocity at quadrature points.
 

Private Member Functions

SpatialDomains::BoundaryConditionsSharedPtr GetDomainBCs (const SpatialDomains::CompositeMap &domain, const SpatialDomains::BoundaryConditions &Allbcs, const std::string &variable)
 

Private Attributes

std::vector< bool > m_negatedFluxNormal
 

Additional Inherited Members

- Static Protected Member Functions inherited from Nektar::MultiRegions::ExpList
static SpatialDomains::BoundaryConditionShPtr GetBoundaryCondition (const SpatialDomains::BoundaryConditionCollection &collection, unsigned int index, const std::string &variable)
 

Detailed Description

This class is the abstractio n of a global discontinuous two- dimensional spectral/hp element expansion which approximates the solution of a set of partial differential equations.

This class augments the list of local expansions inherited from ExpList with boundary conditions. Inter-element boundaries are handled using an discontinuous Galerkin scheme.

Definition at line 55 of file DisContField.h.

Constructor & Destructor Documentation

◆ DisContField() [1/6]

Nektar::MultiRegions::DisContField::DisContField ( )

Default constructor.

Constructs an empty expansion list with no boundary conditions.

Definition at line 63 of file DisContField.cpp.

66{
67}
Array< OneD, SpatialDomains::BoundaryConditionShPtr > m_bndConditions
An array which contains the information about the boundary condition structure definition on the diff...
ExpListSharedPtr m_trace
Trace space storage for points between elements.
Array< OneD, MultiRegions::ExpListSharedPtr > m_bndCondExpansions
An object which contains the discretised boundary conditions.
ExpList(const ExpansionType Type=eNoType)
The default constructor using a type.
static ExpListSharedPtr NullExpListSharedPtr
Definition ExpList.h:1565

◆ DisContField() [2/6]

Nektar::MultiRegions::DisContField::DisContField ( const LibUtilities::SessionReaderSharedPtr pSession,
const SpatialDomains::MeshGraphSharedPtr graph,
const std::string &  variable,
const bool  SetUpJustDG = true,
const bool  DeclareCoeffPhysArrays = true,
const Collections::ImplementationType  ImpType = Collections::eNoImpType,
const std::string  bcvariable = "NotSet" 
)

Constructs a 1D discontinuous field based on a mesh and boundary conditions.

An expansion list for the boundary expansions is generated first for the field. These are subsequently evaluated for time zero. The trace map is then constructed.

Parameters
graph1DA mesh, containing information about the domain and the spectral/hp element expansions.
bcsInformation about the enforced boundary conditions.
variableThe session variable associated with the boundary conditions to enforce.
solnTypeType of global system to use.

Definition at line 81 of file DisContField.cpp.

87 : ExpList(pSession, graph, DeclareCoeffPhysArrays, variable, ImpType),
89{
90 std::string bcvar;
91 if (bcvariable == "NotSet")
92 {
93 bcvar = variable;
94 }
95 else
96 {
97 bcvar = bcvariable;
98 }
99
100 if (bcvar.compare("DefaultVar") != 0)
101 {
102 SpatialDomains::BoundaryConditions bcs(m_session, graph);
103
104 GenerateBoundaryConditionExpansion(graph, bcs, bcvar,
105 DeclareCoeffPhysArrays, ImpType);
106 if (DeclareCoeffPhysArrays)
107 {
108 EvaluateBoundaryConditions(0.0, bcvar);
109 }
111 FindPeriodicTraces(bcs, bcvar);
112 }
113
114 int i, cnt;
115 Array<OneD, int> ElmtID, TraceID;
116 GetBoundaryToElmtMap(ElmtID, TraceID);
117
118 for (cnt = i = 0; i < m_bndCondExpansions.size(); ++i)
119 {
121 locExpList = m_bndCondExpansions[i];
122
123 for (int e = 0; e < locExpList->GetExpSize(); ++e)
124 {
125 (*m_exp)[ElmtID[cnt + e]]->SetTraceExp(TraceID[cnt + e],
126 locExpList->GetExp(e));
127 locExpList->GetExp(e)->SetAdjacentElementExp(
128 TraceID[cnt + e], (*m_exp)[ElmtID[cnt + e]]);
129 }
130 cnt += m_bndCondExpansions[i]->GetExpSize();
131 }
132
133 if (SetUpJustDG)
134 {
135 SetUpDG(variable, ImpType);
136 }
137 else
138 {
139 if (m_session->DefinesSolverInfo("PROJECTION"))
140 {
141 std::string ProjectStr = m_session->GetSolverInfo("PROJECTION");
142 if ((ProjectStr == "MixedCGDG") ||
143 (ProjectStr == "Mixed_CG_Discontinuous"))
144 {
145 SetUpDG(variable);
146 }
147 else
148 {
150 }
151 }
152 else
153 {
155 }
156 }
157}
void SetUpDG(const std::string="DefaultVar", const Collections::ImplementationType ImpType=Collections::eNoImpType)
Set up all DG member variables and maps.
void GenerateBoundaryConditionExpansion(const SpatialDomains::MeshGraphSharedPtr &graph1D, const SpatialDomains::BoundaryConditions &bcs, const std::string variable, const bool DeclareCoeffPhysArrays=true, const Collections::ImplementationType ImpType=Collections::eNoImpType)
Discretises the boundary conditions.
void FindPeriodicTraces(const SpatialDomains::BoundaryConditions &bcs, const std::string variable)
Generate a associative map of periodic vertices in a mesh.
void GetBoundaryToElmtMap(Array< OneD, int > &ElmtID, Array< OneD, int > &EdgeID)
Definition ExpList.h:2362
std::shared_ptr< LocalRegions::ExpansionVector > m_exp
The list of local expansions.
Definition ExpList.h:1164
void EvaluateBoundaryConditions(const NekDouble time=0.0, const std::string varName="", const NekDouble=NekConstants::kNekUnsetDouble, const NekDouble=NekConstants::kNekUnsetDouble)
Definition ExpList.h:2351
void ApplyGeomInfo()
Apply geometry information to each expansion.
LibUtilities::SessionReaderSharedPtr m_session
Session.
Definition ExpList.h:1104
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.

References Nektar::MultiRegions::ExpList::ApplyGeomInfo(), Nektar::MultiRegions::ExpList::EvaluateBoundaryConditions(), FindPeriodicTraces(), GenerateBoundaryConditionExpansion(), Nektar::MultiRegions::ExpList::GetBoundaryToElmtMap(), m_bndCondExpansions, Nektar::MultiRegions::ExpList::m_exp, Nektar::MultiRegions::ExpList::m_session, SetUpDG(), and Nektar::MultiRegions::ExpList::SetUpPhysNormals().

◆ DisContField() [3/6]

Nektar::MultiRegions::DisContField::DisContField ( const LibUtilities::SessionReaderSharedPtr pSession,
const SpatialDomains::MeshGraphSharedPtr graph1D,
const SpatialDomains::CompositeMap domain,
const SpatialDomains::BoundaryConditions Allbcs,
const std::string &  variable,
const LibUtilities::CommSharedPtr comm,
bool  SetToOneSpaceDimension = false,
const Collections::ImplementationType  ImpType = Collections::eNoImpType 
)

Constructor for a DisContField from a List of subdomains New Constructor for arterial network.

Constructor for use in multidomain computations where a domain list can be passed instead of graph1D

Parameters
domainSubdomain specified in the inputfile from which the DisContField is set up

Definition at line 611 of file DisContField.cpp.

619 : ExpList(pSession, domain, graph1D, true, variable, SetToOneSpaceDimension,
620 comm, ImpType)
621{
622 if (variable.compare("DefaultVar") != 0)
623 {
625 GetDomainBCs(domain, Allbcs, variable);
626
627 GenerateBoundaryConditionExpansion(m_graph, *DomBCs, variable, true,
628 ImpType);
629 EvaluateBoundaryConditions(0.0, variable);
631 FindPeriodicTraces(*DomBCs, variable);
632 }
633
634 SetUpDG(variable);
635}
SpatialDomains::BoundaryConditionsSharedPtr GetDomainBCs(const SpatialDomains::CompositeMap &domain, const SpatialDomains::BoundaryConditions &Allbcs, const std::string &variable)
SpatialDomains::MeshGraphSharedPtr m_graph
Mesh associated with this expansion list.
Definition ExpList.h:1106
std::shared_ptr< BoundaryConditions > BoundaryConditionsSharedPtr
Definition Conditions.h:327

References Nektar::MultiRegions::ExpList::ApplyGeomInfo(), Nektar::MultiRegions::ExpList::EvaluateBoundaryConditions(), FindPeriodicTraces(), GenerateBoundaryConditionExpansion(), GetDomainBCs(), Nektar::MultiRegions::ExpList::m_graph, and SetUpDG().

◆ DisContField() [4/6]

Nektar::MultiRegions::DisContField::DisContField ( const DisContField In,
const bool  DeclareCoeffPhysArrays = true 
)

Constructs a 1D discontinuous field based on an existing field.

Constructs a field as a copy of an existing field.

Parameters
InExisting DisContField object to copy.

Definition at line 641 of file DisContField.cpp.

643 : ExpList(In, DeclareCoeffPhysArrays), m_bndConditions(In.m_bndConditions),
644 m_bndCondExpansions(In.m_bndCondExpansions),
645 m_bndCondBndWeight(In.m_bndCondBndWeight),
646 m_interfaceMap(In.m_interfaceMap), m_globalBndMat(In.m_globalBndMat),
647 m_traceMap(In.m_traceMap), m_boundaryTraces(In.m_boundaryTraces),
648 m_periodicVerts(In.m_periodicVerts),
649 m_periodicFwdCopy(In.m_periodicFwdCopy),
650 m_periodicBwdCopy(In.m_periodicBwdCopy),
651 m_leftAdjacentTraces(In.m_leftAdjacentTraces),
652 m_locTraceToTraceMap(In.m_locTraceToTraceMap)
653{
654 if (In.m_trace) // independent trace space
655 {
657 *In.m_trace, DeclareCoeffPhysArrays);
658 }
659
660 if (In.m_locElmtTrace)
661 {
663 *In.m_locElmtTrace, DeclareCoeffPhysArrays);
664 }
665}
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::set< int > m_boundaryTraces
A set storing the global IDs of any boundary Verts.
LocTraceToTraceMapSharedPtr m_locTraceToTraceMap
MultiRegions::ExpListSharedPtr m_locElmtTrace
Local Elemental trace expansions.
AssemblyMapDGSharedPtr m_traceMap
Local to global DG mapping for trace space.
InterfaceMapDGSharedPtr m_interfaceMap
Interfaces mapping for trace space.
Array< OneD, NekDouble > m_bndCondBndWeight
GlobalLinSysMapShPtr m_globalBndMat
Global boundary matrix.
PeriodicMap m_periodicVerts
A map which identifies groups of periodic vertices.
std::vector< int > m_periodicFwdCopy
A vector indicating degress of freedom which need to be copied from forwards to backwards space in ca...
std::vector< bool > m_leftAdjacentTraces

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), m_locElmtTrace, and m_trace.

◆ DisContField() [5/6]

Nektar::MultiRegions::DisContField::DisContField ( const DisContField In,
const SpatialDomains::MeshGraphSharedPtr graph,
const std::string &  variable,
const bool  SetUpJustDG = true,
const bool  DeclareCoeffPhysArrays = true 
)

Definition at line 671 of file DisContField.cpp.

675 : ExpList(In, DeclareCoeffPhysArrays)
676{
677
679
680 // Set up boundary conditions for this variable.
681 // Do not set up BCs if default variable
682 if (variable.compare("DefaultVar") != 0)
683 {
684 SpatialDomains::BoundaryConditions bcs(m_session, graph);
685 GenerateBoundaryConditionExpansion(In.m_bndCondExpansions, bcs,
686 variable);
687
688 if (DeclareCoeffPhysArrays)
689 {
690 EvaluateBoundaryConditions(0.0, variable);
691 }
692
694 {
695 // Find periodic edges for this variable.
696 FindPeriodicTraces(bcs, variable);
697
698 if (SetUpJustDG)
699 {
700 SetUpDG(variable);
701 }
702 else
703 {
704 // set elmt edges to point to robin bc edges if required
705 int i, cnt = 0;
706 Array<OneD, int> ElmtID, TraceID;
707 GetBoundaryToElmtMap(ElmtID, TraceID);
708
709 for (i = 0; i < m_bndCondExpansions.size(); ++i)
710 {
712
713 int e;
714 locExpList = m_bndCondExpansions[i];
715
716 for (e = 0; e < locExpList->GetExpSize(); ++e)
717 {
718 (*m_exp)[ElmtID[cnt + e]]->SetTraceExp(
719 TraceID[cnt + e], locExpList->GetExp(e));
720 locExpList->GetExp(e)->SetAdjacentElementExp(
721 TraceID[cnt + e], (*m_exp)[ElmtID[cnt + e]]);
722 }
723
724 cnt += m_bndCondExpansions[i]->GetExpSize();
725 }
726
727 if (m_session->DefinesSolverInfo("PROJECTION"))
728 {
729 std::string ProjectStr =
730 m_session->GetSolverInfo("PROJECTION");
731
732 if ((ProjectStr == "MixedCGDG") ||
733 (ProjectStr == "Mixed_CG_Discontinuous"))
734 {
735 SetUpDG(variable);
736 }
737 else
738 {
740 }
741 }
742 else
743 {
745 }
746 }
747 }
748 else
749 {
750 m_globalBndMat = In.m_globalBndMat;
751 m_trace = In.m_trace;
752 m_locElmtTrace = In.m_locElmtTrace;
753 m_traceMap = In.m_traceMap;
754 m_interfaceMap = In.m_interfaceMap;
755 m_locTraceToTraceMap = In.m_locTraceToTraceMap;
756 m_periodicVerts = In.m_periodicVerts;
757 m_periodicEdges = In.m_periodicEdges;
758 m_periodicFaces = In.m_periodicFaces;
759 m_periodicFwdCopy = In.m_periodicFwdCopy;
760 m_periodicBwdCopy = In.m_periodicBwdCopy;
761 m_boundaryTraces = In.m_boundaryTraces;
762 m_leftAdjacentTraces = In.m_leftAdjacentTraces;
763
764 if (!SetUpJustDG)
765 {
766 // set elmt edges to point to robin bc edges if required
767 int i, cnt = 0;
768 Array<OneD, int> ElmtID, TraceID;
769 GetBoundaryToElmtMap(ElmtID, TraceID);
770
771 for (i = 0; i < m_bndCondExpansions.size(); ++i)
772 {
774
775 int e;
776 locExpList = m_bndCondExpansions[i];
777
778 for (e = 0; e < locExpList->GetExpSize(); ++e)
779 {
780 (*m_exp)[ElmtID[cnt + e]]->SetTraceExp(
781 TraceID[cnt + e], locExpList->GetExp(e));
782 locExpList->GetExp(e)->SetAdjacentElementExp(
783 TraceID[cnt + e], (*m_exp)[ElmtID[cnt + e]]);
784 }
785 cnt += m_bndCondExpansions[i]->GetExpSize();
786 }
787
789 }
790 }
791 }
792}
PeriodicMap m_periodicEdges
A map which identifies pairs of periodic edges.
PeriodicMap m_periodicFaces
A map which identifies pairs of periodic faces.
bool SameTypeOfBoundaryConditions(const DisContField &In)
Check to see if expansion has the same BCs as In.

References Nektar::MultiRegions::ExpList::EvaluateBoundaryConditions(), FindPeriodicTraces(), GenerateBoundaryConditionExpansion(), Nektar::MultiRegions::ExpList::GetBoundaryToElmtMap(), m_bndCondExpansions, m_boundaryTraces, Nektar::MultiRegions::ExpList::m_exp, m_globalBndMat, m_interfaceMap, m_leftAdjacentTraces, m_locElmtTrace, m_locTraceToTraceMap, m_periodicBwdCopy, m_periodicEdges, m_periodicFaces, m_periodicFwdCopy, m_periodicVerts, Nektar::MultiRegions::ExpList::m_session, m_trace, m_traceMap, Nektar::MultiRegions::NullExpListSharedPtr, SameTypeOfBoundaryConditions(), SetUpDG(), and Nektar::MultiRegions::ExpList::SetUpPhysNormals().

◆ DisContField() [6/6]

Nektar::MultiRegions::DisContField::DisContField ( const ExpList In)

Constructs a 1D discontinuous field based on an existing field. (needed in order to use ContField( const ExpList &In) constructor.

Constructs a field as a copy of an existing explist field.

Parameters
InExisting ExpList object to copy.

Definition at line 798 of file DisContField.cpp.

798 : ExpList(In)
799{
800}

◆ ~DisContField()

Nektar::MultiRegions::DisContField::~DisContField ( )
override

Destructor.

Definition at line 805 of file DisContField.cpp.

806{
807}

Member Function Documentation

◆ DeriveRotate()

void Nektar::MultiRegions::DisContField::DeriveRotate ( TensorOfArray3D< NekDouble > &  Bwd,
const int  dir,
const NekDouble  angle,
const int  offset,
const int  npts 
)
protected

Rotate the slice [offset, offset + npts) of the 3D vector field in Bwd around the axis 'dir' by 'angle'.

Definition at line 4870 of file DisContField.cpp.

4873{
4874 // Precompute trigonometric values using correct angle input
4875 const NekDouble cosA = cos(angle);
4876 const NekDouble sinA = sin(angle);
4877
4878 // Define rotation matrix R (3x3) using Array<OneD, NekDouble> in
4879 // **column-major order**
4880 Array<OneD, NekDouble> R(9, 0.0);
4881
4882 if (dir == 0) // Rotation around X-axis
4883 {
4884 R[0] = 1.0;
4885 R[3] = 0.0;
4886 R[6] = 0.0;
4887 R[1] = 0.0;
4888 R[4] = cosA;
4889 R[7] = -sinA;
4890 R[2] = 0.0;
4891 R[5] = sinA;
4892 R[8] = cosA;
4893 }
4894 else if (dir == 1) // Rotation around Y-axis
4895 {
4896 R[0] = cosA;
4897 R[3] = 0.0;
4898 R[6] = sinA;
4899 R[1] = 0.0;
4900 R[4] = 1.0;
4901 R[7] = 0.0;
4902 R[2] = -sinA;
4903 R[5] = 0.0;
4904 R[8] = cosA;
4905 }
4906 else if (dir == 2) // Rotation around Z-axis
4907 {
4908 R[0] = cosA;
4909 R[3] = -sinA;
4910 R[6] = 0.0;
4911 R[1] = sinA;
4912 R[4] = cosA;
4913 R[7] = 0.0;
4914 R[2] = 0.0;
4915 R[5] = 0.0;
4916 R[8] = 1.0;
4917 }
4918 else
4919 {
4920 NEKERROR(
4922 "Invalid rotation axis for first-order derivative transformation.");
4923 }
4924
4925 for (int p = offset; p < offset + npts; ++p)
4926 {
4927 // Allocate gradient tensor (3x3) in **column-major order**
4928 Array<OneD, NekDouble> gradU(9, 0.0);
4929
4930 // Load original velocity gradient tensor into **column-major** format
4931 gradU[0] = Bwd[0][1][p]; // ∂u_x/∂x
4932 gradU[3] = Bwd[1][1][p]; // ∂u_x/∂y
4933 gradU[6] = Bwd[2][1][p]; // ∂u_x/∂z
4934
4935 gradU[1] = Bwd[0][2][p]; // ∂u_y/∂x
4936 gradU[4] = Bwd[1][2][p]; // ∂u_y/∂y
4937 gradU[7] = Bwd[2][2][p]; // ∂u_y/∂z
4938
4939 gradU[2] = Bwd[0][3][p]; // ∂u_z/∂x
4940 gradU[5] = Bwd[1][3][p]; // ∂u_z/∂y
4941 gradU[8] = Bwd[2][3][p]; // ∂u_z/∂z
4942
4943 // Allocate intermediate matrix R * gradU in **column-major order**
4944 Array<OneD, NekDouble> R_gradU(9, 0.0);
4945
4946 // Perform matrix multiplication R * gradU using Blas::Dgemm in
4947 // **column-major order**
4948 Blas::Dgemm('N', 'N', 3, 3, 3, 1.0, R.data(), 3, gradU.data(), 3, 0.0,
4949 R_gradU.data(), 3);
4950
4951 // Allocate final rotated gradient (R * gradU) * R^T in **column-major
4952 // order**
4953 Array<OneD, NekDouble> gradU_rotated(9, 0.0);
4954
4955 // Perform matrix multiplication (R * gradU) * R^T using Blas::Dgemm in
4956 // **column-major order**
4957 Blas::Dgemm('N', 'T', 3, 3, 3, 1.0, R_gradU.data(), 3, R.data(), 3, 0.0,
4958 gradU_rotated.data(), 3);
4959
4960 // Store rotated gradients back in Bwd in **column-major order**
4961 Bwd[0][1][p] = gradU_rotated[0]; // ∂u_x'/∂x'
4962 Bwd[1][1][p] = gradU_rotated[3]; // ∂u_x'/∂y'
4963 Bwd[2][1][p] = gradU_rotated[6]; // ∂u_x'/∂z'
4964
4965 Bwd[0][2][p] = gradU_rotated[1]; // ∂u_y'/∂x'
4966 Bwd[1][2][p] = gradU_rotated[4]; // ∂u_y'/∂y'
4967 Bwd[2][2][p] = gradU_rotated[7]; // ∂u_y'/∂z'
4968
4969 Bwd[0][3][p] = gradU_rotated[2]; // ∂u_z'/∂x'
4970 Bwd[1][3][p] = gradU_rotated[5]; // ∂u_z'/∂y'
4971 Bwd[2][3][p] = gradU_rotated[8]; // ∂u_z'/∂z'
4972 }
4973}
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where op(A)[m x k], op(B)[k x n], C[m x n] DGEMM perfo...
Definition Blas.hpp:383
std::vector< double > p(NPUPPER)

References Blas::Dgemm(), Nektar::ErrorUtil::efatal, and NEKERROR.

Referenced by v_PeriodicDeriveBwdRot().

◆ EvaluateHDGPostProcessing()

void Nektar::MultiRegions::DisContField::EvaluateHDGPostProcessing ( const Array< OneD, const NekDouble > &  coeffs,
Array< OneD, NekDouble > &  outarray 
)

Evaluate HDG post-processing to increase polynomial order of solution.

This function takes the solution (assumed to be one order lower) in physical space, and postprocesses at the current polynomial order by solving the system:

\[ \begin{aligned} (\nabla w, \nabla u^*) &= (\nabla w, u), \\ \langle \nabla u^*, 1 \rangle &= \langle \nabla u, 1 \rangle \end{aligned} \]

where \( u \) corresponds with the current solution as stored inside m_coeffs.

Parameters
outarrayThe resulting field \( u^* \).

Definition at line 4560 of file DisContField.cpp.

4563{
4564 int i, cnt, e, ncoeff_trace;
4565 Array<OneD, NekDouble> force, out_tmp, qrhs, qrhs1;
4566 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>> &elmtToTrace =
4567 m_traceMap->GetElmtToTrace();
4568
4570
4571 int nq_elmt, nm_elmt;
4572 int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs();
4573 Array<OneD, NekDouble> loc_lambda(LocBndCoeffs), trace_lambda;
4574 Array<OneD, NekDouble> tmp_coeffs;
4575 m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(), loc_lambda);
4576
4577 trace_lambda = loc_lambda;
4578
4579 int dim = (m_expType == e2D) ? 2 : 3;
4580
4581 int num_points[] = {0, 0, 0};
4582 int num_modes[] = {0, 0, 0};
4583
4584 // Calculate Q using standard DG formulation.
4585 for (i = cnt = 0; i < GetExpSize(); ++i)
4586 {
4587 nq_elmt = (*m_exp)[i]->GetTotPoints();
4588 nm_elmt = (*m_exp)[i]->GetNcoeffs();
4589 qrhs = Array<OneD, NekDouble>(nq_elmt);
4590 qrhs1 = Array<OneD, NekDouble>(nq_elmt);
4591 force = Array<OneD, NekDouble>(2 * nm_elmt);
4592 out_tmp = force + nm_elmt;
4594
4595 for (int j = 0; j < dim; ++j)
4596 {
4597 num_points[j] = (*m_exp)[i]->GetBasis(j)->GetNumPoints();
4598 num_modes[j] = (*m_exp)[i]->GetBasis(j)->GetNumModes();
4599 }
4600
4601 // Probably a better way of setting up lambda than this. Note
4602 // cannot use PutCoeffsInToElmts since lambda space is mapped
4603 // during the solve.
4604 int nTraces = (*m_exp)[i]->GetNtraces();
4605 Array<OneD, Array<OneD, NekDouble>> traceCoeffs(nTraces);
4606
4607 for (e = 0; e < (*m_exp)[i]->GetNtraces(); ++e)
4608 {
4609 edgedir = (*m_exp)[i]->GetTraceOrient(e);
4610 ncoeff_trace = elmtToTrace[i][e]->GetNcoeffs();
4611 traceCoeffs[e] = Array<OneD, NekDouble>(ncoeff_trace);
4612 Vmath::Vcopy(ncoeff_trace, trace_lambda, 1, traceCoeffs[e], 1);
4613 if (dim == 2)
4614 {
4615 elmtToTrace[i][e]->SetCoeffsToOrientation(
4616 edgedir, traceCoeffs[e], traceCoeffs[e]);
4617 }
4618 else
4619 {
4620 (*m_exp)[i]
4621 ->as<LocalRegions::Expansion3D>()
4622 ->SetFaceToGeomOrientation(e, traceCoeffs[e]);
4623 }
4624 trace_lambda = trace_lambda + ncoeff_trace;
4625 }
4626
4627 // creating orthogonal expansion (checking if we have quads or
4628 // triangles)
4629 LibUtilities::ShapeType shape = (*m_exp)[i]->DetShapeType();
4630 switch (shape)
4631 {
4633 {
4634 const LibUtilities::PointsKey PkeyQ1(
4636 const LibUtilities::PointsKey PkeyQ2(
4638 LibUtilities::BasisKey BkeyQ1(LibUtilities::eOrtho_A,
4639 num_modes[0], PkeyQ1);
4640 LibUtilities::BasisKey BkeyQ2(LibUtilities::eOrtho_A,
4641 num_modes[1], PkeyQ2);
4642 SpatialDomains::QuadGeom *qGeom =
4643 dynamic_cast<SpatialDomains::QuadGeom *>(
4644 (*m_exp)[i]->GetGeom());
4646 BkeyQ1, BkeyQ2, qGeom);
4647 }
4648 break;
4650 {
4651 const LibUtilities::PointsKey PkeyT1(
4653 const LibUtilities::PointsKey PkeyT2(
4654 num_points[1], LibUtilities::eGaussRadauMAlpha1Beta0);
4655 LibUtilities::BasisKey BkeyT1(LibUtilities::eOrtho_A,
4656 num_modes[0], PkeyT1);
4657 LibUtilities::BasisKey BkeyT2(LibUtilities::eOrtho_B,
4658 num_modes[1], PkeyT2);
4659 SpatialDomains::TriGeom *tGeom =
4660 dynamic_cast<SpatialDomains::TriGeom *>(
4661 (*m_exp)[i]->GetGeom());
4663 BkeyT1, BkeyT2, tGeom);
4664 }
4665 break;
4667 {
4668 const LibUtilities::PointsKey PkeyH1(
4670 const LibUtilities::PointsKey PkeyH2(
4672 const LibUtilities::PointsKey PkeyH3(
4674 LibUtilities::BasisKey BkeyH1(LibUtilities::eOrtho_A,
4675 num_modes[0], PkeyH1);
4676 LibUtilities::BasisKey BkeyH2(LibUtilities::eOrtho_A,
4677 num_modes[1], PkeyH2);
4678 LibUtilities::BasisKey BkeyH3(LibUtilities::eOrtho_A,
4679 num_modes[2], PkeyH3);
4680 SpatialDomains::HexGeom *hGeom =
4681 dynamic_cast<SpatialDomains::HexGeom *>(
4682 (*m_exp)[i]->GetGeom());
4684 BkeyH1, BkeyH2, BkeyH3, hGeom);
4685 }
4686 break;
4688 {
4689 const LibUtilities::PointsKey PkeyT1(
4691 const LibUtilities::PointsKey PkeyT2(
4692 num_points[1], LibUtilities::eGaussRadauMAlpha1Beta0);
4693 const LibUtilities::PointsKey PkeyT3(
4694 num_points[2], LibUtilities::eGaussRadauMAlpha2Beta0);
4695 LibUtilities::BasisKey BkeyT1(LibUtilities::eOrtho_A,
4696 num_modes[0], PkeyT1);
4697 LibUtilities::BasisKey BkeyT2(LibUtilities::eOrtho_B,
4698 num_modes[1], PkeyT2);
4699 LibUtilities::BasisKey BkeyT3(LibUtilities::eOrtho_C,
4700 num_modes[2], PkeyT3);
4701 SpatialDomains::TetGeom *tGeom =
4702 dynamic_cast<SpatialDomains::TetGeom *>(
4703 (*m_exp)[i]->GetGeom());
4705 BkeyT1, BkeyT2, BkeyT3, tGeom);
4706 }
4707 break;
4708 default:
4710 "Wrong shape type, HDG postprocessing is not "
4711 "implemented");
4712 };
4713
4714 // DGDeriv
4715 // (d/dx w, d/dx q_0)
4716 (*m_exp)[i]->DGDeriv(0, tmp_coeffs = coeffs + m_coeff_offset[i],
4717 elmtToTrace[i], traceCoeffs, out_tmp);
4718 (*m_exp)[i]->BwdTrans(out_tmp, qrhs);
4719 ppExp->IProductWRTDerivBase(0, qrhs, force);
4720
4721 // + (d/dy w, d/dy q_1)
4722 (*m_exp)[i]->DGDeriv(1, tmp_coeffs = coeffs + m_coeff_offset[i],
4723 elmtToTrace[i], traceCoeffs, out_tmp);
4724
4725 (*m_exp)[i]->BwdTrans(out_tmp, qrhs);
4726 ppExp->IProductWRTDerivBase(1, qrhs, out_tmp);
4727
4728 Vmath::Vadd(nm_elmt, force, 1, out_tmp, 1, force, 1);
4729
4730 // determine force[0] = (1,u)
4731 (*m_exp)[i]->BwdTrans(tmp_coeffs = coeffs + m_coeff_offset[i], qrhs);
4732 force[0] = (*m_exp)[i]->Integral(qrhs);
4733
4734 // multiply by inverse Laplacian matrix
4735 // get matrix inverse
4736 LocalRegions::MatrixKey lapkey(StdRegions::eInvLaplacianWithUnityMean,
4737 ppExp->DetShapeType(), *ppExp);
4738 DNekScalMatSharedPtr lapsys = ppExp->GetLocMatrix(lapkey);
4739
4740 NekVector<NekDouble> in(nm_elmt, force, eWrapper);
4741 NekVector<NekDouble> out(nm_elmt);
4742
4743 out = (*lapsys) * in;
4744
4745 // Transforming back to modified basis
4746 Array<OneD, NekDouble> work(nq_elmt);
4747 ppExp->BwdTrans(out.GetPtr(), work);
4748 (*m_exp)[i]->FwdTrans(work, tmp_coeffs = outarray + m_coeff_offset[i]);
4749 }
4750}
int GetExpSize(void)
This function returns the number of elements in the expansion.
Definition ExpList.h:2119
Array< OneD, int > m_coeff_offset
Offset of elemental data into the array m_coeffs.
Definition ExpList.h:1173
ExpansionType m_expType
Expansion type.
Definition ExpList.h:1097
@ eGaussLobattoLegendre
1D Gauss-Lobatto-Legendre quadrature points
Definition PointsType.h:51
@ eOrtho_A
Principle Orthogonal Functions .
Definition BasisType.h:42
@ eOrtho_C
Principle Orthogonal Functions .
Definition BasisType.h:46
@ eOrtho_B
Principle Orthogonal Functions .
Definition BasisType.h:44
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition Expansion.h:66
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition Vmath.hpp:180
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::MultiRegions::e2D, Nektar::ErrorUtil::efatal, Nektar::LibUtilities::eGaussLobattoLegendre, Nektar::LibUtilities::eHexahedron, Nektar::StdRegions::eInvLaplacianWithUnityMean, Nektar::LibUtilities::eOrtho_A, Nektar::LibUtilities::eOrtho_B, Nektar::LibUtilities::eOrtho_C, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eTetrahedron, Nektar::LibUtilities::eTriangle, Nektar::eWrapper, Nektar::MultiRegions::ExpList::GetExpSize(), Nektar::NekVector< DataType >::GetPtr(), Nektar::MultiRegions::ExpList::m_coeff_offset, Nektar::MultiRegions::ExpList::m_expType, m_trace, m_traceMap, NEKERROR, Vmath::Vadd(), and Vmath::Vcopy().

◆ FillBwdWithBoundCond()

void Nektar::MultiRegions::DisContField::FillBwdWithBoundCond ( const Array< OneD, NekDouble > &  Fwd,
Array< OneD, NekDouble > &  Bwd,
const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > &  bndConditions,
const Array< OneD, const ExpListSharedPtr > &  bndCondExpansions,
bool  PutFwdInBwdOnBCs 
)
protected

function allowing different BCs to be passed to routine

Definition at line 3328 of file DisContField.cpp.

3334{
3335
3336 // Fill boundary conditions into missing elements
3337 if (PutFwdInBwdOnBCs) // just set Bwd value to be Fwd value on BCs
3338 {
3339 // Fill boundary conditions into missing elements
3340 for (int n = 0, cnt = 0; n < bndCondExpansions.size(); ++n)
3341 {
3342 if (bndConditions[n]->GetBoundaryConditionType() ==
3344 {
3345 auto ne = bndCondExpansions[n]->GetExpSize();
3346 for (int e = 0; e < ne; ++e)
3347 {
3348 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3349 auto id2 = m_trace->GetPhys_Offset(
3350 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3351 Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1);
3352 }
3353
3354 cnt += ne;
3355 }
3356 else if (bndConditions[n]->GetBoundaryConditionType() ==
3358 bndConditions[n]->GetBoundaryConditionType() ==
3360 {
3361 auto ne = bndCondExpansions[n]->GetExpSize();
3362 for (int e = 0; e < ne; ++e)
3363 {
3364 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3365 auto id2 = m_trace->GetPhys_Offset(
3366 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3367 Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1);
3368 }
3369 cnt += ne;
3370 }
3371 else if (bndConditions[n]->GetBoundaryConditionType() !=
3373 {
3374 ASSERTL0(false, "Method not set up for this "
3375 "boundary condition.");
3376 }
3377 }
3378 }
3379 else
3380 {
3381 for (int n = 0, cnt = 0; n < bndCondExpansions.size(); ++n)
3382 {
3383 if (bndConditions[n]->GetBoundaryConditionType() ==
3385 {
3386 auto ne = bndCondExpansions[n]->GetExpSize();
3387 for (int e = 0; e < ne; ++e)
3388 {
3389 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3390 auto id1 = bndCondExpansions[n]->GetPhys_Offset(e);
3391 auto id2 = m_trace->GetPhys_Offset(
3392 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3393
3394 Vmath::Vcopy(npts, &(bndCondExpansions[n]->GetPhys())[id1],
3395 1, &Bwd[id2], 1);
3396 }
3397 cnt += ne;
3398 }
3399 else if (bndConditions[n]->GetBoundaryConditionType() ==
3401 bndConditions[n]->GetBoundaryConditionType() ==
3403 {
3404 auto ne = m_bndCondExpansions[n]->GetExpSize();
3405 for (int e = 0; e < ne; ++e)
3406 {
3407 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3408 auto id1 = bndCondExpansions[n]->GetPhys_Offset(e);
3409
3410 ASSERTL0((bndCondExpansions[n]->GetPhys())[id1] == 0.0,
3411 "Method not set up for non-zero "
3412 "Neumann boundary condition");
3413 auto id2 = m_trace->GetPhys_Offset(
3414 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3415
3416 Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1);
3417 }
3418
3419 cnt += ne;
3420 }
3421 else if (bndConditions[n]->GetBoundaryConditionType() ==
3423 {
3424 // Do nothing
3425 }
3426 else if (bndConditions[n]->GetBoundaryConditionType() !=
3428 {
3430 "Method not set up for this boundary "
3431 "condition.");
3432 }
3433 }
3434 }
3435}
#define ASSERTL0(condition, msg)
const Array< OneD, const NekDouble > & GetPhys() const
This function returns (a reference to) the array (implemented as m_phys) containing the function ev...
Definition ExpList.h:2111

References ASSERTL0, Nektar::SpatialDomains::eDirichlet, Nektar::ErrorUtil::efatal, Nektar::SpatialDomains::eNeumann, Nektar::SpatialDomains::eNotDefined, Nektar::SpatialDomains::ePeriodic, Nektar::SpatialDomains::eRobin, Nektar::MultiRegions::ExpList::GetPhys(), m_bndCondExpansions, m_trace, m_traceMap, NEKERROR, and Vmath::Vcopy().

Referenced by GetFwdBwdTracePhys(), and v_FillBwdWithBoundCond().

◆ FindPeriodicTraces()

void Nektar::MultiRegions::DisContField::FindPeriodicTraces ( const SpatialDomains::BoundaryConditions bcs,
const std::string  variable 
)
protected

Generate a associative map of periodic vertices in a mesh.

Determine the periodic faces, edges and vertices for the given graph.

Parameters
bcsInformation about the boundary conditions.
variableSpecifies the field.

Definition at line 1007 of file DisContField.cpp.

1009{
1011 bcs.GetBoundaryRegions();
1013 bcs.GetBoundaryConditions();
1014
1015 LibUtilities::CommSharedPtr vComm = m_comm->GetRowComm();
1016
1017 switch (m_expType)
1018 {
1019 case e1D:
1020 {
1021 int i, region1ID, region2ID;
1022
1024 map<int, int> BregionToVertMap;
1025
1026 // Construct list of all periodic Region and their
1027 // global vertex on this process.
1028 for (auto &it : bregions)
1029 {
1030 locBCond =
1031 GetBoundaryCondition(bconditions, it.first, variable);
1032
1033 if (locBCond->GetBoundaryConditionType() !=
1035 {
1036 continue;
1037 }
1038 int id =
1039 it.second->begin()->second->m_geomVec[0]->GetGlobalID();
1040
1041 BregionToVertMap[it.first] = id;
1042 }
1043
1044 set<int> islocal;
1045
1046 int n = vComm->GetSize();
1047 int p = vComm->GetRank();
1048
1049 Array<OneD, int> nregions(n, 0);
1050 nregions[p] = BregionToVertMap.size();
1051 vComm->AllReduce(nregions, LibUtilities::ReduceSum);
1052
1053 int totRegions = Vmath::Vsum(n, nregions, 1);
1054
1055 Array<OneD, int> regOffset(n, 0);
1056
1057 for (i = 1; i < n; ++i)
1058 {
1059 regOffset[i] = regOffset[i - 1] + nregions[i - 1];
1060 }
1061
1062 Array<OneD, int> bregmap(totRegions, 0);
1063 Array<OneD, int> bregid(totRegions, 0);
1064
1065 i = regOffset[p];
1066 for (auto &iit : BregionToVertMap)
1067 {
1068 bregid[i] = iit.first;
1069 bregmap[i++] = iit.second;
1070 islocal.insert(iit.first);
1071 }
1072
1073 vComm->AllReduce(bregmap, LibUtilities::ReduceSum);
1074 vComm->AllReduce(bregid, LibUtilities::ReduceSum);
1075
1076 for (int i = 0; i < totRegions; ++i)
1077 {
1078 BregionToVertMap[bregid[i]] = bregmap[i];
1079 }
1080
1081 // Construct list of all periodic pairs local to this process.
1082 for (auto &it : bregions)
1083 {
1084 locBCond =
1085 GetBoundaryCondition(bconditions, it.first, variable);
1086
1087 if (locBCond->GetBoundaryConditionType() !=
1089 {
1090 continue;
1091 }
1092
1093 // Identify periodic boundary region IDs.
1094 region1ID = it.first;
1095 region2ID =
1096 std::static_pointer_cast<
1097 SpatialDomains::PeriodicBoundaryCondition>(locBCond)
1098 ->m_connectedBoundaryRegion;
1099
1100 ASSERTL0(BregionToVertMap.count(region1ID) != 0,
1101 "Cannot determine vertex of region1ID");
1102
1103 ASSERTL0(BregionToVertMap.count(region2ID) != 0,
1104 "Cannot determine vertex of region2ID");
1105
1106 PeriodicEntity ent(BregionToVertMap[region2ID],
1108 islocal.count(region2ID) != 0);
1109
1110 m_periodicVerts[BregionToVertMap[region1ID]].push_back(ent);
1111 }
1112 }
1113 break;
1114 case e2D:
1115 {
1116 int region1ID, region2ID, i, j, k, cnt;
1118
1120 m_graph->GetCompositeOrdering();
1122 m_graph->GetBndRegionOrdering();
1123 SpatialDomains::CompositeMap compMap = m_graph->GetComposites();
1124
1125 // Unique collection of pairs of periodic composites
1126 // (i.e. if composites 1 and 2 are periodic then this
1127 // map will contain either the pair (1,2) or (2,1) but
1128 // not both).
1129 map<int, int> perComps;
1130 map<int, vector<int>> allVerts;
1131 set<int> locVerts;
1132 map<int, pair<int, StdRegions::Orientation>> allEdges;
1133
1134 // Set up a set of all local verts and edges.
1135 for (i = 0; i < (*m_exp).size(); ++i)
1136 {
1137 for (j = 0; j < (*m_exp)[i]->GetNverts(); ++j)
1138 {
1139 int id = (*m_exp)[i]->GetGeom()->GetVid(j);
1140 locVerts.insert(id);
1141 }
1142 }
1143
1144 // Construct list of all periodic pairs local to this process.
1145 for (auto &it : bregions)
1146 {
1147 locBCond =
1148 GetBoundaryCondition(bconditions, it.first, variable);
1149
1150 if (locBCond->GetBoundaryConditionType() !=
1152 {
1153 continue;
1154 }
1155
1156 // Identify periodic boundary region IDs.
1157 region1ID = it.first;
1158 region2ID =
1159 std::static_pointer_cast<
1160 SpatialDomains::PeriodicBoundaryCondition>(locBCond)
1161 ->m_connectedBoundaryRegion;
1162
1163 // From this identify composites. Note that in
1164 // serial this will be an empty map.
1165 int cId1, cId2;
1166 if (vComm->GetSize() == 1)
1167 {
1168 cId1 = it.second->begin()->first;
1169 cId2 = bregions.find(region2ID)->second->begin()->first;
1170 }
1171 else
1172 {
1173 cId1 = bndRegOrder.find(region1ID)->second[0];
1174 cId2 = bndRegOrder.find(region2ID)->second[0];
1175 }
1176
1177 ASSERTL0(it.second->size() == 1,
1178 "Boundary region " + std::to_string(region1ID) +
1179 " should only contain 1 composite.");
1180
1181 vector<unsigned int> tmpOrder;
1182
1183 // Construct set containing all periodic edgesd on
1184 // this process
1186 it.second->begin()->second;
1187
1188 for (i = 0; i < c->m_geomVec.size(); ++i)
1189 {
1190 SpatialDomains::SegGeom *segGeom =
1191 dynamic_cast<SpatialDomains::SegGeom *>(
1192 c->m_geomVec[i]);
1193 ASSERTL0(segGeom, "Unable to cast to SegGeom*");
1194
1196 m_graph->GetElementsFromEdge(segGeom);
1197 ASSERTL0(elmt->size() == 1,
1198 "The periodic boundaries belong to "
1199 "more than one element of the mesh");
1200
1201 SpatialDomains::Geometry2D *geom =
1202 dynamic_cast<SpatialDomains::Geometry2D *>(
1203 elmt->at(0).first);
1204
1205 allEdges[c->m_geomVec[i]->GetGlobalID()] =
1206 make_pair(elmt->at(0).second,
1207 geom->GetEorient(elmt->at(0).second));
1208
1209 // In serial mesh partitioning will not have occurred so
1210 // need to fill composite ordering map manually.
1211 if (vComm->GetSize() == 1)
1212 {
1213 tmpOrder.push_back(c->m_geomVec[i]->GetGlobalID());
1214 }
1215
1216 vector<int> vertList(2);
1217 vertList[0] = segGeom->GetVid(0);
1218 vertList[1] = segGeom->GetVid(1);
1219 allVerts[c->m_geomVec[i]->GetGlobalID()] = vertList;
1220 }
1221
1222 if (vComm->GetSize() == 1)
1223 {
1224 compOrder[it.second->begin()->first] = tmpOrder;
1225 }
1226
1227 // See if we already have either region1 or
1228 // region2 stored in perComps map.
1229 if (perComps.count(cId1) == 0)
1230 {
1231 if (perComps.count(cId2) == 0)
1232 {
1233 perComps[cId1] = cId2;
1234 }
1235 else
1236 {
1237 std::stringstream ss;
1238 ss << "Boundary region " << cId2 << " should be "
1239 << "periodic with " << perComps[cId2] << " but "
1240 << "found " << cId1 << " instead!";
1241 ASSERTL0(perComps[cId2] == cId1, ss.str());
1242 }
1243 }
1244 else
1245 {
1246 std::stringstream ss;
1247 ss << "Boundary region " << cId1 << " should be "
1248 << "periodic with " << perComps[cId1] << " but "
1249 << "found " << cId2 << " instead!";
1250 ASSERTL0(perComps[cId1] == cId1, ss.str());
1251 }
1252 }
1253
1254 // In case of periodic partition being split over many composites
1255 // may not have all periodic matches so check this
1256 int idmax = -1;
1257 for (auto &cIt : perComps)
1258 {
1259 idmax = max(idmax, cIt.first);
1260 idmax = max(idmax, cIt.second);
1261 }
1262 vComm->AllReduce(idmax, LibUtilities::ReduceMax);
1263 idmax++;
1264 Array<OneD, int> perid(idmax, -1);
1265 for (auto &cIt : perComps)
1266 {
1267 perid[cIt.first] = cIt.second;
1268 }
1269 vComm->AllReduce(perid, LibUtilities::ReduceMax);
1270 // update all partitions
1271 for (int i = 0; i < idmax; ++i)
1272 {
1273 if (perid[i] > -1)
1274 {
1275 // skip if complemetary relationship has
1276 // already been speficied in list
1277 if (perComps.count(perid[i]))
1278 {
1279 continue;
1280 }
1281 perComps[i] = perid[i];
1282 }
1283 }
1284
1285 // Process local edge list to obtain relative edge
1286 // orientations.
1287 int n = vComm->GetSize();
1288 int p = vComm->GetRank();
1289 int totEdges;
1290 Array<OneD, int> edgecounts(n, 0);
1291 Array<OneD, int> edgeoffset(n, 0);
1292 Array<OneD, int> vertoffset(n, 0);
1293
1294 edgecounts[p] = allEdges.size();
1295 vComm->AllReduce(edgecounts, LibUtilities::ReduceSum);
1296
1297 edgeoffset[0] = 0;
1298 for (i = 1; i < n; ++i)
1299 {
1300 edgeoffset[i] = edgeoffset[i - 1] + edgecounts[i - 1];
1301 }
1302
1303 totEdges = Vmath::Vsum(n, edgecounts, 1);
1304 Array<OneD, int> edgeIds(totEdges, 0);
1305 Array<OneD, int> edgeIdx(totEdges, 0);
1306 Array<OneD, int> edgeOrient(totEdges, 0);
1307 Array<OneD, int> edgeVerts(totEdges, 0);
1308
1309 auto sIt = allEdges.begin();
1310
1311 for (i = 0; sIt != allEdges.end(); ++sIt)
1312 {
1313 edgeIds[edgeoffset[p] + i] = sIt->first;
1314 edgeIdx[edgeoffset[p] + i] = sIt->second.first;
1315 edgeOrient[edgeoffset[p] + i] = sIt->second.second;
1316 edgeVerts[edgeoffset[p] + i++] = allVerts[sIt->first].size();
1317 }
1318
1319 vComm->AllReduce(edgeIds, LibUtilities::ReduceSum);
1320 vComm->AllReduce(edgeIdx, LibUtilities::ReduceSum);
1321 vComm->AllReduce(edgeOrient, LibUtilities::ReduceSum);
1322 vComm->AllReduce(edgeVerts, LibUtilities::ReduceSum);
1323
1324 // Calculate number of vertices on each processor.
1325 Array<OneD, int> procVerts(n, 0);
1326 int nTotVerts;
1327
1328 // Note if there are no periodic edges at all calling Vsum will
1329 // cause a segfault.
1330 if (totEdges > 0)
1331 {
1332 nTotVerts = Vmath::Vsum(totEdges, edgeVerts, 1);
1333 }
1334 else
1335 {
1336 nTotVerts = 0;
1337 }
1338
1339 for (i = 0; i < n; ++i)
1340 {
1341 if (edgecounts[i] > 0)
1342 {
1343 procVerts[i] = Vmath::Vsum(edgecounts[i],
1344 edgeVerts + edgeoffset[i], 1);
1345 }
1346 else
1347 {
1348 procVerts[i] = 0;
1349 }
1350 }
1351 vertoffset[0] = 0;
1352
1353 for (i = 1; i < n; ++i)
1354 {
1355 vertoffset[i] = vertoffset[i - 1] + procVerts[i - 1];
1356 }
1357
1358 Array<OneD, int> traceIds(nTotVerts, 0);
1359 for (i = 0, sIt = allEdges.begin(); sIt != allEdges.end(); ++sIt)
1360 {
1361 for (j = 0; j < allVerts[sIt->first].size(); ++j)
1362 {
1363 traceIds[vertoffset[p] + i++] = allVerts[sIt->first][j];
1364 }
1365 }
1366
1367 vComm->AllReduce(traceIds, LibUtilities::ReduceSum);
1368
1369 // For simplicity's sake create a map of edge id -> orientation.
1370 map<int, StdRegions::Orientation> orientMap;
1371 map<int, vector<int>> vertMap;
1372
1373 for (cnt = i = 0; i < totEdges; ++i)
1374 {
1375 ASSERTL0(orientMap.count(edgeIds[i]) == 0,
1376 "Already found edge in orientation map!");
1377
1378 // Work out relative orientations. To avoid having
1379 // to exchange vertex locations, we figure out if
1380 // the edges are backwards or forwards orientated
1381 // with respect to a forwards orientation that is
1382 // CCW. Since our local geometries are
1383 // forwards-orientated with respect to the
1384 // Cartesian axes, we need to invert the
1385 // orientation for the top and left edges of a
1386 // quad and the left edge of a triangle.
1388 (StdRegions::Orientation)edgeOrient[i];
1389
1390 if (edgeIdx[i] > 1)
1391 {
1394 }
1395
1396 orientMap[edgeIds[i]] = o;
1397
1398 vector<int> verts(edgeVerts[i]);
1399
1400 for (j = 0; j < edgeVerts[i]; ++j)
1401 {
1402 verts[j] = traceIds[cnt++];
1403 }
1404 vertMap[edgeIds[i]] = verts;
1405 }
1406
1407 // Go through list of composites and figure out which
1408 // edges are parallel from original ordering in
1409 // session file. This includes composites which are
1410 // not necessarily on this process.
1411 map<int, int> allCompPairs;
1412
1413 // Store temporary map of periodic vertices which will hold all
1414 // periodic vertices on the entire mesh so that doubly periodic
1415 // vertices can be counted properly across partitions. Local
1416 // vertices are copied into m_periodicVerts at the end of the
1417 // function.
1418 PeriodicMap periodicVerts;
1419
1420 for (auto &cIt : perComps)
1421 {
1423 const int id1 = cIt.first;
1424 const int id2 = cIt.second;
1425 std::string id1s = std::to_string(id1);
1426 std::string id2s = std::to_string(id2);
1427
1428 if (compMap.count(id1) > 0)
1429 {
1430 c[0] = compMap[id1];
1431 }
1432
1433 if (compMap.count(id2) > 0)
1434 {
1435 c[1] = compMap[id2];
1436 }
1437
1438 // Loop over composite ordering to construct list of all
1439 // periodic edges regardless of whether they are on this
1440 // process.
1441 map<int, int> compPairs;
1442
1443 ASSERTL0(compOrder.count(id1) > 0,
1444 "Unable to find composite " + id1s + " in order map.");
1445 ASSERTL0(compOrder.count(id2) > 0,
1446 "Unable to find composite " + id2s + " in order map.");
1447 WARNINGL0(
1448 compOrder[id1].size() == compOrder[id2].size(),
1449 "Periodic composites " + id1s + " and " + id2s +
1450 " should have the same number of elements. Have " +
1451 std::to_string(compOrder[id1].size()) + " vs " +
1452 std::to_string(compOrder[id2].size()));
1453 ASSERTL0(compOrder[id1].size() > 0, "Periodic composites " +
1454 id1s + " and " + id2s +
1455 " are empty!");
1456
1457 // TODO: Add more checks.
1458 for (i = 0; i < compOrder[id1].size(); ++i)
1459 {
1460 int eId1 = compOrder[id1][i];
1461 int eId2 = compOrder[id2][i];
1462
1463 ASSERTL0(compPairs.count(eId1) == 0, "Already paired.");
1464
1465 if (compPairs.count(eId2) != 0)
1466 {
1467 ASSERTL0(compPairs[eId2] == eId1, "Pairing incorrect");
1468 }
1469 compPairs[eId1] = eId2;
1470 }
1471
1472 // Construct set of all edges that we have
1473 // locally on this processor.
1474 set<int> locEdges;
1475 for (i = 0; i < 2; ++i)
1476 {
1477 if (!c[i])
1478 {
1479 continue;
1480 }
1481
1482 if (c[i]->m_geomVec.size() > 0)
1483 {
1484 for (j = 0; j < c[i]->m_geomVec.size(); ++j)
1485 {
1486 locEdges.insert(c[i]->m_geomVec[j]->GetGlobalID());
1487 }
1488 }
1489 }
1490
1491 // Loop over all edges in the geometry composite.
1492 for (auto &pIt : compPairs)
1493 {
1494 int ids[2] = {pIt.first, pIt.second};
1495 bool local[2] = {locEdges.count(pIt.first) > 0,
1496 locEdges.count(pIt.second) > 0};
1497
1498 ASSERTL0(orientMap.count(ids[0]) > 0 &&
1499 orientMap.count(ids[1]) > 0,
1500 "Unable to find edge in orientation map.");
1501
1502 allCompPairs[pIt.first] = pIt.second;
1503 allCompPairs[pIt.second] = pIt.first;
1504
1505 for (i = 0; i < 2; ++i)
1506 {
1507 if (!local[i])
1508 {
1509 continue;
1510 }
1511
1512 int other = (i + 1) % 2;
1513
1515 orientMap[ids[i]] == orientMap[ids[other]]
1518
1519 PeriodicEntity ent(ids[other], o, local[other]);
1520 m_periodicEdges[ids[i]].push_back(ent);
1521 }
1522
1523 for (i = 0; i < 2; ++i)
1524 {
1525 int other = (i + 1) % 2;
1526
1528 orientMap[ids[i]] == orientMap[ids[other]]
1531
1532 // Determine periodic vertices.
1533 vector<int> perVerts1 = vertMap[ids[i]];
1534 vector<int> perVerts2 = vertMap[ids[other]];
1535
1536 map<int, pair<int, bool>> tmpMap;
1537 if (o == StdRegions::eForwards)
1538 {
1539 tmpMap[perVerts1[0]] = make_pair(
1540 perVerts2[0], locVerts.count(perVerts2[0]) > 0);
1541 tmpMap[perVerts1[1]] = make_pair(
1542 perVerts2[1], locVerts.count(perVerts2[1]) > 0);
1543 }
1544 else
1545 {
1546 tmpMap[perVerts1[0]] = make_pair(
1547 perVerts2[1], locVerts.count(perVerts2[1]) > 0);
1548 tmpMap[perVerts1[1]] = make_pair(
1549 perVerts2[0], locVerts.count(perVerts2[0]) > 0);
1550 }
1551
1552 for (auto &mIt : tmpMap)
1553 {
1554 // See if this vertex has been recorded already.
1555 PeriodicEntity ent2(mIt.second.first,
1557 mIt.second.second);
1558 auto perIt = periodicVerts.find(mIt.first);
1559
1560 if (perIt == periodicVerts.end())
1561 {
1562 periodicVerts[mIt.first].push_back(ent2);
1563 perIt = periodicVerts.find(mIt.first);
1564 }
1565 else
1566 {
1567 bool doAdd = true;
1568 for (j = 0; j < perIt->second.size(); ++j)
1569 {
1570 if (perIt->second[j].id == mIt.second.first)
1571 {
1572 doAdd = false;
1573 break;
1574 }
1575 }
1576
1577 if (doAdd)
1578 {
1579 perIt->second.push_back(ent2);
1580 }
1581 }
1582 }
1583 }
1584 }
1585 }
1586
1587 // Search for periodic vertices and edges which are not in
1588 // a periodic composite but lie in this process. First, loop
1589 // over all information we have from other processors.
1590 for (cnt = i = 0; i < totEdges; ++i)
1591 {
1592 int edgeId = edgeIds[i];
1593
1594 ASSERTL0(allCompPairs.count(edgeId) > 0,
1595 "Unable to find matching periodic edge.");
1596
1597 int perEdgeId = allCompPairs[edgeId];
1598
1599 for (j = 0; j < edgeVerts[i]; ++j, ++cnt)
1600 {
1601 int vId = traceIds[cnt];
1602
1603 auto perId = periodicVerts.find(vId);
1604
1605 if (perId == periodicVerts.end())
1606 {
1607 // This vertex is not included in the
1608 // map. Figure out which vertex it is
1609 // supposed to be periodic with. perEdgeId
1610 // is the edge ID which is periodic with
1611 // edgeId. The logic is much the same as
1612 // the loop above.
1613 int perVertexId =
1614 orientMap[edgeId] == orientMap[perEdgeId]
1615 ? vertMap[perEdgeId][(j + 1) % 2]
1616 : vertMap[perEdgeId][j];
1617
1618 PeriodicEntity ent(perVertexId,
1620 locVerts.count(perVertexId) > 0);
1621
1622 periodicVerts[vId].push_back(ent);
1623 }
1624 }
1625 }
1626
1627 // Loop over all periodic vertices to complete connectivity
1628 // information.
1629 for (auto &perIt : periodicVerts)
1630 {
1631 // Loop over associated vertices.
1632 for (i = 0; i < perIt.second.size(); ++i)
1633 {
1634 auto perIt2 = periodicVerts.find(perIt.second[i].id);
1635 ASSERTL0(perIt2 != periodicVerts.end(),
1636 "Couldn't find periodic vertex.");
1637
1638 for (j = 0; j < perIt2->second.size(); ++j)
1639 {
1640 if (perIt2->second[j].id == perIt.first)
1641 {
1642 continue;
1643 }
1644
1645 bool doAdd = true;
1646 for (k = 0; k < perIt.second.size(); ++k)
1647 {
1648 if (perIt2->second[j].id == perIt.second[k].id)
1649 {
1650 doAdd = false;
1651 break;
1652 }
1653 }
1654
1655 if (doAdd)
1656 {
1657 perIt.second.push_back(perIt2->second[j]);
1658 }
1659 }
1660 }
1661 }
1662
1663 // Do one final loop over periodic vertices to remove non-local
1664 // vertices from map.
1665 for (auto &perIt : periodicVerts)
1666 {
1667 if (locVerts.count(perIt.first) > 0)
1668 {
1669 m_periodicVerts.insert(perIt);
1670 }
1671 }
1672 }
1673 break;
1674 case e3D:
1675 {
1677 m_graph->GetCompositeOrdering();
1679 m_graph->GetBndRegionOrdering();
1680 SpatialDomains::CompositeMap compMap = m_graph->GetComposites();
1681
1682 // perComps: Stores a unique collection of pairs of periodic
1683 // composites (i.e. if composites 1 and 2 are periodic then this map
1684 // will contain either the pair (1,2) or (2,1) but not both).
1685 //
1686 // The four maps allVerts, allCoord, allEdges and allOrient map a
1687 // periodic face to a vector containing the vertex ids of the face;
1688 // their coordinates; the edge ids of the face; and their
1689 // orientation within that face respectively.
1690 //
1691 // Finally the three sets locVerts, locEdges and locFaces store any
1692 // vertices, edges and faces that belong to a periodic composite and
1693 // lie on this process.
1694 map<int, RotPeriodicInfo> rotComp;
1695 map<int, int> perComps;
1696 map<int, vector<int>> allVerts;
1697 map<int, std::vector<SpatialDomains::PointGeom *>> allCoord;
1698 map<int, vector<int>> allEdges;
1699 map<int, vector<StdRegions::Orientation>> allOrient;
1700 set<int> locVerts;
1701 set<int> locEdges;
1702 set<int> locFaces;
1703
1704 int region1ID, region2ID, i, j, k, cnt;
1706
1707 // Set up a set of all local verts and edges.
1708 for (i = 0; i < (*m_exp).size(); ++i)
1709 {
1710 for (j = 0; j < (*m_exp)[i]->GetNverts(); ++j)
1711 {
1712 int id = (*m_exp)[i]->GetGeom()->GetVid(j);
1713 locVerts.insert(id);
1714 }
1715
1716 for (j = 0; j < (*m_exp)[i]->GetGeom()->GetNumEdges(); ++j)
1717 {
1718 int id = (*m_exp)[i]->GetGeom()->GetEid(j);
1719 locEdges.insert(id);
1720 }
1721 }
1722
1723 // Begin by populating the perComps map. We loop over all periodic
1724 // boundary conditions and determine the composite associated with
1725 // it, then fill out the all* maps.
1726 for (auto &it : bregions)
1727 {
1728
1729 locBCond =
1730 GetBoundaryCondition(bconditions, it.first, variable);
1731
1732 if (locBCond->GetBoundaryConditionType() !=
1734 {
1735 continue;
1736 }
1737
1738 // Identify periodic boundary region IDs.
1739 region1ID = it.first;
1740 region2ID =
1741 std::static_pointer_cast<
1742 SpatialDomains::PeriodicBoundaryCondition>(locBCond)
1743 ->m_connectedBoundaryRegion;
1744
1745 // Check the region only contains a single composite.
1746 ASSERTL0(it.second->size() == 1,
1747 "Boundary region " + std::to_string(region1ID) +
1748 " should only contain 1 composite.");
1749
1750 // From this identify composites by looking at the original
1751 // boundary region ordering. Note that in serial the mesh
1752 // partitioner is not run, so this map will be empty and
1753 // therefore needs to be populated by using the corresponding
1754 // boundary region.
1755 int cId1, cId2;
1756 if (vComm->GetSize() == 1)
1757 {
1758 cId1 = it.second->begin()->first;
1759 cId2 = bregions.find(region2ID)->second->begin()->first;
1760 }
1761 else
1762 {
1763 cId1 = bndRegOrder.find(region1ID)->second[0];
1764 cId2 = bndRegOrder.find(region2ID)->second[0];
1765 }
1766
1767 // check to see if boundary is rotationally aligned
1768 if (boost::icontains(locBCond->GetUserDefined(), "Rotated"))
1769 {
1770 vector<string> tmpstr;
1771
1772 boost::split(tmpstr, locBCond->GetUserDefined(),
1773 boost::is_any_of(":"));
1774
1775 if (boost::iequals(tmpstr[0], "Rotated"))
1776 {
1777 ASSERTL1(tmpstr.size() > 2,
1778 "Expected Rotated user defined string to "
1779 "contain direction and rotation angle "
1780 "and optionally a tolerance, "
1781 "i.e. Rotated:dir:PI/2:1e-6");
1782
1783 ASSERTL1((tmpstr[1] == "x") || (tmpstr[1] == "y") ||
1784 (tmpstr[1] == "z"),
1785 "Rotated Dir is "
1786 "not specified as x,y or z");
1787
1788 RotPeriodicInfo RotInfo;
1789 RotInfo.m_dir = (tmpstr[1] == "x") ? 0
1790 : (tmpstr[1] == "y") ? 1
1791 : 2;
1792
1793 LibUtilities::Interpreter strEval;
1794 int ExprId = strEval.DefineFunction("", tmpstr[2]);
1795 RotInfo.m_angle = strEval.Evaluate(ExprId);
1796
1797 if (tmpstr.size() == 4)
1798 {
1799 try
1800 {
1801 RotInfo.m_tol = std::stod(tmpstr[3]);
1802 }
1803 catch (...)
1804 {
1806 "failed to cast tolerance input "
1807 "to a double value in Rotated"
1808 "boundary information");
1809 }
1810 }
1811 else
1812 {
1813 RotInfo.m_tol = 1e-8;
1814 }
1815 rotComp[cId1] = RotInfo;
1816 }
1817 }
1818
1820 it.second->begin()->second;
1821
1822 vector<unsigned int> tmpOrder;
1823
1824 // store the rotation info of this
1825
1826 // From the composite, we now construct the allVerts, allEdges
1827 // and allCoord map so that they can be transferred across
1828 // processors. We also populate the locFaces set to store a
1829 // record of all faces local to this process.
1830 for (i = 0; i < c->m_geomVec.size(); ++i)
1831 {
1832 SpatialDomains::Geometry2D *faceGeom =
1833 dynamic_cast<SpatialDomains::Geometry2D *>(
1834 c->m_geomVec[i]);
1835 ASSERTL1(faceGeom, "Unable to cast to Geometry2D*");
1836
1837 // Get geometry ID of this face and store in locFaces.
1838 int faceId = c->m_geomVec[i]->GetGlobalID();
1839 locFaces.insert(faceId);
1840
1841 // In serial, mesh partitioning will not have occurred so
1842 // need to fill composite ordering map manually.
1843 if (vComm->GetSize() == 1)
1844 {
1845 tmpOrder.push_back(c->m_geomVec[i]->GetGlobalID());
1846 }
1847
1848 // Loop over vertices and edges of the face to populate
1849 // allVerts, allEdges and allCoord maps.
1850 vector<int> vertList, edgeList;
1851 std::vector<SpatialDomains::PointGeom *> coordVec;
1852 vector<StdRegions::Orientation> orientVec;
1853 for (j = 0; j < faceGeom->GetNumVerts(); ++j)
1854 {
1855 vertList.push_back(faceGeom->GetVid(j));
1856 edgeList.push_back(faceGeom->GetEid(j));
1857 coordVec.push_back(faceGeom->GetVertex(j));
1858 orientVec.push_back(faceGeom->GetEorient(j));
1859 }
1860
1861 allVerts[faceId] = vertList;
1862 allEdges[faceId] = edgeList;
1863 allCoord[faceId] = coordVec;
1864 allOrient[faceId] = orientVec;
1865 }
1866
1867 // In serial, record the composite ordering in compOrder for
1868 // later in the routine.
1869 if (vComm->GetSize() == 1)
1870 {
1871 compOrder[it.second->begin()->first] = tmpOrder;
1872 }
1873
1874 // See if we already have either region1 or region2 stored in
1875 // perComps map already and do a sanity check to ensure regions
1876 // are mutually periodic.
1877 if (perComps.count(cId1) == 0)
1878 {
1879 if (perComps.count(cId2) == 0)
1880 {
1881 perComps[cId1] = cId2;
1882 }
1883 else
1884 {
1885 std::stringstream ss;
1886 ss << "Boundary region " << cId2 << " should be "
1887 << "periodic with " << perComps[cId2] << " but "
1888 << "found " << cId1 << " instead!";
1889 ASSERTL0(perComps[cId2] == cId1, ss.str());
1890 }
1891 }
1892 else
1893 {
1894 std::stringstream ss;
1895 ss << "Boundary region " << cId1 << " should be "
1896 << "periodic with " << perComps[cId1] << " but "
1897 << "found " << cId2 << " instead!";
1898 ASSERTL0(perComps[cId1] == cId1, ss.str());
1899 }
1900 }
1901
1902 // In case of periodic partition being split over many composites
1903 // may not have all periodic matches so check this
1904 int idmax = -1;
1905 for (auto &cIt : perComps)
1906 {
1907 idmax = max(idmax, cIt.first);
1908 idmax = max(idmax, cIt.second);
1909 }
1910 vComm->AllReduce(idmax, LibUtilities::ReduceMax);
1911 idmax++;
1912 Array<OneD, int> perid(idmax, -1);
1913 for (auto &cIt : perComps)
1914 {
1915 perid[cIt.first] = cIt.second;
1916 }
1917 vComm->AllReduce(perid, LibUtilities::ReduceMax);
1918 // update all partitions
1919 for (int i = 0; i < idmax; ++i)
1920 {
1921 if (perid[i] > -1)
1922 {
1923 // skip if equivlaent relationship has
1924 // already been speficied in list
1925 if (perComps.count(perid[i]))
1926 {
1927 continue;
1928 }
1929 perComps[i] = perid[i];
1930 }
1931 }
1932
1933 // The next routines process local face lists to
1934 // exchange vertices,
1935 // edges and faces.
1936 int n = vComm->GetSize();
1937 int p = vComm->GetRank();
1938 int totFaces;
1939 Array<OneD, int> facecounts(n, 0);
1940 Array<OneD, int> vertcounts(n, 0);
1941 Array<OneD, int> faceoffset(n, 0);
1942 Array<OneD, int> vertoffset(n, 0);
1943
1944 Array<OneD, int> rotcounts(n, 0);
1945 Array<OneD, int> rotoffset(n, 0);
1946
1947 rotcounts[p] = rotComp.size();
1948 vComm->AllReduce(rotcounts, LibUtilities::ReduceSum);
1949 int totrot = Vmath::Vsum(n, rotcounts, 1);
1950
1951 if (totrot)
1952 {
1953 for (i = 1; i < n; ++i)
1954 {
1955 rotoffset[i] = rotoffset[i - 1] + rotcounts[i - 1];
1956 }
1957
1958 Array<OneD, int> compid(totrot, 0);
1959 Array<OneD, int> rotdir(totrot, 0);
1960 Array<OneD, NekDouble> rotangle(totrot, 0.0);
1961 Array<OneD, NekDouble> rottol(totrot, 0.0);
1962
1963 // fill in rotational informaiton
1964 auto rIt = rotComp.begin();
1965
1966 for (i = 0; rIt != rotComp.end(); ++rIt)
1967 {
1968 compid[rotoffset[p] + i] = rIt->first;
1969 rotdir[rotoffset[p] + i] = rIt->second.m_dir;
1970 rotangle[rotoffset[p] + i] = rIt->second.m_angle;
1971 rottol[rotoffset[p] + i++] = rIt->second.m_tol;
1972 }
1973
1974 vComm->AllReduce(compid, LibUtilities::ReduceSum);
1975 vComm->AllReduce(rotdir, LibUtilities::ReduceSum);
1976 vComm->AllReduce(rotangle, LibUtilities::ReduceSum);
1977 vComm->AllReduce(rottol, LibUtilities::ReduceSum);
1978
1979 // Fill in full rotational composite list
1980 for (i = 0; i < totrot; ++i)
1981 {
1982 RotPeriodicInfo rinfo(rotdir[i], rotangle[i], rottol[i]);
1983
1984 rotComp[compid[i]] = rinfo;
1985 }
1986 }
1987
1988 // First exchange the number of faces on each process.
1989 facecounts[p] = locFaces.size();
1990 vComm->AllReduce(facecounts, LibUtilities::ReduceSum);
1991
1992 // Set up an offset map to allow us to distribute face IDs to all
1993 // processors.
1994 faceoffset[0] = 0;
1995 for (i = 1; i < n; ++i)
1996 {
1997 faceoffset[i] = faceoffset[i - 1] + facecounts[i - 1];
1998 }
1999
2000 // Calculate total number of faces.
2001 totFaces = Vmath::Vsum(n, facecounts, 1);
2002
2003 // faceIds holds face IDs for each periodic face. faceVerts holds
2004 // the number of vertices in this face.
2005 Array<OneD, int> faceIds(totFaces, 0);
2006 Array<OneD, int> faceVerts(totFaces, 0);
2007
2008 // Process p writes IDs of its faces into position faceoffset[p] of
2009 // faceIds which allows us to perform an AllReduce to distribute
2010 // information amongst processors.
2011 auto sIt = locFaces.begin();
2012 for (i = 0; sIt != locFaces.end(); ++sIt)
2013 {
2014 faceIds[faceoffset[p] + i] = *sIt;
2015 faceVerts[faceoffset[p] + i++] = allVerts[*sIt].size();
2016 }
2017
2018 vComm->AllReduce(faceIds, LibUtilities::ReduceSum);
2019 vComm->AllReduce(faceVerts, LibUtilities::ReduceSum);
2020
2021 // procVerts holds number of vertices (and also edges since each
2022 // face is 2D) on each process.
2023 Array<OneD, int> procVerts(n, 0);
2024 int nTotVerts;
2025
2026 // Note if there are no periodic faces at all calling Vsum will
2027 // cause a segfault.
2028 if (totFaces > 0)
2029 {
2030 // Calculate number of vertices on each processor.
2031 nTotVerts = Vmath::Vsum(totFaces, faceVerts, 1);
2032 }
2033 else
2034 {
2035 nTotVerts = 0;
2036 }
2037
2038 for (i = 0; i < n; ++i)
2039 {
2040 if (facecounts[i] > 0)
2041 {
2042 procVerts[i] = Vmath::Vsum(facecounts[i],
2043 faceVerts + faceoffset[i], 1);
2044 }
2045 else
2046 {
2047 procVerts[i] = 0;
2048 }
2049 }
2050
2051 // vertoffset is defined in the same manner as edgeoffset
2052 // beforehand.
2053 vertoffset[0] = 0;
2054 for (i = 1; i < n; ++i)
2055 {
2056 vertoffset[i] = vertoffset[i - 1] + procVerts[i - 1];
2057 }
2058
2059 // At this point we exchange all vertex IDs, edge IDs and vertex
2060 // coordinates for each face. The coordinates are necessary because
2061 // we need to calculate relative face orientations between periodic
2062 // faces to determined edge and vertex connectivity.
2063 Array<OneD, int> vertIds(nTotVerts, 0);
2064 Array<OneD, int> edgeIds(nTotVerts, 0);
2065 Array<OneD, int> edgeOrt(nTotVerts, 0);
2066 Array<OneD, NekDouble> vertX(nTotVerts, 0.0);
2067 Array<OneD, NekDouble> vertY(nTotVerts, 0.0);
2068 Array<OneD, NekDouble> vertZ(nTotVerts, 0.0);
2069
2070 for (cnt = 0, sIt = locFaces.begin(); sIt != locFaces.end(); ++sIt)
2071 {
2072 for (j = 0; j < allVerts[*sIt].size(); ++j)
2073 {
2074 int vertId = allVerts[*sIt][j];
2075 vertIds[vertoffset[p] + cnt] = vertId;
2076 vertX[vertoffset[p] + cnt] = (*allCoord[*sIt][j])(0);
2077 vertY[vertoffset[p] + cnt] = (*allCoord[*sIt][j])(1);
2078 vertZ[vertoffset[p] + cnt] = (*allCoord[*sIt][j])(2);
2079 edgeIds[vertoffset[p] + cnt] = allEdges[*sIt][j];
2080 edgeOrt[vertoffset[p] + cnt++] = allOrient[*sIt][j];
2081 }
2082 }
2083
2084 vComm->AllReduce(vertIds, LibUtilities::ReduceSum);
2085 vComm->AllReduce(vertX, LibUtilities::ReduceSum);
2086 vComm->AllReduce(vertY, LibUtilities::ReduceSum);
2087 vComm->AllReduce(vertZ, LibUtilities::ReduceSum);
2088 vComm->AllReduce(edgeIds, LibUtilities::ReduceSum);
2089 vComm->AllReduce(edgeOrt, LibUtilities::ReduceSum);
2090
2091 // Finally now we have all of this information, we construct maps
2092 // which make accessing the information easier. These are
2093 // conceptually the same as all* maps at the beginning of the
2094 // routine, but now hold information for all periodic vertices.
2095 map<int, vector<int>> vertMap;
2096 map<int, vector<int>> edgeMap;
2097 map<int, std::vector<SpatialDomains::PointGeom *>> coordMap;
2098
2099 // These final two maps are required for determining the relative
2100 // orientation of periodic edges. vCoMap associates vertex IDs with
2101 // their coordinates, and eIdMap maps an edge ID to the two vertices
2102 // which construct it.
2103 map<int, SpatialDomains::PointGeomUniquePtr> vCoMap;
2104 map<int, pair<int, int>> eIdMap;
2105
2106 for (cnt = i = 0; i < totFaces; ++i)
2107 {
2108 vector<int> edges(faceVerts[i]);
2109 vector<int> verts(faceVerts[i]);
2110 std::vector<SpatialDomains::PointGeom *> coord(faceVerts[i]);
2111
2112 // Keep track of cnt to enable correct edge vertices to be
2113 // inserted into eIdMap.
2114 int tmp = cnt;
2115 for (j = 0; j < faceVerts[i]; ++j, ++cnt)
2116 {
2117 edges[j] = edgeIds[cnt];
2118 verts[j] = vertIds[cnt];
2119
2120 auto vIt = vCoMap.find(vertIds[cnt]);
2121
2122 if (vIt == vCoMap.end())
2123 {
2125 AllocateUniquePtr(3, verts[j], vertX[cnt],
2126 vertY[cnt], vertZ[cnt]);
2127 coord[j] = pt.get();
2128 vCoMap[vertIds[cnt]] = std::move(pt);
2129 }
2130 else
2131 {
2132 coord[j] = vIt->second.get();
2133 }
2134
2135 // Try to insert edge into the eIdMap to avoid re-inserting.
2136 auto testIns = eIdMap.insert(make_pair(
2137 edgeIds[cnt],
2138 make_pair(vertIds[tmp + j],
2139 vertIds[tmp + ((j + 1) % faceVerts[i])])));
2140
2141 if (testIns.second == false)
2142 {
2143 continue;
2144 }
2145
2146 // If the edge is reversed with respect to the face, then
2147 // swap the edges so that we have the original ordering of
2148 // the edge in the 3D element. This is necessary to properly
2149 // determine edge orientation. Note that the logic relies on
2150 // the fact that all edge forward directions are CCW
2151 // orientated: we use a tensor product ordering for 2D
2152 // elements so need to reverse this for edge IDs 2 and 3.
2153 StdRegions::Orientation edgeOrient =
2154 static_cast<StdRegions::Orientation>(edgeOrt[cnt]);
2155 if (j > 1)
2156 {
2157 edgeOrient = edgeOrient == StdRegions::eForwards
2160 }
2161
2162 if (edgeOrient == StdRegions::eBackwards)
2163 {
2164 swap(testIns.first->second.first,
2165 testIns.first->second.second);
2166 }
2167 }
2168
2169 vertMap[faceIds[i]] = verts;
2170 edgeMap[faceIds[i]] = edges;
2171 coordMap[faceIds[i]] = coord;
2172 }
2173
2174 // Go through list of composites and figure out which edges are
2175 // parallel from original ordering in session file. This includes
2176 // composites which are not necessarily on this process.
2177
2178 // Store temporary map of periodic vertices which will hold all
2179 // periodic vertices on the entire mesh so that doubly periodic
2180 // vertices/edges can be counted properly across partitions. Local
2181 // vertices/edges are copied into m_periodicVerts and
2182 // m_periodicEdges at the end of the function.
2183 PeriodicMap periodicVerts, periodicEdges;
2184
2185 // Construct two maps which determine how vertices and edges of
2186 // faces connect given a specific face orientation. The key of the
2187 // map is the number of vertices in the face, used to determine
2188 // difference between tris and quads.
2189 map<int, map<StdRegions::Orientation, vector<int>>> vmap;
2190 map<int, map<StdRegions::Orientation, vector<int>>> emap;
2191
2192 map<StdRegions::Orientation, vector<int>> quadVertMap;
2193 quadVertMap[StdRegions::eDir1FwdDir1_Dir2FwdDir2] = {0, 1, 2, 3};
2194 quadVertMap[StdRegions::eDir1FwdDir1_Dir2BwdDir2] = {3, 2, 1, 0};
2195 quadVertMap[StdRegions::eDir1BwdDir1_Dir2FwdDir2] = {1, 0, 3, 2};
2196 quadVertMap[StdRegions::eDir1BwdDir1_Dir2BwdDir2] = {2, 3, 0, 1};
2197 quadVertMap[StdRegions::eDir1FwdDir2_Dir2FwdDir1] = {0, 3, 2, 1};
2198 quadVertMap[StdRegions::eDir1FwdDir2_Dir2BwdDir1] = {1, 2, 3, 0};
2199 quadVertMap[StdRegions::eDir1BwdDir2_Dir2FwdDir1] = {3, 0, 1, 2};
2200 quadVertMap[StdRegions::eDir1BwdDir2_Dir2BwdDir1] = {2, 1, 0, 3};
2201
2202 map<StdRegions::Orientation, vector<int>> quadEdgeMap;
2203 quadEdgeMap[StdRegions::eDir1FwdDir1_Dir2FwdDir2] = {0, 1, 2, 3};
2204 quadEdgeMap[StdRegions::eDir1FwdDir1_Dir2BwdDir2] = {2, 1, 0, 3};
2205 quadEdgeMap[StdRegions::eDir1BwdDir1_Dir2FwdDir2] = {0, 3, 2, 1};
2206 quadEdgeMap[StdRegions::eDir1BwdDir1_Dir2BwdDir2] = {2, 3, 0, 1};
2207 quadEdgeMap[StdRegions::eDir1FwdDir2_Dir2FwdDir1] = {3, 2, 1, 0};
2208 quadEdgeMap[StdRegions::eDir1FwdDir2_Dir2BwdDir1] = {1, 2, 3, 0};
2209 quadEdgeMap[StdRegions::eDir1BwdDir2_Dir2FwdDir1] = {3, 0, 1, 2};
2210 quadEdgeMap[StdRegions::eDir1BwdDir2_Dir2BwdDir1] = {1, 0, 3, 2};
2211
2212 map<StdRegions::Orientation, vector<int>> triVertMap;
2213 triVertMap[StdRegions::eDir1FwdDir1_Dir2FwdDir2] = {0, 1, 2};
2214 triVertMap[StdRegions::eDir1BwdDir1_Dir2FwdDir2] = {1, 0, 2};
2215
2216 map<StdRegions::Orientation, vector<int>> triEdgeMap;
2217 triEdgeMap[StdRegions::eDir1FwdDir1_Dir2FwdDir2] = {0, 1, 2};
2218 triEdgeMap[StdRegions::eDir1BwdDir1_Dir2FwdDir2] = {0, 2, 1};
2219
2220 vmap[3] = triVertMap;
2221 vmap[4] = quadVertMap;
2222 emap[3] = triEdgeMap;
2223 emap[4] = quadEdgeMap;
2224
2225 map<int, int> allCompPairs;
2226
2227 // Collect composite id's of each periodic face for use if rotation
2228 // is required
2229 map<int, int> fIdToCompId;
2230
2231 // Finally we have enough information to populate the periodic
2232 // vertex, edge and face maps. Begin by looping over all pairs of
2233 // periodic composites to determine pairs of periodic faces.
2234 for (auto &cIt : perComps)
2235 {
2237 const int id1 = cIt.first;
2238 const int id2 = cIt.second;
2239 std::string id1s = std::to_string(id1);
2240 std::string id2s = std::to_string(id2);
2241
2242 if (compMap.count(id1) > 0)
2243 {
2244 c[0] = compMap[id1];
2245 }
2246
2247 if (compMap.count(id2) > 0)
2248 {
2249 c[1] = compMap[id2];
2250 }
2251
2252 // Loop over composite ordering to construct list of all
2253 // periodic faces, regardless of whether they are on this
2254 // process.
2255 map<int, int> compPairs;
2256
2257 ASSERTL0(compOrder.count(id1) > 0,
2258 "Unable to find composite " + id1s + " in order map.");
2259 ASSERTL0(compOrder.count(id2) > 0,
2260 "Unable to find composite " + id2s + " in order map.");
2261 WARNINGL0(
2262 compOrder[id1].size() == compOrder[id2].size(),
2263 "Periodic composites " + id1s + " and " + id2s +
2264 " should have the same number of elements. Have " +
2265 std::to_string(compOrder[id1].size()) + " vs " +
2266 std::to_string(compOrder[id2].size()));
2267 ASSERTL0(compOrder[id1].size() > 0, "Periodic composites " +
2268 id1s + " and " + id2s +
2269 " are empty!");
2270
2271 // Look up composite ordering to determine pairs.
2272 for (i = 0; i < compOrder[id1].size(); ++i)
2273 {
2274 int eId1 = compOrder[id1][i];
2275 int eId2 = compOrder[id2][i];
2276
2277 ASSERTL0(compPairs.count(eId1) == 0, "Already paired.");
2278
2279 // Sanity check that the faces are mutually periodic.
2280 if (compPairs.count(eId2) != 0)
2281 {
2282 ASSERTL0(compPairs[eId2] == eId1, "Pairing incorrect");
2283 }
2284 compPairs[eId1] = eId2;
2285
2286 // store a map of face ids to composite ids
2287 fIdToCompId[eId1] = id1;
2288 fIdToCompId[eId2] = id2;
2289 }
2290
2291 // Now that we have all pairs of periodic faces, loop over the
2292 // ones local on this process and populate face/edge/vertex
2293 // maps.
2294 for (auto &pIt : compPairs)
2295 {
2296 int ids[2] = {pIt.first, pIt.second};
2297 bool local[2] = {locFaces.count(pIt.first) > 0,
2298 locFaces.count(pIt.second) > 0};
2299
2300 ASSERTL0(coordMap.count(ids[0]) > 0 &&
2301 coordMap.count(ids[1]) > 0,
2302 "Unable to find face in coordinate map");
2303
2304 allCompPairs[pIt.first] = pIt.second;
2305 allCompPairs[pIt.second] = pIt.first;
2306
2307 // Loop up coordinates of the faces, check they have the
2308 // same number of vertices.
2309 std::vector<SpatialDomains::PointGeom *> tmpVec[2] = {
2310 coordMap[ids[0]], coordMap[ids[1]]};
2311
2312 ASSERTL0(tmpVec[0].size() == tmpVec[1].size(),
2313 "Two periodic faces have different number "
2314 "of vertices!");
2315
2316 // o will store relative orientation of faces. Note that in
2317 // some transpose cases (Dir1FwdDir2_Dir2BwdDir1 and
2318 // Dir1BwdDir1_Dir2FwdDir1) it seems orientation will be
2319 // different going from face1->face2 instead of face2->face1
2320 // (check this).
2322 bool rotbnd = false;
2323 int dir = 0;
2324 NekDouble angle = 0.0;
2325 NekDouble sign = 0.0;
2326 NekDouble tol = 1e-8;
2327
2328 // check to see if perioid boundary is rotated
2329 if (rotComp.count(fIdToCompId[pIt.first]))
2330 {
2331 rotbnd = true;
2332 dir = rotComp[fIdToCompId[pIt.first]].m_dir;
2333 angle = rotComp[fIdToCompId[pIt.first]].m_angle;
2334 tol = rotComp[fIdToCompId[pIt.first]].m_tol;
2335 }
2336
2337 // Record periodic faces.
2338 for (i = 0; i < 2; ++i)
2339 {
2340 if (!local[i])
2341 {
2342 continue;
2343 }
2344
2345 // Reference to the other face.
2346 int other = (i + 1) % 2;
2347
2348 // angle is set up for i = 0 to i = 1
2349 sign = (i == 0) ? 1.0 : -1.0;
2350
2351 // Calculate relative face orientation.
2352 if (tmpVec[0].size() == 3)
2353 {
2355 {tmpVec[i][0], tmpVec[i][1], tmpVec[i][2]},
2356 {tmpVec[other][0], tmpVec[other][1],
2357 tmpVec[other][2]},
2358 rotbnd, dir, sign * angle, tol);
2359 }
2360 else
2361 {
2363 {tmpVec[i][0], tmpVec[i][1], tmpVec[i][2],
2364 tmpVec[i][3]},
2365 {tmpVec[other][0], tmpVec[other][1],
2366 tmpVec[other][2], tmpVec[other][3]},
2367 rotbnd, dir, sign * angle, tol);
2368 }
2369
2370 // Record face ID, orientation and whether other face is
2371 // local.
2372 PeriodicEntity ent(ids[other], o, local[other]);
2373 m_periodicFaces[ids[i]].push_back(ent);
2374 }
2375
2376 int nFaceVerts = vertMap[ids[0]].size();
2377
2378 // Determine periodic vertices.
2379 for (i = 0; i < 2; ++i)
2380 {
2381 int other = (i + 1) % 2;
2382
2383 // angle is set up for i = 0 to i = 1
2384 sign = (i == 0) ? 1.0 : -1.0;
2385
2386 // Calculate relative face orientation.
2387 if (tmpVec[0].size() == 3)
2388 {
2390 {tmpVec[i][0], tmpVec[i][1], tmpVec[i][2]},
2391 {tmpVec[other][0], tmpVec[other][1],
2392 tmpVec[other][2]},
2393 rotbnd, dir, sign * angle, tol);
2394 }
2395 else
2396 {
2398 {tmpVec[i][0], tmpVec[i][1], tmpVec[i][2],
2399 tmpVec[i][3]},
2400 {tmpVec[other][0], tmpVec[other][1],
2401 tmpVec[other][2], tmpVec[other][3]},
2402 rotbnd, dir, sign * angle, tol);
2403 }
2404
2405 if (nFaceVerts == 3)
2406 {
2407 ASSERTL0(
2410 "Unsupported face orientation for face " +
2411 std::to_string(ids[i]));
2412 }
2413
2414 // Look up vertices for this face.
2415 vector<int> per1 = vertMap[ids[i]];
2416 vector<int> per2 = vertMap[ids[other]];
2417
2418 // tmpMap will hold the pairs of vertices which are
2419 // periodic.
2420 map<int, pair<int, bool>> tmpMap;
2421
2422 // Use vmap to determine which vertices connect given
2423 // the orientation o.
2424 for (j = 0; j < nFaceVerts; ++j)
2425 {
2426 int v = vmap[nFaceVerts][o][j];
2427 tmpMap[per1[j]] =
2428 make_pair(per2[v], locVerts.count(per2[v]) > 0);
2429 }
2430
2431 // Now loop over tmpMap to associate periodic vertices.
2432 for (auto &mIt : tmpMap)
2433 {
2434 PeriodicEntity ent2(mIt.second.first,
2436 mIt.second.second);
2437
2438 // See if this vertex has been recorded already.
2439 auto perIt = periodicVerts.find(mIt.first);
2440
2441 if (perIt == periodicVerts.end())
2442 {
2443 // Vertex is new - just record this entity as
2444 // usual.
2445 periodicVerts[mIt.first].push_back(ent2);
2446 perIt = periodicVerts.find(mIt.first);
2447 }
2448 else
2449 {
2450 // Vertex is known - loop over the vertices
2451 // inside the record and potentially add vertex
2452 // mIt.second to the list.
2453 for (k = 0; k < perIt->second.size(); ++k)
2454 {
2455 if (perIt->second[k].id == mIt.second.first)
2456 {
2457 break;
2458 }
2459 }
2460
2461 if (k == perIt->second.size())
2462 {
2463 perIt->second.push_back(ent2);
2464 }
2465 }
2466 }
2467 }
2468
2469 // Determine periodic edges. Logic is the same as above,
2470 // and perhaps should be condensed to avoid replication.
2471 for (i = 0; i < 2; ++i)
2472 {
2473 int other = (i + 1) % 2;
2474
2475 // angle is set up for i = 0 to i = 1
2476 sign = (i == 0) ? 1.0 : -1.0;
2477
2478 if (tmpVec[0].size() == 3)
2479 {
2481 {tmpVec[i][0], tmpVec[i][1], tmpVec[i][2]},
2482 {tmpVec[other][0], tmpVec[other][1],
2483 tmpVec[other][2]},
2484 rotbnd, dir, sign * angle, tol);
2485 }
2486 else
2487 {
2489 {tmpVec[i][0], tmpVec[i][1], tmpVec[i][2],
2490 tmpVec[i][3]},
2491 {tmpVec[other][0], tmpVec[other][1],
2492 tmpVec[other][2], tmpVec[other][3]},
2493 rotbnd, dir, sign * angle, tol);
2494 }
2495
2496 vector<int> per1 = edgeMap[ids[i]];
2497 vector<int> per2 = edgeMap[ids[other]];
2498
2499 map<int, pair<int, bool>> tmpMap;
2500
2501 for (j = 0; j < nFaceVerts; ++j)
2502 {
2503 int e = emap[nFaceVerts][o][j];
2504 tmpMap[per1[j]] =
2505 make_pair(per2[e], locEdges.count(per2[e]) > 0);
2506 }
2507
2508 for (auto &mIt : tmpMap)
2509 {
2510 // Note we assume orientation of edges is forwards -
2511 // this may be reversed later.
2512 PeriodicEntity ent2(mIt.second.first,
2514 mIt.second.second);
2515 auto perIt = periodicEdges.find(mIt.first);
2516
2517 if (perIt == periodicEdges.end())
2518 {
2519 periodicEdges[mIt.first].push_back(ent2);
2520 perIt = periodicEdges.find(mIt.first);
2521 }
2522 else
2523 {
2524 for (k = 0; k < perIt->second.size(); ++k)
2525 {
2526 if (perIt->second[k].id == mIt.second.first)
2527 {
2528 break;
2529 }
2530 }
2531
2532 if (k == perIt->second.size())
2533 {
2534 perIt->second.push_back(ent2);
2535 }
2536 }
2537 }
2538 }
2539 }
2540 }
2541
2542 // Make sure that the nubmer of face pairs and the
2543 // face Id to composite Id map match in size
2544 ASSERTL1(allCompPairs.size() == fIdToCompId.size(),
2545 "At this point the size of allCompPairs "
2546 "should have been the same as fIdToCompId");
2547
2548 // also will need an edge id to composite id at
2549 // end of routine
2550 map<int, int> eIdToCompId;
2551
2552 // Search for periodic vertices and edges which are not
2553 // in a periodic composite but lie in this process. First,
2554 // loop over all information we have from other
2555 // processors.
2556 for (cnt = i = 0; i < totFaces; ++i)
2557 {
2558 bool rotbnd = false;
2559 int dir = 0;
2560 NekDouble angle = 0.0;
2561 NekDouble tol = 1e-8;
2562
2563 int faceId = faceIds[i];
2564
2565 ASSERTL0(allCompPairs.count(faceId) > 0,
2566 "Unable to find matching periodic face. faceId = " +
2567 std::to_string(faceId));
2568
2569 int perFaceId = allCompPairs[faceId];
2570
2571 // check to see if periodic boundary is rotated
2572 ASSERTL1((rotComp.size() == 0) || fIdToCompId.count(faceId) > 0,
2573 "Face " + std::to_string(faceId) +
2574 " not found in fIdtoCompId map");
2575 if (rotComp.count(fIdToCompId[faceId]))
2576 {
2577 rotbnd = true;
2578 dir = rotComp[fIdToCompId[faceId]].m_dir;
2579 angle = rotComp[fIdToCompId[faceId]].m_angle;
2580 tol = rotComp[fIdToCompId[faceId]].m_tol;
2581 }
2582
2583 for (j = 0; j < faceVerts[i]; ++j, ++cnt)
2584 {
2585 int vId = vertIds[cnt];
2586
2587 auto perId = periodicVerts.find(vId);
2588
2589 if (perId == periodicVerts.end())
2590 {
2591
2592 // This vertex is not included in the
2593 // map. Figure out which vertex it is supposed
2594 // to be periodic with. perFaceId is the face
2595 // ID which is periodic with faceId. The logic
2596 // is much the same as the loop above.
2597 std::vector<SpatialDomains::PointGeom *> tmpVec[2] = {
2598 coordMap[faceId], coordMap[perFaceId]};
2599
2600 int nFaceVerts = tmpVec[0].size();
2602 nFaceVerts == 3
2604 {tmpVec[0][0], tmpVec[0][1],
2605 tmpVec[0][2]},
2606 {tmpVec[1][0], tmpVec[1][1],
2607 tmpVec[1][2]},
2608 rotbnd, dir, angle, tol)
2609 : SpatialDomains::QuadGeom::GetFaceOrientation(
2610 {tmpVec[0][0], tmpVec[0][1], tmpVec[0][2],
2611 tmpVec[0][3]},
2612 {tmpVec[1][0], tmpVec[1][1], tmpVec[1][2],
2613 tmpVec[1][3]},
2614 rotbnd, dir, angle, tol);
2615
2616 // Use vmap to determine which vertex of the other face
2617 // should be periodic with this one.
2618 int perVertexId =
2619 vertMap[perFaceId][vmap[nFaceVerts][o][j]];
2620
2621 PeriodicEntity ent(perVertexId,
2622 StdRegions::eNoOrientation,
2623 locVerts.count(perVertexId) > 0);
2624
2625 periodicVerts[vId].push_back(ent);
2626 }
2627
2628 int eId = edgeIds[cnt];
2629
2630 perId = periodicEdges.find(eId);
2631
2632 // this map is required at very end to determine rotation of
2633 // edges.
2634 if (rotbnd)
2635 {
2636 eIdToCompId[eId] = fIdToCompId[faceId];
2637 }
2638
2639 if (perId == periodicEdges.end())
2640 {
2641 // This edge is not included in the map. Figure
2642 // out which edge it is supposed to be periodic
2643 // with. perFaceId is the face ID which is
2644 // periodic with faceId. The logic is much the
2645 // same as the loop above.
2646 std::vector<SpatialDomains::PointGeom *> tmpVec[2] = {
2647 coordMap[faceId], coordMap[perFaceId]};
2648
2649 int nFaceEdges = tmpVec[0].size();
2650 StdRegions::Orientation o =
2651 nFaceEdges == 3
2652 ? SpatialDomains::TriGeom::GetFaceOrientation(
2653 {tmpVec[0][0], tmpVec[0][1],
2654 tmpVec[0][2]},
2655 {tmpVec[1][0], tmpVec[1][1],
2656 tmpVec[1][2]},
2657 rotbnd, dir, angle, tol)
2658 : SpatialDomains::QuadGeom::GetFaceOrientation(
2659 {tmpVec[0][0], tmpVec[0][1], tmpVec[0][2],
2660 tmpVec[0][3]},
2661 {tmpVec[1][0], tmpVec[1][1], tmpVec[1][2],
2662 tmpVec[1][3]},
2663 rotbnd, dir, angle, tol);
2664
2665 // Use emap to determine which edge of the other
2666 // face should be periodic with this one.
2667 int perEdgeId =
2668 edgeMap[perFaceId][emap[nFaceEdges][o][j]];
2669
2670 PeriodicEntity ent(perEdgeId, StdRegions::eForwards,
2671 locEdges.count(perEdgeId) > 0);
2672
2673 periodicEdges[eId].push_back(ent);
2674
2675 // this map is required at very end to
2676 // determine rotation of edges.
2677 if (rotbnd)
2678 {
2679 eIdToCompId[perEdgeId] = fIdToCompId[perFaceId];
2680 }
2681 }
2682 }
2683 }
2684
2685 // Finally, we must loop over the periodicVerts and periodicEdges
2686 // map to complete connectivity information.
2687 for (auto &perIt : periodicVerts)
2688 {
2689 // For each vertex that is periodic with this one...
2690 for (i = 0; i < perIt.second.size(); ++i)
2691 {
2692 // Find the vertex in the periodicVerts map...
2693 auto perIt2 = periodicVerts.find(perIt.second[i].id);
2694 ASSERTL0(perIt2 != periodicVerts.end(),
2695 "Couldn't find periodic vertex.");
2696
2697 // Now search through this vertex's list and make sure that
2698 // we have a record of any vertices which aren't in the
2699 // original list.
2700 for (j = 0; j < perIt2->second.size(); ++j)
2701 {
2702 if (perIt2->second[j].id == perIt.first)
2703 {
2704 continue;
2705 }
2706
2707 for (k = 0; k < perIt.second.size(); ++k)
2708 {
2709 if (perIt2->second[j].id == perIt.second[k].id)
2710 {
2711 break;
2712 }
2713 }
2714
2715 if (k == perIt.second.size())
2716 {
2717 perIt.second.push_back(perIt2->second[j]);
2718 }
2719 }
2720 }
2721 }
2722
2723 for (auto &perIt : periodicEdges)
2724 {
2725 for (i = 0; i < perIt.second.size(); ++i)
2726 {
2727 auto perIt2 = periodicEdges.find(perIt.second[i].id);
2728 ASSERTL0(perIt2 != periodicEdges.end(),
2729 "Couldn't find periodic edge.");
2730
2731 for (j = 0; j < perIt2->second.size(); ++j)
2732 {
2733 if (perIt2->second[j].id == perIt.first)
2734 {
2735 continue;
2736 }
2737
2738 for (k = 0; k < perIt.second.size(); ++k)
2739 {
2740 if (perIt2->second[j].id == perIt.second[k].id)
2741 {
2742 break;
2743 }
2744 }
2745
2746 if (k == perIt.second.size())
2747 {
2748 perIt.second.push_back(perIt2->second[j]);
2749 }
2750 }
2751 }
2752 }
2753
2754 // Loop over periodic edges to determine relative edge orientations.
2755 for (auto &perIt : periodicEdges)
2756 {
2757 bool rotbnd = false;
2758 int dir = 0;
2759 NekDouble angle = 0.0;
2760 NekDouble tol = 1e-8;
2761
2762 // Find edge coordinates
2763 auto eIt = eIdMap.find(perIt.first);
2764 SpatialDomains::PointGeom v[2] = {*vCoMap[eIt->second.first],
2765 *vCoMap[eIt->second.second]};
2766
2767 // check to see if perioid boundary is rotated
2768 if (rotComp.count(eIdToCompId[perIt.first]))
2769 {
2770 rotbnd = true;
2771 dir = rotComp[eIdToCompId[perIt.first]].m_dir;
2772 angle = rotComp[eIdToCompId[perIt.first]].m_angle;
2773 tol = rotComp[eIdToCompId[perIt.first]].m_tol;
2774 }
2775
2776 // Loop over each edge, and construct a vector that takes us
2777 // from one vertex to another. Use this to figure out which
2778 // vertex maps to which.
2779 for (i = 0; i < perIt.second.size(); ++i)
2780 {
2781 eIt = eIdMap.find(perIt.second[i].id);
2782
2783 SpatialDomains::PointGeom w[2] = {
2784 *vCoMap[eIt->second.first],
2785 *vCoMap[eIt->second.second]};
2786
2787 int vMap[2] = {-1, -1};
2788 if (rotbnd)
2789 {
2790
2791 SpatialDomains::PointGeom r;
2792
2793 r.Rotate(v[0], dir, angle);
2794
2795 if (r.dist(w[0]) < tol)
2796 {
2797 vMap[0] = 0;
2798 }
2799 else
2800 {
2801 r.Rotate(v[1], dir, angle);
2802 if (r.dist(w[0]) < tol)
2803 {
2804 vMap[0] = 1;
2805 }
2806 else
2807 {
2808 NEKERROR(ErrorUtil::efatal,
2809 "Unable to align rotationally "
2810 "periodic edge vertex");
2811 }
2812 }
2813 }
2814 else // translation test
2815 {
2816 NekDouble cx =
2817 0.5 * (w[0](0) - v[0](0) + w[1](0) - v[1](0));
2818 NekDouble cy =
2819 0.5 * (w[0](1) - v[0](1) + w[1](1) - v[1](1));
2820 NekDouble cz =
2821 0.5 * (w[0](2) - v[0](2) + w[1](2) - v[1](2));
2822
2823 for (j = 0; j < 2; ++j)
2824 {
2825 NekDouble x = v[j](0);
2826 NekDouble y = v[j](1);
2827 NekDouble z = v[j](2);
2828 for (k = 0; k < 2; ++k)
2829 {
2830 NekDouble x1 = w[k](0) - cx;
2831 NekDouble y1 = w[k](1) - cy;
2832 NekDouble z1 = w[k](2) - cz;
2833
2834 if (sqrt((x1 - x) * (x1 - x) +
2835 (y1 - y) * (y1 - y) +
2836 (z1 - z) * (z1 - z)) < 1e-8)
2837 {
2838 vMap[k] = j;
2839 break;
2840 }
2841 }
2842 }
2843
2844 // Sanity check the map.
2845 ASSERTL0(vMap[0] >= 0 && vMap[1] >= 0,
2846 "Unable to align periodic edge vertex.");
2847 ASSERTL0((vMap[0] == 0 || vMap[0] == 1) &&
2848 (vMap[1] == 0 || vMap[1] == 1) &&
2849 (vMap[0] != vMap[1]),
2850 "Unable to align periodic edge vertex.");
2851 }
2852
2853 // If 0 -> 0 then edges are aligned already; otherwise
2854 // reverse the orientation.
2855 if (vMap[0] != 0)
2856 {
2857 perIt.second[i].orient = StdRegions::eBackwards;
2858 }
2859 }
2860 }
2861
2862 // Do one final loop over periodic vertices/edges to remove
2863 // non-local vertices/edges from map.
2864 for (auto &perIt : periodicVerts)
2865 {
2866 if (locVerts.count(perIt.first) > 0)
2867 {
2868 m_periodicVerts.insert(perIt);
2869 }
2870 }
2871
2872 for (auto &perIt : periodicEdges)
2873 {
2874 if (locEdges.count(perIt.first) > 0)
2875 {
2876 m_periodicEdges.insert(perIt);
2877 }
2878 }
2879 }
2880 break;
2881 default:
2882 ASSERTL1(false, "Not setup for this expansion");
2883 break;
2884 }
2885}
#define WARNINGL0(condition, msg)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
#define sign(a, b)
return the sign(b)*a
Definition Polylib.cpp:47
LibUtilities::CommSharedPtr m_comm
Communicator.
Definition ExpList.h:1102
static SpatialDomains::BoundaryConditionShPtr GetBoundaryCondition(const SpatialDomains::BoundaryConditionCollection &collection, unsigned int index, const std::string &variable)
static std::unique_ptr< DataType, UniquePtrDeleter > AllocateUniquePtr(const Args &...args)
static StdRegions::Orientation GetFaceOrientation(const QuadGeom &face1, const QuadGeom &face2, bool doRot=false, int dir=0, NekDouble angle=0.0, NekDouble tol=1e-8)
Get the orientation of face1.
Definition QuadGeom.cpp:222
static StdRegions::Orientation GetFaceOrientation(const TriGeom &face1, const TriGeom &face2, bool doRot, int dir, NekDouble angle, NekDouble tol)
Get the orientation of face1.
Definition TriGeom.cpp:201
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition Comm.h:55
std::map< int, std::vector< PeriodicEntity > > PeriodicMap
std::shared_ptr< std::vector< std::pair< Geometry *, int > > > GeometryLinkSharedPtr
Definition MeshGraph.h:209
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
Definition Conditions.h:249
std::map< int, std::vector< unsigned int > > CompositeOrdering
Definition MeshGraph.h:170
std::shared_ptr< BoundaryConditionBase > BoundaryConditionShPtr
Definition Conditions.h:251
std::map< int, std::vector< unsigned int > > BndRegionOrdering
Definition MeshGraph.h:171
std::shared_ptr< Composite > CompositeSharedPtr
Definition MeshGraph.h:178
std::map< int, BoundaryConditionMapShPtr > BoundaryConditionCollection
Definition Conditions.h:258
std::map< int, CompositeSharedPtr > CompositeMap
Definition MeshGraph.h:179
std::vector< double > w(NPUPPER)
std::vector< double > z(NPUPPER)
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition Vmath.hpp:608
scalarT< T > max(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:305
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290

References Nektar::ObjPoolManager< DataType >::AllocateUniquePtr(), ASSERTL0, ASSERTL1, Nektar::LibUtilities::Interpreter::DefineFunction(), Nektar::SpatialDomains::PointGeom::dist(), Nektar::MultiRegions::e1D, Nektar::MultiRegions::e2D, Nektar::MultiRegions::e3D, Nektar::StdRegions::eBackwards, Nektar::StdRegions::eDir1BwdDir1_Dir2BwdDir2, Nektar::StdRegions::eDir1BwdDir1_Dir2FwdDir2, Nektar::StdRegions::eDir1BwdDir2_Dir2BwdDir1, Nektar::StdRegions::eDir1BwdDir2_Dir2FwdDir1, Nektar::StdRegions::eDir1FwdDir1_Dir2BwdDir2, Nektar::StdRegions::eDir1FwdDir1_Dir2FwdDir2, Nektar::StdRegions::eDir1FwdDir2_Dir2BwdDir1, Nektar::StdRegions::eDir1FwdDir2_Dir2FwdDir1, Nektar::ErrorUtil::efatal, Nektar::StdRegions::eForwards, Nektar::StdRegions::eNoOrientation, Nektar::SpatialDomains::ePeriodic, Nektar::LibUtilities::Interpreter::Evaluate(), Nektar::MultiRegions::ExpList::GetBoundaryCondition(), Nektar::SpatialDomains::BoundaryConditions::GetBoundaryConditions(), Nektar::SpatialDomains::BoundaryConditions::GetBoundaryRegions(), Nektar::SpatialDomains::Geometry::GetEid(), Nektar::SpatialDomains::Geometry::GetEorient(), Nektar::SpatialDomains::QuadGeom::GetFaceOrientation(), Nektar::SpatialDomains::TriGeom::GetFaceOrientation(), Nektar::SpatialDomains::Geometry::GetNumVerts(), Nektar::SpatialDomains::Geometry::GetVertex(), Nektar::SpatialDomains::Geometry::GetVid(), Nektar::MultiRegions::RotPeriodicInfo::m_angle, Nektar::MultiRegions::ExpList::m_comm, Nektar::MultiRegions::RotPeriodicInfo::m_dir, Nektar::MultiRegions::ExpList::m_expType, Nektar::MultiRegions::ExpList::m_graph, m_periodicEdges, m_periodicFaces, m_periodicVerts, Nektar::MultiRegions::RotPeriodicInfo::m_tol, tinysimd::max(), NEKERROR, Nektar::LibUtilities::ReduceMax, Nektar::LibUtilities::ReduceSum, Nektar::SpatialDomains::PointGeom::Rotate(), sign, tinysimd::sqrt(), Vmath::Vsum(), and WARNINGL0.

Referenced by DisContField(), DisContField(), and DisContField().

◆ GenerateBoundaryConditionExpansion() [1/2]

void Nektar::MultiRegions::DisContField::GenerateBoundaryConditionExpansion ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  In,
const SpatialDomains::BoundaryConditions bcs,
const std::string  variable,
const bool  DeclareCoeffPhysArrays = true,
const Collections::ImplementationType  ImpType = Collections::eNoImpType 
)
protected

Make copy of boundary conditions.

This function discretises the boundary conditions using an already setup expansion list of one-dimensions lower boundary expansions.

According to their boundary region, the separate boundary expansions are bundled together in an object of the class

Parameters
InAn array of boundary conditions from an alread setup expansion and the spectral/hp element expansions.
bcsInformation about the enforced boundary conditions.
variableThe session variable associated with the boundary conditions to enforce.
DeclareCoeffPhysArraysbool to identify if array space should be setup. Default is true.

Definition at line 922 of file DisContField.cpp.

927{
928 int cnt = 0;
932 bcs.GetBoundaryRegions();
934 bcs.GetBoundaryConditions();
935
936 std::set<int> ProcessBnd;
937 if (m_session->DefinesTag("CreateBndRegions"))
938 {
939 // evaluate bnd regions to be generated
940 vector<unsigned int> bndRegions;
942 m_session->GetTag("CreateBndRegions"), bndRegions),
943 "Failed to interpret bnd values string");
944
945 for (auto &bnd : bndRegions)
946 {
947 if (bregions.count(bnd) == 1)
948 {
949 ProcessBnd.insert(bnd);
950 }
951 }
952 }
953 else
954 {
955 for (auto &it : bregions)
956 {
957 ProcessBnd.insert(it.first);
958 }
959 }
960
962 Array<OneD, MultiRegions::ExpListSharedPtr>(ProcessBnd.size());
964 Array<OneD, SpatialDomains::BoundaryConditionShPtr>(ProcessBnd.size());
965
966 m_bndCondBndWeight = Array<OneD, NekDouble>{bregions.size(), 0.0};
967
968 // count the number of non-periodic boundary points
969 for (auto &it : bregions)
970 {
971 // check to see if reduced bnd regions have been set in FieldConvert.
972 if (ProcessBnd.count(it.first) == 0)
973 {
974 continue;
975 }
976
977 bc = GetBoundaryCondition(bconditions, it.first, variable);
978
979 // make a copy of existing Bc passed to generate function
981 *(In[cnt]), DeclareCoeffPhysArrays);
982
983 m_bndCondExpansions[cnt] = locExpList;
984 m_bndConditions[cnt] = bc;
985
986 std::string type = m_bndConditions[cnt]->GetUserDefined();
987
988 // Set up normals on non-Dirichlet boundary conditions. Second
989 // two conditions ideally should be in local solver setup (when
990 // made into factory)
991 if (bc->GetBoundaryConditionType() != SpatialDomains::eDirichlet ||
992 boost::iequals(type, "I") || boost::iequals(type, "CalcBC"))
993 {
995 }
996 cnt++;
997 }
998}
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::SpatialDomains::eDirichlet, Nektar::ParseUtils::GenerateVector(), Nektar::MultiRegions::ExpList::GetBoundaryCondition(), Nektar::SpatialDomains::BoundaryConditions::GetBoundaryConditions(), Nektar::SpatialDomains::BoundaryConditions::GetBoundaryRegions(), m_bndCondBndWeight, m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::ExpList::m_session, and Nektar::MultiRegions::ExpList::SetUpPhysNormals().

◆ GenerateBoundaryConditionExpansion() [2/2]

void Nektar::MultiRegions::DisContField::GenerateBoundaryConditionExpansion ( const SpatialDomains::MeshGraphSharedPtr graph,
const SpatialDomains::BoundaryConditions bcs,
const std::string  variable,
const bool  DeclareCoeffPhysArrays = true,
const Collections::ImplementationType  ImpType = Collections::eNoImpType 
)
protected

Discretises the boundary conditions.

This function discretises the boundary conditions by setting up a list of one-dimensions lower boundary expansions.

According to their boundary region, the separate boundary expansions are bundled together in an object of the class

Parameters
graphA mesh, containing information about the domain and the spectral/hp element expansions.
bcsInformation about the enforced boundary conditions.
variableThe session variable associated with the boundary conditions to enforce.
DeclareCoeffPhysArraysbool to identify if array space should be setup. Default is true.

Definition at line 826 of file DisContField.cpp.

831{
832 int cnt = 0;
836 bcs.GetBoundaryRegions();
838 bcs.GetBoundaryConditions();
839
840 std::set<int> ProcessBnd;
841 if (m_session->DefinesTag("CreateBndRegions"))
842 {
843 // evaluate bnd regions to be generated
844 vector<unsigned int> bndRegions;
846 m_session->GetTag("CreateBndRegions"), bndRegions),
847 "Failed to interpret bnd values string");
848
849 for (auto &bnd : bndRegions)
850 {
851 if (bregions.count(bnd) ==
852 1) // this boundary may not exist on processor
853 {
854 ProcessBnd.insert(bnd);
855 }
856 }
857 }
858 else
859 {
860 for (auto &it : bregions)
861 {
862 ProcessBnd.insert(it.first);
863 }
864 }
865
867 Array<OneD, MultiRegions::ExpListSharedPtr>(ProcessBnd.size());
869 Array<OneD, SpatialDomains::BoundaryConditionShPtr>(ProcessBnd.size());
870
871 m_bndCondBndWeight = Array<OneD, NekDouble>{bregions.size(), 0.0};
872
873 // count the number of non-periodic boundary points
874 for (auto &it : bregions)
875 {
876 // check to see if reduced bnd regions have been set in FieldConvert.
877 if (ProcessBnd.count(it.first) == 0)
878 {
879 continue;
880 }
881
882 bc = GetBoundaryCondition(bconditions, it.first, variable);
883
885 m_session, *(it.second), graph, DeclareCoeffPhysArrays, variable,
886 false, bc->GetComm(), ImpType);
887
888 m_bndCondExpansions[cnt] = locExpList;
889 m_bndConditions[cnt] = bc;
890
891 std::string type = m_bndConditions[cnt]->GetUserDefined();
892
893 // Set up normals on non-Dirichlet boundary conditions. Second
894 // two conditions ideally should be in local solver setup (when
895 // made into factory)
896 if (bc->GetBoundaryConditionType() != SpatialDomains::eDirichlet ||
897 boost::iequals(type, "I") || boost::iequals(type, "CalcBC"))
898 {
900 }
901 cnt++;
902 }
903}

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::SpatialDomains::eDirichlet, Nektar::ParseUtils::GenerateVector(), Nektar::MultiRegions::ExpList::GetBoundaryCondition(), Nektar::SpatialDomains::BoundaryConditions::GetBoundaryConditions(), Nektar::SpatialDomains::BoundaryConditions::GetBoundaryRegions(), m_bndCondBndWeight, m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::ExpList::m_session, and Nektar::MultiRegions::ExpList::SetUpPhysNormals().

Referenced by DisContField(), DisContField(), and DisContField().

◆ GenerateFieldBnd1D()

void Nektar::MultiRegions::DisContField::GenerateFieldBnd1D ( SpatialDomains::BoundaryConditions bcs,
const std::string  variable 
)
protected

◆ GetDomainBCs()

SpatialDomains::BoundaryConditionsSharedPtr Nektar::MultiRegions::DisContField::GetDomainBCs ( const SpatialDomains::CompositeMap domain,
const SpatialDomains::BoundaryConditions Allbcs,
const std::string &  variable 
)
private

Definition at line 521 of file DisContField.cpp.

525{
527
528 returnval =
530
531 map<int, int> GeometryToRegionsMap;
532
534 Allbcs.GetBoundaryRegions();
536 Allbcs.GetBoundaryConditions();
537
538 // Set up a map of all boundary regions
539 for (auto &it : bregions)
540 {
541 for (auto &bregionIt : *it.second)
542 {
543 // can assume that all regions only contain one point in 1D
544 // Really do not need loop above
545 int id = bregionIt.second->m_geomVec[0]->GetGlobalID();
546 GeometryToRegionsMap[id] = it.first;
547 }
548 }
549
550 map<int, SpatialDomains::Geometry *> EndOfDomain;
551
552 // Now find out which points in domain have only one vertex
553 for (auto &domIt : domain)
554 {
555 SpatialDomains::CompositeSharedPtr geomvector = domIt.second;
556 for (int i = 0; i < geomvector->m_geomVec.size(); ++i)
557 {
558 for (int j = 0; j < 2; ++j)
559 {
560 int vid = geomvector->m_geomVec[i]->GetVid(j);
561 if (EndOfDomain.count(vid) == 0)
562 {
563 EndOfDomain[vid] = geomvector->m_geomVec[i]->GetVertex(j);
564 }
565 else
566 {
567 EndOfDomain.erase(vid);
568 }
569 }
570 }
571 }
572 ASSERTL1(EndOfDomain.size() == 2, "Did not find two ends of domain");
573
574 for (auto &regIt : EndOfDomain)
575 {
576 if (GeometryToRegionsMap.count(regIt.first) != 0)
577 {
578 // Set up boundary condition up
579 auto iter = GeometryToRegionsMap.find(regIt.first);
580 ASSERTL1(iter != GeometryToRegionsMap.end(),
581 "Failied to find GeometryToRegionMap");
582
583 int regionId = iter->second;
584 auto bregionsIter = bregions.find(regionId);
585 ASSERTL1(bregionsIter != bregions.end(),
586 "Failed to find boundary region");
587
588 SpatialDomains::BoundaryRegionShPtr breg = bregionsIter->second;
589 returnval->AddBoundaryRegions(regionId, breg);
590
591 auto bconditionsIter = bconditions.find(regionId);
592 ASSERTL1(bconditionsIter != bconditions.end(),
593 "Failed to find boundary collection");
594
596 bconditionsIter->second;
597 returnval->AddBoundaryConditions(regionId, bcond);
598 }
599 }
600
601 return returnval;
602}
std::shared_ptr< BoundaryRegion > BoundaryRegionShPtr
Definition Conditions.h:247
std::shared_ptr< BoundaryConditionMap > BoundaryConditionMapShPtr
Definition Conditions.h:257

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL1, Nektar::SpatialDomains::BoundaryConditions::GetBoundaryConditions(), and Nektar::SpatialDomains::BoundaryConditions::GetBoundaryRegions().

Referenced by DisContField().

◆ GetFwdBwdTracePhys()

void Nektar::MultiRegions::DisContField::GetFwdBwdTracePhys ( const Array< OneD, const NekDouble > &  field,
Array< OneD, NekDouble > &  Fwd,
Array< OneD, NekDouble > &  Bwd,
const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > &  BndCond,
const Array< OneD, const ExpListSharedPtr > &  BndCondExp 
)

This method extracts the "forward" and "backward" trace data from the array field and puts the data into output vectors Fwd and Bwd.

We first define the convention which defines "forwards" and "backwards". First an association is made between the vertex/edge/face of each element and its corresponding vertex/edge/face in the trace space using the mapping m_traceMap. The element can either be left-adjacent or right-adjacent to this trace face (see Expansion2D::GetLeftAdjacentElementExp). Boundary faces are always left-adjacent since left-adjacency is populated first.

If the element is left-adjacent we extract the trace data from field into the forward trace space Fwd; otherwise, we place it in the backwards trace space Bwd. In this way, we form a unique set of trace normals since these are always extracted from left-adjacent elements.

Parameters
fieldis a NekDouble array which contains the fielddata from which we wish to extract the backward and forward orientated trace/face arrays.
Returns
Updates a NekDouble array Fwd and Bwd

Definition at line 3211 of file DisContField.cpp.

3216{
3217 ASSERTL1((*m_exp)[0]->GetBasis(0)->GetBasisType() !=
3219 "Routine not set up for Gauss Lagrange points distribution");
3220
3221 // blocked routine
3222 Array<OneD, NekDouble> tracevals(m_locTraceToTraceMap->GetNLocTracePts());
3223
3224 m_locTraceToTraceMap->LocTracesFromField(field, tracevals);
3225 m_locTraceToTraceMap->InterpLocTracesToTrace(0, tracevals, Fwd);
3226
3227 Array<OneD, NekDouble> invals =
3228 tracevals + m_locTraceToTraceMap->GetNFwdLocTracePts();
3229 m_locTraceToTraceMap->InterpLocTracesToTrace(1, invals, Bwd);
3230
3232
3233 FillBwdWithBoundCond(Fwd, Bwd, BndCond, BndCondExp, false);
3234
3235 // Do parallel exchange for forwards/backwards spaces.
3236 m_traceMap->GetAssemblyCommDG()->PerformExchange(Fwd, Bwd);
3237
3238 // Do exchange of interface traces (local and parallel)
3239 // We may have to split this out into separate local and
3240 // parallel for IP method???
3241 m_interfaceMap->ExchangeTrace(Fwd, Bwd);
3242}
void v_PeriodicBwdCopy(const Array< OneD, const NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd) override
void FillBwdWithBoundCond(const Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > &bndConditions, const Array< OneD, const ExpListSharedPtr > &BndCondExpansions, bool PutFwdInBwdOnBCs)
@ eGauss_Lagrange
Lagrange Polynomials using the Gauss points.
Definition BasisType.h:57

References ASSERTL1, Nektar::LibUtilities::eGauss_Lagrange, FillBwdWithBoundCond(), Nektar::MultiRegions::ExpList::m_exp, m_interfaceMap, m_locTraceToTraceMap, m_traceMap, and v_PeriodicBwdCopy().

◆ GetGlobalBndLinSys()

GlobalLinSysSharedPtr Nektar::MultiRegions::DisContField::GetGlobalBndLinSys ( const GlobalLinSysKey mkey)

For a given key, returns the associated global linear system.

Definition at line 2890 of file DisContField.cpp.

2892{
2893 ASSERTL0(mkey.GetMatrixType() == StdRegions::eHybridDGHelmBndLam,
2894 "Routine currently only tested for HybridDGHelmholtz");
2895
2896 ASSERTL1(mkey.GetGlobalSysSolnType() != eDirectFullMatrix,
2897 "Full matrix global systems are not supported for HDG "
2898 "expansions");
2899
2900 ASSERTL1(mkey.GetGlobalSysSolnType() == m_traceMap->GetGlobalSysSolnType(),
2901 "The local to global map is not set up for the requested "
2902 "solution type");
2903
2904 GlobalLinSysSharedPtr glo_matrix;
2905 auto matrixIter = m_globalBndMat->find(mkey);
2906
2907 if (matrixIter == m_globalBndMat->end())
2908 {
2909 glo_matrix = GenGlobalBndLinSys(mkey, m_traceMap);
2910 (*m_globalBndMat)[mkey] = glo_matrix;
2911 }
2912 else
2913 {
2914 glo_matrix = matrixIter->second;
2915 }
2916
2917 return glo_matrix;
2918}
std::shared_ptr< GlobalLinSys > GenGlobalBndLinSys(const GlobalLinSysKey &mkey, const AssemblyMapSharedPtr &locToGloMap)
Generate a GlobalLinSys from information provided by the key "mkey" and the mapping provided in LocTo...
std::shared_ptr< GlobalLinSys > GlobalLinSysSharedPtr
Pointer to a GlobalLinSys object.

References ASSERTL0, ASSERTL1, Nektar::MultiRegions::eDirectFullMatrix, Nektar::StdRegions::eHybridDGHelmBndLam, Nektar::MultiRegions::ExpList::GenGlobalBndLinSys(), Nektar::MultiRegions::GlobalLinSysKey::GetGlobalSysSolnType(), Nektar::MultiRegions::GlobalMatrixKey::GetMatrixType(), m_globalBndMat, and m_traceMap.

Referenced by v_HelmSolve().

◆ GetLocElmtTrace()

ExpListSharedPtr & Nektar::MultiRegions::DisContField::GetLocElmtTrace ( )
inline

Definition at line 136 of file DisContField.h.

137 {
138 return m_locElmtTrace;
139 }

References m_locElmtTrace.

Referenced by Nektar::SolverUtils::DiffusionIP::AddSymmFluxIntegralToCoeff().

◆ GetLocTraceToTraceMap()

void Nektar::MultiRegions::DisContField::GetLocTraceToTraceMap ( LocTraceToTraceMapSharedPtr LocTraceToTraceMap)
inline

Definition at line 123 of file DisContField.h.

125 {
126 LocTraceToTraceMap = m_locTraceToTraceMap;
127 }

References m_locTraceToTraceMap.

◆ GetNegatedFluxNormal()

vector< bool > & Nektar::MultiRegions::DisContField::GetNegatedFluxNormal ( void  )

Definition at line 2954 of file DisContField.cpp.

2955{
2956 if (m_negatedFluxNormal.size() == 0)
2957 {
2958 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>>
2959 &elmtToTrace = m_traceMap->GetElmtToTrace();
2960
2961 m_negatedFluxNormal.resize(2 * GetExpSize());
2962
2963 for (int i = 0; i < GetExpSize(); ++i)
2964 {
2965
2966 for (int v = 0; v < 2; ++v)
2967 {
2969 elmtToTrace[i][v]->as<LocalRegions::Expansion0D>();
2970
2971 if (vertExp->GetLeftAdjacentElementExp()
2972 ->GetGeom()
2973 ->GetGlobalID() !=
2974 (*m_exp)[i]->GetGeom()->GetGlobalID())
2975 {
2976 m_negatedFluxNormal[2 * i + v] = true;
2977 }
2978 else
2979 {
2980 m_negatedFluxNormal[2 * i + v] = false;
2981 }
2982 }
2983 }
2984 }
2985
2986 return m_negatedFluxNormal;
2987}
std::vector< bool > m_negatedFluxNormal
std::shared_ptr< Expansion0D > Expansion0DSharedPtr
Definition Expansion0D.h:47

References Nektar::MultiRegions::ExpList::GetExpSize(), m_negatedFluxNormal, and m_traceMap.

Referenced by v_AddTraceIntegral().

◆ IsLeftAdjacentTrace()

bool Nektar::MultiRegions::DisContField::IsLeftAdjacentTrace ( const int  n,
const int  e 
)
protected

This routine determines if an element is to the "left" of the adjacent trace, which arises from the idea there is a local normal direction between two elements (i.e. on the trace) and one elements would then be the left.

This is typically required since we only define one normal direction along the trace which goes from the left adjacent element to the right adjacent element. It is also useful in DG discretisations to set up a local Riemann problem where we need to have the concept of a local normal direction which is unique between two elements.

There are two cases to be checked:

1) First is the trace on a boundary condition (perioidic or otherwise) or on a partition boundary. If a partition boundary then trace is always considered to be the left adjacent trace and the normal is pointing outward of the soltuion domain. We have to perform an additional case for a periodic boundary where wer chose the element with the lowest global id. If the trace is on a parallel partition we use a member of the traceMap where one side is chosen to contribute to a unique map and have a value which is not -1 so this is the identifier for the left adjacent side

2) If the element is a elemental boundary on one element the left adjacent element is defined by a link to the left element from the trace expansion and this is consistent with the defitiion of the normal which is determined by the largest id (in contrast to the periodic boundary definition !). This reversal of convention does not really matter providing the normals are defined consistently.

Definition at line 480 of file DisContField.cpp.

481{
483 m_traceMap->GetElmtToTrace()[n][e];
484
485 PeriodicMap periodicTraces = (m_expType == e1D) ? m_periodicVerts
488
489 bool fwd = true;
490 if (traceEl->GetLeftAdjacentElementTrace() == -1 ||
491 traceEl->GetRightAdjacentElementTrace() == -1)
492 {
493 // Boundary edge (1 connected element). Do nothing in
494 // serial.
495 auto it = m_boundaryTraces.find(traceEl->GetElmtId());
496
497 // If the edge does not have a boundary condition set on
498 // it, then assume it is a partition edge or periodic.
499 if (it == m_boundaryTraces.end())
500 {
501 fwd = true;
502 }
503 }
504 else if (traceEl->GetLeftAdjacentElementTrace() != -1 &&
505 traceEl->GetRightAdjacentElementTrace() != -1)
506 {
507 // Non-boundary edge (2 connected elements).
508 fwd = (traceEl->GetLeftAdjacentElementExp().get()) == (*m_exp)[n].get();
509 }
510 else
511 {
512 ASSERTL2(false, "Unconnected trace element!");
513 }
514
515 return fwd;
516}
#define ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed to...

References ASSERTL2, Nektar::MultiRegions::e1D, Nektar::MultiRegions::e2D, m_boundaryTraces, Nektar::MultiRegions::ExpList::m_exp, Nektar::MultiRegions::ExpList::m_expType, m_periodicEdges, m_periodicFaces, m_periodicVerts, and m_traceMap.

Referenced by SetUpDG().

◆ L2_DGDeriv()

NekDouble Nektar::MultiRegions::DisContField::L2_DGDeriv ( const int  dir,
const Array< OneD, const NekDouble > &  coeffs,
const Array< OneD, const NekDouble > &  soln 
)

Calculate the \( L^2 \) error of the \( Q_{\rm dir} \) derivative using the consistent DG evaluation of \( Q_{\rm dir} \).

The solution provided is of the primative variation at the quadrature points and the derivative is compared to the discrete derivative at these points, which is likely to be undesirable unless using a much higher number of quadrature points than the polynomial order used to evaluate \( Q_{\rm dir} \).

Definition at line 4489 of file DisContField.cpp.

4492{
4493 int i, e, ncoeff_edge;
4494 Array<OneD, const NekDouble> tmp_coeffs;
4495 Array<OneD, NekDouble> out_d(m_ncoeffs), out_tmp;
4496
4497 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>> &elmtToTrace =
4498 m_traceMap->GetElmtToTrace();
4499
4501
4502 int cnt;
4503 int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs();
4504 Array<OneD, NekDouble> loc_lambda(LocBndCoeffs), edge_lambda;
4505 m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(), loc_lambda);
4506
4507 edge_lambda = loc_lambda;
4508
4509 // Calculate Q using standard DG formulation.
4510 for (i = cnt = 0; i < GetExpSize(); ++i)
4511 {
4512 // Probably a better way of setting up lambda than this.
4513 // Note cannot use PutCoeffsInToElmts since lambda space
4514 // is mapped during the solve.
4515 int nEdges = (*m_exp)[i]->GetGeom()->GetNumEdges();
4516 Array<OneD, Array<OneD, NekDouble>> edgeCoeffs(nEdges);
4517
4518 for (e = 0; e < nEdges; ++e)
4519 {
4520 edgedir = (*m_exp)[i]->GetTraceOrient(e);
4521 ncoeff_edge = elmtToTrace[i][e]->GetNcoeffs();
4522 edgeCoeffs[e] = Array<OneD, NekDouble>(ncoeff_edge);
4523 Vmath::Vcopy(ncoeff_edge, edge_lambda, 1, edgeCoeffs[e], 1);
4524 elmtToTrace[i][e]->SetCoeffsToOrientation(edgedir, edgeCoeffs[e],
4525 edgeCoeffs[e]);
4526 edge_lambda = edge_lambda + ncoeff_edge;
4527 }
4528
4529 (*m_exp)[i]->DGDeriv(dir, tmp_coeffs = coeffs + m_coeff_offset[i],
4530 elmtToTrace[i], edgeCoeffs, out_tmp = out_d + cnt);
4531 cnt += (*m_exp)[i]->GetNcoeffs();
4532 }
4533
4534 Array<OneD, NekDouble> phys(m_npoints);
4535 BwdTrans(out_d, phys);
4536 Vmath::Vsub(m_npoints, phys, 1, soln, 1, phys, 1);
4537 return L2(phys);
4538}
int m_ncoeffs
The total number of local degrees of freedom. m_ncoeffs .
Definition ExpList.h:1109
NekDouble L2(const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &soln=NullNekDouble1DArray)
This function calculates the error of the global This function calculates the error with respect to...
Definition ExpList.h:521
void BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function elementally evaluates the backward transformation of the global spectral/hp element exp...
Definition ExpList.h:1787
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition Vmath.hpp:220

References Nektar::MultiRegions::ExpList::BwdTrans(), Nektar::MultiRegions::ExpList::GetExpSize(), Nektar::MultiRegions::ExpList::L2(), Nektar::MultiRegions::ExpList::m_coeff_offset, Nektar::MultiRegions::ExpList::m_ncoeffs, Nektar::MultiRegions::ExpList::m_npoints, m_trace, m_traceMap, Vmath::Vcopy(), and Vmath::Vsub().

◆ Rotate()

void Nektar::MultiRegions::DisContField::Rotate ( Array< OneD, Array< OneD, NekDouble > > &  Bwd,
const int  dir,
const NekDouble  angle,
const int  offset,
const int  npts 
)
protected

Rotate the slice [offset, offset + npts) of the 3D vector field in Bwd around the axis 'dir' by 'angle'.

Definition at line 4785 of file DisContField.cpp.

4788{
4789 // Precompute trigonometric values for improved precision
4790 const NekDouble cosA = cos(angle);
4791 const NekDouble sinA = sin(angle);
4792
4793 switch (dir)
4794 {
4795 // ----------------------------------------------------------
4796 // Rotate around the x-axis by 'angle':
4797 // y' = y*cos(angle) - z*sin(angle)
4798 // z' = y*sin(angle) + z*cos(angle)
4799 // x' = x (unchanged)
4800 // ----------------------------------------------------------
4801 case 0:
4802 {
4803 for (int i = offset; i < offset + npts; ++i)
4804 {
4805 NekDouble tmpY = Bwd[2][i];
4806 NekDouble tmpZ = Bwd[3][i];
4807
4808 NekDouble yrot = cosA * tmpY - sinA * tmpZ;
4809 NekDouble zrot = sinA * tmpY + cosA * tmpZ;
4810
4811 Bwd[2][i] = yrot;
4812 Bwd[3][i] = zrot;
4813 }
4814 }
4815 break;
4816
4817 // ----------------------------------------------------------
4818 // Rotate around the y-axis by 'angle':
4819 // z' = z*cos(angle) - x*sin(angle)
4820 // x' = z*sin(angle) + x*cos(angle)
4821 // y' = y (unchanged)
4822 // ----------------------------------------------------------
4823 case 1:
4824 {
4825 for (int i = offset; i < offset + npts; ++i)
4826 {
4827 NekDouble tmpX = Bwd[1][i];
4828 NekDouble tmpZ = Bwd[3][i];
4829
4830 NekDouble zrot = cosA * tmpZ - sinA * tmpX;
4831 NekDouble xrot = sinA * tmpZ + cosA * tmpX;
4832
4833 Bwd[1][i] = xrot;
4834 Bwd[3][i] = zrot;
4835 }
4836 }
4837 break;
4838
4839 // ----------------------------------------------------------
4840 // Rotate around the z-axis by 'angle':
4841 // x' = x*cos(angle) - y*sin(angle)
4842 // y' = x*sin(angle) + y*cos(angle)
4843 // z' = z (unchanged)
4844 // ----------------------------------------------------------
4845 case 2:
4846 {
4847 for (int i = offset; i < offset + npts; ++i)
4848 {
4849 NekDouble tmpX = Bwd[1][i];
4850 NekDouble tmpY = Bwd[2][i];
4851
4852 NekDouble xrot = cosA * tmpX - sinA * tmpY;
4853 NekDouble yrot = sinA * tmpX + cosA * tmpY;
4854
4855 Bwd[1][i] = xrot;
4856 Bwd[2][i] = yrot;
4857 }
4858 }
4859 break;
4860
4861 default:
4863 "Rotate() axis must be 0 (x), 1 (y), or 2 (z).");
4864 break;
4865 }
4866}

References Nektar::ErrorUtil::efatal, and NEKERROR.

Referenced by v_PeriodicBwdRot().

◆ SameTypeOfBoundaryConditions()

bool Nektar::MultiRegions::DisContField::SameTypeOfBoundaryConditions ( const DisContField In)

Check to see if expansion has the same BCs as In.

For each boundary region, checks that the types and number of boundary expansions in that region match.

Parameters
InField to compare with.
Returns
True if boundary conditions match.

Definition at line 2926 of file DisContField.cpp.

2927{
2928 int i;
2929 bool returnval = true;
2930
2931 for (i = 0; i < m_bndConditions.size(); ++i)
2932 {
2933 // check to see if boundary condition type is the same
2934 // and there are the same number of boundary
2935 // conditions in the boundary definition.
2936 if ((m_bndConditions[i]->GetBoundaryConditionType() !=
2937 In.m_bndConditions[i]->GetBoundaryConditionType()) ||
2938 (m_bndCondExpansions[i]->GetExpSize() !=
2939 In.m_bndCondExpansions[i]->GetExpSize()))
2940 {
2941 returnval = false;
2942 break;
2943 }
2944 }
2945
2946 // Compare with all other processes. Return true only if all
2947 // processes report having the same boundary conditions.
2948 int vSame = (returnval ? 1 : 0);
2949 m_comm->GetRowComm()->AllReduce(vSame, LibUtilities::ReduceMin);
2950
2951 return (vSame == 1);
2952}

References m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::ExpList::m_comm, and Nektar::LibUtilities::ReduceMin.

Referenced by Nektar::MultiRegions::ContField::ContField(), and DisContField().

◆ SetUpDG()

void Nektar::MultiRegions::DisContField::SetUpDG ( const std::string  variable = "DefaultVar",
const Collections::ImplementationType  ImpType = Collections::eNoImpType 
)
protected

Set up all DG member variables and maps.

Definition at line 162 of file DisContField.cpp.

164{
165 // Check for multiple calls
167 {
168 return;
169 }
170
171 // Set up matrix map
173
174 // Set up trace space
177 m_comm, true, "DefaultVar", ImpType);
178
180 m_session, *m_exp, GetGraph(), true, "LocElmtTrace");
181
182 PeriodicMap periodicTraces = (m_expType == e1D) ? m_periodicVerts
185
188 m_bndConditions, periodicTraces, variable);
189
190 if (m_session->DefinesCmdLineArgument("verbose"))
191 {
192 m_traceMap->PrintStats(std::cout, variable);
193 }
194
195 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>> &elmtToTrace =
196 m_traceMap->GetElmtToTrace();
197
198 // Scatter trace to elements. For each element, we find
199 // the trace associated to each elemental trace. The element
200 // then retains a pointer to the elemental trace, to
201 // ensure uniqueness of normals when retrieving from two
202 // adjoining elements which do not lie in a plane.
203 for (int i = 0; i < m_exp->size(); ++i)
204 {
205 for (int j = 0; j < (*m_exp)[i]->GetNtraces(); ++j)
206 {
207 LocalRegions::ExpansionSharedPtr exp = elmtToTrace[i][j];
208 ;
209
210 exp->SetAdjacentElementExp(j, (*m_exp)[i]);
211 (*m_exp)[i]->SetTraceExp(j, exp);
212 }
213 }
214
215 // Set up physical normals
217
218 // Create interface exchange object
221
222 int cnt, n;
223
224 // Identify boundary trace
225 for (cnt = 0, n = 0; n < m_bndCondExpansions.size(); ++n)
226 {
227 if (m_bndConditions[n]->GetBoundaryConditionType() !=
229 {
230 for (int v = 0; v < m_bndCondExpansions[n]->GetExpSize(); ++v)
231 {
232 m_boundaryTraces.insert(
233 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + v));
234 }
235 cnt += m_bndCondExpansions[n]->GetExpSize();
236 }
237 }
238
239 // Set up information for periodic boundary conditions.
240 std::unordered_map<int, pair<int, int>> perTraceToExpMap;
241 for (cnt = n = 0; n < m_exp->size(); ++n)
242 {
243 for (int v = 0; v < (*m_exp)[n]->GetNtraces(); ++v, ++cnt)
244 {
245 auto it = periodicTraces.find((*m_exp)[n]->GetGeom()->GetTid(v));
246
247 if (it != periodicTraces.end())
248 {
249 perTraceToExpMap[it->first] = make_pair(n, v);
250 }
251 }
252 }
253
254 // Set up left-adjacent tracelist.
255 m_leftAdjacentTraces.resize(cnt);
256
257 // count size of trace
258 for (cnt = n = 0; n < m_exp->size(); ++n)
259 {
260 for (int v = 0; v < (*m_exp)[n]->GetNtraces(); ++v, ++cnt)
261 {
263 }
264 }
265
266 // Set up mapping to copy Fwd of periodic bcs to Bwd of other edge.
267 for (cnt = n = 0; n < m_exp->size(); ++n)
268 {
269 for (int v = 0; v < (*m_exp)[n]->GetNtraces(); ++v, ++cnt)
270 {
271 int GeomId = (*m_exp)[n]->GetGeom()->GetTid(v);
272
273 // Check to see if this trace is periodic.
274 auto it = periodicTraces.find(GeomId);
275
276 if (it != periodicTraces.end())
277 {
278 const PeriodicEntity &ent = it->second[0];
279 auto it2 = perTraceToExpMap.find(ent.id);
280
281 if (it2 == perTraceToExpMap.end())
282 {
283 if (m_session->GetComm()->GetRowComm()->GetSize() > 1 &&
284 !ent.isLocal)
285 {
286 continue;
287 }
288 else
289 {
290 ASSERTL1(false, "Periodic trace not found!");
291 }
292 }
293
295 "Periodic trace in non-forward space?");
296
297 int offset = m_trace->GetPhys_Offset(
298 (m_traceMap->GetElmtToTrace())[n][v]->GetElmtId());
299
300 int offset2 = m_trace->GetPhys_Offset(
301 (m_traceMap->GetElmtToTrace())[it2->second.first]
302 [it2->second.second]
303 ->GetElmtId());
304
305 switch (m_expType)
306 {
307 case e1D:
308 {
309 m_periodicFwdCopy.push_back(offset);
310 m_periodicBwdCopy.push_back(offset2);
311 }
312 break;
313 case e2D:
314 {
315 // Calculate relative orientations between trace to
316 // calculate copying map.
317 int nquad = elmtToTrace[n][v]->GetNumPoints(0);
318
319 vector<int> tmpBwd(nquad);
320 vector<int> tmpFwd(nquad);
321
322 if (ent.orient == StdRegions::eForwards)
323 {
324 for (int i = 0; i < nquad; ++i)
325 {
326 tmpBwd[i] = offset2 + i;
327 tmpFwd[i] = offset + i;
328 }
329 }
330 else
331 {
332 for (int i = 0; i < nquad; ++i)
333 {
334 tmpBwd[i] = offset2 + i;
335 tmpFwd[i] = offset + nquad - i - 1;
336 }
337 }
338
339 for (int i = 0; i < nquad; ++i)
340 {
341 m_periodicFwdCopy.push_back(tmpFwd[i]);
342 m_periodicBwdCopy.push_back(tmpBwd[i]);
343 }
344 }
345 break;
346 case e3D:
347 {
348 // Calculate relative orientations between faces to
349 // calculate copying map.
350 int nquad1 = elmtToTrace[n][v]->GetNumPoints(0);
351 int nquad2 = elmtToTrace[n][v]->GetNumPoints(1);
352
353 vector<int> tmpBwd(nquad1 * nquad2);
354 vector<int> tmpFwd(nquad1 * nquad2);
355
356 if (ent.orient ==
358 ent.orient ==
360 ent.orient ==
363 {
364 for (int i = 0; i < nquad2; ++i)
365 {
366 for (int j = 0; j < nquad1; ++j)
367 {
368 tmpBwd[i * nquad1 + j] =
369 offset2 + i * nquad1 + j;
370 tmpFwd[i * nquad1 + j] =
371 offset + j * nquad2 + i;
372 }
373 }
374 }
375 else
376 {
377 for (int i = 0; i < nquad2; ++i)
378 {
379 for (int j = 0; j < nquad1; ++j)
380 {
381 tmpBwd[i * nquad1 + j] =
382 offset2 + i * nquad1 + j;
383 tmpFwd[i * nquad1 + j] =
384 offset + i * nquad1 + j;
385 }
386 }
387 }
388
389 if (ent.orient ==
391 ent.orient ==
393 ent.orient ==
396 {
397 // Reverse x direction
398 for (int i = 0; i < nquad2; ++i)
399 {
400 for (int j = 0; j < nquad1 / 2; ++j)
401 {
402 swap(tmpFwd[i * nquad1 + j],
403 tmpFwd[i * nquad1 + nquad1 - j - 1]);
404 }
405 }
406 }
407
408 if (ent.orient ==
410 ent.orient ==
412 ent.orient ==
415 {
416 // Reverse y direction
417 for (int j = 0; j < nquad1; ++j)
418 {
419 for (int i = 0; i < nquad2 / 2; ++i)
420 {
421 swap(tmpFwd[i * nquad1 + j],
422 tmpFwd[(nquad2 - i - 1) * nquad1 + j]);
423 }
424 }
425 }
426
427 for (int i = 0; i < nquad1 * nquad2; ++i)
428 {
429 m_periodicFwdCopy.push_back(tmpFwd[i]);
430 m_periodicBwdCopy.push_back(tmpBwd[i]);
431 }
432 }
433 break;
434 default:
435 ASSERTL1(false, "not set up");
436 }
437 }
438 }
439 }
440
442 *this, m_trace, elmtToTrace, m_leftAdjacentTraces);
443}
bool IsLeftAdjacentTrace(const int n, const int e)
This routine determines if an element is to the "left" of the adjacent trace, which arises from the i...
SpatialDomains::MeshGraphSharedPtr GetGraph()
Definition ExpList.h:990

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL1, Nektar::MultiRegions::e1D, Nektar::MultiRegions::e2D, Nektar::MultiRegions::e3D, Nektar::StdRegions::eDir1BwdDir1_Dir2BwdDir2, Nektar::StdRegions::eDir1BwdDir1_Dir2FwdDir2, Nektar::StdRegions::eDir1BwdDir2_Dir2BwdDir1, Nektar::StdRegions::eDir1BwdDir2_Dir2FwdDir1, Nektar::StdRegions::eDir1FwdDir1_Dir2BwdDir2, Nektar::StdRegions::eDir1FwdDir2_Dir2BwdDir1, Nektar::StdRegions::eDir1FwdDir2_Dir2FwdDir1, Nektar::StdRegions::eForwards, Nektar::SpatialDomains::ePeriodic, Nektar::MultiRegions::ExpList::GetGraph(), Nektar::MultiRegions::PeriodicEntity::id, IsLeftAdjacentTrace(), Nektar::MultiRegions::PeriodicEntity::isLocal, m_bndCondExpansions, m_bndConditions, m_boundaryTraces, Nektar::MultiRegions::ExpList::m_comm, Nektar::MultiRegions::ExpList::m_exp, Nektar::MultiRegions::ExpList::m_expType, m_globalBndMat, Nektar::MultiRegions::ExpList::m_graph, m_interfaceMap, m_leftAdjacentTraces, m_locElmtTrace, m_locTraceToTraceMap, m_periodicBwdCopy, m_periodicEdges, m_periodicFaces, m_periodicFwdCopy, m_periodicVerts, Nektar::MultiRegions::ExpList::m_session, m_trace, m_traceMap, Nektar::MultiRegions::NullExpListSharedPtr, Nektar::MultiRegions::PeriodicEntity::orient, and Nektar::MultiRegions::ExpList::SetUpPhysNormals().

Referenced by DisContField(), DisContField(), DisContField(), and v_GetTrace().

◆ v_AddFwdBwdTraceIntegral()

void Nektar::MultiRegions::DisContField::v_AddFwdBwdTraceIntegral ( const Array< OneD, const NekDouble > &  Fwd,
const Array< OneD, const NekDouble > &  Bwd,
Array< OneD, NekDouble > &  outarray 
)
overrideprotectedvirtual

Add trace contributions into elemental coefficient spaces.

Given some quantity \( \vec{q} \), calculate the elemental integral

\[ \int_{\Omega^e} \vec{q}, \mathrm{d}S \]

and adds this to the coefficient space provided by outarray. The value of q is determined from the routine IsLeftAdjacentTrace() which if true we use Fwd else we use Bwd

Parameters
FwdThe trace quantities associated with left (fwd) adjancent elmt.
BwdThe trace quantities associated with right (bwd) adjacent elet.
outarrayResulting coefficient space.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3726 of file DisContField.cpp.

3729{
3730 ASSERTL0(m_expType != e1D, "This method is not setup or "
3731 "tested for 1D expansion");
3732 Array<OneD, NekDouble> Coeffs(m_trace->GetNcoeffs());
3733 m_trace->IProductWRTBase(Fwd, Coeffs);
3734 m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(0, Coeffs, outarray);
3735 m_trace->IProductWRTBase(Bwd, Coeffs);
3736 m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(1, Coeffs, outarray);
3737}

References ASSERTL0, Nektar::MultiRegions::e1D, Nektar::MultiRegions::ExpList::m_expType, m_locTraceToTraceMap, and m_trace.

◆ v_AddTraceIntegral()

void Nektar::MultiRegions::DisContField::v_AddTraceIntegral ( const Array< OneD, const NekDouble > &  Fn,
Array< OneD, NekDouble > &  outarray 
)
overrideprotectedvirtual

Add trace contributions into elemental coefficient spaces.

Given some quantity \( \vec{Fn} \), which conatins this routine calculates the integral

\[ \int_{\Omega^e} \vec{Fn}, \mathrm{d}S \]

and adds this to the coefficient space provided by outarray.

See also
Expansion3D::AddFaceNormBoundaryInt
Parameters
FnThe trace quantities.
outarrayResulting 3D coefficient space.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3555 of file DisContField.cpp.

3557{
3558 if (m_expType == e1D)
3559 {
3560 int n, offset, t_offset;
3561 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>>
3562 &elmtToTrace = m_traceMap->GetElmtToTrace();
3563 vector<bool> negatedFluxNormal = GetNegatedFluxNormal();
3564 for (n = 0; n < GetExpSize(); ++n)
3565 {
3566 // Number of coefficients on each element
3567 int e_ncoeffs = (*m_exp)[n]->GetNcoeffs();
3568 offset = GetCoeff_Offset(n);
3569 // Implementation for every points except Gauss points
3570 if ((*m_exp)[n]->GetBasis(0)->GetBasisType() !=
3572 {
3573 t_offset =
3574 GetTrace()->GetCoeff_Offset(elmtToTrace[n][0]->GetElmtId());
3575 if (negatedFluxNormal[2 * n])
3576 {
3577 outarray[offset] -= Fn[t_offset];
3578 }
3579 else
3580 {
3581 outarray[offset] += Fn[t_offset];
3582 }
3583 t_offset =
3584 GetTrace()->GetCoeff_Offset(elmtToTrace[n][1]->GetElmtId());
3585 if (negatedFluxNormal[2 * n + 1])
3586 {
3587 outarray[offset + (*m_exp)[n]->GetVertexMap(1)] -=
3588 Fn[t_offset];
3589 }
3590 else
3591 {
3592 outarray[offset + (*m_exp)[n]->GetVertexMap(1)] +=
3593 Fn[t_offset];
3594 }
3595 }
3596 else
3597 {
3598 int j;
3599 static DNekMatSharedPtr m_Ixm, m_Ixp;
3600 static int sav_ncoeffs = 0;
3601 if (!m_Ixm.get() || e_ncoeffs != sav_ncoeffs)
3602 {
3604 const LibUtilities::PointsKey BS_p(
3606 const LibUtilities::BasisKey BS_k(
3607 LibUtilities::eGauss_Lagrange, e_ncoeffs, BS_p);
3608 BASE = LibUtilities::BasisManager()[BS_k];
3609 Array<OneD, NekDouble> coords(1, 0.0);
3610 coords[0] = -1.0;
3611 m_Ixm = BASE->GetI(coords);
3612 coords[0] = 1.0;
3613 m_Ixp = BASE->GetI(coords);
3614 sav_ncoeffs = e_ncoeffs;
3615 }
3616 t_offset =
3617 GetTrace()->GetCoeff_Offset(elmtToTrace[n][0]->GetElmtId());
3618 if (negatedFluxNormal[2 * n])
3619 {
3620 for (j = 0; j < e_ncoeffs; j++)
3621 {
3622 outarray[offset + j] -=
3623 (m_Ixm->GetPtr())[j] * Fn[t_offset];
3624 }
3625 }
3626 else
3627 {
3628 for (j = 0; j < e_ncoeffs; j++)
3629 {
3630 outarray[offset + j] +=
3631 (m_Ixm->GetPtr())[j] * Fn[t_offset];
3632 }
3633 }
3634 t_offset =
3635 GetTrace()->GetCoeff_Offset(elmtToTrace[n][1]->GetElmtId());
3636 if (negatedFluxNormal[2 * n + 1])
3637 {
3638 for (j = 0; j < e_ncoeffs; j++)
3639 {
3640 outarray[offset + j] -=
3641 (m_Ixp->GetPtr())[j] * Fn[t_offset];
3642 }
3643 }
3644 else
3645 {
3646 for (j = 0; j < e_ncoeffs; j++)
3647 {
3648 outarray[offset + j] +=
3649 (m_Ixp->GetPtr())[j] * Fn[t_offset];
3650 }
3651 }
3652 }
3653 }
3654 }
3655 else // other dimensions
3656 {
3657 // Basis definition on each element
3658 LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0);
3659 if ((m_expType != e1D) &&
3660 (basis->GetBasisType() != LibUtilities::eGauss_Lagrange))
3661 {
3662 Array<OneD, NekDouble> Fcoeffs(m_trace->GetNcoeffs());
3663 m_trace->IProductWRTBase(Fn, Fcoeffs);
3664 m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(Fcoeffs,
3665 outarray);
3666 }
3667 else
3668 {
3669 int e, n, offset, t_offset;
3670 Array<OneD, NekDouble> e_outarray;
3671 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>>
3672 &elmtToTrace = m_traceMap->GetElmtToTrace();
3673 if (m_expType == e2D)
3674 {
3675 for (n = 0; n < GetExpSize(); ++n)
3676 {
3677 offset = GetCoeff_Offset(n);
3678 for (e = 0; e < (*m_exp)[n]->GetNtraces(); ++e)
3679 {
3680 t_offset = GetTrace()->GetPhys_Offset(
3681 elmtToTrace[n][e]->GetElmtId());
3682 (*m_exp)[n]->AddEdgeNormBoundaryInt(
3683 e, elmtToTrace[n][e], Fn + t_offset,
3684 e_outarray = outarray + offset);
3685 }
3686 }
3687 }
3688 else if (m_expType == e3D)
3689 {
3690 for (n = 0; n < GetExpSize(); ++n)
3691 {
3692 offset = GetCoeff_Offset(n);
3693 for (e = 0; e < (*m_exp)[n]->GetNtraces(); ++e)
3694 {
3695 t_offset = GetTrace()->GetPhys_Offset(
3696 elmtToTrace[n][e]->GetElmtId());
3697 (*m_exp)[n]->AddFaceNormBoundaryInt(
3698 e, elmtToTrace[n][e], Fn + t_offset,
3699 e_outarray = outarray + offset);
3700 }
3701 }
3702 }
3703 }
3704 }
3705}
std::vector< bool > & GetNegatedFluxNormal(void)
std::shared_ptr< ExpList > & GetTrace()
Definition ExpList.h:2234
int GetCoeff_Offset(int n) const
Get the start offset position for a local contiguous list of coeffs correspoinding to element n.
Definition ExpList.h:2159
BasisManagerT & BasisManager(void)
std::shared_ptr< Basis > BasisSharedPtr
@ eGaussGaussLegendre
1D Gauss-Gauss-Legendre quadrature points
Definition PointsType.h:46
std::shared_ptr< DNekMat > DNekMatSharedPtr

References Nektar::LibUtilities::BasisManager(), Nektar::MultiRegions::e1D, Nektar::MultiRegions::e2D, Nektar::MultiRegions::e3D, Nektar::LibUtilities::eGauss_Lagrange, Nektar::LibUtilities::eGaussGaussLegendre, Nektar::MultiRegions::ExpList::GetCoeff_Offset(), Nektar::MultiRegions::ExpList::GetExpSize(), GetNegatedFluxNormal(), Nektar::MultiRegions::ExpList::GetTrace(), Nektar::MultiRegions::ExpList::m_exp, Nektar::MultiRegions::ExpList::m_expType, m_locTraceToTraceMap, m_trace, and m_traceMap.

◆ v_AddTraceIntegralToOffDiag()

void Nektar::MultiRegions::DisContField::v_AddTraceIntegralToOffDiag ( const Array< OneD, const NekDouble > &  FwdFlux,
const Array< OneD, const NekDouble > &  BwdFlux,
Array< OneD, NekDouble > &  outarray 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4770 of file DisContField.cpp.

4774{
4775 Array<OneD, NekDouble> FCoeffs(m_trace->GetNcoeffs());
4776
4777 m_trace->IProductWRTBase(FwdFlux, FCoeffs);
4778 m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(1, FCoeffs, outarray);
4779 m_trace->IProductWRTBase(BwdFlux, FCoeffs);
4780 m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(0, FCoeffs, outarray);
4781}

References m_locTraceToTraceMap, and m_trace.

◆ v_AddTraceQuadPhysToField()

void Nektar::MultiRegions::DisContField::v_AddTraceQuadPhysToField ( const Array< OneD, const NekDouble > &  Fwd,
const Array< OneD, const NekDouble > &  Bwd,
Array< OneD, NekDouble > &  field 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3447 of file DisContField.cpp.

3450{
3451 // Basis definition on each element
3452 LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0);
3453 if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange)
3454 {
3455 Array<OneD, NekDouble> tracevals(
3456 m_locTraceToTraceMap->GetNLocTracePts(), 0.0);
3457
3458 Array<OneD, NekDouble> invals =
3459 tracevals + m_locTraceToTraceMap->GetNFwdLocTracePts();
3460
3461 m_locTraceToTraceMap->InterpTraceToLocTrace(1, Bwd, invals);
3462
3463 m_locTraceToTraceMap->InterpTraceToLocTrace(0, Fwd, tracevals);
3464
3465 m_locTraceToTraceMap->AddLocTracesToField(tracevals, field);
3466 }
3467 else
3468 {
3470 "v_AddTraceQuadPhysToField not coded for eGauss_Lagrange");
3471 }
3472}

References Nektar::ErrorUtil::efatal, Nektar::LibUtilities::eGauss_Lagrange, m_locTraceToTraceMap, and NEKERROR.

◆ v_EvaluateBoundaryConditions()

void Nektar::MultiRegions::DisContField::v_EvaluateBoundaryConditions ( const NekDouble  time = 0.0,
const std::string  varName = "",
const NekDouble  x2_in = NekConstants::kNekUnsetDouble,
const NekDouble  x3_in = NekConstants::kNekUnsetDouble 
)
overrideprotectedvirtual

Evaluate all boundary conditions at a given time..

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3907 of file DisContField.cpp.

3911{
3912 int i;
3913 int npoints;
3914
3916
3917 for (i = 0; i < m_bndCondExpansions.size(); ++i)
3918 {
3919 if (m_bndCondExpansions[i] &&
3920 (time == 0.0 || m_bndConditions[i]->IsTimeDependent()))
3921 {
3922 m_bndCondBndWeight[i] = 1.0;
3923 locExpList = m_bndCondExpansions[i];
3924
3925 npoints = locExpList->GetNpoints();
3926 Array<OneD, NekDouble> x0(npoints, 0.0);
3927 Array<OneD, NekDouble> x1(npoints, 0.0);
3928 Array<OneD, NekDouble> x2(npoints, 0.0);
3929
3930 locExpList->GetCoords(x0, x1, x2);
3931
3932 if (x2_in != NekConstants::kNekUnsetDouble &&
3934 {
3935 Vmath::Fill(npoints, x2_in, x1, 1);
3936 Vmath::Fill(npoints, x3_in, x2, 1);
3937 }
3938 else if (x2_in != NekConstants::kNekUnsetDouble)
3939 {
3940 Vmath::Fill(npoints, x2_in, x2, 1);
3941 }
3942
3943 // treat 1D expansions separately since we only
3944 // require an evaluation at a point rather than
3945 // any projections or inner products that are not
3946 // available in a PointExp
3947 if (m_expType == e1D)
3948 {
3949 if (m_bndConditions[i]->GetBoundaryConditionType() ==
3951 {
3952 for (int n = 0; n < npoints; ++n)
3953 {
3954 m_bndCondExpansions[i]->SetCoeff(
3955 n, (std::static_pointer_cast<
3956 SpatialDomains::DirichletBoundaryCondition>(
3957 m_bndConditions[i])
3958 ->m_dirichletCondition)
3959 ->Evaluate(x0[n], x1[n], x2[n], time));
3960 m_bndCondExpansions[i]->SetPhys(
3961 n, m_bndCondExpansions[i]->GetCoeff(n));
3962 }
3963 }
3964 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3966 {
3967 for (int n = 0; n < npoints; ++n)
3968 {
3969 m_bndCondExpansions[i]->SetCoeff(
3970 n, (std::static_pointer_cast<
3971 SpatialDomains::NeumannBoundaryCondition>(
3972 m_bndConditions[i])
3973 ->m_neumannCondition)
3974 ->Evaluate(x0[n], x1[n], x2[n], time));
3975 }
3976 }
3977 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3979 {
3980 for (int n = 0; n < npoints; ++n)
3981 {
3982 m_bndCondExpansions[i]->SetCoeff(
3983 n, (std::static_pointer_cast<
3984 SpatialDomains::RobinBoundaryCondition>(
3985 m_bndConditions[i])
3986 ->m_robinFunction)
3987 ->Evaluate(x0[n], x1[n], x2[n], time));
3988 }
3989 }
3990 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3992 {
3993 continue;
3994 }
3995 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3997 {
3998 }
3999 else
4000 {
4002 "This type of BC not implemented yet");
4003 }
4004 }
4005 else // 2D and 3D versions
4006 {
4007 if (m_bndConditions[i]->GetBoundaryConditionType() ==
4009 {
4011 std::static_pointer_cast<
4012 SpatialDomains::DirichletBoundaryCondition>(
4013 m_bndConditions[i]);
4014
4015 Array<OneD, NekDouble> valuesFile(npoints, 1.0),
4016 valuesExp(npoints, 1.0);
4017
4018 string bcfilename = bcPtr->m_filename;
4019 string exprbcs = bcPtr->m_expr;
4020
4021 if (bcfilename != "")
4022 {
4023 locExpList->ExtractCoeffsFromFile(
4024 bcfilename, bcPtr->GetComm(), varName,
4025 locExpList->UpdateCoeffs());
4026 locExpList->BwdTrans(locExpList->GetCoeffs(),
4027 locExpList->UpdatePhys());
4028 valuesFile = locExpList->GetPhys();
4029 }
4030
4031 if (exprbcs != "")
4032 {
4034 std::static_pointer_cast<
4035 SpatialDomains::DirichletBoundaryCondition>(
4036 m_bndConditions[i])
4037 ->m_dirichletCondition;
4038
4039 condition->Evaluate(x0, x1, x2, time, valuesExp);
4040 }
4041
4042 Vmath::Vmul(npoints, valuesExp, 1, valuesFile, 1,
4043 locExpList->UpdatePhys(), 1);
4044 locExpList->FwdTransBndConstrained(
4045 locExpList->GetPhys(), locExpList->UpdateCoeffs());
4046 }
4047 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4049 {
4051 std::static_pointer_cast<
4052 SpatialDomains::NeumannBoundaryCondition>(
4053 m_bndConditions[i]);
4054 string bcfilename = bcPtr->m_filename;
4055
4056 if (bcfilename != "")
4057 {
4058 locExpList->ExtractCoeffsFromFile(
4059 bcfilename, bcPtr->GetComm(), varName,
4060 locExpList->UpdateCoeffs());
4061 locExpList->BwdTrans(locExpList->GetCoeffs(),
4062 locExpList->UpdatePhys());
4063 }
4064 else
4065 {
4067 std::static_pointer_cast<
4068 SpatialDomains::NeumannBoundaryCondition>(
4069 m_bndConditions[i])
4070 ->m_neumannCondition;
4071 condition->Evaluate(x0, x1, x2, time,
4072 locExpList->UpdatePhys());
4073 }
4074
4075 locExpList->IProductWRTBase(locExpList->GetPhys(),
4076 locExpList->UpdateCoeffs());
4077 }
4078 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4080 {
4082 std::static_pointer_cast<
4083 SpatialDomains::RobinBoundaryCondition>(
4084 m_bndConditions[i]);
4085
4086 string bcfilename = bcPtr->m_filename;
4087
4088 if (bcfilename != "")
4089 {
4090 locExpList->ExtractCoeffsFromFile(
4091 bcfilename, bcPtr->GetComm(), varName,
4092 locExpList->UpdateCoeffs());
4093 locExpList->BwdTrans(locExpList->GetCoeffs(),
4094 locExpList->UpdatePhys());
4095 }
4096 else
4097 {
4099 std::static_pointer_cast<
4100 SpatialDomains::RobinBoundaryCondition>(
4101 m_bndConditions[i])
4102 ->m_robinFunction;
4103 condition->Evaluate(x0, x1, x2, time,
4104 locExpList->UpdatePhys());
4105 }
4106
4107 locExpList->IProductWRTBase(locExpList->GetPhys(),
4108 locExpList->UpdateCoeffs());
4109 }
4110 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4112 {
4113 continue;
4114 }
4115 else
4116 {
4118 "This type of BC not implemented yet");
4119 }
4120 }
4121 }
4122 }
4123}
NekDouble GetCoeff(int i)
Get the i th value (coefficient) of m_coeffs.
Definition ExpList.h:2091
std::shared_ptr< Equation > EquationSharedPtr
Definition Equation.h:131
static const NekDouble kNekUnsetDouble
std::shared_ptr< DirichletBoundaryCondition > DirichletBCShPtr
Definition Conditions.h:252
std::shared_ptr< NeumannBoundaryCondition > NeumannBCShPtr
Definition Conditions.h:253
std::shared_ptr< RobinBoundaryCondition > RobinBCShPtr
Definition Conditions.h:254
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition Vmath.hpp:72
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition Vmath.hpp:54

References Nektar::MultiRegions::e1D, Nektar::SpatialDomains::eDirichlet, Nektar::ErrorUtil::efatal, Nektar::SpatialDomains::eNeumann, Nektar::SpatialDomains::eNotDefined, Nektar::SpatialDomains::ePeriodic, Nektar::SpatialDomains::eRobin, Vmath::Fill(), Nektar::MultiRegions::ExpList::GetCoeff(), Nektar::NekConstants::kNekUnsetDouble, m_bndCondBndWeight, m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::ExpList::m_expType, Nektar::SpatialDomains::NeumannBoundaryCondition::m_filename, Nektar::SpatialDomains::RobinBoundaryCondition::m_filename, NEKERROR, and Vmath::Vmul().

◆ v_ExtractTracePhys() [1/2]

void Nektar::MultiRegions::DisContField::v_ExtractTracePhys ( Array< OneD, NekDouble > &  outarray)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3474 of file DisContField.cpp.

3475{
3476 ASSERTL1(m_physState == true, "local physical space is not true ");
3477 v_ExtractTracePhys(m_phys, outarray);
3478}
void v_ExtractTracePhys(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool gridVelocity=false) override
This method extracts the trace (verts in 1D) from the field inarray and puts the values in outarray.
bool m_physState
The state of the array m_phys.
Definition ExpList.h:1153
Array< OneD, NekDouble > m_phys
The global expansion evaluated at the quadrature points.
Definition ExpList.h:1145

References ASSERTL1, Nektar::MultiRegions::ExpList::m_phys, Nektar::MultiRegions::ExpList::m_physState, and v_ExtractTracePhys().

◆ v_ExtractTracePhys() [2/2]

void Nektar::MultiRegions::DisContField::v_ExtractTracePhys ( const Array< OneD, const NekDouble > &  inarray,
Array< OneD, NekDouble > &  outarray,
bool  gridVelocity = false 
)
overrideprotectedvirtual

This method extracts the trace (verts in 1D) from the field inarray and puts the values in outarray.

It assumes the field is C0 continuous so that it can overwrite the edge data when visited by the two adjacent elements.

Parameters
inarrayAn array containing the 1D data from which we wish to extract the edge data.
outarrayThe resulting edge information.
gridVelocityAvoid performing parallel exchanges of the grid velocity

This will not work for non-boundary expansions

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3495 of file DisContField.cpp.

3498{
3499 LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0);
3500 if ((basis->GetBasisType() != LibUtilities::eGauss_Lagrange))
3501 {
3502 Vmath::Zero(outarray.size(), outarray, 1);
3503 Array<OneD, NekDouble> tracevals(
3504 m_locTraceToTraceMap->GetNFwdLocTracePts());
3505 m_locTraceToTraceMap->FwdLocTracesFromField(inarray, tracevals);
3506 m_locTraceToTraceMap->InterpLocTracesToTrace(0, tracevals, outarray);
3507 if (!gridVelocity)
3508 {
3509 m_traceMap->GetAssemblyCommDG()->PerformExchange(outarray,
3510 outarray);
3511 }
3512 }
3513 else
3514 {
3515 // Loop over elemente and collect forward expansion
3516 int nexp = GetExpSize();
3517 int n, p, offset, phys_offset;
3518 Array<OneD, NekDouble> t_tmp;
3519 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>>
3520 &elmtToTrace = m_traceMap->GetElmtToTrace();
3521 ASSERTL1(outarray.size() >= m_trace->GetNpoints(),
3522 "input array is of insufficient length");
3523 for (n = 0; n < nexp; ++n)
3524 {
3525 phys_offset = GetPhys_Offset(n);
3526 for (p = 0; p < (*m_exp)[n]->GetNtraces(); ++p)
3527 {
3528 offset =
3529 m_trace->GetPhys_Offset(elmtToTrace[n][p]->GetElmtId());
3530 (*m_exp)[n]->GetTracePhysVals(p, elmtToTrace[n][p],
3531 inarray + phys_offset,
3532 t_tmp = outarray + offset);
3533 }
3534 }
3535 }
3536}
int GetPhys_Offset(int n) const
Get the start offset position for a local contiguous list of quadrature points in a full array corres...
Definition ExpList.h:2166
void Zero(int n, T *x, const int incx)
Zero vector.
Definition Vmath.hpp:273

References ASSERTL1, Nektar::LibUtilities::eGauss_Lagrange, Nektar::MultiRegions::ExpList::GetExpSize(), Nektar::MultiRegions::ExpList::GetPhys_Offset(), m_locTraceToTraceMap, m_trace, m_traceMap, and Vmath::Zero().

Referenced by v_ExtractTracePhys().

◆ v_FillBwdWithBoundCond()

void Nektar::MultiRegions::DisContField::v_FillBwdWithBoundCond ( const Array< OneD, NekDouble > &  Fwd,
Array< OneD, NekDouble > &  Bwd,
bool  PutFwdInBwdOnBCs 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3318 of file DisContField.cpp.

3321{
3323 PutFwdInBwdOnBCs);
3324}

References FillBwdWithBoundCond(), m_bndCondExpansions, and m_bndConditions.

Referenced by v_GetFwdBwdTracePhys().

◆ v_FillBwdWithBwdWeight()

void Nektar::MultiRegions::DisContField::v_FillBwdWithBwdWeight ( Array< OneD, NekDouble > &  weightave,
Array< OneD, NekDouble > &  weightjmp 
)
overrideprotectedvirtual

Fill the weight with m_bndCondBndWeight.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4128 of file DisContField.cpp.

4130{
4131 int cnt;
4132 int npts;
4133 int e = 0;
4134
4135 // Fill boundary conditions into missing elements
4136 int id2 = 0;
4137
4138 for (int n = cnt = 0; n < m_bndCondExpansions.size(); ++n)
4139 {
4140
4141 if (m_bndConditions[n]->GetBoundaryConditionType() ==
4143 {
4144 for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e)
4145 {
4146 npts = m_bndCondExpansions[n]->GetExp(e)->GetTotPoints();
4147 id2 = m_trace->GetPhys_Offset(
4148 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
4149 Vmath::Fill(npts, m_bndCondBndWeight[n], &weightave[id2], 1);
4150 Vmath::Fill(npts, 0.0, &weightjmp[id2], 1);
4151 }
4152
4153 cnt += e;
4154 }
4155 else if (m_bndConditions[n]->GetBoundaryConditionType() ==
4157 m_bndConditions[n]->GetBoundaryConditionType() ==
4159 {
4160 for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e)
4161 {
4162 npts = m_bndCondExpansions[n]->GetExp(e)->GetTotPoints();
4163 id2 = m_trace->GetPhys_Offset(
4164 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
4165 Vmath::Fill(npts, m_bndCondBndWeight[n], &weightave[id2], 1);
4166 Vmath::Fill(npts, 0.0, &weightjmp[id2], 1);
4167 }
4168
4169 cnt += e;
4170 }
4171 else if (m_bndConditions[n]->GetBoundaryConditionType() !=
4173 {
4175 "Method not set up for this boundary condition.");
4176 }
4177 }
4178}

References Nektar::SpatialDomains::eDirichlet, Nektar::ErrorUtil::efatal, Nektar::SpatialDomains::eNeumann, Nektar::SpatialDomains::ePeriodic, Nektar::SpatialDomains::eRobin, Vmath::Fill(), m_bndCondBndWeight, m_bndCondExpansions, m_bndConditions, m_trace, m_traceMap, and NEKERROR.

◆ v_GetBndCondBwdWeight()

const Array< OneD, const NekDouble > & Nektar::MultiRegions::DisContField::v_GetBndCondBwdWeight ( )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3437 of file DisContField.cpp.

3438{
3439 return m_bndCondBndWeight;
3440}

References m_bndCondBndWeight.

◆ v_GetBndCondExpansions()

const Array< OneD, const MultiRegions::ExpListSharedPtr > & Nektar::MultiRegions::DisContField::v_GetBndCondExpansions ( void  )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3023 of file DisContField.cpp.

3025{
3026 return m_bndCondExpansions;
3027}

References m_bndCondExpansions.

◆ v_GetBndConditions()

const Array< OneD, const SpatialDomains::BoundaryConditionShPtr > & Nektar::MultiRegions::DisContField::v_GetBndConditions ( )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3029 of file DisContField.cpp.

3031{
3032 return m_bndConditions;
3033}

References m_bndConditions.

◆ v_GetBndElmtExpansion()

void Nektar::MultiRegions::DisContField::v_GetBndElmtExpansion ( int  i,
std::shared_ptr< ExpList > &  result,
const bool  DeclareCoeffPhysArrays 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4347 of file DisContField.cpp.

4350{
4351 int n, cnt;
4352 std::vector<unsigned int> eIDs;
4353
4354 Array<OneD, int> ElmtID, TraceID;
4355 GetBoundaryToElmtMap(ElmtID, TraceID);
4356
4357 // Skip other boundary regions
4358 for (cnt = n = 0; n < i; ++n)
4359 {
4360 cnt += m_bndCondExpansions[n]->GetExpSize();
4361 }
4362
4363 // Populate eIDs with information from BoundaryToElmtMap
4364 for (n = 0; n < m_bndCondExpansions[i]->GetExpSize(); ++n)
4365 {
4366 eIDs.push_back(ElmtID[cnt + n]);
4367 }
4368
4369 // Create expansion list
4371 *this, eIDs, DeclareCoeffPhysArrays, Collections::eNoCollection);
4372 // Copy phys and coeffs to new explist
4373 if (DeclareCoeffPhysArrays)
4374 {
4375 int nq;
4376 int offsetOld, offsetNew;
4377 Array<OneD, NekDouble> tmp1, tmp2;
4378 for (n = 0; n < result->GetExpSize(); ++n)
4379 {
4380 nq = GetExp(ElmtID[cnt + n])->GetTotPoints();
4381 offsetOld = GetPhys_Offset(ElmtID[cnt + n]);
4382 offsetNew = result->GetPhys_Offset(n);
4383 Vmath::Vcopy(nq, tmp1 = GetPhys() + offsetOld, 1,
4384 tmp2 = result->UpdatePhys() + offsetNew, 1);
4385 nq = GetExp(ElmtID[cnt + n])->GetNcoeffs();
4386 offsetOld = GetCoeff_Offset(ElmtID[cnt + n]);
4387 offsetNew = result->GetCoeff_Offset(n);
4388 Vmath::Vcopy(nq, tmp1 = GetCoeffs() + offsetOld, 1,
4389 tmp2 = result->UpdateCoeffs() + offsetNew, 1);
4390 }
4391 }
4392}
const Array< OneD, const NekDouble > & GetCoeffs() const
This function returns (a reference to) the array (implemented as m_coeffs) containing all local expa...
Definition ExpList.h:2017
const std::shared_ptr< LocalRegions::ExpansionVector > GetExp() const
This function returns the vector of elements in the expansion.
Definition ExpList.h:2151

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::Collections::eNoCollection, Nektar::MultiRegions::ExpList::GetBoundaryToElmtMap(), Nektar::MultiRegions::ExpList::GetCoeff_Offset(), Nektar::MultiRegions::ExpList::GetCoeffs(), Nektar::MultiRegions::ExpList::GetExp(), Nektar::MultiRegions::ExpList::GetPhys(), Nektar::MultiRegions::ExpList::GetPhys_Offset(), m_bndCondExpansions, and Vmath::Vcopy().

◆ v_GetBoundaryToElmtMap()

void Nektar::MultiRegions::DisContField::v_GetBoundaryToElmtMap ( Array< OneD, int > &  ElmtID,
Array< OneD, int > &  TraceID 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4182 of file DisContField.cpp.

4184{
4185
4186 if (m_BCtoElmMap.size() == 0)
4187 {
4188 switch (m_expType)
4189 {
4190 case e1D:
4191 {
4192 map<int, int> VertGID;
4193 int i, n, id;
4194 int bid, cnt, Vid;
4195 int nbcs = 0;
4196 // Determine number of boundary condition expansions.
4197 for (i = 0; i < m_bndConditions.size(); ++i)
4198 {
4199 nbcs += m_bndCondExpansions[i]->GetExpSize();
4200 }
4201
4202 // make sure arrays are of sufficient length
4203 m_BCtoElmMap = Array<OneD, int>(nbcs, -1);
4204 m_BCtoTraceMap = Array<OneD, int>(nbcs);
4205
4206 // setup map of all global ids along boundary
4207 cnt = 0;
4208 for (n = 0; n < m_bndCondExpansions.size(); ++n)
4209 {
4210 for (i = 0; i < m_bndCondExpansions[n]->GetExpSize(); ++i)
4211 {
4212 Vid = m_bndCondExpansions[n]
4213 ->GetExp(i)
4214 ->GetGeom()
4215 ->GetVid(0);
4216 VertGID[Vid] = cnt++;
4217 }
4218 }
4219
4220 // Loop over elements and find verts that match;
4222 for (cnt = n = 0; n < GetExpSize(); ++n)
4223 {
4224 exp = (*m_exp)[n];
4225 for (i = 0; i < exp->GetNverts(); ++i)
4226 {
4227 id = exp->GetGeom()->GetVid(i);
4228
4229 if (VertGID.count(id) > 0)
4230 {
4231 bid = VertGID.find(id)->second;
4232 ASSERTL1(m_BCtoElmMap[bid] == -1,
4233 "Edge already set");
4234 m_BCtoElmMap[bid] = n;
4235 m_BCtoTraceMap[bid] = i;
4236 cnt++;
4237 }
4238 }
4239 }
4240 ASSERTL1(cnt == nbcs,
4241 "Failed to visit all boundary condtiions");
4242 }
4243 break;
4244 case e2D:
4245 {
4246 map<int, int> globalIdMap;
4247 int i, n;
4248 int cnt;
4249 int nbcs = 0;
4250
4251 // Populate global ID map (takes global geometry
4252 // ID to local expansion list ID).
4253 for (i = 0; i < GetExpSize(); ++i)
4254 {
4255 globalIdMap[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
4256 }
4257
4258 // Determine number of boundary condition expansions.
4259 for (i = 0; i < m_bndConditions.size(); ++i)
4260 {
4261 nbcs += m_bndCondExpansions[i]->GetExpSize();
4262 }
4263
4264 // Initialize arrays
4265 m_BCtoElmMap = Array<OneD, int>(nbcs);
4266 m_BCtoTraceMap = Array<OneD, int>(nbcs);
4267
4269 cnt = 0;
4270 for (n = 0; n < m_bndCondExpansions.size(); ++n)
4271 {
4272 for (i = 0; i < m_bndCondExpansions[n]->GetExpSize();
4273 ++i, ++cnt)
4274 {
4275 exp1d = m_bndCondExpansions[n]
4276 ->GetExp(i)
4277 ->as<LocalRegions::Expansion1D>();
4278
4279 // Use edge to element map from MeshGraph.
4281 m_graph->GetElementsFromEdge(exp1d->GetGeom1D());
4282
4283 m_BCtoElmMap[cnt] =
4284 globalIdMap[(*tmp)[0].first->GetGlobalID()];
4285 m_BCtoTraceMap[cnt] = (*tmp)[0].second;
4286 }
4287 }
4288 }
4289 break;
4290 case e3D:
4291 {
4292 map<int, int> globalIdMap;
4293 int i, n;
4294 int cnt;
4295 int nbcs = 0;
4296
4297 // Populate global ID map (takes global geometry ID to local
4298 // expansion list ID).
4300 for (i = 0; i < GetExpSize(); ++i)
4301 {
4302 globalIdMap[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
4303 }
4304
4305 // Determine number of boundary condition expansions.
4306 for (i = 0; i < m_bndConditions.size(); ++i)
4307 {
4308 if (m_bndCondExpansions[i])
4309 {
4310 nbcs += m_bndCondExpansions[i]->GetExpSize();
4311 }
4312 }
4313
4314 // Initialize arrays
4315 m_BCtoElmMap = Array<OneD, int>(nbcs);
4316 m_BCtoTraceMap = Array<OneD, int>(nbcs);
4317
4319 for (cnt = n = 0; n < m_bndCondExpansions.size(); ++n)
4320 {
4321 for (i = 0; i < m_bndCondExpansions[n]->GetExpSize();
4322 ++i, ++cnt)
4323 {
4324 exp2d = m_bndCondExpansions[n]
4325 ->GetExp(i)
4326 ->as<LocalRegions::Expansion2D>();
4327
4329 m_graph->GetElementsFromFace(exp2d->GetGeom2D());
4330 m_BCtoElmMap[cnt] =
4331 globalIdMap[tmp->at(0).first->GetGlobalID()];
4332 m_BCtoTraceMap[cnt] = tmp->at(0).second;
4333 }
4334 }
4335 }
4336 break;
4337 default:
4338 ASSERTL1(false, "Not setup for this expansion");
4339 break;
4340 }
4341 }
4342
4343 ElmtID = m_BCtoElmMap;
4344 TraceID = m_BCtoTraceMap;
4345}
std::shared_ptr< Expansion2D > Expansion2DSharedPtr
Definition Expansion1D.h:46
std::shared_ptr< Expansion1D > Expansion1DSharedPtr
Definition Expansion1D.h:50
std::shared_ptr< Expansion3D > Expansion3DSharedPtr
Definition Expansion2D.h:47

References ASSERTL1, Nektar::MultiRegions::e1D, Nektar::MultiRegions::e2D, Nektar::MultiRegions::e3D, Nektar::MultiRegions::ExpList::GetExpSize(), m_BCtoElmMap, m_BCtoTraceMap, m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::ExpList::m_expType, and Nektar::MultiRegions::ExpList::m_graph.

◆ v_GetFwdBwdTracePhys() [1/2]

void Nektar::MultiRegions::DisContField::v_GetFwdBwdTracePhys ( Array< OneD, NekDouble > &  Fwd,
Array< OneD, NekDouble > &  Bwd 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3168 of file DisContField.cpp.

3170{
3171 v_GetFwdBwdTracePhys(m_phys, Fwd, Bwd);
3172}
void v_GetFwdBwdTracePhys(Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd) override

References Nektar::MultiRegions::ExpList::m_phys, and v_GetFwdBwdTracePhys().

Referenced by v_GetFwdBwdTracePhys().

◆ v_GetFwdBwdTracePhys() [2/2]

void Nektar::MultiRegions::DisContField::v_GetFwdBwdTracePhys ( const Array< OneD, const NekDouble > &  field,
Array< OneD, NekDouble > &  Fwd,
Array< OneD, NekDouble > &  Bwd,
bool  FillBnd = true,
bool  PutFwdInBwdOnBCs = false,
bool  DoExchange = true 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3244 of file DisContField.cpp.

3249{
3250 // Is this zeroing necessary?
3251 // Zero forward/backward vectors.
3252 Vmath::Zero(Fwd.size(), Fwd, 1);
3253 Vmath::Zero(Bwd.size(), Bwd, 1);
3254
3255 // Basis definition on each element
3256 LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0);
3257 if ((basis->GetBasisType() != LibUtilities::eGauss_Lagrange))
3258 {
3259 // blocked routine
3260 Array<OneD, NekDouble> tracevals(
3261 m_locTraceToTraceMap->GetNLocTracePts());
3262
3263 m_locTraceToTraceMap->LocTracesFromField(field, tracevals);
3264 m_locTraceToTraceMap->InterpLocTracesToTrace(0, tracevals, Fwd);
3265
3266 Array<OneD, NekDouble> invals =
3267 tracevals + m_locTraceToTraceMap->GetNFwdLocTracePts();
3268 m_locTraceToTraceMap->InterpLocTracesToTrace(1, invals, Bwd);
3269 }
3270 else
3271 {
3272 // Loop over elements and collect forward expansion
3273 auto nexp = GetExpSize();
3274 Array<OneD, NekDouble> e_tmp;
3276
3277 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>>
3278 &elmtToTrace = m_traceMap->GetElmtToTrace();
3279
3280 for (int n = 0, cnt = 0; n < nexp; ++n)
3281 {
3282 exp = (*m_exp)[n];
3283 auto phys_offset = GetPhys_Offset(n);
3284
3285 for (int e = 0; e < exp->GetNtraces(); ++e, ++cnt)
3286 {
3287 auto offset =
3288 m_trace->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId());
3289
3290 e_tmp =
3291 (m_leftAdjacentTraces[cnt]) ? Fwd + offset : Bwd + offset;
3292
3293 exp->GetTracePhysVals(e, elmtToTrace[n][e], field + phys_offset,
3294 e_tmp);
3295 }
3296 }
3297 }
3298
3300
3301 if (FillBnd)
3302 {
3303 v_FillBwdWithBoundCond(Fwd, Bwd, PutFwdInBwdOnBCs);
3304 }
3305
3306 if (DoExchange)
3307 {
3308 // Do parallel exchange for forwards/backwards spaces.
3309 m_traceMap->GetAssemblyCommDG()->PerformExchange(Fwd, Bwd);
3310
3311 // Do exchange of interface traces (local and parallel)
3312 // We may have to split this out into separate local and
3313 // parallel for IP method???
3314 m_interfaceMap->ExchangeTrace(Fwd, Bwd);
3315 }
3316}
void v_FillBwdWithBoundCond(const Array< OneD, NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, bool PutFwdInBwdOnBCs) override

References Nektar::LibUtilities::eGauss_Lagrange, Nektar::MultiRegions::ExpList::GetExpSize(), Nektar::MultiRegions::ExpList::GetPhys_Offset(), m_interfaceMap, m_leftAdjacentTraces, m_locTraceToTraceMap, m_trace, m_traceMap, v_FillBwdWithBoundCond(), v_PeriodicBwdCopy(), and Vmath::Zero().

◆ v_GetInterfaceMap()

InterfaceMapDGSharedPtr & Nektar::MultiRegions::DisContField::v_GetInterfaceMap ( void  )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3004 of file DisContField.cpp.

3005{
3006 return m_interfaceMap;
3007}

References m_interfaceMap.

◆ v_GetLeftAdjacentTraces()

std::vector< bool > & Nektar::MultiRegions::DisContField::v_GetLeftAdjacentTraces ( void  )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3018 of file DisContField.cpp.

3019{
3020 return m_leftAdjacentTraces;
3021}

References m_leftAdjacentTraces.

◆ v_GetLocTraceFromTracePts()

void Nektar::MultiRegions::DisContField::v_GetLocTraceFromTracePts ( const Array< OneD, const NekDouble > &  Fwd,
const Array< OneD, const NekDouble > &  Bwd,
Array< OneD, NekDouble > &  locTraceFwd,
Array< OneD, NekDouble > &  locTraceBwd 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4752 of file DisContField.cpp.

4756{
4757 if (locTraceFwd != NullNekDouble1DArray)
4758 {
4759 m_locTraceToTraceMap->InterpLocTracesToTraceTranspose(0, Fwd,
4760 locTraceFwd);
4761 }
4762
4763 if (locTraceBwd != NullNekDouble1DArray)
4764 {
4765 m_locTraceToTraceMap->InterpLocTracesToTraceTranspose(1, Bwd,
4766 locTraceBwd);
4767 }
4768}
static Array< OneD, NekDouble > NullNekDouble1DArray

References m_locTraceToTraceMap, and Nektar::NullNekDouble1DArray.

◆ v_GetLocTraceToTraceMap()

const LocTraceToTraceMapSharedPtr & Nektar::MultiRegions::DisContField::v_GetLocTraceToTraceMap ( void  ) const
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3009 of file DisContField.cpp.

3011{
3012 return m_locTraceToTraceMap;
3013}

References m_locTraceToTraceMap.

◆ v_GetPeriodicEntities()

void Nektar::MultiRegions::DisContField::v_GetPeriodicEntities ( PeriodicMap periodicVerts,
PeriodicMap periodicEdges,
PeriodicMap periodicFaces 
)
overrideprotectedvirtual

Obtain a copy of the periodic edges and vertices for this field.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3178 of file DisContField.cpp.

3181{
3182 periodicVerts = m_periodicVerts;
3183 periodicEdges = m_periodicEdges;
3184 periodicFaces = m_periodicFaces;
3185}

References m_periodicEdges, m_periodicFaces, and m_periodicVerts.

◆ v_GetRobinBCInfo()

map< int, RobinBCInfoSharedPtr > Nektar::MultiRegions::DisContField::v_GetRobinBCInfo ( void  )
overrideprotectedvirtual

Search through the edge expansions and identify which ones have Robin/Mixed type boundary conditions. If find a Robin boundary then store the edge id of the boundary condition and the array of points of the physical space boundary condition which are hold the boundary condition primitive variable coefficient at the quatrature points

Returns
std map containing the robin boundary condition info using a key of the element id

There is a next member to allow for more than one Robin boundary condition per element

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4422 of file DisContField.cpp.

4423{
4424 int i, cnt;
4425 map<int, RobinBCInfoSharedPtr> returnval;
4426 Array<OneD, int> ElmtID, TraceID;
4427 GetBoundaryToElmtMap(ElmtID, TraceID);
4428
4429 for (cnt = i = 0; i < m_bndCondExpansions.size(); ++i)
4430 {
4432
4433 if (m_bndConditions[i]->GetBoundaryConditionType() ==
4435 {
4436 int e, elmtid;
4437 Array<OneD, NekDouble> Array_tmp;
4438
4439 locExpList = m_bndCondExpansions[i];
4440
4441 int npoints = locExpList->GetNpoints();
4442 Array<OneD, NekDouble> x0(npoints, 0.0);
4443 Array<OneD, NekDouble> x1(npoints, 0.0);
4444 Array<OneD, NekDouble> x2(npoints, 0.0);
4445 Array<OneD, NekDouble> coeffphys(npoints);
4446
4447 locExpList->GetCoords(x0, x1, x2);
4448
4450 std::static_pointer_cast<
4451 SpatialDomains::RobinBoundaryCondition>(m_bndConditions[i])
4452 ->m_robinPrimitiveCoeff;
4453
4454 // evalaute coefficient
4455 coeffeqn->Evaluate(x0, x1, x2, 0.0, coeffphys);
4456
4457 for (e = 0; e < locExpList->GetExpSize(); ++e)
4458 {
4459 RobinBCInfoSharedPtr rInfo =
4461 TraceID[cnt + e],
4462 Array_tmp = coeffphys + locExpList->GetPhys_Offset(e));
4463
4464 elmtid = ElmtID[cnt + e];
4465 // make link list if necessary
4466 if (returnval.count(elmtid) != 0)
4467 {
4468 rInfo->next = returnval.find(elmtid)->second;
4469 }
4470 returnval[elmtid] = rInfo;
4471 }
4472 }
4473 cnt += m_bndCondExpansions[i]->GetExpSize();
4474 }
4475
4476 return returnval;
4477}
std::shared_ptr< RobinBCInfo > RobinBCInfoSharedPtr

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), Nektar::SpatialDomains::eRobin, Nektar::MultiRegions::ExpList::GetBoundaryToElmtMap(), m_bndCondExpansions, and m_bndConditions.

◆ v_GetTrace()

ExpListSharedPtr & Nektar::MultiRegions::DisContField::v_GetTrace ( )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 2989 of file DisContField.cpp.

2990{
2992 {
2993 SetUpDG();
2994 }
2995
2996 return m_trace;
2997}

References m_trace, Nektar::MultiRegions::NullExpListSharedPtr, and SetUpDG().

◆ v_GetTraceMap()

AssemblyMapDGSharedPtr & Nektar::MultiRegions::DisContField::v_GetTraceMap ( void  )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 2999 of file DisContField.cpp.

3000{
3001 return m_traceMap;
3002}

References m_traceMap.

◆ v_HelmSolve()

GlobalLinSysKey Nektar::MultiRegions::DisContField::v_HelmSolve ( const Array< OneD, const NekDouble > &  inarray,
Array< OneD, NekDouble > &  outarray,
const StdRegions::ConstFactorMap factors,
const StdRegions::VarCoeffMap varcoeff,
const MultiRegions::VarFactorsMap varfactors,
const Array< OneD, const NekDouble > &  dirForcing,
const bool  PhysSpaceForcing 
)
overrideprotectedvirtual

Solve the Helmholtz equation.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3739 of file DisContField.cpp.

3746{
3747 int i, n, cnt, nbndry;
3748 int nexp = GetExpSize();
3749 Array<OneD, NekDouble> f(m_ncoeffs);
3750 DNekVec F(m_ncoeffs, f, eWrapper);
3751 Array<OneD, NekDouble> e_f, e_l;
3752 //----------------------------------
3753 // Setup RHS Inner product if required
3754 //----------------------------------
3755 if (PhysSpaceForcing)
3756 {
3757 IProductWRTBase(inarray, f);
3758 Vmath::Neg(m_ncoeffs, f, 1);
3759 }
3760 else
3761 {
3762 Vmath::Smul(m_ncoeffs, -1.0, inarray, 1, f, 1);
3763 }
3764 //----------------------------------
3765 // Solve continuous Boundary System
3766 //----------------------------------
3767 int GloBndDofs = m_traceMap->GetNumGlobalBndCoeffs();
3768 int NumDirBCs = m_traceMap->GetNumLocalDirBndCoeffs();
3769 int e_ncoeffs;
3770 GlobalMatrixKey HDGLamToUKey(StdRegions::eHybridDGLamToU,
3771 NullAssemblyMapSharedPtr, factors, varcoeff);
3772 const DNekScalBlkMatSharedPtr &HDGLamToU = GetBlockMatrix(HDGLamToUKey);
3773 // Retrieve number of local trace space coefficients N_{\lambda},
3774 // and set up local elemental trace solution \lambda^e.
3775 int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs();
3776 Array<OneD, NekDouble> bndrhs(LocBndCoeffs, 0.0);
3777 Array<OneD, NekDouble> loclambda(LocBndCoeffs, 0.0);
3778 DNekVec LocLambda(LocBndCoeffs, loclambda, eWrapper);
3779 //----------------------------------
3780 // Evaluate Trace Forcing
3781 // Kirby et al, 2010, P23, Step 5.
3782 //----------------------------------
3783 // Determing <u_lam,f> terms using HDGLamToU matrix
3784 for (cnt = n = 0; n < nexp; ++n)
3785 {
3786 nbndry = (*m_exp)[n]->NumDGBndryCoeffs();
3787 e_ncoeffs = (*m_exp)[n]->GetNcoeffs();
3788 e_f = f + m_coeff_offset[n];
3789 e_l = bndrhs + cnt;
3790 // use outarray as tmp space
3791 DNekVec Floc(nbndry, e_l, eWrapper);
3792 DNekVec ElmtFce(e_ncoeffs, e_f, eWrapper);
3793 Floc = Transpose(*(HDGLamToU->GetBlock(n, n))) * ElmtFce;
3794 cnt += nbndry;
3795 }
3796 Array<OneD, const int> bndCondMap =
3797 m_traceMap->GetBndCondCoeffsToLocalTraceMap();
3798 Array<OneD, const NekDouble> Sign = m_traceMap->GetLocalToGlobalBndSign();
3799 // Copy Dirichlet boundary conditions and weak forcing
3800 // into trace space
3801 int locid;
3802 cnt = 0;
3803 for (i = 0; i < m_bndCondExpansions.size(); ++i)
3804 {
3805 const Array<OneD, const NekDouble> bndcoeffs =
3806 m_bndCondExpansions[i]->GetCoeffs();
3807
3808 if (m_bndConditions[i]->GetBoundaryConditionType() ==
3810 {
3811 for (int j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j)
3812 {
3813 locid = bndCondMap[cnt + j];
3814 loclambda[locid] = Sign[locid] * bndcoeffs[j];
3815 }
3816 }
3817 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3819 m_bndConditions[i]->GetBoundaryConditionType() ==
3821 {
3822 // Add weak boundary condition to trace forcing
3823 for (int j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j)
3824 {
3825 locid = bndCondMap[cnt + j];
3826 bndrhs[locid] += Sign[locid] * bndcoeffs[j];
3827 }
3828 }
3829 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3831 {
3832 // skip increment of cnt if ePeriodic
3833 // because bndCondMap does not include ePeriodic
3834 continue;
3835 }
3836 cnt += (m_bndCondExpansions[i])->GetNcoeffs();
3837 }
3838
3839 //----------------------------------
3840 // Solve trace problem: \Lambda = K^{-1} F
3841 // K is the HybridDGHelmBndLam matrix.
3842 //----------------------------------
3843 if (GloBndDofs - NumDirBCs > 0)
3844 {
3845 GlobalLinSysKey key(StdRegions::eHybridDGHelmBndLam, m_traceMap,
3846 factors, varcoeff);
3848 LinSys->Solve(bndrhs, loclambda, m_traceMap);
3849
3850 // For consistency with previous version put global
3851 // solution into m_trace->m_coeffs
3852 m_traceMap->LocalToGlobal(loclambda, m_trace->UpdateCoeffs());
3853 }
3854
3855 //----------------------------------
3856 // Internal element solves
3857 //----------------------------------
3858 GlobalMatrixKey invHDGhelmkey(StdRegions::eInvHybridDGHelmholtz,
3859 NullAssemblyMapSharedPtr, factors, varcoeff);
3860
3861 const DNekScalBlkMatSharedPtr &InvHDGHelm = GetBlockMatrix(invHDGhelmkey);
3862 DNekVec out(m_ncoeffs, outarray, eWrapper);
3863 Vmath::Zero(m_ncoeffs, outarray, 1);
3864
3865 // out = u_f + u_lam = (*InvHDGHelm)*f + (LamtoU)*Lam
3866 out = (*InvHDGHelm) * F + (*HDGLamToU) * LocLambda;
3867
3868 // Return empty GlobalLinSysKey
3869 return NullGlobalLinSysKey;
3870}
GlobalLinSysSharedPtr GetGlobalBndLinSys(const GlobalLinSysKey &mkey)
For a given key, returns the associated global linear system.
void IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function calculates the inner product of a function with respect to all local expansion modes .
Definition ExpList.h:1720
int GetNcoeffs(void) const
Returns the total number of local degrees of freedom .
Definition ExpList.h:1578
const DNekScalBlkMatSharedPtr & GetBlockMatrix(const GlobalMatrixKey &gkey)
static AssemblyMapSharedPtr NullAssemblyMapSharedPtr
Definition AssemblyMap.h:51
static GlobalLinSysKey NullGlobalLinSysKey(StdRegions::eNoMatrixType)
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
NekVector< NekDouble > DNekVec
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition Vmath.hpp:292
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition Vmath.hpp:100

References Nektar::SpatialDomains::eDirichlet, Nektar::StdRegions::eHybridDGHelmBndLam, Nektar::StdRegions::eHybridDGLamToU, Nektar::StdRegions::eInvHybridDGHelmholtz, Nektar::SpatialDomains::eNeumann, Nektar::SpatialDomains::ePeriodic, Nektar::SpatialDomains::eRobin, Nektar::eWrapper, Nektar::MultiRegions::ExpList::GetBlockMatrix(), Nektar::MultiRegions::ExpList::GetExpSize(), GetGlobalBndLinSys(), Nektar::MultiRegions::ExpList::GetNcoeffs(), Nektar::MultiRegions::ExpList::IProductWRTBase(), m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::ExpList::m_coeff_offset, Nektar::MultiRegions::ExpList::m_ncoeffs, m_trace, m_traceMap, Vmath::Neg(), Nektar::MultiRegions::NullAssemblyMapSharedPtr, Nektar::MultiRegions::NullGlobalLinSysKey(), Vmath::Smul(), Nektar::Transpose(), and Vmath::Zero().

◆ v_PeriodicBwdCopy()

void Nektar::MultiRegions::DisContField::v_PeriodicBwdCopy ( const Array< OneD, const NekDouble > &  Fwd,
Array< OneD, NekDouble > &  Bwd 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3046 of file DisContField.cpp.

3048{
3049 for (int n = 0; n < m_periodicFwdCopy.size(); ++n)
3050 {
3051 Bwd[m_periodicBwdCopy[n]] = Fwd[m_periodicFwdCopy[n]];
3052 }
3053}

References m_periodicBwdCopy, and m_periodicFwdCopy.

Referenced by GetFwdBwdTracePhys(), and v_GetFwdBwdTracePhys().

◆ v_PeriodicBwdRot()

void Nektar::MultiRegions::DisContField::v_PeriodicBwdRot ( Array< OneD, Array< OneD, NekDouble > > &  Bwd)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3055 of file DisContField.cpp.

3056{
3057 int cnt = 0;
3058 for (int n = 0; n < m_bndConditions.size(); ++n)
3059 {
3060 // check to see if boundary is rotationally aligned
3061 if (boost::icontains(m_bndConditions[n]->GetUserDefined(), "Rotated"))
3062 {
3063 vector<string> tmpstr;
3064
3065 boost::split(tmpstr, m_bndConditions[n]->GetUserDefined(),
3066 boost::is_any_of(":"));
3067
3068 ASSERTL1(tmpstr.size() > 2,
3069 "Expected Rotated user defined string to "
3070 "contain direction and rotation angle "
3071 "and optionally a tolerance, "
3072 "i.e. Rotated:dir:PI/2:1e-6");
3073
3074 ASSERTL1((tmpstr[1] == "x") || (tmpstr[1] == "y") ||
3075 (tmpstr[1] == "z"),
3076 "Rotated Dir is "
3077 "not specified as x,y or z");
3078
3079 RotPeriodicInfo RotInfo;
3080 RotInfo.m_dir = (tmpstr[1] == "x") ? 0 : (tmpstr[1] == "y") ? 1 : 2;
3081
3082 LibUtilities::Interpreter strEval;
3083 int ExprId = strEval.DefineFunction("", tmpstr[2]);
3084 RotInfo.m_angle = strEval.Evaluate(ExprId);
3085
3086 auto ne = m_bndCondExpansions[n]->GetExpSize();
3087
3088 // Loop over each element in the boundary condition and rotate
3089 // velocity
3090 for (int e = 0; e < ne; ++e)
3091 {
3092 auto id2 = m_trace->GetPhys_Offset(
3093 m_traceMap->GetPerBndCondIDToGlobalTraceID(e + cnt));
3094 int npts = m_bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3095 Rotate(Bwd, RotInfo.m_dir, -RotInfo.m_angle, id2, npts);
3096 }
3097 cnt += ne;
3098 }
3099 }
3100}
void Rotate(Array< OneD, Array< OneD, NekDouble > > &Bwd, const int dir, const NekDouble angle, const int offset, const int npts)
Rotate the slice [offset, offset + npts) of the 3D vector field in Bwd around the axis 'dir' by 'angl...

References ASSERTL1, Nektar::LibUtilities::Interpreter::DefineFunction(), Nektar::LibUtilities::Interpreter::Evaluate(), Nektar::MultiRegions::RotPeriodicInfo::m_angle, m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::RotPeriodicInfo::m_dir, m_trace, m_traceMap, and Rotate().

◆ v_PeriodicDeriveBwdRot()

void Nektar::MultiRegions::DisContField::v_PeriodicDeriveBwdRot ( TensorOfArray3D< NekDouble > &  Bwd)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3102 of file DisContField.cpp.

3103{
3104 int cnt = 0;
3105 for (int n = 0; n < m_bndConditions.size(); ++n)
3106 {
3107 // check to see if boundary is rotationally aligned
3108 if (boost::icontains(m_bndConditions[n]->GetUserDefined(), "Rotated"))
3109 {
3110 vector<string> tmpstr;
3111
3112 boost::split(tmpstr, m_bndConditions[n]->GetUserDefined(),
3113 boost::is_any_of(":"));
3114
3115 ASSERTL1(tmpstr.size() > 2,
3116 "Expected Rotated user defined string to "
3117 "contain direction and rotation angle "
3118 "and optionally a tolerance, "
3119 "i.e. Rotated:dir:PI/2:1e-6");
3120
3121 ASSERTL1((tmpstr[1] == "x") || (tmpstr[1] == "y") ||
3122 (tmpstr[1] == "z"),
3123 "Rotated Dir is "
3124 "not specified as x,y or z");
3125
3126 RotPeriodicInfo RotInfo;
3127 RotInfo.m_dir = (tmpstr[1] == "x") ? 0 : (tmpstr[1] == "y") ? 1 : 2;
3128
3129 LibUtilities::Interpreter strEval;
3130 int ExprId = strEval.DefineFunction("", tmpstr[2]);
3131 RotInfo.m_angle = strEval.Evaluate(ExprId);
3132
3133 auto ne = m_bndCondExpansions[n]->GetExpSize();
3134 // Loop over each element in the boundary condition and rotate
3135 // velocity
3136 for (int e = 0; e < ne; ++e)
3137 {
3138 auto id2 = m_trace->GetPhys_Offset(
3139 m_traceMap->GetPerBndCondIDToGlobalTraceID(e + cnt));
3140 int npts = m_bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3141 DeriveRotate(Bwd, RotInfo.m_dir, -RotInfo.m_angle, id2, npts);
3142 }
3143 cnt += ne;
3144 }
3145 }
3146}
void DeriveRotate(TensorOfArray3D< NekDouble > &Bwd, const int dir, const NekDouble angle, const int offset, const int npts)
Rotate the slice [offset, offset + npts) of the 3D vector field in Bwd around the axis 'dir' by 'angl...

References ASSERTL1, Nektar::LibUtilities::Interpreter::DefineFunction(), DeriveRotate(), Nektar::LibUtilities::Interpreter::Evaluate(), Nektar::MultiRegions::RotPeriodicInfo::m_angle, m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::RotPeriodicInfo::m_dir, m_trace, and m_traceMap.

◆ v_Reset()

void Nektar::MultiRegions::DisContField::v_Reset ( )
overrideprotectedvirtual

Reset this field, so that geometry information can be updated.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4397 of file DisContField.cpp.

4398{
4400
4401 // Reset boundary condition expansions.
4402 for (int n = 0; n < m_bndCondExpansions.size(); ++n)
4403 {
4404 m_bndCondExpansions[n]->Reset();
4405 }
4406}

References m_bndCondExpansions, and Nektar::MultiRegions::ExpList::v_Reset().

◆ v_RotLocalBwdDeriveTrace()

void Nektar::MultiRegions::DisContField::v_RotLocalBwdDeriveTrace ( TensorOfArray3D< NekDouble > &  Bwd)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3158 of file DisContField.cpp.

3159{
3160 int nDim = GetCoordim(0);
3161 for (auto &interfaceTrace : m_interfaceMap->GetLocalInterface())
3162 {
3163
3164 interfaceTrace->RotLocalBwdDeriveTrace(Bwd, nDim);
3165 }
3166}
int GetCoordim(int eid)
This function returns the dimension of the coordinates of the element eid.
Definition ExpList.h:1976

References Nektar::MultiRegions::ExpList::GetCoordim(), and m_interfaceMap.

◆ v_RotLocalBwdTrace()

void Nektar::MultiRegions::DisContField::v_RotLocalBwdTrace ( Array< OneD, Array< OneD, NekDouble > > &  Bwd)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3148 of file DisContField.cpp.

3149{
3150 int nDim = GetCoordim(0);
3151 for (auto &interfaceTrace : m_interfaceMap->GetLocalInterface())
3152 {
3153
3154 interfaceTrace->RotLocalBwdTrace(Bwd, nDim);
3155 }
3156}

References Nektar::MultiRegions::ExpList::GetCoordim(), and m_interfaceMap.

◆ v_SetBndCondBwdWeight()

void Nektar::MultiRegions::DisContField::v_SetBndCondBwdWeight ( const int  index,
const NekDouble  value 
)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3442 of file DisContField.cpp.

3443{
3444 m_bndCondBndWeight[index] = value;
3445}

References m_bndCondBndWeight.

◆ v_UpdateBndCondExpansion()

MultiRegions::ExpListSharedPtr & Nektar::MultiRegions::DisContField::v_UpdateBndCondExpansion ( int  i)
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3035 of file DisContField.cpp.

3036{
3037 return m_bndCondExpansions[i];
3038}

References m_bndCondExpansions.

◆ v_UpdateBndConditions()

Array< OneD, SpatialDomains::BoundaryConditionShPtr > & Nektar::MultiRegions::DisContField::v_UpdateBndConditions ( )
overrideprotectedvirtual

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3040 of file DisContField.cpp.

3042{
3043 return m_bndConditions;
3044}

References m_bndConditions.

Member Data Documentation

◆ m_BCtoElmMap

Array<OneD, int> Nektar::MultiRegions::DisContField::m_BCtoElmMap

Definition at line 58 of file DisContField.h.

Referenced by v_GetBoundaryToElmtMap().

◆ m_BCtoTraceMap

Array<OneD, int> Nektar::MultiRegions::DisContField::m_BCtoTraceMap

Definition at line 59 of file DisContField.h.

Referenced by v_GetBoundaryToElmtMap().

◆ m_bndCondBndWeight

Array<OneD, NekDouble> Nektar::MultiRegions::DisContField::m_bndCondBndWeight
protected

◆ m_bndCondExpansions

Array<OneD, MultiRegions::ExpListSharedPtr> Nektar::MultiRegions::DisContField::m_bndCondExpansions
protected

An object which contains the discretised boundary conditions.

It is an array of size equal to the number of boundary regions and consists of entries of the type MultiRegions::ExpList. Every entry corresponds to the spectral/hp expansion on a single boundary region. The values of the boundary conditions are stored as the coefficients of the one-dimensional expansion.

Definition at line 157 of file DisContField.h.

Referenced by Nektar::MultiRegions::ContField::ContField(), Nektar::MultiRegions::ContField::ContField(), DisContField(), DisContField(), FillBwdWithBoundCond(), GenerateBoundaryConditionExpansion(), GenerateBoundaryConditionExpansion(), Nektar::MultiRegions::ContField::LaplaceSolve(), SameTypeOfBoundaryConditions(), SetUpDG(), v_EvaluateBoundaryConditions(), Nektar::MultiRegions::ContField::v_FillBndCondFromField(), Nektar::MultiRegions::ContField::v_FillBndCondFromField(), v_FillBwdWithBoundCond(), v_FillBwdWithBwdWeight(), Nektar::MultiRegions::ContField::v_GetBndCondExpansions(), v_GetBndCondExpansions(), v_GetBndElmtExpansion(), v_GetBoundaryToElmtMap(), v_GetRobinBCInfo(), Nektar::MultiRegions::ContField::v_HelmSolve(), v_HelmSolve(), Nektar::MultiRegions::ContField::v_ImposeDirichletConditions(), Nektar::MultiRegions::ContField::v_ImposeNeumannConditions(), Nektar::MultiRegions::ContField::v_ImposeRobinConditions(), Nektar::MultiRegions::ContField::v_LinearAdvectionDiffusionReactionSolve(), Nektar::MultiRegions::ContField::v_LinearAdvectionReactionSolve(), v_PeriodicBwdRot(), v_PeriodicDeriveBwdRot(), v_Reset(), and v_UpdateBndCondExpansion().

◆ m_bndConditions

Array<OneD, SpatialDomains::BoundaryConditionShPtr> Nektar::MultiRegions::DisContField::m_bndConditions
protected

◆ m_boundaryTraces

std::set<int> Nektar::MultiRegions::DisContField::m_boundaryTraces
protected

A set storing the global IDs of any boundary Verts.

Definition at line 179 of file DisContField.h.

Referenced by DisContField(), IsLeftAdjacentTrace(), and SetUpDG().

◆ m_globalBndMat

GlobalLinSysMapShPtr Nektar::MultiRegions::DisContField::m_globalBndMat
protected

Global boundary matrix.

Definition at line 165 of file DisContField.h.

Referenced by DisContField(), GetGlobalBndLinSys(), and SetUpDG().

◆ m_interfaceMap

InterfaceMapDGSharedPtr Nektar::MultiRegions::DisContField::m_interfaceMap
protected

Interfaces mapping for trace space.

Definition at line 162 of file DisContField.h.

Referenced by DisContField(), GetFwdBwdTracePhys(), SetUpDG(), v_GetFwdBwdTracePhys(), v_GetInterfaceMap(), v_RotLocalBwdDeriveTrace(), and v_RotLocalBwdTrace().

◆ m_leftAdjacentTraces

std::vector<bool> Nektar::MultiRegions::DisContField::m_leftAdjacentTraces
protected

◆ m_locElmtTrace

MultiRegions::ExpListSharedPtr Nektar::MultiRegions::DisContField::m_locElmtTrace
protected

Local Elemental trace expansions.

Definition at line 171 of file DisContField.h.

Referenced by DisContField(), DisContField(), GetLocElmtTrace(), and SetUpDG().

◆ m_locTraceToTraceMap

LocTraceToTraceMapSharedPtr Nektar::MultiRegions::DisContField::m_locTraceToTraceMap
protected

◆ m_negatedFluxNormal

std::vector<bool> Nektar::MultiRegions::DisContField::m_negatedFluxNormal
private

Definition at line 365 of file DisContField.h.

Referenced by GetNegatedFluxNormal().

◆ m_periodicBwdCopy

std::vector<int> Nektar::MultiRegions::DisContField::m_periodicBwdCopy
protected

Definition at line 202 of file DisContField.h.

Referenced by DisContField(), SetUpDG(), and v_PeriodicBwdCopy().

◆ m_periodicEdges

PeriodicMap Nektar::MultiRegions::DisContField::m_periodicEdges
protected

◆ m_periodicFaces

PeriodicMap Nektar::MultiRegions::DisContField::m_periodicFaces
protected

◆ m_periodicFwdCopy

std::vector<int> Nektar::MultiRegions::DisContField::m_periodicFwdCopy
protected

A vector indicating degress of freedom which need to be copied from forwards to backwards space in case of a periodic boundary condition.

Definition at line 201 of file DisContField.h.

Referenced by DisContField(), SetUpDG(), and v_PeriodicBwdCopy().

◆ m_periodicVerts

PeriodicMap Nektar::MultiRegions::DisContField::m_periodicVerts
protected

◆ m_trace

ExpListSharedPtr Nektar::MultiRegions::DisContField::m_trace
protected

◆ m_traceMap

AssemblyMapDGSharedPtr Nektar::MultiRegions::DisContField::m_traceMap
protected