6 #ifndef EXECUTABLE_DIMENSION
7 #define EXECUTABLE_DIMENSION 3
11 static 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; };
327 CHKERR pipeline_mng->setDomainLhsIntegrationRule(rule_lhs);
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",
768 int main(
int argc,
char *argv[]) {
770 const char param_file[] =
"param_file.petsc";
776 DMType dm_name =
"DMMOFEM";