v0.13.1
Searching...
No Matches
VEC-1: Eigen elastic

Note
Prerequisites of this tutorial include MSH-1: Create a 2D mesh from Gmsh

Note
Intended learning outcome:
• general structure of a program developed using MoFEM
• idea of Simple Interface in MoFEM and how to use it
• solving eigen problem
• Use of form integators
• How to push the developed UDOs to the Pipeline

# Source code

/**
* \file eigen_elastic.cpp
* \example eigen_elastic.cpp
*
* Calculate natural frequencies in 2d and 3d problems.
*
*/
#include <MoFEM.hpp>
#undef EPS
#include <slepceps.h>
using namespace MoFEM;
template <int DIM> struct ElementsAndOps {};
template <> struct ElementsAndOps<2> {
};
template <> struct ElementsAndOps<3> {
};
constexpr int SPACE_DIM =
EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
double rho = 7829e-12;
double young_modulus = 207e3;
double poisson_ratio = 0.33;
double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
int order = 1;
struct Example {
Example(MoFEM::Interface &m_field) : mField(m_field) {}
private:
boost::shared_ptr<MatrixDouble> matDPtr;
std::array<SmartPetscObj<Vec>, 6> rigidBodyMotion;
};
//! [Create common data]
CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-rho", &rho, PETSC_NULL);
CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-young_modulus", &young_modulus,
PETSC_NULL);
CHKERR PetscOptionsGetScalar(PETSC_NULL, "", "-poisson_ratio", &poisson_ratio,
PETSC_NULL);
auto set_matrial_stiffens = [&]() {
auto t_D = getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(*matDPtr);
const double A = (SPACE_DIM == 2)
: 1;
t_D(i, j, k, l) = 2 * shear_modulus_G * ((t_kd(i, k) ^ t_kd(j, l)) / 4.) +
A * (bulk_modulus_K - (2. / 3.) * shear_modulus_G) *
t_kd(i, j) * t_kd(k, l);
};
matDPtr = boost::make_shared<MatrixDouble>();
constexpr auto size_symm = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
matDPtr->resize(size_symm * size_symm, 1);
CHKERR set_matrial_stiffens();
}
//! [Create common data]
//! [Run problem]
}
//! [Run problem]
MOFEM_LOG("EXAMPLE", Sev::inform)
<< "Read mesh for problem in " << EXECUTABLE_DIMENSION;
CHKERR simple->getOptions();
}
//! [Set up problem]
CHKERR PetscOptionsGetInt(PETSC_NULL, "", "-order", &order, PETSC_NULL);
CHKERR simple->setFieldOrder("U", order);
CHKERR simple->setUp();
}
//! [Set up problem]
//! [Boundary condition]
for (int n = 1; n != 6; ++n)
// Create space of vectors or rigid motion
auto problem_ptr = mField.get_problem(simple->getProblemName());
auto dofs = problem_ptr->getNumeredRowDofsPtr();
// Get all vertices
const auto bit_number = mField.get_field_bit_number("U");
auto lo_uid =
DofEntity::getUniqueIdCalculate(0, get_id_for_min_type<MBVERTEX>());
auto hi_uid =
DofEntity::getUniqueIdCalculate(2, get_id_for_max_type<MBVERTEX>());
auto hi = dofs->upper_bound(lo_uid);
std::array<double, 3> coords;
for (auto lo = dofs->lower_bound(lo_uid); lo != hi; ++lo) {
if ((*lo)->getPart() == mField.get_comm_rank()) {
auto ent = (*lo)->getEnt();
CHKERR mField.get_moab().get_coords(&ent, 1, coords.data());
if ((*lo)->getDofCoeffIdx() == 0) {
CHKERR VecSetValue(rigidBodyMotion[0], (*lo)->getPetscGlobalDofIdx(), 1,
INSERT_VALUES);
CHKERR VecSetValue(rigidBodyMotion[3], (*lo)->getPetscGlobalDofIdx(),
-coords[1], INSERT_VALUES);
if (SPACE_DIM == 3)
CHKERR VecSetValue(rigidBodyMotion[4], (*lo)->getPetscGlobalDofIdx(),
-coords[2], INSERT_VALUES);
} else if ((*lo)->getDofCoeffIdx() == 1) {
CHKERR VecSetValue(rigidBodyMotion[1], (*lo)->getPetscGlobalDofIdx(), 1,
INSERT_VALUES);
CHKERR VecSetValue(rigidBodyMotion[3], (*lo)->getPetscGlobalDofIdx(),
coords[0], INSERT_VALUES);
if (SPACE_DIM == 3)
CHKERR VecSetValue(rigidBodyMotion[5], (*lo)->getPetscGlobalDofIdx(),
-coords[2], INSERT_VALUES);
} else if ((*lo)->getDofCoeffIdx() == 2) {
if (SPACE_DIM == 3) {
CHKERR VecSetValue(rigidBodyMotion[2], (*lo)->getPetscGlobalDofIdx(),
1, INSERT_VALUES);
CHKERR VecSetValue(rigidBodyMotion[4], (*lo)->getPetscGlobalDofIdx(),
coords[0], INSERT_VALUES);
CHKERR VecSetValue(rigidBodyMotion[5], (*lo)->getPetscGlobalDofIdx(),
coords[1], INSERT_VALUES);
}
}
}
}
for (int n = 0; n != rigidBodyMotion.size(); ++n) {
CHKERR VecAssemblyBegin(rigidBodyMotion[n]);
CHKERR VecAssemblyEnd(rigidBodyMotion[n]);
CHKERR VecGhostUpdateBegin(rigidBodyMotion[n], INSERT_VALUES,
SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(rigidBodyMotion[n], INSERT_VALUES,
SCATTER_FORWARD);
}
}
//! [Boundary condition]
//! [Push operators to pipeline]
auto *pipeline_mng = mField.getInterface<PipelineManager>();
auto dm = simple->getDM();
M = smartMatDuplicate(K, MAT_SHARE_NONZERO_PATTERN);
auto calculate_stiffness_matrix = [&]() {
pipeline_mng->getDomainLhsFE().reset();
auto det_ptr = boost::make_shared<VectorDouble>();
auto jac_ptr = boost::make_shared<MatrixDouble>();
auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainLhsPipeline().push_back(
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpInvertMatrix<SPACE_DIM>(jac_ptr, det_ptr, inv_jac_ptr));
pipeline_mng->getOpDomainLhsPipeline().push_back(
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpSetHOWeights(det_ptr));
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpK("U", "U", matDPtr));
auto integration_rule = [](int, int, int approx_order) {
return 2 * (approx_order - 1);
};
CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
pipeline_mng->getDomainLhsFE()->B = K;
CHKERR MatZeroEntries(K);
CHKERR pipeline_mng->loopFiniteElements();
CHKERR MatAssemblyBegin(K, MAT_FINAL_ASSEMBLY);
CHKERR MatAssemblyEnd(K, MAT_FINAL_ASSEMBLY);
};
auto calculate_mass_matrix = [&]() {
pipeline_mng->getDomainLhsFE().reset();
auto det_ptr = boost::make_shared<VectorDouble>();
auto jac_ptr = boost::make_shared<MatrixDouble>();
auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
pipeline_mng->getOpDomainLhsPipeline().push_back(
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpInvertMatrix<SPACE_DIM>(jac_ptr, det_ptr, inv_jac_ptr));
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpSetHOWeights(det_ptr));
auto get_rho = [](const double, const double, const double) { return rho; };
pipeline_mng->getOpDomainLhsPipeline().push_back(
new OpMass("U", "U", get_rho));
auto integration_rule = [](int, int, int approx_order) {
return 2 * approx_order;
};
CHKERR pipeline_mng->setDomainLhsIntegrationRule(integration_rule);
CHKERR MatZeroEntries(M);
pipeline_mng->getDomainLhsFE()->B = M;
CHKERR pipeline_mng->loopFiniteElements();
CHKERR MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY);
CHKERR MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY);
};
CHKERR calculate_stiffness_matrix();
CHKERR calculate_mass_matrix();
}
//! [Push operators to pipeline]
//! [Solve]
auto is_manager = mField.getInterface<ISManager>();
auto create_eps = [](MPI_Comm comm) {
EPS eps;
CHKERR EPSCreate(comm, &eps);
};
auto deflate_vectors = [&]() {
// Deflate vectors
std::array<Vec, 6> deflate_vectors;
for (int n = 0; n != 6; ++n) {
deflate_vectors[n] = rigidBodyMotion[n];
}
CHKERR EPSSetDeflationSpace(ePS, 6, &deflate_vectors[0]);
};
auto print_info = [&]() {
ST st;
EPSType type;
PetscReal tol;
PetscInt nev, maxit, its;
// Optional: Get some information from the solver and display it
CHKERR EPSGetIterationNumber(ePS, &its);
MOFEM_LOG_C("EXAMPLE", Sev::inform,
" Number of iterations of the method: %d", its);
CHKERR EPSGetST(ePS, &st);
CHKERR EPSGetType(ePS, &type);
MOFEM_LOG_C("EXAMPLE", Sev::inform, " Solution method: %s", type);
CHKERR EPSGetDimensions(ePS, &nev, NULL, NULL);
MOFEM_LOG_C("EXAMPLE", Sev::inform, " Number of requested eigenvalues: %d",
nev);
CHKERR EPSGetTolerances(ePS, &tol, &maxit);
MOFEM_LOG_C("EXAMPLE", Sev::inform,
" Stopping condition: tol=%.4g, maxit=%d", (double)tol, maxit);
PetscScalar eigr, eigi;
for (int nn = 0; nn < nev; nn++) {
CHKERR EPSGetEigenpair(ePS, nn, &eigr, &eigi, PETSC_NULL, PETSC_NULL);
MOFEM_LOG_C("EXAMPLE", Sev::inform,
" ncov = %d eigr = %.4g eigi = %.4g (inv eigr = %.4g)", nn,
eigr, eigi, 1. / eigr);
}
};
auto setup_eps = [&]() {
CHKERR EPSSetProblemType(ePS, EPS_GHEP);
CHKERR EPSSetWhichEigenpairs(ePS, EPS_SMALLEST_MAGNITUDE);
CHKERR EPSSetFromOptions(ePS);
};
// Create eigensolver context
ePS = create_eps(mField.get_comm());
CHKERR EPSSetOperators(ePS, K, M);
// Setup eps
CHKERR setup_eps();
// Deflate vectors
CHKERR deflate_vectors();
// Solve problem
CHKERR EPSSolve(ePS);
// Print info
CHKERR print_info();
}
//! [Solve]
//! [Postprocess results]
auto *pipeline_mng = mField.getInterface<PipelineManager>();
pipeline_mng->getDomainLhsFE().reset();
auto post_proc_fe = boost::make_shared<PostProcEle>(mField);
auto det_ptr = boost::make_shared<VectorDouble>();
auto jac_ptr = boost::make_shared<MatrixDouble>();
auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
post_proc_fe->getOpPtrVector().push_back(
post_proc_fe->getOpPtrVector().push_back(
new OpInvertMatrix<SPACE_DIM>(jac_ptr, det_ptr, inv_jac_ptr));
post_proc_fe->getOpPtrVector().push_back(
auto u_ptr = boost::make_shared<MatrixDouble>();
auto strain_ptr = boost::make_shared<MatrixDouble>();
auto stress_ptr = boost::make_shared<MatrixDouble>();
post_proc_fe->getOpPtrVector().push_back(
post_proc_fe->getOpPtrVector().push_back(
post_proc_fe->getOpPtrVector().push_back(
post_proc_fe->getOpPtrVector().push_back(
"U", strain_ptr, stress_ptr, matDPtr));
post_proc_fe->getOpPtrVector().push_back(
new OpPPMap(
post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
OpPPMap::DataMapMat{{"U", u_ptr}},
OpPPMap::DataMapMat{{"STRAIN", strain_ptr}, {"STRESS", stress_ptr}}
)
);
pipeline_mng->getDomainRhsFE() = post_proc_fe;
auto dm = simple->getDM();
auto D = smartCreateDMVector(dm);
PetscInt nev;
CHKERR EPSGetDimensions(ePS, &nev, NULL, NULL);
PetscScalar eigr, eigi, nrm2r;
for (int nn = 0; nn < nev; nn++) {
CHKERR EPSGetEigenpair(ePS, nn, &eigr, &eigi, D, PETSC_NULL);
CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
CHKERR VecNorm(D, NORM_2, &nrm2r);
MOFEM_LOG_C("EXAMPLE", Sev::inform,
" ncov = %d omega2 = %.8g omega = %.8g frequency = %.8g", nn,
eigr, std::sqrt(std::abs(eigr)),
std::sqrt(std::abs(eigr)) / (2 * M_PI));
CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
CHKERR pipeline_mng->loopFiniteElements();
post_proc_fe->writeFile("out_eig_" + boost::lexical_cast<std::string>(nn) +
".h5m");
}
}
//! [Postprocess results]
//! [Check]
PetscBool test_flg = PETSC_FALSE;
CHKERR PetscOptionsGetBool(PETSC_NULL, "", "-test", &test_flg, PETSC_NULL);
if (test_flg) {
PetscScalar eigr, eigi;
CHKERR EPSGetEigenpair(ePS, 0, &eigr, &eigi, PETSC_NULL, PETSC_NULL);
constexpr double regression_value = 12579658;
if (fabs(eigr - regression_value) > 1)
SETERRQ(PETSC_COMM_WORLD, MOFEM_ATOM_TEST_INVALID,
"Regression test faileed; wrong eigen value.");
}
}
//! [Check]
static char help[] = "...\n\n";
int main(int argc, char *argv[]) {
// Initialisation of MoFEM/PETSc and MOAB data structures
const char param_file[] = "param_file.petsc";
SlepcInitialize(&argc, &argv, param_file, help);
// Add logging channel for example
auto core_log = logging::core::get();
LogManager::createSink(LogManager::getStrmWorld(), "EXAMPLE"));
LogManager::setLog("EXAMPLE");
MOFEM_LOG_TAG("EXAMPLE", "example");
try {
//! [Register MoFEM discrete manager in PETSc]
DMType dm_name = "DMMOFEM";
//! [Register MoFEM discrete manager in PETSc
//! [Create MoAB]
moab::Core mb_instance; ///< mesh database
moab::Interface &moab = mb_instance; ///< mesh database interface
//! [Create MoAB]
//! [Create MoFEM]
MoFEM::Core core(moab); ///< finite element database
MoFEM::Interface &m_field = core; ///< finite element database insterface
//! [Create MoFEM]
//! [Example]
Example ex(m_field);
CHKERR ex.runProblem();
//! [Example]
}
SlepcFinalize();
}
std::string param_file
#define MOFEM_LOG_C(channel, severity, format,...)
Definition: LogManager.hpp:304
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
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
Kronecker Delta class symmetric.
#define CATCH_ERRORS
Catch errors.
Definition: definitions.h:372
@ AINSWORTH_BERNSTEIN_BEZIER_BASE
Definition: definitions.h:64
@ H1
continuous field
Definition: definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:346
@ MOFEM_ATOM_TEST_INVALID
Definition: definitions.h:40
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:416
#define CHKERR
Inline error check.
Definition: definitions.h:535
constexpr double shear_modulus_G
Definition: elastic.cpp:63
constexpr double bulk_modulus_K
Definition: elastic.cpp:62
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
ElementsAndOps< SPACE_DIM >::PostProcEle PostProcEle
FTensor::Index< 'n', SPACE_DIM > n
auto integration_rule
constexpr auto t_kd
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition: DMMMoFEM.cpp:470
PetscErrorCode DMCreateMatrix_MoFEM(DM dm, Mat *M)
Definition: DMMMoFEM.cpp:1144
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition: DMMMoFEM.cpp:47
auto smartCreateDMVector(DM dm)
Get smart vector from DM.
Definition: DMMoFEM.hpp:965
virtual const Problem * get_problem(const std::string problem_name) const =0
Get the problem object.
#define MOFEM_LOG(channel, severity)
Log.
Definition: LogManager.hpp:301
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
Definition: LogManager.hpp:332
double D
FTensor::Index< 'k', 3 > k
double tol
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:56
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:10
SmartPetscObj< Mat > smartMatDuplicate(Mat &mat, MatDuplicateOption op)
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
SmartPetscObj< Vec > smartVectorDuplicate(SmartPetscObj< Vec > &vec)
Create duplicate vector of smart vector.
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
double young_modulus
Definition: plastic.cpp:96
double rho
Definition: plastic.cpp:98
#define EXECUTABLE_DIMENSION
Definition: plastic.cpp:10
constexpr auto size_symm
Definition: plastic.cpp:33
constexpr AssemblyType A
Definition: plastic.cpp:35
static constexpr int approx_order
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'i', 3 > i
[Example]
Definition: plastic.cpp:137
MoFEMErrorCode boundaryCondition()
[Set up problem]
Definition: helmholtz.cpp:106
MoFEMErrorCode assembleSystem()
[Applying essential BC]
Definition: helmholtz.cpp:154
[run problem]
Definition: helmholtz.cpp:73
MoFEMErrorCode checkResults()
[Postprocess results]
Definition: contact.cpp:659
MoFEMErrorCode solveSystem()
[Push operators to pipeline]
Definition: helmholtz.cpp:235
MoFEMErrorCode createCommonData()
[Set up problem]
Definition: plastic.cpp:257
std::array< SmartPetscObj< Vec >, 6 > rigidBodyMotion
SmartPetscObj< Mat > M
MoFEMErrorCode runProblem()
[Run problem]
Definition: plastic.cpp:172
SmartPetscObj< EPS > ePS
SmartPetscObj< Mat > K
MoFEM::Interface & mField
Definition: plastic.cpp:144
MoFEMErrorCode setupProblem()
[Run problem]
Definition: plastic.cpp:184
MoFEMErrorCode outputResults()
[Solve]
Definition: helmholtz.cpp:255
boost::shared_ptr< MatrixDouble > matDPtr
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
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)
Section manager is used to create indexes and sections.
Definition: ISManager.hpp:23
Get values at integration pts for tensor filed rank 1, i.e. vector field.
Post post-proc data at points from hash maps.
std::map< std::string, boost::shared_ptr< VectorDouble > > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
Set inverse jacobian to base functions.
Set inverse jacobian to base functions.
PipelineManager interface.
auto & getNumeredRowDofsPtr() const