6#ifndef EXECUTABLE_DIMENSION
7#define EXECUTABLE_DIMENSION 3
11static char help[] =
"...\n\n";
67 {
"permittivity",
"charge_density"});
81 auto get_ents_by_dim = [&](
const auto dim) {
95 auto get_base = [&]() {
96 auto domain_ents = get_ents_by_dim(
SPACE_DIM);
97 if (domain_ents.empty())
115 auto base = get_base();
130 auto project_ho_geometry = [&]() {
136 CHKERR project_ho_geometry();
142 Range mat_electr_ents;
144 if (
bit->getName().compare(0, 12,
"MAT_ELECTRIC") == 0) {
145 const int id =
bit->getMeshsetId();
146 auto &block_data = (*permBlockSetsPtr)[id];
149 bit->getMeshset(),
SPACE_DIM, block_data.domainEnts,
true);
150 mat_electr_ents.merge(block_data.domainEnts);
152 std::vector<double> attributes;
153 bit->getAttributes(attributes);
154 if (attributes.size() < 1) {
156 " At least one permittivity attributes should be given but "
160 block_data.epsPermit = attributes[0];
167 Range int_electr_ents;
169 if (
bit->getName().compare(0, 12,
"INT_ELECTRIC") == 0) {
170 const int id =
bit->getMeshsetId();
171 auto &block_data = (*intBlockSetsPtr)[id];
174 bit->getMeshset(),
SPACE_DIM - 1, block_data.interfaceEnts,
true);
175 int_electr_ents.merge(block_data.interfaceEnts);
177 std::vector<double> attributes;
178 bit->getAttributes(attributes);
179 if (attributes.size() < 1) {
181 "At least one charge attributes should be given but found %zu",
184 block_data.chargeDensity = attributes[0];
191 Range electrode_ents;
192 int electrodeCount = 0;
194 if (
bit->getName().compare(0, 9,
"ELECTRODE") == 0) {
195 const int id =
bit->getMeshsetId();
196 auto &block_data = (*electrodeBlockSetsPtr)[id];
200 bit->getMeshset(),
SPACE_DIM - 1, block_data.electrodeEnts,
true);
201 electrode_ents.merge(block_data.electrodeEnts);
204 if (electrodeCount > 2) {
206 "Three or more electrode blocksets found");
227 CHKERR skinner.find_skin(0, mat_electr_ents,
false, skin_tris);
229 ParallelComm *pcomm =
232 CHKERR pcomm->filter_pstatus(skin_tris,
233 PSTATUS_SHARED | PSTATUS_MULTISHARED,
234 PSTATUS_NOT, -1, &proc_skin);
236 proc_skin = skin_tris;
280 DMType dm_name =
"DMMOFEM";
287 CHKERR DMSetType(dm, dm_name);
326 auto rule_lhs = [
this](int, int,
int p) ->
int {
return 2 * p +
geomOrder -1; };
327 auto rule_rhs = [
this](int, int,
int p) ->
int {
return 2 * p +
geomOrder -1; };
331 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule_rhs);
344 auto add_domain_base_ops = [&](
auto &pipeline) {
352 add_domain_base_ops(pipeline_mng->getOpDomainLhsPipeline());
358 pipeline_mng->getOpDomainLhsPipeline().push_back(
363 auto set_values_to_bc_dofs = [&](
auto &fe) {
364 auto get_bc_hook = [&]() {
368 fe->preProcessHook = get_bc_hook();
371 auto calculate_residual_from_set_values_on_bc = [&](
auto &pipeline) {
376 add_domain_base_ops(pipeline_mng->getOpDomainRhsPipeline());
378 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
379 pipeline_mng->getOpDomainRhsPipeline().push_back(
385 pipeline_mng->getOpDomainRhsPipeline().push_back(
386 new OpInternal(
domainField, grad_u_ptr, minus_epsilon));
389 set_values_to_bc_dofs(pipeline_mng->getDomainRhsFE());
390 calculate_residual_from_set_values_on_bc(
391 pipeline_mng->getOpDomainRhsPipeline());
396 pipeline_mng->getOpDomainRhsPipeline().push_back(
432 auto ksp_solver = pipeline_mng->
createKSP();
434 boost::shared_ptr<ForcesAndSourcesCore> null;
440 CHKERR KSPSetFromOptions(ksp_solver);
446 CHKERR KSPSetUp(ksp_solver);
449 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
450 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
453 CHKERR VecNorm(
F, NORM_2, &fnorm);
454 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"F norm = %9.8e\n", fnorm);
457 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
458 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
461 CHKERR VecNorm(
D, NORM_2, &dnorm);
462 CHKERR PetscPrintf(PETSC_COMM_WORLD,
"D norm = %9.8e\n", dnorm);
474 auto post_proc_fe = boost::make_shared<PostProcEle>(
mField);
477 auto calculate_e_field = [&](
auto &pipeline) {
478 auto u_ptr = boost::make_shared<VectorDouble>();
479 auto x_ptr = boost::make_shared<MatrixDouble>();
480 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
481 auto e_field_ptr = boost::make_shared<MatrixDouble>();
495 return boost::make_tuple(u_ptr, e_field_ptr, x_ptr);
498 auto [u_ptr, e_field_ptr, x_ptr] =
499 calculate_e_field(post_proc_fe->getOpPtrVector());
501 auto e_field_times_perm_ptr = boost::make_shared<MatrixDouble>();
502 auto energy_density_ptr = boost::make_shared<VectorDouble>();
504 post_proc_fe->getOpPtrVector().push_back(
507 post_proc_fe->getOpPtrVector().push_back(
512 post_proc_fe->getOpPtrVector().push_back(
new OpPPMap(
513 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
516 {
"ENERGY_DENSITY", energy_density_ptr}},
519 {
"ELECTRIC_FIELD", e_field_ptr},
520 {
"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr},
529 CHKERR pipeline_mng->loopFiniteElementsPostProc();
530 CHKERR post_proc_fe->writeFile(
"out.h5m");
534 auto post_proc_skin = boost::make_shared<PostProcFaceEle>(mField);
536 mField, simpleInterface->getDomainFEName(),
SPACE_DIM);
538 auto [u_ptr, e_field_ptr, x_ptr] =
539 calculate_e_field(op_loop_skin->getOpPtrVector());
541 op_loop_skin->getOpPtrVector().push_back(
543 permBlockSetsPtr, commonDataPtr));
544 op_loop_skin->getOpPtrVector().push_back(
546 permBlockSetsPtr, commonDataPtr));
549 post_proc_skin->getOpPtrVector().push_back(op_loop_skin);
551 post_proc_skin->getOpPtrVector().push_back(
new OpPPMap(
552 post_proc_skin->getPostProcMesh(), post_proc_skin->getMapGaussPts(),
554 {
"ENERGY_DENSITY", energy_density_ptr}},
557 {
"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr}},
562 CHKERR post_proc_skin->writeFile(
"out_skin.h5m");
573 auto rule = [
this](int, int,
int p) {
return 2 * p +
geomOrder - 1; };
575 auto &evaluation_pipeline = pip_energy->getOpEvaluationPipeline();
579 boost::shared_ptr<std::map<int, BlockData>> intrnlDomnBlckSetPtr =
580 boost::make_shared<std::map<int, BlockData>>();
581 Range internal_domain;
583 if (
bit->getName().compare(0, 10,
"DOMAIN_INT") == 0) {
584 const int id =
bit->getMeshsetId();
585 auto &block_data = (*intrnlDomnBlckSetPtr)[id];
588 bit->getMeshset(),
SPACE_DIM, block_data.internalDomainEnts,
true);
589 internal_domain.merge(block_data.internalDomainEnts);
599 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
600 auto e_field_ptr = boost::make_shared<MatrixDouble>();
602 evaluation_pipeline.push_back(
604 evaluation_pipeline.push_back(
new OpElectricField(e_field_ptr, grad_u_ptr));
608 evaluation_pipeline.push_back(
612 CHKERR pip_energy->loopFiniteElementsEvaluation();
616 double total_energy = 0.0;
621 total_energy = array[
ZERO];
623 MOFEM_LOG_C(
"SELF", Sev::inform,
"Total Energy: %6.15f", total_energy);
638 op_loop_side->getOpPtrVector(), {H1},
"GEOMETRY");
640 auto grad_u_ptr_charge = boost::make_shared<MatrixDouble>();
641 auto e_ptr_charge = boost::make_shared<MatrixDouble>();
643 op_loop_side->getOpPtrVector().push_back(
647 op_loop_side->getOpPtrVector().push_back(
649 auto d_jump = boost::make_shared<MatrixDouble>();
675 double aLpha = array[0];
676 double bEta = array[1];
679 "CHARGE_ELEC_1: %6.15f , CHARGE_ELEC_2: %6.15f",
aLpha,
bEta);
684 double cal_charge_elec1;
685 double cal_charge_elec2;
686 double cal_total_energy;
687 const double *c_ptr, *te_ptr;
694 double ref_charge_elec1;
695 double ref_charge_elec2;
697 double ref_tot_energy;
699 cal_charge_elec1 = c_ptr[0];
700 cal_charge_elec2 = c_ptr[1];
701 cal_total_energy = te_ptr[0];
702 if (std::isnan(cal_charge_elec1) || std::isnan(cal_charge_elec2) ||
703 std::isnan(cal_total_energy)) {
705 "Atom test failed! NaN detected in calculated values.");
711 ref_charge_elec1 = 50.0;
712 ref_charge_elec2 = -50.0;
714 ref_tot_energy = 500.0;
718 ref_charge_elec1 = 10.00968352472943;
719 ref_charge_elec2 = 0.0;
720 ref_tot_energy = 50.5978;
725 "atom test %d does not exist",
atomTest);
729 if (std::abs(ref_charge_elec1 - cal_charge_elec1) >
tol ||
730 std::abs(ref_charge_elec2 - cal_charge_elec2) >
tol ||
731 std::abs(ref_tot_energy - cal_total_energy) >
tol) {
734 "atom test %d failed! Calculated values do not match expected values",
765int main(
int argc,
char *argv[]) {
767 const char param_file[] =
"param_file.petsc";
773 DMType dm_name =
"DMMOFEM";
777 moab::Core mb_instance;
778 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.
static MoFEMErrorCode addCanonicalAttributeNames(const std::vector< std::string > &names)
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.
MoFEMErrorCode setEvaluationIntegrationRule(RuleHookFun rule)
Set integration rule for domain evaluation finite element.
boost::shared_ptr< FEMethod > & getDomainPostProcFE()
Get domain postprocessing 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.