6#ifndef EXECUTABLE_DIMENSION 
    7#define EXECUTABLE_DIMENSION 3 
   11static char help[] = 
"...\n\n";
 
   78  auto get_ents_by_dim = [&](
const auto dim) {
 
   92  auto get_base = [&]() {
 
   93    auto domain_ents = get_ents_by_dim(
SPACE_DIM);
 
   94    if (domain_ents.empty())
 
  112  auto base = get_base();
 
  127  auto project_ho_geometry = [&]() {
 
  133  CHKERR project_ho_geometry();
 
  139  Range mat_electr_ents; 
 
  141    if (
bit->getName().compare(0, 12, 
"MAT_ELECTRIC") == 0) {
 
  142      const int id = 
bit->getMeshsetId();
 
  143      auto &block_data = (*permBlockSetsPtr)[id];
 
  146          bit->getMeshset(), 
SPACE_DIM, block_data.domainEnts, 
true);
 
  147      mat_electr_ents.merge(block_data.domainEnts);
 
  149      std::vector<double> attributes;
 
  150      bit->getAttributes(attributes);
 
  151      if (attributes.size() < 1) {
 
  153                 " At least one permittivity attributes should be given but " 
  158      block_data.epsPermit = attributes[0]; 
 
  164  Range int_electr_ents; 
 
  166    if (
bit->getName().compare(0, 12, 
"INT_ELECTRIC") == 0) {
 
  167      const int id = 
bit->getMeshsetId();
 
  168      auto &block_data = (*intBlockSetsPtr)[id];
 
  171          bit->getMeshset(), 
SPACE_DIM - 1, block_data.interfaceEnts, 
true);
 
  172      int_electr_ents.merge(block_data.interfaceEnts);
 
  174      std::vector<double> attributes;
 
  175      bit->getAttributes(attributes);
 
  176      if (attributes.size() < 1) {
 
  178                 "At least one charge attributes should be given but found %d",
 
  183      block_data.chargeDensity = attributes[0]; 
 
  188  Range electrode_ents; 
 
  189  int electrodeCount = 0;
 
  191    if (
bit->getName().compare(0, 9, 
"ELECTRODE") == 0) {
 
  192      const int id = 
bit->getMeshsetId();
 
  193      auto &block_data = (*electrodeBlockSetsPtr)[id];
 
  197          bit->getMeshset(), 
SPACE_DIM - 1, block_data.electrodeEnts, 
true);
 
  198      electrode_ents.merge(block_data.electrodeEnts);
 
  201      if (electrodeCount > 2) {
 
  203                "Three or more electrode blocksets found");
 
  224  CHKERR skinner.find_skin(0, mat_electr_ents, 
false, skin_tris);
 
  226  ParallelComm *pcomm =
 
  229    CHKERR pcomm->filter_pstatus(skin_tris,
 
  230                                 PSTATUS_SHARED | PSTATUS_MULTISHARED,
 
  231                                 PSTATUS_NOT, -1, &proc_skin);
 
  233    proc_skin = skin_tris;
 
  277  DMType dm_name = 
"DMMOFEM";
 
  284  CHKERR DMSetType(dm, dm_name);
 
 
  323  auto rule_lhs = [
this](int, int, 
int p) -> 
int { 
return 2 * p + 
geomOrder -1; };
 
  324  auto rule_rhs = [
this](int, int, 
int p) -> 
int { 
return 2 * p + 
geomOrder -1; };
 
  328  CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule_rhs);
 
 
  341  auto add_domain_base_ops = [&](
auto &pipeline) {
 
  349  add_domain_base_ops(pipeline_mng->getOpDomainLhsPipeline());
 
  355    pipeline_mng->getOpDomainLhsPipeline().push_back(
 
  360    auto set_values_to_bc_dofs = [&](
auto &fe) {
 
  361      auto get_bc_hook = [&]() {
 
  365      fe->preProcessHook = get_bc_hook();
 
  368    auto calculate_residual_from_set_values_on_bc = [&](
auto &pipeline) {
 
  373      add_domain_base_ops(pipeline_mng->getOpDomainRhsPipeline());
 
  375      auto grad_u_ptr = boost::make_shared<MatrixDouble>();
 
  376      pipeline_mng->getOpDomainRhsPipeline().push_back(
 
  382      pipeline_mng->getOpDomainRhsPipeline().push_back(
 
  383          new OpInternal(
domainField, grad_u_ptr, minus_epsilon));
 
  386    set_values_to_bc_dofs(pipeline_mng->getDomainRhsFE());
 
  387    calculate_residual_from_set_values_on_bc(
 
  388        pipeline_mng->getOpDomainRhsPipeline());
 
  393    pipeline_mng->getOpDomainRhsPipeline().push_back(
 
 
  429  auto ksp_solver = pipeline_mng->
createKSP();
 
  431  boost::shared_ptr<ForcesAndSourcesCore> null; 
 
  437  CHKERR KSPSetFromOptions(ksp_solver);
 
  443  CHKERR KSPSetUp(ksp_solver);
 
  446  CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
 
  447  CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
 
  450  CHKERR VecNorm(
F, NORM_2, &fnorm);
 
  451  CHKERR PetscPrintf(PETSC_COMM_WORLD, 
"F norm  = %9.8e\n", fnorm);
 
  454  CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
 
  455  CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
 
  458  CHKERR VecNorm(
D, NORM_2, &dnorm);
 
  459  CHKERR PetscPrintf(PETSC_COMM_WORLD, 
"D norm  = %9.8e\n", dnorm);
 
 
  472  pipeline_mng->getBoundaryLhsFE().reset();
 
  473  pipeline_mng->getBoundaryRhsFE().reset(); 
 
  474  pipeline_mng->getDomainLhsFE().reset();
 
  475  auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
 
  478  auto calculate_e_field = [&](
auto &pipeline) {
 
  479    auto u_ptr = boost::make_shared<VectorDouble>();
 
  480    auto x_ptr = boost::make_shared<MatrixDouble>();
 
  481    auto grad_u_ptr = boost::make_shared<MatrixDouble>();
 
  482    auto e_field_ptr = boost::make_shared<MatrixDouble>();
 
  496    return boost::make_tuple(u_ptr, e_field_ptr, x_ptr);
 
  499  auto [u_ptr, e_field_ptr, x_ptr] =
 
  500      calculate_e_field(post_proc_fe->getOpPtrVector());
 
  502  auto e_field_times_perm_ptr = boost::make_shared<MatrixDouble>();
 
  503  auto energy_density_ptr = boost::make_shared<VectorDouble>();
 
  505  post_proc_fe->getOpPtrVector().push_back(
 
  508  post_proc_fe->getOpPtrVector().push_back(
 
  513  post_proc_fe->getOpPtrVector().push_back(
new OpPPMap(
 
  514      post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
 
  517                          {
"ENERGY_DENSITY", energy_density_ptr}},
 
  520          {
"ELECTRIC_FIELD", e_field_ptr},
 
  521          {
"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr},
 
  529  pipeline_mng->getDomainRhsFE() = post_proc_fe;
 
  530  CHKERR pipeline_mng->loopFiniteElements();
 
  531  CHKERR post_proc_fe->writeFile(
"out.h5m");
 
  535    auto post_proc_skin = boost::make_shared<PostProcFaceEle>(mField);
 
  537        mField, simpleInterface->getDomainFEName(), 
SPACE_DIM);
 
  539    auto [u_ptr, e_field_ptr, x_ptr] =
 
  540        calculate_e_field(op_loop_skin->getOpPtrVector());
 
  542    op_loop_skin->getOpPtrVector().push_back(
 
  544                            permBlockSetsPtr, commonDataPtr));
 
  545    op_loop_skin->getOpPtrVector().push_back(
 
  547                            permBlockSetsPtr, commonDataPtr));
 
  550    post_proc_skin->getOpPtrVector().push_back(op_loop_skin);
 
  552    post_proc_skin->getOpPtrVector().push_back(
new OpPPMap(
 
  553        post_proc_skin->getPostProcMesh(), post_proc_skin->getMapGaussPts(),
 
  555                            {
"ENERGY_DENSITY", energy_density_ptr}},
 
  558                            {
"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr}},
 
  563    CHKERR post_proc_skin->writeFile(
"out_skin.h5m");
 
 
  574  pip_energy->getDomainLhsFE().reset();
 
  575  pip_energy->getBoundaryLhsFE().reset();
 
  576  pip_energy->getBoundaryRhsFE().reset();
 
  577  pip_energy->getOpDomainRhsPipeline().clear();
 
  578  pip_energy->getOpDomainLhsPipeline().clear();
 
  582  boost::shared_ptr<std::map<int, BlockData>> intrnlDomnBlckSetPtr =
 
  583      boost::make_shared<std::map<int, BlockData>>();
 
  584  Range internal_domain; 
 
  586    if (
bit->getName().compare(0, 10, 
"DOMAIN_INT") == 0) {
 
  587      const int id = 
bit->getMeshsetId();
 
  588      auto &block_data = (*intrnlDomnBlckSetPtr)[id];
 
  591          bit->getMeshset(), 
SPACE_DIM, block_data.internalDomainEnts, 
true);
 
  592      internal_domain.merge(block_data.internalDomainEnts);
 
  600      pip_energy->getOpDomainRhsPipeline(), {H1}, 
"GEOMETRY");
 
  602  auto grad_u_ptr = boost::make_shared<MatrixDouble>();
 
  603  auto e_field_ptr = boost::make_shared<MatrixDouble>();
 
  605  pip_energy->getOpDomainRhsPipeline().push_back(
 
  607  pip_energy->getOpDomainRhsPipeline().push_back(
 
  612  pip_energy->getOpDomainRhsPipeline().push_back(
 
  616  pip_energy->loopFiniteElements();
 
  620  double total_energy = 0.0; 
 
  625    total_energy = array[
ZERO];
 
  627    MOFEM_LOG_C(
"SELF", Sev::inform, 
"Total Energy: %6.15f", total_energy);
 
 
  642      op_loop_side->getOpPtrVector(), {H1}, 
"GEOMETRY");
 
  644  auto grad_u_ptr_charge = boost::make_shared<MatrixDouble>();
 
  645  auto e_ptr_charge = boost::make_shared<MatrixDouble>();
 
  647  op_loop_side->getOpPtrVector().push_back(
 
  651  op_loop_side->getOpPtrVector().push_back(
 
  653  auto d_jump = boost::make_shared<MatrixDouble>();
 
  679    double aLpha = array[0]; 
 
  680    double bEta = array[1];  
 
  683                "CHARGE_ELEC_1: %6.15f , CHARGE_ELEC_2: %6.15f", 
aLpha, 
bEta);
 
  688    double cal_charge_elec1;
 
  689    double cal_charge_elec2;
 
  690    double cal_total_energy;
 
  691    const double *c_ptr, *te_ptr;
 
  698    double ref_charge_elec1;
 
  699    double ref_charge_elec2;
 
  701    double ref_tot_energy;
 
  703    cal_charge_elec1 = c_ptr[0];  
 
  704    cal_charge_elec2 = c_ptr[1];  
 
  705    cal_total_energy = te_ptr[0]; 
 
  706    if (std::isnan(cal_charge_elec1) || std::isnan(cal_charge_elec2) ||
 
  707        std::isnan(cal_total_energy)) {
 
  709              "Atom test failed! NaN detected in calculated values.");
 
  714      ref_charge_elec1 = 50.0;
 
  715      ref_charge_elec2 = -50.0;
 
  717      ref_tot_energy = 500.0;
 
  721      ref_charge_elec1 = 10.00968352472943;
 
  722      ref_charge_elec2 = 0.0; 
 
  723      ref_tot_energy = 50.5978;
 
  728               "atom test %d does not exist", 
atomTest);
 
  732    if (std::abs(ref_charge_elec1 - cal_charge_elec1) > 
tol ||
 
  733        std::abs(ref_charge_elec2 - cal_charge_elec2) > 
tol ||
 
  734        std::abs(ref_tot_energy - cal_total_energy) > 
tol) {
 
  737          "atom test %d failed! Calculated values do not match expected values",
 
 
  768int main(
int argc, 
char *argv[]) {
 
  770  const char param_file[] = 
"param_file.petsc";
 
  776    DMType dm_name = 
"DMMOFEM";
 
  780    moab::Core mb_instance;              
 
  781    moab::Interface &moab = mb_instance; 
 
 
#define MOFEM_LOG_C(channel, severity, format,...)
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
FormsIntegrators< IntEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpInterfaceRhsVectorF
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< BASE_DIM, FIELD_DIM, SPACE_DIM > OpDomainLhsMatrixK
constexpr auto domainField
intPostProc< SPACE_DIM >::intEle IntElementForcesAndSourcesCore
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpBodySourceVectorb
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
PetscErrorCode DMMoFEMKSPSetComputeRHS(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set KSP right hand side evaluation function
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
auto createDMVector(DM dm)
Get smart vector from DM.
PetscErrorCode DMoFEMLoopFiniteElementsUpAndLowRank(DM dm, const char fe_name[], MoFEM::FEMethod *method, int low_rank, int up_rank, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
SmartPetscObj< KSP > createKSP(SmartPetscObj< DM > dm=nullptr)
Create KSP (linear) solver.
virtual MoFEMErrorCode add_ents_to_finite_element_by_dim(const EntityHandle entities, const int dim, const std::string name, const bool recursive=true)=0
add entities to finite element
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 build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
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 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
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
#define _IT_CUBITMESHSETS_BY_SET_TYPE_FOR_LOOP_(MESHSET_MANAGER, CUBITBCTYPE, IT)
Iterator that loops over a specific Cubit MeshSet having a particular BC meshset in a moFEM field.
MoFEMErrorCode removeBlockDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true, bool is_distributed_mesh=true)
Remove DOFs from problem based on block entities.
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
auto type_from_handle(const EntityHandle h)
get type from entity handle
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)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
boost::shared_ptr< ForcesAndSourcesCore > electrodeRhsFe
boost::shared_ptr< ForcesAndSourcesCore > interFaceRhsFe
boost::shared_ptr< std::map< int, BlockData > > intBlockSetsPtr
SmartPetscObj< Vec > petscVec
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
MoFEM::Interface & mField
MoFEMErrorCode runProgram()
[Get Charges]
MoFEMErrorCode setupProblem()
[Read mesh]
MoFEMErrorCode outputResults()
[Solve system]
MoFEMErrorCode setIntegrationRules()
[Boundary condition]
Electrostatics(MoFEM::Interface &m_field)
MoFEMErrorCode getElectrodeCharge()
[Get Total Energy]
MoFEMErrorCode readMesh()
[Read mesh]
SmartPetscObj< Vec > petscVecEnergy
boost::shared_ptr< std::map< int, BlockData > > permBlockSetsPtr
MoFEMErrorCode assembleSystem()
[Set integration rules]
boost::shared_ptr< std::map< int, BlockData > > electrodeBlockSetsPtr
MoFEMErrorCode getTotalEnergy()
[Output results]
MoFEMErrorCode boundaryCondition()
[Setup problem]
MoFEMErrorCode solveSystem()
[Assemble system]
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Template specialization for scalar field boundary conditions.
virtual int get_comm_size() const =0
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Deprecated interface functions.
Class (Function) to enforce essential constrains.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for double precision scalar field values calculation.
Specialization for double precision vector field values calculation.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
std::map< std::string, boost::shared_ptr< VectorDouble > > DataMapVec
PipelineManager interface.
boost::shared_ptr< FEMethod > & getDomainRhsFE()
Get domain right-hand side finite element.
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain left-hand side finite element.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
MoFEMErrorCode buildProblem()
Build problem.
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.
MoFEMErrorCode defineFiniteElements()
Define finite elements.
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
MoFEMErrorCode buildFiniteElements()
Build finite elements.
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.
MoFEMErrorCode getOptions()
get options
MoFEMErrorCode getDM(DM *dm)
Get DM.
MoFEMErrorCode buildFields()
Build fields.
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
MoFEMErrorCode defineProblem(const PetscBool is_partitioned=PETSC_TRUE)
define problem
MoFEMErrorCode addDataField(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 data field.
bool & getAddSkeletonFE()
Get the addSkeletonFE flag.
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
const std::string getProblemName() const
Get the Problem Name.
const std::string getDomainFEName() const
Get the Domain FE Name.
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.