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 nme:nme847.
#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.
constexpr auto domainField
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpBodySourceVectorb
intPostProc< SPACE_DIM >::intEle IntElementForcesAndSourcesCore
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
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 compute operator for KSP solver via sub-matrix and IS.
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.
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.
Simple interface for fast problem set-up.
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.
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 filed rank 0, i.e. vector field.
Get value at integration points for scalar field.
Get values at integration pts for tensor filed rank 1, i.e. vector field.
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< VectorDouble > > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
PipelineManager interface.
boost::shared_ptr< FEMethod > & getDomainRhsFE()
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
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 field on domain.
bool & getAddSkeletonFE()
Get the addSkeletonFE.
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.