v0.15.5
Loading...
Searching...
No Matches
mofem/tools/mesh_smoothing.cpp
/** \file mesh_smoothing.cpp
* \brief Improve mesh quality using Volume-length quality measure with barrier
* \example mofem/tools/mesh_smoothing.cpp
*
*/
#include <MoFEM.hpp>
using namespace MoFEM;
#include <PostProc.hpp>
using namespace MoFEM;
static char help[] = "mesh smoothing\n\n";
PetscBool output_vtk = PETSC_TRUE;
double tol = 0.1;
double gamma_factor = 0.8;
constexpr bool fix_edge_blocks = true;
Range &output_edges,
Range &output_vertices);
int main(int argc, char *argv[]) {
MoFEM::Core::Initialize(&argc, &argv, (char *)0, help);
try {
PetscOptionsBegin(PETSC_COMM_WORLD, "", "Mesh cut options", "none");
CHKERR PetscOptionsInt("-edges_block_set", "edges side set", "",
edges_block_set, &edges_block_set, PETSC_NULLPTR);
CHKERR PetscOptionsInt("-vertex_block_set", "vertex side set", "",
CHKERR PetscOptionsBool("-output_vtk", "if true outout vtk file", "",
output_vtk, &output_vtk, PETSC_NULLPTR);
CHKERR PetscOptionsScalar("-quality_reduction_tol", "",
"Tolerance of quality reduction", tol, &tol,
PETSC_NULLPTR);
CHKERR PetscOptionsScalar("-gamma_factor", "",
"Gamma factor", gamma_factor, &gamma_factor,
PETSC_NULLPTR);
PetscOptionsEnd();
// Create MoAB database
moab::Core moab_core; // create database
moab::Interface &moab = moab_core; // create interface to database
// Create MoFEM database and link it to MoAB
MoFEM::Core mofem_core(moab); // create database
MoFEM::Interface &m_field = mofem_core; // create interface to database
// Register DM Manager
CHKERR DMRegister_MoFEM("DMMOFEM"); // register MoFEM DM in PETSc
// Get simple interface is simplified version enabling quick and
// easy construction of problem.
Simple *simple_interface = m_field.getInterface<Simple>();
Range edges, vertices, fixed_vertex;
// Build problem with simple interface
{
// Get options for simple interface from command line
CHKERR simple_interface->getOptions();
// Load mesh file to database
CHKERR simple_interface->loadFile();
// Add domain field "U" in space H1 and Legendre base, Ainsworth recipe is
// used to construct base functions.
CHKERR simple_interface->addDomainField("MESH_NODE_POSITIONS", H1,
// Add Lagrange multiplier field on body boundary
CHKERR simple_interface->addBoundaryField("LAMBDA_SURFACE", H1,
// Set fields order domain and boundary fields.
CHKERR simple_interface->setFieldOrder("MESH_NODE_POSITIONS",
1); // to approximate function
CHKERR simple_interface->setFieldOrder("LAMBDA_SURFACE",
1); // to Lagrange multipliers
simple_interface->getDomainFEName() = "SMOOTHING";
simple_interface->getBoundaryFEName() = "SURFACE_SLIDING";
// Other fields and finite elements added to database directly
->getEntitiesByDimension(edges_block_set, BLOCKSET, 1, edges,
true);
} else {
CHKERR extract_mesh_edges(m_field, edges, fixed_vertex);
}
->getEntitiesByDimension(vertex_block_set, BLOCKSET, 0,
fixed_vertex, true);
}
CHKERR m_field.get_moab().get_connectivity(edges, vertices, true);
if(!edges.empty() && !fix_edge_blocks) {
// Declare approximation fields
CHKERR m_field.add_field("LAMBDA_EDGE", H1, AINSWORTH_LOBATTO_BASE, 2,
MB_TAG_SPARSE, MF_ZERO);
CHKERR m_field.add_ents_to_field_by_type(edges, MBEDGE,
"LAMBDA_EDGE");
->synchroniseFieldEntities("LAMBDA_EDGE");
CHKERR m_field.set_field_order(0, MBVERTEX, "LAMBDA_EDGE", 1);
CHKERR m_field.add_finite_element("EDGE_SLIDING");
"EDGE_SLIDING", "MESH_NODE_POSITIONS");
"EDGE_SLIDING", "MESH_NODE_POSITIONS");
"EDGE_SLIDING", "MESH_NODE_POSITIONS");
"LAMBDA_EDGE");
"LAMBDA_EDGE");
"LAMBDA_EDGE");
"EDGE_SLIDING");
simple_interface->getOtherFiniteElements().push_back("EDGE_SLIDING");
}
CHKERR simple_interface->defineFiniteElements();
CHKERR simple_interface->defineProblem();
CHKERR simple_interface->buildFields();
CHKERR simple_interface->buildFiniteElements();
CHKERR simple_interface->buildProblem();
// Remove vertices form LAMBDA_SURFACE which are on the edges
if (!edges.empty()) {
Range edges;
CHKERR m_field.getInterface<MeshsetsManager>()->getEntitiesByDimension(
edges_block_set, BLOCKSET, 1, edges, true);
Range verts;
CHKERR m_field.get_moab().get_connectivity(edges, verts, true);
Simple *simple_interface = m_field.getInterface<Simple>();
auto prb_mng = m_field.getInterface<ProblemsManager>();
CHKERR prb_mng->removeDofsOnEntities(simple_interface->getProblemName(),
"LAMBDA_SURFACE", verts, 0, 1);
CHKERR prb_mng->removeDofsOnEntities(
simple_interface->getProblemName(), "MESH_NODE_POSITIONS", verts,
0, 3);
}
}
}
MeshSmoothingOps::Config smoothing_cfg;
smoothing_cfg.geometryField = "MESH_NODE_POSITIONS";
smoothing_cfg.meshReferenceField = "NONE";
smoothing_cfg.lambdaSurfaceField = "LAMBDA_SURFACE";
smoothing_cfg.lambdaEdgeField = "LAMBDA_EDGE";
smoothing_cfg.enableSurfaceSliding = true;
smoothing_cfg.fixEdgeBlocks = fix_edge_blocks;
smoothing_cfg.gamma = 0.0;
MeshSmoothingOps::Handles smoothing_handles;
CHKERR MeshSmoothingOps::createOperators(m_field, smoothing_cfg, fixed_vertex,
edges, smoothing_handles);
DM dm;
CHKERR simple_interface->getDM(&dm);
CHKERR MeshSmoothingOps::addToSnesDM(dm, smoothing_cfg, smoothing_handles);
struct Solve {
MoFEMErrorCode operator()(DM dm) const {
auto solver = SmartPetscObj<SNES>();
auto hook = [&](SNES snes, Vec x, Vec F,
boost::shared_ptr<CacheTuple> cache_ptr,
void *ctx) -> MoFEMErrorCode {
auto *m_field_ptr = getInterfacePtr(dm);
auto post_proc_fe =
boost::make_shared<PostProcEleDomain>(*m_field_ptr);
auto &pip = post_proc_fe->getOpPtrVector();
auto X_ptr = boost::make_shared<MatrixDouble>();
"MESH_NODE_POSITIONS", X_ptr));
auto res_X_ptr = boost::make_shared<MatrixDouble>();
"MESH_NODE_POSITIONS", res_X_ptr, SmartPetscObj<Vec>(F, true)));
auto lambda_ptr = boost::make_shared<VectorDouble>();
pip.push_back(
new OpCalculateScalarFieldValues("LAMBDA_SURFACE", lambda_ptr));
auto res_lambda_ptr = boost::make_shared<VectorDouble>();
pip.push_back(new OpCalculateScalarFieldValues(
"LAMBDA_SURFACE", res_lambda_ptr, SmartPetscObj<Vec>(F, true)));
pip.push_back(
new OpPPMap(
post_proc_fe->getPostProcMesh(),
post_proc_fe->getMapGaussPts(),
{{"LAMBDA_SURFACE", lambda_ptr},
{"RES_LAMBDA_SURFACE", res_lambda_ptr}},
{{"MESH_NODE_POSITIONS", X_ptr},
{"RES_MESH_NODE_POSITIONS", res_X_ptr}},
{},
{}
)
);
CHKERR DMoFEMLoopFiniteElements(dm, "SURFACE_SLIDING", post_proc_fe);
CHKERR post_proc_fe->writeFile("debug_smoothing.h5m");
};
auto snes_ctx_ptr = getDMSnesCtx(dm);
snes_ctx_ptr->getRhsHook() = hook;
CHKERR MeshSmoothingOps::solveSnes(dm, solver, {"LAMBDA_SURFACE"});
}
MoFEMErrorCode setCoordsFromField(DM dm) const {
MoFEM::Interface *m_field_ptr;
CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
"MESH_NODE_POSITIONS", it)) {
if (it->get()->getEntType() != MBVERTEX)
continue;
VectorDouble3 coords(3);
for(int dd = 0;dd!=3;++dd)
coords[dd] = it->get()->getEntFieldData()[dd];
EntityHandle ent = it->get()->getEnt();
CHKERR m_field_ptr->get_moab().set_coords(&ent, 1, &*coords.begin());
}
}
MoFEMErrorCode setFieldFromCoords(DM dm) const {
MoFEM::Interface *m_field_ptr;
CHKERR DMoFEMGetInterfacePtr(dm, &m_field_ptr);
"MESH_NODE_POSITIONS", it)) {
if (it->get()->getEntType() != MBVERTEX)
continue;
EntityHandle ent = it->get()->getEnt();
VectorDouble3 coords(3);
CHKERR m_field_ptr->get_moab().get_coords(&ent, 1, &*coords.begin());
for(int dd = 0;dd!=3;++dd)
it->get()->getEntFieldData()[dd] = coords[dd];
}
}
};
Solve solve;
CHKERR solve.setFieldFromCoords(dm);
double min_quality = 0;
dm, simple_interface->getDomainFEName(), smoothing_handles, min_quality);
PetscPrintf(PETSC_COMM_WORLD, "Min quality = %4.3f\n", min_quality);
double gamma = min_quality > 0 ? gamma_factor * min_quality
: min_quality / gamma_factor;
CHKERR MeshSmoothingOps::updateBarrierGamma(smoothing_handles, gamma);
double min_quality_p, eps;
do {
min_quality_p = min_quality;
CHKERR solve(dm);
CHKERR solve.setCoordsFromField(dm);
dm, simple_interface->getDomainFEName(), smoothing_handles,
min_quality);
eps = (min_quality - min_quality_p) / min_quality;
PetscPrintf(PETSC_COMM_WORLD, "Min quality = %4.3f eps = %4.3f\n",
min_quality, eps);
double gamma = min_quality > 0 ? gamma_factor * min_quality
: min_quality / gamma_factor;
CHKERR MeshSmoothingOps::updateBarrierGamma(smoothing_handles, gamma);
} while (eps > tol);
// if (m_field.getInterface<MeshsetsManager>()->checkMeshset(edges_block_set,
// BLOCKSET)) {
// Range edges;
// CHKERR m_field.getInterface<MeshsetsManager>()->getEntitiesByDimension(
// edges_block_set, BLOCKSET, 1, edges, true);
// Range tets;
// CHKERR moab.get_entities_by_type(0,MBTET,tets);
// Skinner skin(&moab);
// Range skin_faces; // skin faces from 3d ents
// CHKERR skin.find_skin(0, tets, false, skin_faces);
// CHKERR EdgeSlidingConstrains::CalculateEdgeBase::setTags(moab, edges,
// skin_faces);
// CHKERR EdgeSlidingConstrains::CalculateEdgeBase::saveEdges(
// moab, "out_edges.vtk", edges);
// }
CHKERR m_field.getInterface<BitRefManager>()->writeBitLevelByType(
BitRefLevel().set(0), BitRefLevel().set(), MBTET, "out.vtk", "VTK",
"");
}
}
Range &output_edges,
Range &output_vertices) {
Range fineFeatureTris;
Range vols;
CHKERR m_field.get_moab().get_entities_by_dimension(0, 3, vols);
if (vols.empty()) {
SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
"no 3d entities found in the mesh");
}
Skinner skinner(&m_field.get_moab());
Range skin_tris;
CHKERR skinner.find_skin(0, vols, false, skin_tris);
if (skin_tris.empty()) {
SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
"no skin triangles found in the mesh");
}
auto tri_normal = [&](const EntityHandle tri,
CHKERR m_field.getInterface<Tools>()->getTriNormal(tri, &normal(0));
normal.normalize();
};
const double fine_planar_cos = std::cos(1e-6); //FIXME: parameter?
Range skin_edges;
CHKERR m_field.get_moab().get_adjacencies(skin_tris, 1, true, skin_edges,
moab::Interface::UNION);
for (auto edge : skin_edges) {
Range adj_tris;
CHKERR m_field.get_moab().get_adjacencies(&edge, 1, 2, false, adj_tris,
moab::Interface::UNION);
adj_tris = intersect(adj_tris, skin_tris);
if (adj_tris.size() != 2) {
continue;
}
CHKERR tri_normal(adj_tris[0], n0);
CHKERR tri_normal(adj_tris[1], n1);
const double dot = n0(i) * n1(i);
if (std::abs(dot) <= fine_planar_cos) {
fineFeatureTris.insert(adj_tris[0]);
fineFeatureTris.insert(adj_tris[1]);
output_edges.insert(edge);
}
}
std::map<EntityHandle, std::vector<EntityHandle>> vert_edges;
for (auto edge : output_edges) {
const EntityHandle *conn = nullptr;
int nconn = 0;
CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
if (nconn != 2)
continue;
vert_edges[conn[0]].push_back(edge);
vert_edges[conn[1]].push_back(edge);
}
Range straight_edges;
for (auto edge : output_edges) {
const EntityHandle *conn = nullptr;
int nconn = 0;
CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
if (nconn != 2)
continue;
bool keep_edge = true;
for (int vv = 0; vv < 2; ++vv) {
const auto v = conn[vv];
const auto it = vert_edges.find(v);
if (it == vert_edges.end()) {
keep_edge = false;
break;
}
const auto &inc_edges = it->second;
if (inc_edges.size() > 2) {
keep_edge = false;
break;
}
if (inc_edges.size() == 2) {
const auto other_edge =
(inc_edges[0] == edge) ? inc_edges[1] : inc_edges[0];
const EntityHandle *conn_other = nullptr;
int nconn_other = 0;
CHKERR m_field.get_moab().get_connectivity(other_edge, conn_other,
nconn_other, false);
if (nconn_other != 2) {
keep_edge = false;
break;
}
const EntityHandle v_other =
(conn_other[0] == v) ? conn_other[1] : conn_other[0];
double pv[3], pa[3], pb[3];
CHKERR m_field.get_moab().get_coords(&v, 1, pv);
EntityHandle va = conn[1 - vv];
CHKERR m_field.get_moab().get_coords(&va, 1, pa);
CHKERR m_field.get_moab().get_coords(&v_other, 1, pb);
&pv[2]);
&pa[2]);
&pb[2]);
a(i) = t_pa(i) - t_pv(i);
b(i) = t_pb(i) - t_pv(i);
const double na = a.l2();
const double nb = b.l2();
if (na == 0 || nb == 0) {
keep_edge = false;
break;
}
const double dot = (a(i) * b(i)) / (na * nb);
if (std::abs(dot) < fine_planar_cos) {
keep_edge = false;
break;
}
}
}
if (keep_edge) {
straight_edges.insert(edge);
}
}
output_edges = straight_edges;
output_vertices.clear();
if (!output_edges.empty()) {
std::map<EntityHandle, int> vert_count;
for (auto edge : output_edges) {
const EntityHandle *conn = nullptr;
int nconn = 0;
CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
if (nconn != 2)
continue;
vert_count[conn[0]]++;
vert_count[conn[1]]++;
}
Range filtered_edges;
for (auto edge : output_edges) {
const EntityHandle *conn = nullptr;
int nconn = 0;
CHKERR m_field.get_moab().get_connectivity(edge, conn, nconn, false);
if (nconn != 2)
continue;
const int d0 = vert_count[conn[0]];
const int d1 = vert_count[conn[1]];
if (!(d0 == 1 && d1 == 1)) {
filtered_edges.insert(edge);
for (int vv = 0; vv < 2; ++vv) {
const auto v = conn[vv];
auto it = vert_count.find(v);
if (it != vert_count.end() && it->second == 1) {
output_vertices.insert(v);
}
}
}
}
output_edges = filtered_edges;
}
if (!fineFeatureTris.empty())
"tri_features_test.vtk", fineFeatureTris);
if (!output_edges.empty())
CHKERR CutMeshInterface::SaveData(m_field.get_moab())("edges_test.vtk",
output_edges);
if (!output_vertices.empty())
CHKERR CutMeshInterface::SaveData(m_field.get_moab())("vertices_test.vtk",
output_vertices);
}
Post-process fields on refined mesh.
#define FTENSOR_INDEX(DIM, I)
static char help[]
int main()
constexpr double a
static const double eps
#define CATCH_ERRORS
Catch errors.
@ MF_ZERO
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ AINSWORTH_LOBATTO_BASE
Definition definitions.h:62
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ 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 ...
@ BLOCKSET
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PostProcEleByDim< SPACE_DIM >::PostProcEleDomain PostProcEleDomain
@ F
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:576
PetscErrorCode DMoFEMGetInterfacePtr(DM dm, MoFEM::Interface **m_field_ptr)
Get pointer to MoFEM::Interface.
Definition DMMoFEM.cpp:410
#define _IT_GET_ENT_FIELD_BY_NAME_FOR_LOOP_(MFIELD, NAME, IT)
loop over all dofs from a moFEM field and particular field
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode add_ents_to_finite_element_by_type(const EntityHandle entities, const EntityType type, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
bool checkMeshset(const int ms_id, const CubitBCType cubit_bc_type) const
Check for CUBIT meshset by ID and type.
FTensor::Index< 'i', SPACE_DIM > i
MoFEM::PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::DomainEle Ele
const double v
phase velocity of light in medium (cm/ns)
const FTensor::Tensor2< T, Dim, Dim > Vec
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition ddTensor0.hpp:33
MoFEMErrorCode updateBarrierGamma(Handles &handles, double gamma)
MoFEMErrorCode evaluateMinQuality(DM dm, const std::string &domain_fe_name, const Handles &handles, double &min_quality)
MoFEMErrorCode createSnes(DM dm, SmartPetscObj< SNES > &snes)
MoFEMErrorCode solveSnes(DM dm, SNES snes, const std::vector< std::string > &zero_vertex_fields={})
MoFEMErrorCode createOperators(MoFEM::Interface &m_field, const Config &cfg, const Range &fixed_vertices, const Range &edge_entities, Handles &handles)
MoFEMErrorCode addToSnesDM(DM dm, const Config &cfg, const Handles &handles)
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
VectorBoundedArray< double, 3 > VectorDouble3
Definition Types.hpp:92
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto getInterfacePtr(DM dm)
Get the Interface Ptr object.
Definition DMMoFEM.hpp:1171
auto getDMSnesCtx(DM dm)
Get SNES context data structure used by DM.
Definition DMMoFEM.hpp:1265
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
AdolCOps::VolumeLengthQualityType qualityType
Managing BitRefLevels.
Managing BitRefLevels.
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
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:118
Deprecated interface functions.
Interface for managing meshsets containing materials and boundary conditions.
Specialization for double precision scalar field values calculation.
Specialization for double precision vector field values calculation.
Post post-proc data at points from hash maps.
Template struct for dimension-specific finite element types.
Problem manager is used to build and partition problems.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode buildProblem()
Build problem.
Definition Simple.cpp:721
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
const std::string getBoundaryFEName() const
Get the Boundary FE Name.
Definition Simple.hpp:436
MoFEMErrorCode defineFiniteElements()
Define finite elements.
Definition Simple.cpp:471
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
Definition Simple.cpp:191
MoFEMErrorCode buildFiniteElements()
Build finite elements.
Definition Simple.cpp:659
MoFEMErrorCode addBoundaryField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on boundary.
Definition Simple.cpp:355
std::vector< std::string > & getOtherFiniteElements()
Get the Other Finite Elements.
Definition Simple.hpp:508
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
MoFEMErrorCode buildFields()
Build fields.
Definition Simple.cpp:584
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
Definition Simple.cpp:575
MoFEMErrorCode defineProblem(const PetscBool is_partitioned=PETSC_TRUE)
define problem
Definition Simple.cpp:551
const std::string getProblemName() const
Get the Problem Name.
Definition Simple.hpp:450
const std::string getDomainFEName() const
Get the Domain FE Name.
Definition Simple.hpp:429
intrusive_ptr for managing petsc objects
Auxiliary tools.
Definition Tools.hpp:19
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
double tol
PetscBool output_vtk
constexpr bool fix_edge_blocks
static MoFEMErrorCode extract_mesh_edges(MoFEM::Interface &m_field, Range &output_edges, Range &output_vertices)
double gamma_factor
int vertex_block_set
int edges_block_set