v0.14.0 |
Template arguments:
Operator | Usage |
---|---|
Scalar fields | |
Evaluate scalar field at integration points. MoFEM::OpCalculateScalarFieldValues \[ u^h(\pmb\xi^g) = \sum_i^N \phi^i(\pmb\xi^g) \overline{u}_i \] where \(u^h(\pmb\xi^g)\) is the field value at integration point \(g\), \(\phi^i(\pmb\xi^g)\) is value of base function \(i\) at integtation point coordinate \(\pmb\xi^g\), and \(\overline{u}_i\) is \(i\)-th degree of freedom. This function has a similar variant that is used to calculate time derivative, when a time solver is used, see MoFEM::OpCalculateScalarFieldValuesDot \[ \frac{\partial u^h}{\partial t} (\pmb\xi^g) = \sum_i^N \phi^i(\pmb\xi^g) \frac{\partial \overline{u}}{\partial t} \] where \( \frac{\partial u^h}{\partial t} (\pmb\xi^g) \) (or \(\dot{u}^h(\pmb\xi^g)\) in short) is the rate value at integration point \(g\) and \( \frac{\partial \overline{u}}{\partial t} \) (or \(\dot{\overline{u}}_i\) in short) is the rate of \(i\)-th degree of freedom. Note that this funtion will work only with TS solver which is the numerical scheme used to calculate time derivative depends on time solver method. |
Basic usage: auto vals_U_at_integration_pts = boost::make_shared<VectorDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateScalarFieldValues("U", vals_U_at_integration_pts));
Operator for a given field calulates values of a scalar field at integration points. Values are stored in, for example, vals_U_at_integration_pts. Then value can be accessed as follows auto nb_integration_pts = vals_U_at_integration_pts->size();
auto t_val = getFTensor0FromVec(vals_U_at_integration_pts);
for(auto gg = 0;gg!=nb_integration_pts;++gg) {
// do something here
++t_val;
}
|
Evaluate scalar field gradient MoFEM::OpCalculateScalarFieldGradient \[ {u}^h_{,j} (\pmb\xi^g) = \sum_i^N \phi^i_{,j}(\pmb\xi^g) \overline{u}_i \] where \[ \phi^i_{,j} = \left. \frac{\partial \phi^i}{\partial \xi_j} \right|_{\pmb\xi^g} \] Depending on code context, derivatives are calculated in reference element or on the current physical element. For most cases, the gradient is calculated on the current physical element. Then derivative of base function is interpreted as \[ \phi^i_{,j} = \left. \frac{\partial \phi^i}{\partial \xi_ks} \frac{\partial \xi_k}{\partial x_j} \right|_{\mathbf{x}(\pmb\xi^g)} \] |
Basic usage: constexpr int SPACE_DIM = 3;
auto grad_U_at_integration_pts = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateVectorFieldValues<SPACE_DIM>("U", grad_U_at_integration_pts));
Operator for a given field calculate values of scalar field gradient at integration points. Values are stored in, for example, grad_U_at_integration_pts. Then value can be accessed as follows constexpr int FIELD_DIM = 3;
auto nb_integration_pts = grad_U_at_integration_pts->size2();
auto t_grad = getFTensor1FromMat<FIELD_DIM>((grad_U_at_integration_pts);
for(auto gg = 0;gg!=nb_integration_pts;++gg) {
++t_grad;
}
|
Vector fields | |
Evaluate vector field at integration points MoFEM::OpCalculateVectorFieldValues \[ u_j^h(\pmb\xi^g) = \sum_i^N \phi^i(\pmb\xi^g) \overline{u}_i^j \] where \(j\) is vector element index. This function has a similar variant to calculate rates when a time solver is used; see MoFEM::OpCalculateVectorFieldValuesDot, which can be used with a time solver (TS). Also is a variant to calculate accelerations (second derivatives with respect to time), MoFEM::OpCalculateVectorFieldValuesDotDot, which can be used with a second-order time solver (TS2). PETSc has currently implemented the alpha method for second-order time differential equations. |
Basic usage: constexpr int FIELD_DIM = 3;
auto vals_U_at_integration_pts = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateVectorFieldValues<FIELD_DIM>("U", vals_U_at_integration_pts));
Operator for a given field calulates values of vector field at integration points. Values are stored in, for example, vals_U_at_integration_pts. Then value can be accessed as follows constexpr int FIELD_DIM = 3;
auto nb_integration_pts = vals_U_at_integration_pts->size2();
auto t_val = getFTensor1FromMat<FIELD_DIM>((vals_U_at_integration_pts);
for(auto gg = 0;gg!=nb_integration_pts;++gg) {
++t_val;
}
|
Evaluate vector field gradient at integration points MoFEM::OpCalculateVectorFieldGradient \[ u_{jk}^h(\pmb\xi^g) = \sum_i^N \phi^i_{,k}(\pmb\xi^g) \overline{u}_i^{j} \] where \(j\) is vector element index, \(k\) is derivative and \(i\) is index of base function. This function has a similar variant to calculate rates, when a time solver is used, see MoFEM::OpCalculateVectorFieldGradientDot, which can be used with time solver (TS). |
Basic usage: constexpr int FIELD_DIM = 3;
constexpr int SPACE_DIM = 3;
auto grad_U_at_integration_pts = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
Operator for a given field calulates gradient of a vector field at integration points. Values are stored in for example in grad_U_at_integration_pts. Then value can be accessed as follows |
Tensor fields | |
Evaluate tensor field at integration points MoFEM::OpCalculateTensor2FieldValues \[ u_{jk}^h(\pmb\xi^g) = \sum_i^N \phi^i(\pmb\xi^g) \overline{u}_i^{jk} \] where \(j\) and \(k\) are tensor element (coefficient) indices. This function has a similar variant to calculate rates, when a time solver is used, see MoFEM::OpCalculateTensor2FieldValuesDot, which can be used with time solver (TS). |
Basic usage: constexpr int FIELD_DIM = 3;
auto vals_U_at_integration_pts = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateTensor2FieldValues<FIELD_DIM, FIELD_DIM>("U", vals_U_at_integration_pts));
Operator for a given field calulates values of tensor field at integration points. Values are stored in, for example, vals_U_at_integration_pts. Then value can be accessed as follows constexpr int FIELD_DIM = 3;
auto nb_integration_pts = vals_U_at_integration_pts->size2();
auto t_val = getFTensor2FromMat<FIELD_DIM, FIELD_DIM>((vals_U_at_integration_pts);
for(auto gg = 0;gg!=nb_integration_pts;++gg) {
++t_val;
}
|
Evaluate symmetric tensor field at integration points MoFEM::OpCalculateTensor2SymmetricFieldValues \[ u_{jk}^h(\pmb\xi^g) = \sum_i^N \phi^i(\pmb\xi^g) \overline{u}_i^{jk} \] where \(j\) and \(k\) are tensor element (coefficient) indices. Note that field degree of freedom represents only symmetric coefficients, so for each base function, we have a number of DOFs given by formula (FIELD_DIM * (FIELD_DIM + 1)) / 2. For example, for 3D case, six DOFs for each base function. This function has a similar variant to calculate rates, when a time solver is used, see MoFEM::OpCalculateTensor2SymmetricFieldValuesDot, which can be used with a time solver (TS). |
Basic usage: constexpr int FIELD_DIM = 3;
auto vals_U_at_integration_pts = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateTensor2SymmetricFieldValues<FIELD_DIM>("U", vals_U_at_integration_pts));
Operator for a given field calulates values of tensor field at integration points. Values are stored in, for example, vals_U_at_integration_pts. Then value can be accessed as follows constexpr int FIELD_DIM = 3;
auto nb_integration_pts = vals_U_at_integration_pts->size2();
auto t_val = getFTensor2SymmetricFromMat<FIELD_DIM>((vals_U_at_integration_pts);
for(auto gg = 0;gg!=nb_integration_pts;++gg) {
++t_val;
}
|
Evaluate tesorial field values for vectorial bases (Hdiv and Hcurl) MoFEM::OpCalculateHVecVectorField \[ u_{j}^h(\pmb\xi^g) = \sum_i^N \phi^i_j(\pmb\xi^g) \overline{u}_i^{jk} \] where \(j\) and \(k\) tensor element (coefficient) indices. |
Example constexpr int BASE_DIM = 3;
auto vals_integration_pts = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateHVecTensorField<3, 3>(
field_name, vals_integration_pts));
|
User data operators are defined in file UserDataOperators.hpp
Operator | Usage |
---|---|
Face operators | |
Calculate Jacobian and inverse Jacobian on face. See MoFEM::OpCalculateJacForFace and MoFEM::OpInvertMatrix For 2D element on plane XY, Jacobian is given by, \[ J_{ij} = \frac{\partial X_i}{\partial \xi_j},\quad i,j=0,1 \]
| Example usage auto det_ptr = boost::make_shared<VectorDouble>();
auto jac_ptr = boost::make_shared<MatrixDouble>();
auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateJacForFace(jac_ptr));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpInvertMatrix<2>(jac_ptr, det_ptr, inv_jac_ptr));
|
Push face base function to physical element configuration. MoFEM::OpSetHOInvJacToScalarBases<2> This operator assumes that the face element is on the XY plane. \[ \frac{\partial \phi}{\partial X_i} = \frac{\partial \phi}{\partial \xi_j} J^{-1}_{ij} \]
| Example usage auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpSetHOInvJacToScalarBases<2>(inv_jac_ptr));
|
Apply contravariant (Piola) transfer to Hdiv space on face MoFEM::OpSetContravariantPiolaTransformOnFace2D and MoFEM::OpSetContravariantPiolaTransformOnFace2DEmbeddedIn3DSpace Contravariant Piola transformation \[ \psi_i = \frac{1}{\textrm{det}(J)}J_{ij}\hat{\psi}_j\\ \frac{\partial \psi_i}{\partial \xi_j} = \frac{1}{\textrm{det}(J)}J_{ik}\frac{\partial \hat{\psi}_k}{\partial \xi_j} \] |
Example for 2D problem for face in XY space auto jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateJacForFace(jac_ptr));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpMakeHdivFromHcurl());
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpSetContravariantPiolaTransformOnFace2D(jac_ptr))
Example for face emerged in 3D space auto det_ptr = boost::make_shared<VectorDouble>();
auto jac_ptr = boost::make_shared<MatrixDouble>();
auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateJacForFaceEmbeddedIn3DSpace(jac_ptr));
pipeline.push_back(new OpInvertMatrix<3>(jac_ptr, det_ptr, inv_jac_ptr));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpMakeHdivFromHcurl());
pipeline_mng->getOpDomainRhsPipeline().push_back(
new
Note, in this case problem is 2D, however surface on which PDE is solved is emerged in 3D space. |
Transform local reference derivatives of shape function to global derivatives for face MoFEM::OpSetInvJacHcurlFace and MoFEM::OpSetInvJacHcurlFaceEmbeddedIn3DSpace \[ \frac{\partial \psi_i}{\partial X_j}= \frac{\partial \psi_i}{\partial \xi_k} \frac{\partial \xi_k}{\partial X_j} \] |
Example for 2D problem for face in XY space auto jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateJacForFace(jac_ptr));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpMakeHdivFromHcurl());
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpSetContravariantPiolaTransformOnFace2D(jac_ptr));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpSetContravariantPiolaTransformOnFace2D(jac_ptr))
|
Make H-div space from H-curl space in 2D MoFEM::OpMakeHdivFromHcurl \[ \pmb \psi^\textrm{Hdiv} = \left\{ \psi^\textrm{Hcurl}_{1}, -\psi^\textrm{Hcurl}_{0}, 0 \right\} \] where \(\psi^\textrm{Hdiv}\) are base functions for H-div space. Note that applying function twice will transform base from H-curl space and then back to H-div space. |
Example for 2D problem for face in XY space auto jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateJacForFace(jac_ptr));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpMakeHdivFromHcurl());
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpSetContravariantPiolaTransformOnFace2D(jac_ptr));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpSetContravariantPiolaTransformOnFace2D(jac_ptr))
|
Modify integration weights on face to take in account higher-order geometry MoFEM::OpSetHOWeightsOnFace Suppose Jacobian is not constant on the finite element, then this operator sets integration weights to take into account the geometry of the finite element, that is, a case for a non-parallelepiped quad. Also, that is a case for any face element given by higher-order geometry approximation. Note that geometry in MoFEM can be represented by an arbitrary order approximation field. \[ w^g = \left(\frac{\|J(\pmb\xi^g)\|}{A}\right) W^g \] where \(w^g\) is weight on update configuration, \(W^g\) integration weight at intergration point \(g\), at reference point \(\pmb\xi^g\). \(\|J(\pmb\xi^g)\|\) is determinant of the Jacobian, and \(A\) is area of face element. |
Example pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpSetHOWeightsOnFace());
|
Generic operators | |
Scale base (default L2) functions by inverses of measure of element MoFEM::OpScaleBaseBySpaceInverseOfMeasure Scale base \[ \overline{\phi}^m = \frac{1}{\mu(\Omega^e)} \phi^m \] where \(\mu(\Omega^e)\) is length, area or volume, depending on dimension of the finite elemen entitiy. Note that function scales also base function derivatives. |
Call that functions at front of the operators, before you evaluate field on given space, i.e. L2 space. Example: using OpScaleL2 = MoFEM::OpScaleBaseBySpaceInverseOfMeasure<DomainEleOp>;
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpScaleL2());
|
User data operators are defined in file UserDataOperators.hpp
Operator | Usage |
---|---|
Integrate source term for scalar and vectorial fields MoFEM::OpSourceImpl \[ (v_i,f_i(\mathbf{x}))_\Omega = \int_\Omega v_i f_i (x,y,z) \textrm{d}\Omega \] Template arguments: using OpSource =
FormsIntegrators<OP>::
Assembly<ASSEMBLE_TYPE>::
LinearForm<INTEGRATION_TYPE>::
OpSource<BASE_DIM, FIELD_DIM>;
|
Example usage for scalar base and scalar field: using OpDomainSource = FormsIntegrators<DomainEleOp>::Assembly<
PETSC>::LinearForm<GAUSS>::OpSource<1, 1>;
};
pipeline_mng->getOpDomainRhsPipeline().push_back(
Example usage for scalar base and vector field: using OpDomainSource = FormsIntegrators<DomainEleOp>::Assembly<
PETSC>::LinearForm<GAUSS>::OpSource<1, 3>;
};
pipeline_mng->getOpDomainRhsPipeline().push_back(
Example usage for vector base and vector field: using OpDomainSource = FormsIntegrators<DomainEleOp>::Assembly<
PETSC>::LinearForm<GAUSS>::OpSource<3, 3>;
};
pipeline_mng->getOpDomainRhsPipeline().push_back(
|
Integrate term for discrete scalar fields MoFEM::OpBaseTimesScalarImpl |
Example using OpBaseTimesV = FormsIntegrators<DomainEleOp>::Assembly<PETSC>::LinearForm<
GAUSS>::OpBaseTimesScalar<1>;
auto vec_at_gauss_pts = boost::make_shared<VectorDouble>();
// Push operator which sets vec_at_gauss_pts
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpBaseTimesV("U", vec_ptr_at_gauss_pts));
|
Integrate term for discrete vector fields MoFEM::OpBaseTimesScalarImpl |
Example for scalar base and field vector field (e.g. body forces) using OpBaseFlux = FormsIntegrators<DomainEleOp>::Assembly<PETSC>::LinearForm<
GAUSS>::OpBaseTimesVector<1, 3, 0>;
auto body_force = boost::make_shared<MatrixDouble>();
auto t_body_force = getFTensor1FromMat<3, 0>(*body_force);
t_body_force(0) = 0;
t_body_force(1) = 0;
t_body_force(2) = -9.81;
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpBaseFlux("U", body_force));
Example for base in Hdiv space and field in Hdiv space using OpBaseFlux = FormsIntegrators<DomainEleOp>::Assembly<PETSC>::LinearForm<
GAUSS>::OpBaseTimesVector<3, 3, 1>;
auto flux_at_gauss_pts = boost::make_shared<MatrixDouble>();
// Push operator which sets flux at integration points
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpBaseFlux("U", flux_at_gauss_pts));
|
Integrate natural boundary condidition |
Example using OpTemperatureBC = FormsIntegrators<BoundaryEleOp>::Assembly<
pipeline.push_back(
boost::make_shared<Range>(skin_edges)));
Example usage thermo_elastic.cpp |
Operator | Usage |
---|---|
Integrate Grad Grad operator MoFEM::OpGradGradImpl using OpDomainGradGrad =
FormsIntegrators<OP>::Assembly<ASSEMBLY_TYPE>::
BiLinearForm<INTEGRATION_TYPE>::
OpGradGrad<BASE_DIM, FIELD_DIM, SPACE_DIM>;
|
Example for scalar base, scalar field and 3D problem auto beta = [](double x, double y , double z) {
return 1;
};
using OpDomainGradGrad = FormsIntegrators<DomainEleOp>::Assembly<
PETSC>::BiLinearForm<GAUSS>::OpGradGrad<1, 1, 3>;
pipeline_mng->getOpDomainLhsPipeline().push_back(
Example usage: helmholtz.cpp |
Integrate mass MoFEM::OpMassImpl using OpMass =
FormsIntegrators<OP>::Assembly<ASSEMBLY_TYPE>::
BiLinearForm<INTEGRATION_TYPE>::
OpMass<BASE_DIM, FIELD_DIM>;
Example usage: helmholtz.cpp |
Example for scalar base and scalar field auto volume_specific_heat_capacity = [](double x, double y , double z) {
return 1;
};
using OpCapacity =
FormsIntegrators<OP>::Assembly< PETSC>::BiLinearForm<GAUSS>::OpMass<1, 1>;
pipeline_mng->getOpDomainLhsPipeline().push_back(
Example usage: helmholtz.cpp |
Integrate base divergence times base MoFEM::OpMixDivTimesScalarImpl using OpHcurlHcurl =
FormsIntegrators<OP>::Assembly<
ASSEMBLY_TYPE>::
BiLinearForm<INTEGRATION_TYPE>::
OpMixDivTimesScalarImpl<SPACE_DIM>;
Example usage: mixed_poisson.cpp |
Example GAUSS>::OpMixDivTimesScalar<2>;
auto unity = []() { return 1; };
pipeline_mng->getOpDomainLhsPipeline().push_back(
Example usage: mixed_poisson.cpp |
Bilinear froms are defined in file BiLinearFormsIntegrators.hpp