6#ifndef EXECUTABLE_DIMENSION
7#define EXECUTABLE_DIMENSION 3
11static char help[] =
"...\n\n";
79 auto get_ents_by_dim = [&](
const auto dim) {
93 auto get_base = [&]() {
94 auto domain_ents = get_ents_by_dim(
SPACE_DIM);
95 if (domain_ents.empty())
113 auto base = get_base();
128 auto project_ho_geometry = [&]() {
134 CHKERR project_ho_geometry();
141 Range mat_electr_ents;
143 if (
bit->getName().compare(0, 12,
"MAT_ELECTRIC") == 0) {
144 const int id =
bit->getMeshsetId();
145 auto &block_data = (*permBlockSetsPtr)[id];
148 bit->getMeshset(),
SPACE_DIM, block_data.domainEnts,
true);
149 mat_electr_ents.merge(block_data.domainEnts);
151 const auto params_from_json =
152 json_config->getParamsFromBlockset(
"MAT_ELECTRIC",
id);
153 if (!params_from_json.empty()) {
154 block_data.epsPermit = params_from_json.at(
"permittivity");
156 std::vector<double> attributes;
157 bit->getAttributes(attributes);
158 if (attributes.size() < 1) {
160 " At least one permittivity attributes should be given but "
164 block_data.epsPermit = attributes[0];
172 Range int_electr_ents;
174 if (
bit->getName().compare(0, 12,
"INT_ELECTRIC") == 0) {
175 const int id =
bit->getMeshsetId();
176 auto &block_data = (*intBlockSetsPtr)[id];
179 bit->getMeshset(),
SPACE_DIM - 1, block_data.interfaceEnts,
true);
180 int_electr_ents.merge(block_data.interfaceEnts);
182 const auto params_from_json =
183 json_config->getParamsFromBlockset(
"INT_ELECTRIC",
id);
184 if (!params_from_json.empty()) {
185 block_data.chargeDensity = params_from_json.at(
"charge_density");
187 std::vector<double> attributes;
188 bit->getAttributes(attributes);
189 if (attributes.size() < 1) {
191 "At least one charge attributes should be given but found %zu",
194 block_data.chargeDensity = attributes[0];
202 Range electrode_ents;
203 int electrodeCount = 0;
205 if (
bit->getName().compare(0, 9,
"ELECTRODE") == 0) {
206 const int id =
bit->getMeshsetId();
207 auto &block_data = (*electrodeBlockSetsPtr)[id];
211 bit->getMeshset(),
SPACE_DIM - 1, block_data.electrodeEnts,
true);
212 electrode_ents.merge(block_data.electrodeEnts);
215 if (electrodeCount > 2) {
217 "Three or more electrode blocksets found");
238 CHKERR skinner.find_skin(0, mat_electr_ents,
false, skin_tris);
240 ParallelComm *pcomm =
243 CHKERR pcomm->filter_pstatus(skin_tris,
244 PSTATUS_SHARED | PSTATUS_MULTISHARED,
245 PSTATUS_NOT, -1, &proc_skin);
247 proc_skin = skin_tris;
291 DMType dm_name =
"DMMOFEM";
298 CHKERR DMSetType(dm, dm_name);
337 auto rule_lhs = [
this](int, int,
int p) ->
int {
return 2 * p +
geomOrder -1; };
338 auto rule_rhs = [
this](int, int,
int p) ->
int {
return 2 * p +
geomOrder -1; };
342 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule_rhs);
355 auto add_domain_base_ops = [&](
auto &pipeline) {
363 add_domain_base_ops(pipeline_mng->getOpDomainLhsPipeline());
369 pipeline_mng->getOpDomainLhsPipeline().push_back(
374 auto set_values_to_bc_dofs = [&](
auto &fe) {
375 auto get_bc_hook = [&]() {
379 fe->preProcessHook = get_bc_hook();
382 auto calculate_residual_from_set_values_on_bc = [&](
auto &pipeline) {
387 add_domain_base_ops(pipeline_mng->getOpDomainRhsPipeline());
389 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
390 pipeline_mng->getOpDomainRhsPipeline().push_back(
396 pipeline_mng->getOpDomainRhsPipeline().push_back(
397 new OpInternal(
domainField, grad_u_ptr, minus_epsilon));
400 set_values_to_bc_dofs(pipeline_mng->getDomainRhsFE());
401 calculate_residual_from_set_values_on_bc(
402 pipeline_mng->getOpDomainRhsPipeline());
407 pipeline_mng->getOpDomainRhsPipeline().push_back(
443 auto ksp_solver = pipeline_mng->
createKSP();
445 boost::shared_ptr<ForcesAndSourcesCore> null;
451 CHKERR KSPSetFromOptions(ksp_solver);
457 CHKERR KSPSetUp(ksp_solver);
460 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
461 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
464 CHKERR VecNorm(
F, NORM_2, &fnorm);
465 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"F norm = %9.8e\n", fnorm);
468 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
469 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
472 CHKERR VecNorm(
D, NORM_2, &dnorm);
473 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"D norm = %9.8e\n", dnorm);
486 pipeline_mng->getBoundaryLhsFE().reset();
487 pipeline_mng->getBoundaryRhsFE().reset();
488 pipeline_mng->getDomainLhsFE().reset();
489 auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
492 auto calculate_e_field = [&](
auto &pipeline) {
493 auto u_ptr = boost::make_shared<VectorDouble>();
494 auto x_ptr = boost::make_shared<MatrixDouble>();
495 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
496 auto e_field_ptr = boost::make_shared<MatrixDouble>();
510 return boost::make_tuple(u_ptr, e_field_ptr, x_ptr);
513 auto [u_ptr, e_field_ptr, x_ptr] =
514 calculate_e_field(post_proc_fe->getOpPtrVector());
516 auto e_field_times_perm_ptr = boost::make_shared<MatrixDouble>();
517 auto energy_density_ptr = boost::make_shared<VectorDouble>();
519 post_proc_fe->getOpPtrVector().push_back(
522 post_proc_fe->getOpPtrVector().push_back(
527 post_proc_fe->getOpPtrVector().push_back(
new OpPPMap(
528 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
531 {
"ENERGY_DENSITY", energy_density_ptr}},
534 {
"ELECTRIC_FIELD", e_field_ptr},
535 {
"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr},
543 pipeline_mng->getDomainRhsFE() = post_proc_fe;
544 CHKERR pipeline_mng->loopFiniteElements();
545 CHKERR post_proc_fe->writeFile(
"out.h5m");
549 auto post_proc_skin = boost::make_shared<PostProcFaceEle>(mField);
551 mField, simpleInterface->getDomainFEName(),
SPACE_DIM);
553 auto [u_ptr, e_field_ptr, x_ptr] =
554 calculate_e_field(op_loop_skin->getOpPtrVector());
556 op_loop_skin->getOpPtrVector().push_back(
558 permBlockSetsPtr, commonDataPtr));
559 op_loop_skin->getOpPtrVector().push_back(
561 permBlockSetsPtr, commonDataPtr));
564 post_proc_skin->getOpPtrVector().push_back(op_loop_skin);
566 post_proc_skin->getOpPtrVector().push_back(
new OpPPMap(
567 post_proc_skin->getPostProcMesh(), post_proc_skin->getMapGaussPts(),
569 {
"ENERGY_DENSITY", energy_density_ptr}},
572 {
"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr}},
577 CHKERR post_proc_skin->writeFile(
"out_skin.h5m");
588 pip_energy->getDomainLhsFE().reset();
589 pip_energy->getBoundaryLhsFE().reset();
590 pip_energy->getBoundaryRhsFE().reset();
591 pip_energy->getOpDomainRhsPipeline().clear();
592 pip_energy->getOpDomainLhsPipeline().clear();
596 boost::shared_ptr<std::map<int, BlockData>> intrnlDomnBlckSetPtr =
597 boost::make_shared<std::map<int, BlockData>>();
598 Range internal_domain;
600 if (
bit->getName().compare(0, 10,
"DOMAIN_INT") == 0) {
601 const int id =
bit->getMeshsetId();
602 auto &block_data = (*intrnlDomnBlckSetPtr)[id];
605 bit->getMeshset(),
SPACE_DIM, block_data.internalDomainEnts,
true);
606 internal_domain.merge(block_data.internalDomainEnts);
614 pip_energy->getOpDomainRhsPipeline(), {H1},
"GEOMETRY");
616 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
617 auto e_field_ptr = boost::make_shared<MatrixDouble>();
619 pip_energy->getOpDomainRhsPipeline().push_back(
621 pip_energy->getOpDomainRhsPipeline().push_back(
626 pip_energy->getOpDomainRhsPipeline().push_back(
630 pip_energy->loopFiniteElements();
634 double total_energy = 0.0;
639 total_energy = array[
ZERO];
641 MOFEM_LOG_C(
"SELF", Sev::inform,
"Total Energy: %6.15f", total_energy);
656 op_loop_side->getOpPtrVector(), {H1},
"GEOMETRY");
658 auto grad_u_ptr_charge = boost::make_shared<MatrixDouble>();
659 auto e_ptr_charge = boost::make_shared<MatrixDouble>();
661 op_loop_side->getOpPtrVector().push_back(
665 op_loop_side->getOpPtrVector().push_back(
667 auto d_jump = boost::make_shared<MatrixDouble>();
693 double aLpha = array[0];
694 double bEta = array[1];
697 "CHARGE_ELEC_1: %6.15f , CHARGE_ELEC_2: %6.15f",
aLpha,
bEta);
702 double cal_charge_elec1;
703 double cal_charge_elec2;
704 double cal_total_energy;
705 const double *c_ptr, *te_ptr;
712 double ref_charge_elec1;
713 double ref_charge_elec2;
715 double ref_tot_energy;
717 cal_charge_elec1 = c_ptr[0];
718 cal_charge_elec2 = c_ptr[1];
719 cal_total_energy = te_ptr[0];
720 if (std::isnan(cal_charge_elec1) || std::isnan(cal_charge_elec2) ||
721 std::isnan(cal_total_energy)) {
723 "Atom test failed! NaN detected in calculated values.");
729 ref_charge_elec1 = 50.0;
730 ref_charge_elec2 = -50.0;
732 ref_tot_energy = 500.0;
736 ref_charge_elec1 = 10.00968352472943;
737 ref_charge_elec2 = 0.0;
738 ref_tot_energy = 50.5978;
743 "atom test %d does not exist",
atomTest);
747 if (std::abs(ref_charge_elec1 - cal_charge_elec1) >
tol ||
748 std::abs(ref_charge_elec2 - cal_charge_elec2) >
tol ||
749 std::abs(ref_tot_energy - cal_total_energy) >
tol) {
752 "atom test %d failed! Calculated values do not match expected values",
783int main(
int argc,
char *argv[]) {
785 const char param_file[] =
"param_file.petsc";
791 DMType dm_name =
"DMMOFEM";
795 moab::Core mb_instance;
796 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, RowColData rc=RowColData::COL)
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, RowColData rc=RowColData::COL)
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.
Interface for managing meshsets containing materials and boundary conditions.
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 MatrixDouble 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, ScalarDataPtr > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
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.