v0.9.1
basic_elastic.cpp

Plane stress elastic problem

/**
* \file basic_elastic.cpp
* \example basic_elastic.cpp
*
* Plane stress elastic problem
*
*/
/* This file is part of MoFEM.
* MoFEM is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* MoFEM is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with MoFEM. If not, see <http://www.gnu.org/licenses/>. */
#include <MoFEM.hpp>
using namespace MoFEM;
constexpr int order = 2;
constexpr double young_modulus = 1;
constexpr double poisson_ratio = 0.25;
#include <ElasticOps.hpp>
using namespace OpElasticTools;
struct Example {
Example(MoFEM::Interface &m_field) : mField(m_field) {}
MoFEMErrorCode runProblem();
private:
MoFEMErrorCode setUP();
MoFEMErrorCode createCommonData();
MoFEMErrorCode kspSolve();
MoFEMErrorCode postProcess();
MoFEMErrorCode checkResults();
boost::shared_ptr<CommonData> commonDataPtr;
};
//! [Run problem]
CHKERR setUP();
CHKERR createCommonData();
CHKERR bC();
CHKERR OPs();
CHKERR kspSolve();
CHKERR postProcess();
CHKERR checkResults();
}
//! [Run problem]
//! [Set up problem]
Simple *simple = mField.getInterface<Simple>();
// Add field
CHKERR simple->addDomainField("U", H1, AINSWORTH_LEGENDRE_BASE, 2);
CHKERR simple->addBoundaryField("U", H1, AINSWORTH_LEGENDRE_BASE, 2);
CHKERR simple->setFieldOrder("U", order);
CHKERR simple->setUp();
}
//! [Set up problem]
//! [Create common data]
auto get_matrial_stiffens = [&](FTensor::Ddg<double, 2, 2> &t_D) {
t_D(i, j, k, l) = 0;
constexpr double c = young_modulus / (1 - poisson_ratio * poisson_ratio);
constexpr double o = poisson_ratio * c;
t_D(0, 0, 0, 0) = c;
t_D(0, 0, 1, 1) = o;
t_D(1, 1, 0, 0) = o;
t_D(1, 1, 1, 1) = c;
t_D(0, 1, 0, 1) = (1 - poisson_ratio) * c;
};
commonDataPtr = boost::make_shared<CommonData>();
CHKERR get_matrial_stiffens(commonDataPtr->tD);
commonDataPtr->mGradPtr = boost::make_shared<MatrixDouble>();
commonDataPtr->mStrainPtr = boost::make_shared<MatrixDouble>();
commonDataPtr->mStressPtr = boost::make_shared<MatrixDouble>();
}
//! [Create common data]
//! [Boundary condition]
auto fix_disp = [&](const std::string blockset_name) {
Range fix_ents;
if (it->getName().compare(0, blockset_name.length(), blockset_name) ==
0) {
CHKERR mField.get_moab().get_entities_by_handle(it->meshset, fix_ents,
true);
}
}
return fix_ents;
};
auto remove_ents = [&](const Range &&ents, const bool fix_x,
const bool fix_y) {
auto prb_mng = mField.getInterface<ProblemsManager>();
auto simple = mField.getInterface<Simple>();
Range verts;
CHKERR mField.get_moab().get_connectivity(ents, verts, true);
verts.merge(ents);
const int lo_coeff = fix_x ? 0 : 1;
const int hi_coeff = fix_y ? 1 : 0;
CHKERR prb_mng->removeDofsOnEntities(simple->getProblemName(), "U", verts,
lo_coeff, hi_coeff);
};
CHKERR remove_ents(fix_disp("FIX_X"), true, false);
CHKERR remove_ents(fix_disp("FIX_Y"), false, true);
CHKERR remove_ents(fix_disp("FIX_ALL"), true, true);
}
//! [Boundary condition]
//! [Push operators to pipeline]
Basic *basic = mField.getInterface<Basic>();
basic->getOpDomainLhsPipeline().push_back(
basic->getOpDomainLhsPipeline().push_back(
new OpStiffnessMatrixLhs("U", "U", commonDataPtr));
auto gravity = [](double x, double y) {
return FTensor::Tensor1<double, 2>{0., -1.};
};
basic->getOpDomainRhsPipeline().push_back(
new OpForceRhs("U", commonDataPtr, gravity));
auto integration_rule = [](int, int, int approx_order) {
return 2 * (approx_order - 1);
};
CHKERR basic->setDomainRhsIntegrationRule(integration_rule);
CHKERR basic->setDomainLhsIntegrationRule(integration_rule);
}
//! [Push operators to pipeline]
//! [Solve]
Simple *simple = mField.getInterface<Simple>();
Basic *basic = mField.getInterface<Basic>();
auto solver = basic->createKSP();
CHKERR KSPSetFromOptions(solver);
CHKERR KSPSetUp(solver);
auto dm = simple->getDM();
auto D = smartCreateDMVector(dm);
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);
}
//! [Solve]
//! [Postprocess results]
Basic *basic = mField.getInterface<Basic>();
basic->getDomainLhsFE().reset();
auto post_proc_fe = boost::make_shared<PostProcFaceOnRefinedMesh>(mField);
post_proc_fe->generateReferenceElementMesh();
post_proc_fe->getOpPtrVector().push_back(
post_proc_fe->getOpPtrVector().push_back(new OpSetInvJacH1ForFace(invJac));
post_proc_fe->getOpPtrVector().push_back(
new OpCalculateVectorFieldGradient<2, 2>("U", commonDataPtr->mGradPtr));
post_proc_fe->getOpPtrVector().push_back(new OpStrain("U", commonDataPtr));
post_proc_fe->getOpPtrVector().push_back(new OpStress("U", commonDataPtr));
post_proc_fe->getOpPtrVector().push_back(
new OpPostProcElastic("U", post_proc_fe->postProcMesh,
post_proc_fe->mapGaussPts, commonDataPtr));
post_proc_fe->addFieldValuesPostProc("U");
basic->getDomainRhsFE() = post_proc_fe;
CHKERR post_proc_fe->writeFile("out_elastic.h5m");
}
//! [Postprocess results]
//! [Check]
Simple *simple = mField.getInterface<Simple>();
Basic *basic = mField.getInterface<Basic>();
basic->getDomainRhsFE().reset();
basic->getDomainLhsFE().reset();
basic->getOpDomainRhsPipeline().push_back(
basic->getOpDomainRhsPipeline().push_back(new OpSetInvJacH1ForFace(invJac));
basic->getOpDomainRhsPipeline().push_back(
new OpCalculateVectorFieldGradient<2, 2>("U", commonDataPtr->mGradPtr));
basic->getOpDomainRhsPipeline().push_back(new OpStrain("U", commonDataPtr));
basic->getOpDomainRhsPipeline().push_back(new OpStress("U", commonDataPtr));
basic->getOpDomainRhsPipeline().push_back(
new OpInternalForceRhs("U", commonDataPtr));
auto gravity = [](double x, double y) {
};
basic->getOpDomainRhsPipeline().push_back(
new OpForceRhs("U", commonDataPtr, gravity));
auto integration_rule = [](int, int, int p_data) { return 2 * (p_data - 1); };
CHKERR basic->setDomainRhsIntegrationRule(integration_rule);
auto dm = simple->getDM();
auto res = smartCreateDMVector(dm);
basic->getDomainRhsFE()->ksp_f = res;
CHKERR VecZeroEntries(res);
CHKERR basic->loopFiniteElements();
CHKERR VecGhostUpdateBegin(res, ADD_VALUES, SCATTER_REVERSE);
CHKERR VecGhostUpdateEnd(res, ADD_VALUES, SCATTER_REVERSE);
CHKERR VecAssemblyBegin(res);
CHKERR VecAssemblyEnd(res);
double nrm2;
CHKERR VecNorm(res, NORM_2, &nrm2);
PetscPrintf(PETSC_COMM_WORLD, "residual = %3.4e\n", nrm2);
constexpr double eps = 1e-8;
if (nrm2 > eps)
SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY, "Residual is not zero");
}
//! [Check]
static char help[] = "...\n\n";
int main(int argc, char *argv[]) {
MoFEM::Core::Initialize(&argc, &argv, (char *)0, help);
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]
//! [Load mesh]
CHKERR simple->getOptions();
CHKERR simple->loadFile("");
//! [Load mesh]
//! [Example]
Example ex(m_field);
CHKERR ex.runProblem();
//! [Example]
}
}