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.
 
unsigned GetTraceElmtId (const unsigned elmtid, const unsigned traceid)
 
ExpListSharedPtrGetLocElmtTrace ()
 
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.
 
- 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 StdRegions::VarFactorsMap &varfactors=StdRegions::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 StdRegions::VarFactorsMap &varfactors=StdRegions::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 StdRegions::VarFactorsMap &varfactors=StdRegions::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 AvgAssemble (bool useComm=true)
 Assemble the average global coefficients \(\boldsymbol{\hat{u}}_g\) from the local coefficients \(\boldsymbol{\hat{u}}_l\) .
 
void AvgAssemble (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool useComm=true)
 
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 SetBCsToHomogeneous (void)
 Set boundary conditions to be homogeneous.
 
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)
 
const std::shared_ptr< GJPStabilisationGetGJPData (void)
 
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.
 
void MultiplyByBlockMatrix (const GlobalMatrixKey &gkey, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool Transpose=false)
 
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.
 
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..
 
void v_SetBCsToHomogeneous (void) override
 Set boundary conditions to be homogeneous.
 
GlobalLinSysKey v_HelmSolve (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::ConstFactorMap &factors, const StdRegions::VarCoeffMap &varcoeff, const StdRegions::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)
 
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 StdRegions::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 StdRegions::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_AvgAssemble (bool UseComm)
 
virtual void v_AvgAssemble (const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseComm)
 
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)
 
virtual const std::shared_ptr< GJPStabilisationv_GetGJPData (void)
 

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:1594

◆ 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:2406
std::shared_ptr< LocalRegions::ExpansionVector > m_exp
The list of local expansions.
Definition ExpList.h:1184
void EvaluateBoundaryConditions(const NekDouble time=0.0, const std::string varName="", const NekDouble=NekConstants::kNekUnsetDouble, const NekDouble=NekConstants::kNekUnsetDouble)
Definition ExpList.h:2389
void ApplyGeomInfo()
Apply geometry information to each expansion.
LibUtilities::SessionReaderSharedPtr m_session
Session.
Definition ExpList.h:1124
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 608 of file DisContField.cpp.

616 : ExpList(pSession, domain, graph1D, true, variable, SetToOneSpaceDimension,
617 comm, ImpType)
618{
619 if (variable.compare("DefaultVar") != 0)
620 {
622 GetDomainBCs(domain, Allbcs, variable);
623
624 GenerateBoundaryConditionExpansion(m_graph, *DomBCs, variable, true,
625 ImpType);
626 EvaluateBoundaryConditions(0.0, variable);
628 FindPeriodicTraces(*DomBCs, variable);
629 }
630
631 SetUpDG(variable);
632}
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:1126
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 638 of file DisContField.cpp.

640 : ExpList(In, DeclareCoeffPhysArrays), m_bndConditions(In.m_bndConditions),
641 m_bndCondExpansions(In.m_bndCondExpansions),
642 m_bndCondBndWeight(In.m_bndCondBndWeight),
643 m_interfaceMap(In.m_interfaceMap), m_globalBndMat(In.m_globalBndMat),
644 m_traceMap(In.m_traceMap), m_boundaryTraces(In.m_boundaryTraces),
645 m_periodicVerts(In.m_periodicVerts),
646 m_periodicFwdCopy(In.m_periodicFwdCopy),
647 m_periodicBwdCopy(In.m_periodicBwdCopy),
648 m_leftAdjacentTraces(In.m_leftAdjacentTraces),
649 m_locTraceToTraceMap(In.m_locTraceToTraceMap)
650{
651 if (In.m_trace) // independent trace space
652 {
654 *In.m_trace, DeclareCoeffPhysArrays);
655 }
656
657 if (In.m_locElmtTrace)
658 {
660 *In.m_locElmtTrace, DeclareCoeffPhysArrays);
661 }
662}
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 668 of file DisContField.cpp.

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

794 : ExpList(In)
795{
796}

◆ ~DisContField()

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

Destructor.

Definition at line 801 of file DisContField.cpp.

802{
803}

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 4962 of file DisContField.cpp.

4965{
4966 // Precompute trigonometric values using correct angle input
4967 const NekDouble cosA = cos(angle);
4968 const NekDouble sinA = sin(angle);
4969
4970 // Define rotation matrix R (3x3) using Array<OneD, NekDouble> in
4971 // **column-major order**
4972 Array<OneD, NekDouble> R(9, 0.0);
4973
4974 if (dir == 0) // Rotation around X-axis
4975 {
4976 R[0] = 1.0;
4977 R[3] = 0.0;
4978 R[6] = 0.0;
4979 R[1] = 0.0;
4980 R[4] = cosA;
4981 R[7] = -sinA;
4982 R[2] = 0.0;
4983 R[5] = sinA;
4984 R[8] = cosA;
4985 }
4986 else if (dir == 1) // Rotation around Y-axis
4987 {
4988 R[0] = cosA;
4989 R[3] = 0.0;
4990 R[6] = sinA;
4991 R[1] = 0.0;
4992 R[4] = 1.0;
4993 R[7] = 0.0;
4994 R[2] = -sinA;
4995 R[5] = 0.0;
4996 R[8] = cosA;
4997 }
4998 else if (dir == 2) // Rotation around Z-axis
4999 {
5000 R[0] = cosA;
5001 R[3] = -sinA;
5002 R[6] = 0.0;
5003 R[1] = sinA;
5004 R[4] = cosA;
5005 R[7] = 0.0;
5006 R[2] = 0.0;
5007 R[5] = 0.0;
5008 R[8] = 1.0;
5009 }
5010 else
5011 {
5012 NEKERROR(
5014 "Invalid rotation axis for first-order derivative transformation.");
5015 }
5016
5017 for (int p = offset; p < offset + npts; ++p)
5018 {
5019 // Allocate gradient tensor (3x3) in **column-major order**
5020 Array<OneD, NekDouble> gradU(9, 0.0);
5021
5022 // Load original velocity gradient tensor into **column-major** format
5023 gradU[0] = Bwd[0][1][p]; // ∂u_x/∂x
5024 gradU[3] = Bwd[1][1][p]; // ∂u_x/∂y
5025 gradU[6] = Bwd[2][1][p]; // ∂u_x/∂z
5026
5027 gradU[1] = Bwd[0][2][p]; // ∂u_y/∂x
5028 gradU[4] = Bwd[1][2][p]; // ∂u_y/∂y
5029 gradU[7] = Bwd[2][2][p]; // ∂u_y/∂z
5030
5031 gradU[2] = Bwd[0][3][p]; // ∂u_z/∂x
5032 gradU[5] = Bwd[1][3][p]; // ∂u_z/∂y
5033 gradU[8] = Bwd[2][3][p]; // ∂u_z/∂z
5034
5035 // Allocate intermediate matrix R * gradU in **column-major order**
5036 Array<OneD, NekDouble> R_gradU(9, 0.0);
5037
5038 // Perform matrix multiplication R * gradU using Blas::Dgemm in
5039 // **column-major order**
5040 Blas::Dgemm('N', 'N', 3, 3, 3, 1.0, R.data(), 3, gradU.data(), 3, 0.0,
5041 R_gradU.data(), 3);
5042
5043 // Allocate final rotated gradient (R * gradU) * R^T in **column-major
5044 // order**
5045 Array<OneD, NekDouble> gradU_rotated(9, 0.0);
5046
5047 // Perform matrix multiplication (R * gradU) * R^T using Blas::Dgemm in
5048 // **column-major order**
5049 Blas::Dgemm('N', 'T', 3, 3, 3, 1.0, R_gradU.data(), 3, R.data(), 3, 0.0,
5050 gradU_rotated.data(), 3);
5051
5052 // Store rotated gradients back in Bwd in **column-major order**
5053 Bwd[0][1][p] = gradU_rotated[0]; // ∂u_x'/∂x'
5054 Bwd[1][1][p] = gradU_rotated[3]; // ∂u_x'/∂y'
5055 Bwd[2][1][p] = gradU_rotated[6]; // ∂u_x'/∂z'
5056
5057 Bwd[0][2][p] = gradU_rotated[1]; // ∂u_y'/∂x'
5058 Bwd[1][2][p] = gradU_rotated[4]; // ∂u_y'/∂y'
5059 Bwd[2][2][p] = gradU_rotated[7]; // ∂u_y'/∂z'
5060
5061 Bwd[0][3][p] = gradU_rotated[2]; // ∂u_z'/∂x'
5062 Bwd[1][3][p] = gradU_rotated[5]; // ∂u_z'/∂y'
5063 Bwd[2][3][p] = gradU_rotated[8]; // ∂u_z'/∂z'
5064 }
5065}
#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:324
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 4652 of file DisContField.cpp.

4655{
4656 int i, cnt, e, ncoeff_trace;
4657 Array<OneD, NekDouble> force, out_tmp, qrhs, qrhs1;
4658 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>> &elmtToTrace =
4659 m_traceMap->GetElmtToTrace();
4660
4662
4663 int nq_elmt, nm_elmt;
4664 int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs();
4665 Array<OneD, NekDouble> loc_lambda(LocBndCoeffs), trace_lambda;
4666 Array<OneD, NekDouble> tmp_coeffs;
4667 m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(), loc_lambda);
4668
4669 trace_lambda = loc_lambda;
4670
4671 int dim = (m_expType == e2D) ? 2 : 3;
4672
4673 int num_points[] = {0, 0, 0};
4674 int num_modes[] = {0, 0, 0};
4675
4676 // Calculate Q using standard DG formulation.
4677 for (i = cnt = 0; i < GetExpSize(); ++i)
4678 {
4679 nq_elmt = (*m_exp)[i]->GetTotPoints();
4680 nm_elmt = (*m_exp)[i]->GetNcoeffs();
4681 qrhs = Array<OneD, NekDouble>(nq_elmt);
4682 qrhs1 = Array<OneD, NekDouble>(nq_elmt);
4683 force = Array<OneD, NekDouble>(2 * nm_elmt);
4684 out_tmp = force + nm_elmt;
4686
4687 for (int j = 0; j < dim; ++j)
4688 {
4689 num_points[j] = (*m_exp)[i]->GetBasis(j)->GetNumPoints();
4690 num_modes[j] = (*m_exp)[i]->GetBasis(j)->GetNumModes();
4691 }
4692
4693 // Probably a better way of setting up lambda than this. Note
4694 // cannot use PutCoeffsInToElmts since lambda space is mapped
4695 // during the solve.
4696 int nTraces = (*m_exp)[i]->GetNtraces();
4697 Array<OneD, Array<OneD, NekDouble>> traceCoeffs(nTraces);
4698
4699 for (e = 0; e < (*m_exp)[i]->GetNtraces(); ++e)
4700 {
4701 edgedir = (*m_exp)[i]->GetTraceOrient(e);
4702 ncoeff_trace = elmtToTrace[i][e]->GetNcoeffs();
4703 traceCoeffs[e] = Array<OneD, NekDouble>(ncoeff_trace);
4704 Vmath::Vcopy(ncoeff_trace, trace_lambda, 1, traceCoeffs[e], 1);
4705 if (dim == 2)
4706 {
4707 elmtToTrace[i][e]->SetCoeffsToOrientation(
4708 edgedir, traceCoeffs[e], traceCoeffs[e]);
4709 }
4710 else
4711 {
4712 (*m_exp)[i]
4713 ->as<LocalRegions::Expansion3D>()
4714 ->SetFaceToGeomOrientation(e, traceCoeffs[e]);
4715 }
4716 trace_lambda = trace_lambda + ncoeff_trace;
4717 }
4718
4719 // creating orthogonal expansion (checking if we have quads or
4720 // triangles)
4721 LibUtilities::ShapeType shape = (*m_exp)[i]->DetShapeType();
4722 switch (shape)
4723 {
4725 {
4726 const LibUtilities::PointsKey PkeyQ1(
4728 const LibUtilities::PointsKey PkeyQ2(
4730 LibUtilities::BasisKey BkeyQ1(LibUtilities::eOrtho_A,
4731 num_modes[0], PkeyQ1);
4732 LibUtilities::BasisKey BkeyQ2(LibUtilities::eOrtho_A,
4733 num_modes[1], PkeyQ2);
4734 SpatialDomains::QuadGeom *qGeom =
4735 dynamic_cast<SpatialDomains::QuadGeom *>(
4736 (*m_exp)[i]->GetGeom());
4738 BkeyQ1, BkeyQ2, qGeom);
4739 }
4740 break;
4742 {
4743 const LibUtilities::PointsKey PkeyT1(
4745 const LibUtilities::PointsKey PkeyT2(
4746 num_points[1], LibUtilities::eGaussRadauMAlpha1Beta0);
4747 LibUtilities::BasisKey BkeyT1(LibUtilities::eOrtho_A,
4748 num_modes[0], PkeyT1);
4749 LibUtilities::BasisKey BkeyT2(LibUtilities::eOrtho_B,
4750 num_modes[1], PkeyT2);
4751 SpatialDomains::TriGeom *tGeom =
4752 dynamic_cast<SpatialDomains::TriGeom *>(
4753 (*m_exp)[i]->GetGeom());
4755 BkeyT1, BkeyT2, tGeom);
4756 }
4757 break;
4759 {
4760 const LibUtilities::PointsKey PkeyH1(
4762 const LibUtilities::PointsKey PkeyH2(
4764 const LibUtilities::PointsKey PkeyH3(
4766 LibUtilities::BasisKey BkeyH1(LibUtilities::eOrtho_A,
4767 num_modes[0], PkeyH1);
4768 LibUtilities::BasisKey BkeyH2(LibUtilities::eOrtho_A,
4769 num_modes[1], PkeyH2);
4770 LibUtilities::BasisKey BkeyH3(LibUtilities::eOrtho_A,
4771 num_modes[2], PkeyH3);
4772 SpatialDomains::HexGeom *hGeom =
4773 dynamic_cast<SpatialDomains::HexGeom *>(
4774 (*m_exp)[i]->GetGeom());
4776 BkeyH1, BkeyH2, BkeyH3, hGeom);
4777 }
4778 break;
4780 {
4781 const LibUtilities::PointsKey PkeyT1(
4783 const LibUtilities::PointsKey PkeyT2(
4784 num_points[1], LibUtilities::eGaussRadauMAlpha1Beta0);
4785 const LibUtilities::PointsKey PkeyT3(
4786 num_points[2], LibUtilities::eGaussRadauMAlpha2Beta0);
4787 LibUtilities::BasisKey BkeyT1(LibUtilities::eOrtho_A,
4788 num_modes[0], PkeyT1);
4789 LibUtilities::BasisKey BkeyT2(LibUtilities::eOrtho_B,
4790 num_modes[1], PkeyT2);
4791 LibUtilities::BasisKey BkeyT3(LibUtilities::eOrtho_C,
4792 num_modes[2], PkeyT3);
4793 SpatialDomains::TetGeom *tGeom =
4794 dynamic_cast<SpatialDomains::TetGeom *>(
4795 (*m_exp)[i]->GetGeom());
4797 BkeyT1, BkeyT2, BkeyT3, tGeom);
4798 }
4799 break;
4800 default:
4802 "Wrong shape type, HDG postprocessing is not "
4803 "implemented");
4804 };
4805
4806 // DGDeriv
4807 // (d/dx w, d/dx q_0)
4808 (*m_exp)[i]->DGDeriv(0, tmp_coeffs = coeffs + m_coeff_offset[i],
4809 elmtToTrace[i], traceCoeffs, out_tmp);
4810 (*m_exp)[i]->BwdTrans(out_tmp, qrhs);
4811 ppExp->IProductWRTDerivBase(0, qrhs, force);
4812
4813 // + (d/dy w, d/dy q_1)
4814 (*m_exp)[i]->DGDeriv(1, tmp_coeffs = coeffs + m_coeff_offset[i],
4815 elmtToTrace[i], traceCoeffs, out_tmp);
4816
4817 (*m_exp)[i]->BwdTrans(out_tmp, qrhs);
4818 ppExp->IProductWRTDerivBase(1, qrhs, out_tmp);
4819
4820 Vmath::Vadd(nm_elmt, force, 1, out_tmp, 1, force, 1);
4821
4822 // determine force[0] = (1,u)
4823 (*m_exp)[i]->BwdTrans(tmp_coeffs = coeffs + m_coeff_offset[i], qrhs);
4824 force[0] = (*m_exp)[i]->Integral(qrhs);
4825
4826 // multiply by inverse Laplacian matrix
4827 // get matrix inverse
4828 LocalRegions::MatrixKey lapkey(StdRegions::eInvLaplacianWithUnityMean,
4829 ppExp->DetShapeType(), *ppExp);
4830 DNekScalMatSharedPtr lapsys = ppExp->GetLocMatrix(lapkey);
4831
4832 NekVector<NekDouble> in(nm_elmt, force, eWrapper);
4833 NekVector<NekDouble> out(nm_elmt);
4834
4835 out = (*lapsys) * in;
4836
4837 // Transforming back to modified basis
4838 Array<OneD, NekDouble> work(nq_elmt);
4839 ppExp->BwdTrans(out.GetPtr(), work);
4840 (*m_exp)[i]->FwdTrans(work, tmp_coeffs = outarray + m_coeff_offset[i]);
4841 }
4842}
int GetExpSize(void)
This function returns the number of elements in the expansion.
Definition ExpList.h:2157
Array< OneD, int > m_coeff_offset
Offset of elemental data into the array m_coeffs.
Definition ExpList.h:1193
ExpansionType m_expType
Expansion type.
Definition ExpList.h:1117
@ 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 3324 of file DisContField.cpp.

3330{
3331
3332 // Fill boundary conditions into missing elements
3333 if (PutFwdInBwdOnBCs) // just set Bwd value to be Fwd value on BCs
3334 {
3335 // Fill boundary conditions into missing elements
3336 for (int n = 0, cnt = 0; n < bndCondExpansions.size(); ++n)
3337 {
3338 if (bndConditions[n]->GetBoundaryConditionType() ==
3340 {
3341 auto ne = bndCondExpansions[n]->GetExpSize();
3342 for (int e = 0; e < ne; ++e)
3343 {
3344 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3345 auto id2 = m_trace->GetPhys_Offset(
3346 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3347 Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1);
3348 }
3349
3350 cnt += ne;
3351 }
3352 else if (bndConditions[n]->GetBoundaryConditionType() ==
3354 bndConditions[n]->GetBoundaryConditionType() ==
3356 {
3357 auto ne = bndCondExpansions[n]->GetExpSize();
3358 for (int e = 0; e < ne; ++e)
3359 {
3360 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3361 auto id2 = m_trace->GetPhys_Offset(
3362 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3363 Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1);
3364 }
3365 cnt += ne;
3366 }
3367 else if (bndConditions[n]->GetBoundaryConditionType() !=
3369 {
3370 ASSERTL0(false, "Method not set up for this "
3371 "boundary condition.");
3372 }
3373 }
3374 }
3375 else
3376 {
3377 for (int n = 0, cnt = 0; n < bndCondExpansions.size(); ++n)
3378 {
3379 if (bndConditions[n]->GetBoundaryConditionType() ==
3381 {
3382 auto ne = bndCondExpansions[n]->GetExpSize();
3383 for (int e = 0; e < ne; ++e)
3384 {
3385 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3386 auto id1 = bndCondExpansions[n]->GetPhys_Offset(e);
3387 auto id2 = m_trace->GetPhys_Offset(
3388 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3389
3390 Vmath::Vcopy(npts, &(bndCondExpansions[n]->GetPhys())[id1],
3391 1, &Bwd[id2], 1);
3392 }
3393 cnt += ne;
3394 }
3395 else if (bndConditions[n]->GetBoundaryConditionType() ==
3397 bndConditions[n]->GetBoundaryConditionType() ==
3399 {
3400 auto ne = m_bndCondExpansions[n]->GetExpSize();
3401 for (int e = 0; e < ne; ++e)
3402 {
3403 auto npts = bndCondExpansions[n]->GetExp(e)->GetTotPoints();
3404 auto id1 = bndCondExpansions[n]->GetPhys_Offset(e);
3405
3406 ASSERTL0((bndCondExpansions[n]->GetPhys())[id1] == 0.0,
3407 "Method not set up for non-zero "
3408 "Neumann boundary condition");
3409 auto id2 = m_trace->GetPhys_Offset(
3410 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
3411
3412 Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1);
3413 }
3414
3415 cnt += ne;
3416 }
3417 else if (bndConditions[n]->GetBoundaryConditionType() ==
3419 {
3420 // Do nothing
3421 }
3422 else if (bndConditions[n]->GetBoundaryConditionType() !=
3424 {
3426 "Method not set up for this boundary "
3427 "condition.");
3428 }
3429 }
3430 }
3431}
#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:2149

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 1003 of file DisContField.cpp.

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

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

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

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 518 of file DisContField.cpp.

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

3212{
3213 ASSERTL1((*m_exp)[0]->GetBasis(0)->GetBasisType() !=
3215 "Routine not set up for Gauss Lagrange points distribution");
3216
3217 // blocked routine
3218 Array<OneD, NekDouble> tracevals(m_locTraceToTraceMap->GetNLocTracePts());
3219
3220 m_locTraceToTraceMap->LocTracesFromField(field, tracevals);
3221 m_locTraceToTraceMap->InterpLocTracesToTrace(0, tracevals, Fwd);
3222
3223 Array<OneD, NekDouble> invals =
3224 tracevals + m_locTraceToTraceMap->GetNFwdLocTracePts();
3225 m_locTraceToTraceMap->InterpLocTracesToTrace(1, invals, Bwd);
3226
3228
3229 FillBwdWithBoundCond(Fwd, Bwd, BndCond, BndCondExp, false);
3230
3231 // Do parallel exchange for forwards/backwards spaces.
3232 m_traceMap->GetAssemblyCommDG()->PerformExchange(Fwd, Bwd);
3233
3234 // Do exchange of interface traces (local and parallel)
3235 // We may have to split this out into separate local and
3236 // parallel for IP method???
3237 m_interfaceMap->ExchangeTrace(Fwd, Bwd);
3238}
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 2886 of file DisContField.cpp.

2888{
2889 ASSERTL0(mkey.GetMatrixType() == StdRegions::eHybridDGHelmBndLam,
2890 "Routine currently only tested for HybridDGHelmholtz");
2891
2892 ASSERTL1(mkey.GetGlobalSysSolnType() != eDirectFullMatrix,
2893 "Full matrix global systems are not supported for HDG "
2894 "expansions");
2895
2896 ASSERTL1(mkey.GetGlobalSysSolnType() == m_traceMap->GetGlobalSysSolnType(),
2897 "The local to global map is not set up for the requested "
2898 "solution type");
2899
2900 GlobalLinSysSharedPtr glo_matrix;
2901 auto matrixIter = m_globalBndMat->find(mkey);
2902
2903 if (matrixIter == m_globalBndMat->end())
2904 {
2905 glo_matrix = GenGlobalBndLinSys(mkey, m_traceMap);
2906 (*m_globalBndMat)[mkey] = glo_matrix;
2907 }
2908 else
2909 {
2910 glo_matrix = matrixIter->second;
2911 }
2912
2913 return glo_matrix;
2914}
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

◆ 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 2950 of file DisContField.cpp.

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

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

Referenced by v_AddTraceIntegral().

◆ GetTraceElmtId()

unsigned Nektar::MultiRegions::DisContField::GetTraceElmtId ( const unsigned  elmtid,
const unsigned  traceid 
)
inline

Definition at line 136 of file DisContField.h.

138 {
139 return m_traceMap->GetElmtToTrace()[elmtid][traceid]->GetElmtId();
140 }

References m_traceMap.

◆ IsLeftAdjacentTrace()

bool Nektar::MultiRegions::DisContField::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.

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 477 of file DisContField.cpp.

478{
480 m_traceMap->GetElmtToTrace()[n][e];
481
482 PeriodicMap periodicTraces = (m_expType == e1D) ? m_periodicVerts
485
486 bool fwd = true;
487 if (traceEl->GetLeftAdjacentElementTrace() == -1 ||
488 traceEl->GetRightAdjacentElementTrace() == -1)
489 {
490 // Boundary edge (1 connected element). Do nothing in
491 // serial.
492 auto it = m_boundaryTraces.find(traceEl->GetElmtId());
493
494 // If the edge does not have a boundary condition set on
495 // it, then assume it is a partition edge or periodic.
496 if (it == m_boundaryTraces.end())
497 {
498 fwd = true;
499 }
500 }
501 else if (traceEl->GetLeftAdjacentElementTrace() != -1 &&
502 traceEl->GetRightAdjacentElementTrace() != -1)
503 {
504 // Non-boundary edge (2 connected elements).
505 fwd = (traceEl->GetLeftAdjacentElementExp().get()) == (*m_exp)[n].get();
506 }
507 else
508 {
509 ASSERTL2(false, "Unconnected trace element!");
510 }
511
512 return fwd;
513}
#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 4581 of file DisContField.cpp.

4584{
4585 int i, e, ncoeff_edge;
4586 Array<OneD, const NekDouble> tmp_coeffs;
4587 Array<OneD, NekDouble> out_d(m_ncoeffs), out_tmp;
4588
4589 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>> &elmtToTrace =
4590 m_traceMap->GetElmtToTrace();
4591
4593
4594 int cnt;
4595 int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs();
4596 Array<OneD, NekDouble> loc_lambda(LocBndCoeffs), edge_lambda;
4597 m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(), loc_lambda);
4598
4599 edge_lambda = loc_lambda;
4600
4601 // Calculate Q using standard DG formulation.
4602 for (i = cnt = 0; i < GetExpSize(); ++i)
4603 {
4604 // Probably a better way of setting up lambda than this.
4605 // Note cannot use PutCoeffsInToElmts since lambda space
4606 // is mapped during the solve.
4607 int nEdges = (*m_exp)[i]->GetGeom()->GetNumEdges();
4608 Array<OneD, Array<OneD, NekDouble>> edgeCoeffs(nEdges);
4609
4610 for (e = 0; e < nEdges; ++e)
4611 {
4612 edgedir = (*m_exp)[i]->GetTraceOrient(e);
4613 ncoeff_edge = elmtToTrace[i][e]->GetNcoeffs();
4614 edgeCoeffs[e] = Array<OneD, NekDouble>(ncoeff_edge);
4615 Vmath::Vcopy(ncoeff_edge, edge_lambda, 1, edgeCoeffs[e], 1);
4616 elmtToTrace[i][e]->SetCoeffsToOrientation(edgedir, edgeCoeffs[e],
4617 edgeCoeffs[e]);
4618 edge_lambda = edge_lambda + ncoeff_edge;
4619 }
4620
4621 (*m_exp)[i]->DGDeriv(dir, tmp_coeffs = coeffs + m_coeff_offset[i],
4622 elmtToTrace[i], edgeCoeffs, out_tmp = out_d + cnt);
4623 cnt += (*m_exp)[i]->GetNcoeffs();
4624 }
4625
4626 Array<OneD, NekDouble> phys(m_npoints);
4627 BwdTrans(out_d, phys);
4628 Vmath::Vsub(m_npoints, phys, 1, soln, 1, phys, 1);
4629 return L2(phys);
4630}
int m_ncoeffs
The total number of local degrees of freedom. m_ncoeffs .
Definition ExpList.h:1129
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:527
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:1816
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 4877 of file DisContField.cpp.

4880{
4881 // Precompute trigonometric values for improved precision
4882 const NekDouble cosA = cos(angle);
4883 const NekDouble sinA = sin(angle);
4884
4885 switch (dir)
4886 {
4887 // ----------------------------------------------------------
4888 // Rotate around the x-axis by 'angle':
4889 // y' = y*cos(angle) - z*sin(angle)
4890 // z' = y*sin(angle) + z*cos(angle)
4891 // x' = x (unchanged)
4892 // ----------------------------------------------------------
4893 case 0:
4894 {
4895 for (int i = offset; i < offset + npts; ++i)
4896 {
4897 NekDouble tmpY = Bwd[2][i];
4898 NekDouble tmpZ = Bwd[3][i];
4899
4900 NekDouble yrot = cosA * tmpY - sinA * tmpZ;
4901 NekDouble zrot = sinA * tmpY + cosA * tmpZ;
4902
4903 Bwd[2][i] = yrot;
4904 Bwd[3][i] = zrot;
4905 }
4906 }
4907 break;
4908
4909 // ----------------------------------------------------------
4910 // Rotate around the y-axis by 'angle':
4911 // z' = z*cos(angle) - x*sin(angle)
4912 // x' = z*sin(angle) + x*cos(angle)
4913 // y' = y (unchanged)
4914 // ----------------------------------------------------------
4915 case 1:
4916 {
4917 for (int i = offset; i < offset + npts; ++i)
4918 {
4919 NekDouble tmpX = Bwd[1][i];
4920 NekDouble tmpZ = Bwd[3][i];
4921
4922 NekDouble zrot = cosA * tmpZ - sinA * tmpX;
4923 NekDouble xrot = sinA * tmpZ + cosA * tmpX;
4924
4925 Bwd[1][i] = xrot;
4926 Bwd[3][i] = zrot;
4927 }
4928 }
4929 break;
4930
4931 // ----------------------------------------------------------
4932 // Rotate around the z-axis by 'angle':
4933 // x' = x*cos(angle) - y*sin(angle)
4934 // y' = x*sin(angle) + y*cos(angle)
4935 // z' = z (unchanged)
4936 // ----------------------------------------------------------
4937 case 2:
4938 {
4939 for (int i = offset; i < offset + npts; ++i)
4940 {
4941 NekDouble tmpX = Bwd[1][i];
4942 NekDouble tmpY = Bwd[2][i];
4943
4944 NekDouble xrot = cosA * tmpX - sinA * tmpY;
4945 NekDouble yrot = sinA * tmpX + cosA * tmpY;
4946
4947 Bwd[1][i] = xrot;
4948 Bwd[2][i] = yrot;
4949 }
4950 }
4951 break;
4952
4953 default:
4955 "Rotate() axis must be 0 (x), 1 (y), or 2 (z).");
4956 break;
4957 }
4958}

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 2922 of file DisContField.cpp.

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

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

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::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_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 3722 of file DisContField.cpp.

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

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 3551 of file DisContField.cpp.

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

4866{
4867 Array<OneD, NekDouble> FCoeffs(m_trace->GetNcoeffs());
4868
4869 m_trace->IProductWRTBase(FwdFlux, FCoeffs);
4870 m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(1, FCoeffs, outarray);
4871 m_trace->IProductWRTBase(BwdFlux, FCoeffs);
4872 m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(0, FCoeffs, outarray);
4873}

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 3443 of file DisContField.cpp.

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

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 3903 of file DisContField.cpp.

3907{
3908 int i;
3909 int npoints;
3910
3912
3913 for (i = 0; i < m_bndCondExpansions.size(); ++i)
3914 {
3915 if (m_bndCondExpansions[i] &&
3916 (time == 0.0 || m_bndConditions[i]->IsTimeDependent()))
3917 {
3918 m_bndCondBndWeight[i] = 1.0;
3919 locExpList = m_bndCondExpansions[i];
3920
3921 npoints = locExpList->GetNpoints();
3922 Array<OneD, NekDouble> x0(npoints, 0.0);
3923 Array<OneD, NekDouble> x1(npoints, 0.0);
3924 Array<OneD, NekDouble> x2(npoints, 0.0);
3925
3926 locExpList->GetCoords(x0, x1, x2);
3927
3928 if (x2_in != NekConstants::kNekUnsetDouble &&
3930 {
3931 Vmath::Fill(npoints, x2_in, x1, 1);
3932 Vmath::Fill(npoints, x3_in, x2, 1);
3933 }
3934 else if (x2_in != NekConstants::kNekUnsetDouble)
3935 {
3936 Vmath::Fill(npoints, x2_in, x2, 1);
3937 }
3938
3939 // treat 1D expansions separately since we only
3940 // require an evaluation at a point rather than
3941 // any projections or inner products that are not
3942 // available in a PointExp
3943 if (m_expType == e1D)
3944 {
3945 if (m_bndConditions[i]->GetBoundaryConditionType() ==
3947 {
3948 for (int n = 0; n < npoints; ++n)
3949 {
3950 m_bndCondExpansions[i]->SetCoeff(
3951 n, (std::static_pointer_cast<
3952 SpatialDomains::DirichletBoundaryCondition>(
3953 m_bndConditions[i])
3954 ->m_dirichletCondition)
3955 ->Evaluate(x0[n], x1[n], x2[n], time));
3956 m_bndCondExpansions[i]->SetPhys(
3957 n, m_bndCondExpansions[i]->GetCoeff(n));
3958 }
3959 }
3960 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3962 {
3963 for (int n = 0; n < npoints; ++n)
3964 {
3965 m_bndCondExpansions[i]->SetCoeff(
3966 n, (std::static_pointer_cast<
3967 SpatialDomains::NeumannBoundaryCondition>(
3968 m_bndConditions[i])
3969 ->m_neumannCondition)
3970 ->Evaluate(x0[n], x1[n], x2[n], time));
3971 }
3972 }
3973 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3975 {
3976 for (int n = 0; n < npoints; ++n)
3977 {
3978 m_bndCondExpansions[i]->SetCoeff(
3979 n, (std::static_pointer_cast<
3980 SpatialDomains::RobinBoundaryCondition>(
3981 m_bndConditions[i])
3982 ->m_robinFunction)
3983 ->Evaluate(x0[n], x1[n], x2[n], time));
3984 }
3985 }
3986 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3988 {
3989 continue;
3990 }
3991 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
3993 {
3994 }
3995 else
3996 {
3998 "This type of BC not implemented yet");
3999 }
4000 }
4001 else // 2D and 3D versions
4002 {
4003 if (m_bndConditions[i]->GetBoundaryConditionType() ==
4005 {
4007 std::static_pointer_cast<
4008 SpatialDomains::DirichletBoundaryCondition>(
4009 m_bndConditions[i]);
4010
4011 Array<OneD, NekDouble> valuesFile(npoints, 1.0),
4012 valuesExp(npoints, 1.0);
4013
4014 string bcfilename = bcPtr->m_filename;
4015 string exprbcs = bcPtr->m_expr;
4016
4017 if (bcfilename != "")
4018 {
4019 locExpList->ExtractCoeffsFromFile(
4020 bcfilename, bcPtr->GetComm(), varName,
4021 locExpList->UpdateCoeffs());
4022 locExpList->BwdTrans(locExpList->GetCoeffs(),
4023 locExpList->UpdatePhys());
4024 valuesFile = locExpList->GetPhys();
4025 }
4026
4027 if (exprbcs != "")
4028 {
4030 std::static_pointer_cast<
4031 SpatialDomains::DirichletBoundaryCondition>(
4032 m_bndConditions[i])
4033 ->m_dirichletCondition;
4034
4035 condition->Evaluate(x0, x1, x2, time, valuesExp);
4036 }
4037
4038 Vmath::Vmul(npoints, valuesExp, 1, valuesFile, 1,
4039 locExpList->UpdatePhys(), 1);
4040 locExpList->FwdTransBndConstrained(
4041 locExpList->GetPhys(), locExpList->UpdateCoeffs());
4042 }
4043 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4045 {
4047 std::static_pointer_cast<
4048 SpatialDomains::NeumannBoundaryCondition>(
4049 m_bndConditions[i]);
4050 string bcfilename = bcPtr->m_filename;
4051
4052 if (bcfilename != "")
4053 {
4054 locExpList->ExtractCoeffsFromFile(
4055 bcfilename, bcPtr->GetComm(), varName,
4056 locExpList->UpdateCoeffs());
4057 locExpList->BwdTrans(locExpList->GetCoeffs(),
4058 locExpList->UpdatePhys());
4059 }
4060 else
4061 {
4063 std::static_pointer_cast<
4064 SpatialDomains::NeumannBoundaryCondition>(
4065 m_bndConditions[i])
4066 ->m_neumannCondition;
4067 condition->Evaluate(x0, x1, x2, time,
4068 locExpList->UpdatePhys());
4069 }
4070
4071 locExpList->IProductWRTBase(locExpList->GetPhys(),
4072 locExpList->UpdateCoeffs());
4073 }
4074 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4076 {
4078 std::static_pointer_cast<
4079 SpatialDomains::RobinBoundaryCondition>(
4080 m_bndConditions[i]);
4081
4082 string bcfilename = bcPtr->m_filename;
4083
4084 if (bcfilename != "")
4085 {
4086 locExpList->ExtractCoeffsFromFile(
4087 bcfilename, bcPtr->GetComm(), varName,
4088 locExpList->UpdateCoeffs());
4089 locExpList->BwdTrans(locExpList->GetCoeffs(),
4090 locExpList->UpdatePhys());
4091 }
4092 else
4093 {
4095 std::static_pointer_cast<
4096 SpatialDomains::RobinBoundaryCondition>(
4097 m_bndConditions[i])
4098 ->m_robinFunction;
4099 condition->Evaluate(x0, x1, x2, time,
4100 locExpList->UpdatePhys());
4101 }
4102
4103 locExpList->IProductWRTBase(locExpList->GetPhys(),
4104 locExpList->UpdateCoeffs());
4105 }
4106 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4108 {
4109 continue;
4110 }
4111 else
4112 {
4114 "This type of BC not implemented yet");
4115 }
4116 }
4117 }
4118 }
4119}
NekDouble GetCoeff(int i)
Get the i th value (coefficient) of m_coeffs.
Definition ExpList.h:2129
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 3470 of file DisContField.cpp.

3471{
3472 ASSERTL1(m_physState == true, "local physical space is not true ");
3473 v_ExtractTracePhys(m_phys, outarray);
3474}
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:1173
Array< OneD, NekDouble > m_phys
The global expansion evaluated at the quadrature points.
Definition ExpList.h:1165

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 3491 of file DisContField.cpp.

3494{
3495 LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0);
3496 if ((basis->GetBasisType() != LibUtilities::eGauss_Lagrange))
3497 {
3498 Vmath::Zero(outarray.size(), outarray, 1);
3499 Array<OneD, NekDouble> tracevals(
3500 m_locTraceToTraceMap->GetNFwdLocTracePts());
3501 m_locTraceToTraceMap->FwdLocTracesFromField(inarray, tracevals);
3502 m_locTraceToTraceMap->InterpLocTracesToTrace(0, tracevals, outarray);
3503 if (!gridVelocity)
3504 {
3505 m_traceMap->GetAssemblyCommDG()->PerformExchange(outarray,
3506 outarray);
3507 }
3508 }
3509 else
3510 {
3511 // Loop over elemente and collect forward expansion
3512 int nexp = GetExpSize();
3513 int n, p, offset, phys_offset;
3514 Array<OneD, NekDouble> t_tmp;
3515 Array<OneD, Array<OneD, LocalRegions::ExpansionSharedPtr>>
3516 &elmtToTrace = m_traceMap->GetElmtToTrace();
3517 ASSERTL1(outarray.size() >= m_trace->GetNpoints(),
3518 "input array is of insufficient length");
3519 for (n = 0; n < nexp; ++n)
3520 {
3521 phys_offset = GetPhys_Offset(n);
3522 for (p = 0; p < (*m_exp)[n]->GetNtraces(); ++p)
3523 {
3524 offset =
3525 m_trace->GetPhys_Offset(elmtToTrace[n][p]->GetElmtId());
3526 (*m_exp)[n]->GetTracePhysVals(p, elmtToTrace[n][p],
3527 inarray + phys_offset,
3528 t_tmp = outarray + offset);
3529 }
3530 }
3531 }
3532}
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:2204
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 3314 of file DisContField.cpp.

3317{
3319 PutFwdInBwdOnBCs);
3320}

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 4220 of file DisContField.cpp.

4222{
4223 int cnt;
4224 int npts;
4225 int e = 0;
4226
4227 // Fill boundary conditions into missing elements
4228 int id2 = 0;
4229
4230 for (int n = cnt = 0; n < m_bndCondExpansions.size(); ++n)
4231 {
4232
4233 if (m_bndConditions[n]->GetBoundaryConditionType() ==
4235 {
4236 for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e)
4237 {
4238 npts = m_bndCondExpansions[n]->GetExp(e)->GetTotPoints();
4239 id2 = m_trace->GetPhys_Offset(
4240 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
4241 Vmath::Fill(npts, m_bndCondBndWeight[n], &weightave[id2], 1);
4242 Vmath::Fill(npts, 0.0, &weightjmp[id2], 1);
4243 }
4244
4245 cnt += e;
4246 }
4247 else if (m_bndConditions[n]->GetBoundaryConditionType() ==
4249 m_bndConditions[n]->GetBoundaryConditionType() ==
4251 {
4252 for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e)
4253 {
4254 npts = m_bndCondExpansions[n]->GetExp(e)->GetTotPoints();
4255 id2 = m_trace->GetPhys_Offset(
4256 m_traceMap->GetBndCondIDToGlobalTraceID(cnt + e));
4257 Vmath::Fill(npts, m_bndCondBndWeight[n], &weightave[id2], 1);
4258 Vmath::Fill(npts, 0.0, &weightjmp[id2], 1);
4259 }
4260
4261 cnt += e;
4262 }
4263 else if (m_bndConditions[n]->GetBoundaryConditionType() !=
4265 {
4267 "Method not set up for this boundary condition.");
4268 }
4269 }
4270}

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 3433 of file DisContField.cpp.

3434{
3435 return m_bndCondBndWeight;
3436}

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 3019 of file DisContField.cpp.

3021{
3022 return m_bndCondExpansions;
3023}

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 3025 of file DisContField.cpp.

3027{
3028 return m_bndConditions;
3029}

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 4439 of file DisContField.cpp.

4442{
4443 int n, cnt;
4444 std::vector<unsigned int> eIDs;
4445
4446 Array<OneD, int> ElmtID, TraceID;
4447 GetBoundaryToElmtMap(ElmtID, TraceID);
4448
4449 // Skip other boundary regions
4450 for (cnt = n = 0; n < i; ++n)
4451 {
4452 cnt += m_bndCondExpansions[n]->GetExpSize();
4453 }
4454
4455 // Populate eIDs with information from BoundaryToElmtMap
4456 for (n = 0; n < m_bndCondExpansions[i]->GetExpSize(); ++n)
4457 {
4458 eIDs.push_back(ElmtID[cnt + n]);
4459 }
4460
4461 // Create expansion list
4463 *this, eIDs, DeclareCoeffPhysArrays, Collections::eNoCollection);
4464 // Copy phys and coeffs to new explist
4465 if (DeclareCoeffPhysArrays)
4466 {
4467 int nq;
4468 int offsetOld, offsetNew;
4469 Array<OneD, NekDouble> tmp1, tmp2;
4470 for (n = 0; n < result->GetExpSize(); ++n)
4471 {
4472 nq = GetExp(ElmtID[cnt + n])->GetTotPoints();
4473 offsetOld = GetPhys_Offset(ElmtID[cnt + n]);
4474 offsetNew = result->GetPhys_Offset(n);
4475 Vmath::Vcopy(nq, tmp1 = GetPhys() + offsetOld, 1,
4476 tmp2 = result->UpdatePhys() + offsetNew, 1);
4477 nq = GetExp(ElmtID[cnt + n])->GetNcoeffs();
4478 offsetOld = GetCoeff_Offset(ElmtID[cnt + n]);
4479 offsetNew = result->GetCoeff_Offset(n);
4480 Vmath::Vcopy(nq, tmp1 = GetCoeffs() + offsetOld, 1,
4481 tmp2 = result->UpdateCoeffs() + offsetNew, 1);
4482 }
4483 }
4484}
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:2046
const std::shared_ptr< LocalRegions::ExpansionVector > GetExp() const
This function returns the vector of elements in the expansion.
Definition ExpList.h:2189

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 4274 of file DisContField.cpp.

4276{
4277
4278 if (m_BCtoElmMap.size() == 0)
4279 {
4280 switch (m_expType)
4281 {
4282 case e1D:
4283 {
4284 map<int, int> VertGID;
4285 int i, n, id;
4286 int bid, cnt, Vid;
4287 int nbcs = 0;
4288 // Determine number of boundary condition expansions.
4289 for (i = 0; i < m_bndConditions.size(); ++i)
4290 {
4291 nbcs += m_bndCondExpansions[i]->GetExpSize();
4292 }
4293
4294 // make sure arrays are of sufficient length
4295 m_BCtoElmMap = Array<OneD, int>(nbcs, -1);
4296 m_BCtoTraceMap = Array<OneD, int>(nbcs);
4297
4298 // setup map of all global ids along boundary
4299 cnt = 0;
4300 for (n = 0; n < m_bndCondExpansions.size(); ++n)
4301 {
4302 for (i = 0; i < m_bndCondExpansions[n]->GetExpSize(); ++i)
4303 {
4304 Vid = m_bndCondExpansions[n]
4305 ->GetExp(i)
4306 ->GetGeom()
4307 ->GetVid(0);
4308 VertGID[Vid] = cnt++;
4309 }
4310 }
4311
4312 // Loop over elements and find verts that match;
4314 for (cnt = n = 0; n < GetExpSize(); ++n)
4315 {
4316 exp = (*m_exp)[n];
4317 for (i = 0; i < exp->GetNverts(); ++i)
4318 {
4319 id = exp->GetGeom()->GetVid(i);
4320
4321 if (VertGID.count(id) > 0)
4322 {
4323 bid = VertGID.find(id)->second;
4324 ASSERTL1(m_BCtoElmMap[bid] == -1,
4325 "Edge already set");
4326 m_BCtoElmMap[bid] = n;
4327 m_BCtoTraceMap[bid] = i;
4328 cnt++;
4329 }
4330 }
4331 }
4332 ASSERTL1(cnt == nbcs,
4333 "Failed to visit all boundary condtiions");
4334 }
4335 break;
4336 case e2D:
4337 {
4338 map<int, int> globalIdMap;
4339 int i, n;
4340 int cnt;
4341 int nbcs = 0;
4342
4343 // Populate global ID map (takes global geometry
4344 // ID to local expansion list ID).
4345 for (i = 0; i < GetExpSize(); ++i)
4346 {
4347 globalIdMap[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
4348 }
4349
4350 // Determine number of boundary condition expansions.
4351 for (i = 0; i < m_bndConditions.size(); ++i)
4352 {
4353 nbcs += m_bndCondExpansions[i]->GetExpSize();
4354 }
4355
4356 // Initialize arrays
4357 m_BCtoElmMap = Array<OneD, int>(nbcs);
4358 m_BCtoTraceMap = Array<OneD, int>(nbcs);
4359
4361 cnt = 0;
4362 for (n = 0; n < m_bndCondExpansions.size(); ++n)
4363 {
4364 for (i = 0; i < m_bndCondExpansions[n]->GetExpSize();
4365 ++i, ++cnt)
4366 {
4367 exp1d = m_bndCondExpansions[n]
4368 ->GetExp(i)
4369 ->as<LocalRegions::Expansion1D>();
4370
4371 // Use edge to element map from MeshGraph.
4373 m_graph->GetElementsFromEdge(exp1d->GetGeom1D());
4374
4375 m_BCtoElmMap[cnt] =
4376 globalIdMap[(*tmp)[0].first->GetGlobalID()];
4377 m_BCtoTraceMap[cnt] = (*tmp)[0].second;
4378 }
4379 }
4380 }
4381 break;
4382 case e3D:
4383 {
4384 map<int, int> globalIdMap;
4385 int i, n;
4386 int cnt;
4387 int nbcs = 0;
4388
4389 // Populate global ID map (takes global geometry ID to local
4390 // expansion list ID).
4392 for (i = 0; i < GetExpSize(); ++i)
4393 {
4394 globalIdMap[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i;
4395 }
4396
4397 // Determine number of boundary condition expansions.
4398 for (i = 0; i < m_bndConditions.size(); ++i)
4399 {
4400 if (m_bndCondExpansions[i])
4401 {
4402 nbcs += m_bndCondExpansions[i]->GetExpSize();
4403 }
4404 }
4405
4406 // Initialize arrays
4407 m_BCtoElmMap = Array<OneD, int>(nbcs);
4408 m_BCtoTraceMap = Array<OneD, int>(nbcs);
4409
4411 for (cnt = n = 0; n < m_bndCondExpansions.size(); ++n)
4412 {
4413 for (i = 0; i < m_bndCondExpansions[n]->GetExpSize();
4414 ++i, ++cnt)
4415 {
4416 exp2d = m_bndCondExpansions[n]
4417 ->GetExp(i)
4418 ->as<LocalRegions::Expansion2D>();
4419
4421 m_graph->GetElementsFromFace(exp2d->GetGeom2D());
4422 m_BCtoElmMap[cnt] =
4423 globalIdMap[tmp->at(0).first->GetGlobalID()];
4424 m_BCtoTraceMap[cnt] = tmp->at(0).second;
4425 }
4426 }
4427 }
4428 break;
4429 default:
4430 ASSERTL1(false, "Not setup for this expansion");
4431 break;
4432 }
4433 }
4434
4435 ElmtID = m_BCtoElmMap;
4436 TraceID = m_BCtoTraceMap;
4437}
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 3164 of file DisContField.cpp.

3166{
3167 v_GetFwdBwdTracePhys(m_phys, Fwd, Bwd);
3168}
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 3240 of file DisContField.cpp.

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

3001{
3002 return m_interfaceMap;
3003}

References m_interfaceMap.

◆ v_GetLeftAdjacentTraces()

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

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3014 of file DisContField.cpp.

3015{
3016 return m_leftAdjacentTraces;
3017}

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 4844 of file DisContField.cpp.

4848{
4849 if (locTraceFwd != NullNekDouble1DArray)
4850 {
4851 m_locTraceToTraceMap->InterpLocTracesToTraceTranspose(0, Fwd,
4852 locTraceFwd);
4853 }
4854
4855 if (locTraceBwd != NullNekDouble1DArray)
4856 {
4857 m_locTraceToTraceMap->InterpLocTracesToTraceTranspose(1, Bwd,
4858 locTraceBwd);
4859 }
4860}
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 3005 of file DisContField.cpp.

3007{
3008 return m_locTraceToTraceMap;
3009}

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 3174 of file DisContField.cpp.

3177{
3178 periodicVerts = m_periodicVerts;
3179 periodicEdges = m_periodicEdges;
3180 periodicFaces = m_periodicFaces;
3181}

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 4514 of file DisContField.cpp.

4515{
4516 int i, cnt;
4517 map<int, RobinBCInfoSharedPtr> returnval;
4518 Array<OneD, int> ElmtID, TraceID;
4519 GetBoundaryToElmtMap(ElmtID, TraceID);
4520
4521 for (cnt = i = 0; i < m_bndCondExpansions.size(); ++i)
4522 {
4524
4525 if (m_bndConditions[i]->GetBoundaryConditionType() ==
4527 {
4528 int e, elmtid;
4529 Array<OneD, NekDouble> Array_tmp;
4530
4531 locExpList = m_bndCondExpansions[i];
4532
4533 int npoints = locExpList->GetNpoints();
4534 Array<OneD, NekDouble> x0(npoints, 0.0);
4535 Array<OneD, NekDouble> x1(npoints, 0.0);
4536 Array<OneD, NekDouble> x2(npoints, 0.0);
4537 Array<OneD, NekDouble> coeffphys(npoints);
4538
4539 locExpList->GetCoords(x0, x1, x2);
4540
4542 std::static_pointer_cast<
4543 SpatialDomains::RobinBoundaryCondition>(m_bndConditions[i])
4544 ->m_robinPrimitiveCoeff;
4545
4546 // evalaute coefficient
4547 coeffeqn->Evaluate(x0, x1, x2, 0.0, coeffphys);
4548
4549 for (e = 0; e < locExpList->GetExpSize(); ++e)
4550 {
4551 RobinBCInfoSharedPtr rInfo =
4553 TraceID[cnt + e],
4554 Array_tmp = coeffphys + locExpList->GetPhys_Offset(e));
4555
4556 elmtid = ElmtID[cnt + e];
4557 // make link list if necessary
4558 if (returnval.count(elmtid) != 0)
4559 {
4560 rInfo->next = returnval.find(elmtid)->second;
4561 }
4562 returnval[elmtid] = rInfo;
4563 }
4564 }
4565 cnt += m_bndCondExpansions[i]->GetExpSize();
4566 }
4567
4568 return returnval;
4569}
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 2985 of file DisContField.cpp.

2986{
2988 {
2989 SetUpDG();
2990 }
2991
2992 return m_trace;
2993}

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 2995 of file DisContField.cpp.

2996{
2997 return m_traceMap;
2998}

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 StdRegions::VarFactorsMap varfactors,
const Array< OneD, const NekDouble > &  dirForcing,
const bool  PhysSpaceForcing 
)
overrideprotectedvirtual

Solve the Helmholtz equation.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3735 of file DisContField.cpp.

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

3044{
3045 for (int n = 0; n < m_periodicFwdCopy.size(); ++n)
3046 {
3047 Bwd[m_periodicBwdCopy[n]] = Fwd[m_periodicFwdCopy[n]];
3048 }
3049}

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 3051 of file DisContField.cpp.

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

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

4490{
4492
4493 // Reset boundary condition expansions.
4494 for (int n = 0; n < m_bndCondExpansions.size(); ++n)
4495 {
4496 m_bndCondExpansions[n]->Reset();
4497 }
4498}

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 3154 of file DisContField.cpp.

3155{
3156 int nDim = GetCoordim(0);
3157 for (auto &interfaceTrace : m_interfaceMap->GetLocalInterface())
3158 {
3159
3160 interfaceTrace->RotLocalBwdDeriveTrace(Bwd, nDim);
3161 }
3162}
int GetCoordim(int eid)
This function returns the dimension of the coordinates of the element eid.
Definition ExpList.h:2005

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 3144 of file DisContField.cpp.

3145{
3146 int nDim = GetCoordim(0);
3147 for (auto &interfaceTrace : m_interfaceMap->GetLocalInterface())
3148 {
3149
3150 interfaceTrace->RotLocalBwdTrace(Bwd, nDim);
3151 }
3152}

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

◆ v_SetBCsToHomogeneous()

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

Set boundary conditions to be homogeneous.

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 4121 of file DisContField.cpp.

4122{
4123 int i;
4124 int npoints;
4125
4127
4128 for (i = 0; i < m_bndCondExpansions.size(); ++i)
4129 {
4130 locExpList = m_bndCondExpansions[i];
4131
4132 npoints = locExpList->GetNpoints();
4133
4134 // treat 1D expansions separately since we only
4135 // require an evaluation at a point rather than
4136 // any projections or inner products that are not
4137 // available in a PointExp
4138 if (m_expType == e1D)
4139 {
4141 "Function needs setting up for 1D boundary expansion");
4142 }
4143 else // 2D and 3D versions
4144 {
4145 if (m_bndConditions[i]->GetBoundaryConditionType() ==
4147 {
4149 std::static_pointer_cast<
4150 SpatialDomains::DirichletBoundaryCondition>(
4151 m_bndConditions[i]);
4152
4153 Array<OneD, NekDouble> valuesExp(npoints, 0.0);
4154 bcPtr->m_filename = "";
4155 bcPtr->m_expr = "0.0";
4156
4157 bcPtr->m_dirichletCondition =
4158 std::make_shared<LibUtilities::Equation>(
4159 m_session->GetInterpreter(), bcPtr->m_expr);
4160
4161 Vmath::Zero(locExpList->GetNcoeffs(),
4162 locExpList->UpdateCoeffs(), 1);
4163 Vmath::Zero(locExpList->GetNpoints(), locExpList->UpdatePhys(),
4164 1);
4165 }
4166 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4168 {
4169 SpatialDomains::NeumannBCShPtr bcPtr = std::static_pointer_cast<
4170 SpatialDomains::NeumannBoundaryCondition>(
4171 m_bndConditions[i]);
4172
4173 bcPtr->m_filename = "";
4174 std::string eqn = "0.0";
4175
4176 bcPtr->m_neumannCondition =
4177 std::make_shared<LibUtilities::Equation>(
4178 m_session->GetInterpreter(), eqn);
4179
4180 Vmath::Zero(locExpList->GetNcoeffs(),
4181 locExpList->UpdateCoeffs(), 1);
4182 Vmath::Zero(locExpList->GetNpoints(), locExpList->UpdatePhys(),
4183 1);
4184 }
4185 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4187 {
4188 SpatialDomains::RobinBCShPtr bcPtr = std::static_pointer_cast<
4189 SpatialDomains::RobinBoundaryCondition>(m_bndConditions[i]);
4190
4191 bcPtr->m_filename = "";
4192 std::string eqn = "0.0";
4193
4194 bcPtr->m_robinFunction =
4195 std::make_shared<LibUtilities::Equation>(
4196 m_session->GetInterpreter(), eqn);
4197
4198 Vmath::Zero(locExpList->GetNcoeffs(),
4199 locExpList->UpdateCoeffs(), 1);
4200 Vmath::Zero(locExpList->GetNpoints(), locExpList->UpdatePhys(),
4201 1);
4202 }
4203 else if (m_bndConditions[i]->GetBoundaryConditionType() ==
4205 {
4206 continue;
4207 }
4208 else
4209 {
4211 "This type of BC not implemented yet");
4212 }
4213 }
4214 }
4215}

References Nektar::MultiRegions::e1D, Nektar::SpatialDomains::eDirichlet, Nektar::ErrorUtil::efatal, Nektar::SpatialDomains::eNeumann, Nektar::SpatialDomains::ePeriodic, Nektar::SpatialDomains::eRobin, m_bndCondExpansions, m_bndConditions, Nektar::MultiRegions::ExpList::m_expType, Nektar::SpatialDomains::NeumannBoundaryCondition::m_filename, Nektar::SpatialDomains::RobinBoundaryCondition::m_filename, Nektar::MultiRegions::ExpList::m_session, NEKERROR, and Vmath::Zero().

◆ v_SetBndCondBwdWeight()

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

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3438 of file DisContField.cpp.

3439{
3440 m_bndCondBndWeight[index] = value;
3441}

References m_bndCondBndWeight.

◆ v_UpdateBndCondExpansion()

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

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3031 of file DisContField.cpp.

3032{
3033 return m_bndCondExpansions[i];
3034}

References m_bndCondExpansions.

◆ v_UpdateBndConditions()

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

Reimplemented from Nektar::MultiRegions::ExpList.

Definition at line 3036 of file DisContField.cpp.

3038{
3039 return m_bndConditions;
3040}

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 172 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(), v_SetBCsToHomogeneous(), 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 194 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 180 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 177 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 186 of file DisContField.h.

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

◆ m_locTraceToTraceMap

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

◆ m_negatedFluxNormal

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

Definition at line 381 of file DisContField.h.

Referenced by GetNegatedFluxNormal().

◆ m_periodicBwdCopy

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

Definition at line 217 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 216 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