v0.14.0
Loading...
Searching...
No Matches
hdiv_check_approx_in_3d.cpp

Approximate vectorial polynomial in 3D and check derivatives

/**
* \file hdiv_check_approx_in_3d
* \example hdiv_check_approx_in_3d.cpp
*
* Approximate vectorial polynomial in 3D and check derivatives
*
*/
#include <MoFEM.hpp>
using namespace MoFEM;
static char help[] = "...\n\n";
constexpr int BASE_DIM = 3;
constexpr int SPACE_DIM = 3;
using EleOp = Ele::UserDataOperator;
/**
* @brief OPerator to integrate mass matrix for least square approximation
*
*/
/**
* @brief Operator to integrate the right hand side matrix for the problem
*
*/
GAUSS>::OpSource<BASE_DIM, SPACE_DIM>;
constexpr double a0 = 0.0;
constexpr double a1 = 2.0;
constexpr double a2 = -15.0 * a0;
constexpr double a3 = -20.0 / 6 * a1;
constexpr double a4 = 15.0 * a0;
constexpr double a5 = a1;
constexpr double a6 = -a0;
static FTensor::Tensor1<double, BASE_DIM> fUn(const double x, const double y,
double z) {
// x
x + y*y + x*x*x,
// y
y + z*x + y*y*y,
// z
z + x*x + z*z*z);
}
diffFun(const double x, const double y, const double z) {
// x,x
1. + 3 * x * x,
// x,y
2. * y,
// x, z
0.,
// y,x
z,
// y,y
1. + 3 * y * y,
// y,z
x,
// z
2 * x, 0., 1. + 3 * z * z);
}
}; // namespace ApproxFunctions
struct OpCheckValsDiffVals : public EleOp {
boost::shared_ptr<MatrixDouble> ptrVals;
boost::shared_ptr<MatrixDouble> ptrGrad;
OpCheckValsDiffVals(boost::shared_ptr<MatrixDouble> ptr_vals,
boost::shared_ptr<MatrixDouble> ptr_grad)
: EleOp(NOSPACE, OPSPACE), ptrVals(ptr_vals), ptrGrad(ptr_grad) {}
MoFEMErrorCode doWork(int side, EntityType type,
const double eps = 1e-6;
const int nb_gauss_pts = getGaussPts().size2();
auto t_vals_from_op = getFTensor1FromMat<SPACE_DIM>(*ptrVals);
for (int gg = 0; gg != nb_gauss_pts; gg++) {
const double x = getCoordsAtGaussPts()(gg, 0);
const double y = getCoordsAtGaussPts()(gg, 1);
const double z = getCoordsAtGaussPts()(gg, 2);
// Check approximation
delta_val(i) = t_vals_from_op(i) - ApproxFunctions::fUn(x, y, z)(i);
double err_val = sqrt(delta_val(i) * delta_val(i));
MOFEM_LOG("SELF", Sev::verbose) << "Approximation error: " << err_val;
if (err_val > eps)
SETERRQ1(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID, "Wrong value %4.3e",
err_val);
delta_diff_val(i, j) =
t_grad_from_op(i, j) - ApproxFunctions::diffFun(x, y, z)(i, j);
double err_diff_val = sqrt(delta_diff_val(i, j) * delta_diff_val(i, j));
if (err_diff_val > eps)
SETERRQ1(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
"Wrong derivative of value %4.3e", err_diff_val);
++t_vals_from_op;
++t_grad_from_op;
}
}
};
int main(int argc, char *argv[]) {
MoFEM::Core::Initialize(&argc, &argv, (char *)0, help);
try {
DMType dm_name = "DMMOFEM";
moab::Core mb_instance;
moab::Interface &moab = mb_instance;
// Create MoFEM instance
MoFEM::Core core(moab);
MoFEM::Interface &m_field = core;
PipelineManager *pipeline_mng = m_field.getInterface<PipelineManager>();
CHKERR simple->getOptions();
CHKERR simple->loadFile();
// Declare elements
enum bases { AINSWORTH, DEMKOWICZ, LASBASETOP };
const char *list_bases[] = {"ainsworth", "demkowicz"};
PetscBool flg;
PetscInt choice_base_value = AINSWORTH;
CHKERR PetscOptionsGetEList(PETSC_NULL, NULL, "-base", list_bases,
LASBASETOP, &choice_base_value, &flg);
if (flg != PETSC_TRUE)
SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "base not set");
if (choice_base_value == AINSWORTH)
else if (choice_base_value == DEMKOWICZ)
AinsworthOrderHooks::broken_nbfacetri_edge_hdiv = [](int p) { return p; };
AinsworthOrderHooks::broken_nbfacetri_face_hdiv = [](int p) { return p; };
AinsworthOrderHooks::broken_nbvolumetet_edge_hdiv = [](int p) { return p; };
AinsworthOrderHooks::broken_nbvolumetet_face_hdiv = [](int p) { return p; };
AinsworthOrderHooks::broken_nbvolumetet_volume_hdiv = [](int p) {
return p;
};
CHKERR simple->addDomainField("FIELD1", HDIV, base, 1);
constexpr int order = 4;
CHKERR simple->setFieldOrder("FIELD1", order);
CHKERR simple->setUp();
auto dm = simple->getDM();
MatrixDouble vals, diff_vals;
auto assemble_matrices_and_vectors = [&]() {
pipeline_mng->getOpDomainRhsPipeline(), {HDIV});
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpDomainSource("FIELD1", ApproxFunctions::fUn));
pipeline_mng->getOpDomainLhsPipeline(), {HDIV});
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpDomainMass("FIELD1", "FIELD1",
[](double x, double, double) { return 1; })
);
auto integration_rule = [](int, int, int p_data) {
return 2 * p_data + 1;
};
CHKERR pipeline_mng->setDomainRhsIntegrationRule(integration_rule);
CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
};
auto solve_problem = [&] {
auto solver = pipeline_mng->createKSP();
CHKERR KSPSetFromOptions(solver);
CHKERR KSPSetUp(solver);
auto D = createDMVector(dm);
auto F = vectorDuplicate(D);
CHKERR KSPSolve(solver, F, D);
CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
};
auto check_solution = [&] {
pipeline_mng->getOpDomainLhsPipeline().clear();
pipeline_mng->getOpDomainRhsPipeline().clear();
auto ptr_values = boost::make_shared<MatrixDouble>();
auto ptr_grad = boost::make_shared<MatrixDouble>();
// Change H-curl to H-div in 2D, and apply Piola transform
pipeline_mng->getOpDomainRhsPipeline(), {HDIV});
// Calculate field values at integration points
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCalculateHVecVectorField<BASE_DIM>("FIELD1", ptr_values));
// Gradient
pipeline_mng->getOpDomainRhsPipeline().push_back(
ptr_grad));
pipeline_mng->getOpDomainRhsPipeline().push_back(
new OpCheckValsDiffVals(ptr_values, ptr_grad));
CHKERR pipeline_mng->loopFiniteElements();
};
CHKERR assemble_matrices_and_vectors();
CHKERR solve_problem();
CHKERR check_solution();
}
}
#define FTENSOR_INDEX(DIM, I)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
static char help[]
int main()
static const double eps
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
constexpr int SPACE_DIM
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, FIELD_DIM > OpDomainMass
#define CATCH_ERRORS
Catch errors.
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base nme:nme847.
Definition definitions.h:60
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
@ NOSPACE
Definition definitions.h:83
@ HDIV
field with continuous normal traction
Definition definitions.h:87
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int BASE_DIM
constexpr int order
@ F
auto integration_rule
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:523
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1099
#define MOFEM_LOG(channel, severity)
Log.
constexpr double a5
constexpr double a2
constexpr double a4
constexpr double a0
constexpr double a3
constexpr double a1
constexpr double a6
MoFEM::PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle Ele
double D
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
FTensor::Tensor1< FTensor::PackPtr< T *, S >, Tensor_Dim > getFTensor1FromMat(ublas::matrix< T, L, A > &data)
Get tensor rank 1 (vector) form data matrix.
FTensor::Tensor2< FTensor::PackPtr< double *, 1 >, Tensor_Dim1, Tensor_Dim2 > getFTensor2FromMat(MatrixDouble &data)
Get tensor rank 2 (matrix) form data matrix.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
constexpr int SPACE_DIM
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:56
static FTensor::Tensor2< double, BASE_DIM, SPACE_DIM > diffFun(const double x, const double y)
static FTensor::Tensor1< double, BASE_DIM > fUn(const double x, const double y, double z)
Core (interface) class.
Definition Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:112
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
MatrixDouble & getCoordsAtGaussPts()
Gauss points and weight, matrix (nb. of points x 3)
@ OPSPACE
operator do Work is execute on space data
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
Get vector field for H-div approximation.
Calculate gradient of vector field.
PipelineManager interface.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
FTensor::Index< 'i', 3 > i
boost::shared_ptr< MatrixDouble > ptrVals
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCheckValsDiffVals(boost::shared_ptr< MatrixDouble > ptr_vals, boost::shared_ptr< VectorDouble > ptr_div, boost::shared_ptr< MatrixDouble > ptr_grad, boost::shared_ptr< MatrixDouble > ptr_hess)
FTensor::Index< 'j', 2 > j
boost::shared_ptr< MatrixDouble > ptrGrad
FTensor::Index< 'k', 2 > k