v0.16.0
Loading...
Searching...
No Matches
Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
Electrostatics Struct Reference
Collaboration diagram for Electrostatics:
[legend]

Public Member Functions

 Electrostatics (MoFEM::Interface &m_field)
 
MoFEMErrorCode runProgram ()
 [Get Charges]
 

Private Types

enum  VecElements { ZERO = 0 , ONE = 1 , LAST_ELEMENT }
 

Private Member Functions

MoFEMErrorCode readMesh ()
 [Read mesh]
 
MoFEMErrorCode setupProblem ()
 [Read mesh]
 
MoFEMErrorCode boundaryCondition ()
 [Setup problem]
 
MoFEMErrorCode setIntegrationRules ()
 [Boundary condition]
 
MoFEMErrorCode assembleSystem ()
 [Set integration rules]
 
MoFEMErrorCode solveSystem ()
 [Assemble system]
 
MoFEMErrorCode outputResults ()
 [Solve system]
 
MoFEMErrorCode getTotalEnergy ()
 [Output results]
 
MoFEMErrorCode getElectrodeCharge ()
 [Get Total Energy]
 

Private Attributes

int oRder = 2
 
int geomOrder = 1
 
MoFEM::InterfacemField
 
SimplesimpleInterface
 
std::string domainField
 
boost::shared_ptr< std::map< int, BlockData > > permBlockSetsPtr
 
boost::shared_ptr< std::map< int, BlockData > > intBlockSetsPtr
 
boost::shared_ptr< std::map< int, BlockData > > electrodeBlockSetsPtr
 
boost::shared_ptr< DataAtIntegrationPtscommonDataPtr
 
boost::shared_ptr< ForcesAndSourcesCoreinterFaceRhsFe
 
boost::shared_ptr< ForcesAndSourcesCoreelectrodeRhsFe
 
double aLpha = 0.0
 
double bEta = 0.0
 
SmartPetscObj< Vec > petscVec
 
SmartPetscObj< Vec > petscVecEnergy
 
PetscBool out_skin = PETSC_FALSE
 
PetscBool is_partitioned = PETSC_FALSE
 
int atomTest = 0
 

Detailed Description

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 12 of file electrostatics.cpp.

Member Enumeration Documentation

◆ VecElements

Enumerator
ZERO 
ONE 
LAST_ELEMENT 
Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 50 of file electrostatics.cpp.

Constructor & Destructor Documentation

◆ Electrostatics()

Electrostatics::Electrostatics ( MoFEM::Interface m_field)
Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 54 of file electrostatics.cpp.

55 : domainField("POTENTIAL"), mField(m_field) {}
MoFEM::Interface & mField
std::string domainField

Member Function Documentation

◆ assembleSystem()

MoFEMErrorCode Electrostatics::assembleSystem ( )
private

[Set integration rules]

[Assemble system]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 349 of file electrostatics.cpp.

349 {
351
352 auto pipeline_mng = mField.getInterface<PipelineManager>();
353 commonDataPtr = boost::make_shared<DataAtIntegrationPts>(mField);
354
355 auto add_domain_base_ops = [&](auto &pipeline) {
357 "GEOMETRY");
358
359 pipeline.push_back(
361 };
362
363 add_domain_base_ops(pipeline_mng->getOpDomainLhsPipeline());
364 auto epsilon = [&](const double, const double, const double) {
365 return commonDataPtr->blockPermittivity;
366 };
367
368 { // Push operators to the Pipeline that is responsible for calculating LHS
369 pipeline_mng->getOpDomainLhsPipeline().push_back(
371 }
372
373 { // Push operators to the Pipeline that is responsible for calculating RHS
374 auto set_values_to_bc_dofs = [&](auto &fe) {
375 auto get_bc_hook = [&]() {
377 return hook;
378 };
379 fe->preProcessHook = get_bc_hook();
380 };
381 // Set essential BC
382 auto calculate_residual_from_set_values_on_bc = [&](auto &pipeline) {
383 using OpInternal =
386
387 add_domain_base_ops(pipeline_mng->getOpDomainRhsPipeline());
388
389 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
390 pipeline_mng->getOpDomainRhsPipeline().push_back(
392 grad_u_ptr));
393 auto minus_epsilon = [&](double, double, double) constexpr {
394 return -commonDataPtr->blockPermittivity;
395 };
396 pipeline_mng->getOpDomainRhsPipeline().push_back(
397 new OpInternal(domainField, grad_u_ptr, minus_epsilon));
398 };
399
400 set_values_to_bc_dofs(pipeline_mng->getDomainRhsFE());
401 calculate_residual_from_set_values_on_bc(
402 pipeline_mng->getOpDomainRhsPipeline());
403
404 auto bodySourceTerm = [&](const double, const double, const double) {
405 return bodySource;
406 };
407 pipeline_mng->getOpDomainRhsPipeline().push_back(
408 new OpBodySourceVectorb(domainField, bodySourceTerm));
409 }
410
411 interFaceRhsFe = boost::shared_ptr<ForcesAndSourcesCore>(
413 interFaceRhsFe->getRuleHook = [this](int, int, int p) {
414 return 2 * p + geomOrder -1;
415 };
416
417 {
418
420 interFaceRhsFe->getOpPtrVector(), {NOSPACE}, "GEOMETRY");
421
422 interFaceRhsFe->getOpPtrVector().push_back(
424
425 auto sIgma = [&](const double, const double, const double) {
426 return commonDataPtr->blockChrgDens;
427 };
428
429 interFaceRhsFe->getOpPtrVector().push_back(
431 }
432
434}
@ H1
continuous field
Definition definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#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
intPostProc< SPACE_DIM >::intEle IntElementForcesAndSourcesCore
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpBodySourceVectorb
const double bodySource
@ GAUSS
Gaussian quadrature integration.
@ PETSC
Standard PETSc assembly.
FormsIntegrators< DomainEleOp >::Assembly< A >::LinearForm< I >::OpGradTimesTensor< 1, FIELD_DIM, SPACE_DIM > OpGradTimesTensor
boost::shared_ptr< ForcesAndSourcesCore > interFaceRhsFe
boost::shared_ptr< std::map< int, BlockData > > intBlockSetsPtr
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
boost::shared_ptr< std::map< int, BlockData > > permBlockSetsPtr
Add operators pushing bases from local to physical configuration.
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
PipelineManager interface.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.

◆ boundaryCondition()

MoFEMErrorCode Electrostatics::boundaryCondition ( )
private

[Setup problem]

[Boundary condition]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 319 of file electrostatics.cpp.

319 {
321
322 auto bc_mng = mField.getInterface<BcManager>();
323
324 // Remove_BCs_from_blockset name "BOUNDARY_CONDITION";
326 simpleInterface->getProblemName(), "BOUNDARY_CONDITION",
327 std::string(domainField), true);
328
330}
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.
Definition BcManager.cpp:72
Simple * simpleInterface
Boundary condition manager for finite element problem setup.
Template specialization for scalar field boundary conditions.
const std::string getProblemName() const
Get the Problem Name.
Definition Simple.hpp:450

◆ getElectrodeCharge()

MoFEMErrorCode Electrostatics::getElectrodeCharge ( )
private

[Get Total Energy]

[Get Charges]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 650 of file electrostatics.cpp.

650 {
652 auto op_loop_side = new OpLoopSide<SideEle>(
654
656 op_loop_side->getOpPtrVector(), {H1}, "GEOMETRY");
657
658 auto grad_u_ptr_charge = boost::make_shared<MatrixDouble>();
659 auto e_ptr_charge = boost::make_shared<MatrixDouble>();
660
661 op_loop_side->getOpPtrVector().push_back(
663 grad_u_ptr_charge));
664
665 op_loop_side->getOpPtrVector().push_back(
666 new OpElectricField(e_ptr_charge, grad_u_ptr_charge));
667 auto d_jump = boost::make_shared<MatrixDouble>();
668 op_loop_side->getOpPtrVector().push_back(new OpElectricDispJump<SPACE_DIM>(
669 domainField, e_ptr_charge, d_jump, commonDataPtr, permBlockSetsPtr));
670
671 electrodeRhsFe = boost::shared_ptr<ForcesAndSourcesCore>(
673 electrodeRhsFe->getRuleHook = [this](int, int, int p) {
674 return 2 * p + geomOrder -1;
675 };
676
677 // push all the operators in on the side to the electrodeRhsFe
678 electrodeRhsFe->getOpPtrVector().push_back(op_loop_side);
679
680 electrodeRhsFe->getOpPtrVector().push_back(new OpElectrodeCharge<SPACE_DIM>(
682 CHKERR VecZeroEntries(petscVec);
684 "ELECTRODE", electrodeRhsFe, 0,
686 CHKERR VecAssemblyBegin(petscVec);
687 CHKERR VecAssemblyEnd(petscVec);
688
689 if (!mField.get_comm_rank()) {
690 const double *array;
691
692 CHKERR(VecGetArrayRead(petscVec, &array));
693 double aLpha = array[0]; // Use explicit index instead of ZERO
694 double bEta = array[1]; // Use explicit index instead of ONE
695 MOFEM_LOG_CHANNEL("SELF");
696 MOFEM_LOG_C("SELF", Sev::inform,
697 "CHARGE_ELEC_1: %6.15f , CHARGE_ELEC_2: %6.15f", aLpha, bEta);
698
699 CHKERR(VecRestoreArrayRead(petscVec, &array));
700 }
701 if (atomTest && !mField.get_comm_rank()) {
702 double cal_charge_elec1;
703 double cal_charge_elec2;
704 double cal_total_energy;
705 const double *c_ptr, *te_ptr;
706
707 // Get a pointer to the PETSc vector data
708 CHKERR(VecGetArrayRead(petscVec, &c_ptr));
709 CHKERR(VecGetArrayRead(petscVecEnergy, &te_ptr));
710
711 // Expected charges at the electrodes
712 double ref_charge_elec1;
713 double ref_charge_elec2;
714 // Expected total energy of the system
715 double ref_tot_energy;
716 double tol;
717 cal_charge_elec1 = c_ptr[0]; // Read charge at the first electrode
718 cal_charge_elec2 = c_ptr[1]; // Read charge at the second electrode
719 cal_total_energy = te_ptr[0]; // Read total energy of the system
720 if (std::isnan(cal_charge_elec1) || std::isnan(cal_charge_elec2) ||
721 std::isnan(cal_total_energy)) {
722 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
723 "Atom test failed! NaN detected in calculated values.");
724 }
725 switch (atomTest) {
726 case 1: // 2D & 3D test
727 case 3: // JSON clear-block 2D test
728 // Expected charges at the electrodes
729 ref_charge_elec1 = 50.0;
730 ref_charge_elec2 = -50.0;
731 // Expected total energy of the system
732 ref_tot_energy = 500.0;
733 tol = 1e-10;
734 break;
735 case 2: // wavy 3D test
736 ref_charge_elec1 = 10.00968352472943;
737 ref_charge_elec2 = 0.0; // no electrode
738 ref_tot_energy = 50.5978;
739 tol = 1e-4;
740 break;
741 default:
742 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
743 "atom test %d does not exist", atomTest);
744 }
745
746 // Validate the results
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) {
750 SETERRQ(
751 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
752 "atom test %d failed! Calculated values do not match expected values",
753 atomTest);
754 }
755
756 CHKERR(VecRestoreArrayRead(petscVec,
757 &c_ptr)); // Restore the PETSc vector array
758 CHKERR(VecRestoreArrayRead(petscVecEnergy, &te_ptr));
759 }
760
762}
#define MOFEM_LOG_C(channel, severity, format,...)
constexpr int SPACE_DIM
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_INVALID_DATA
Definition definitions.h:36
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.
Definition DMMoFEM.cpp:557
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
boost::shared_ptr< ForcesAndSourcesCore > electrodeRhsFe
SmartPetscObj< Vec > petscVec
SmartPetscObj< Vec > petscVecEnergy
boost::shared_ptr< std::map< int, BlockData > > electrodeBlockSetsPtr
virtual int get_comm_size() const =0
virtual int get_comm_rank() const =0
Element used to execute operators on side of the element.
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
const std::string getDomainFEName() const
Get the Domain FE Name.
Definition Simple.hpp:429
double tol

◆ getTotalEnergy()

MoFEMErrorCode Electrostatics::getTotalEnergy ( )
private

[Output results]

[Get Total Energy]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 584 of file electrostatics.cpp.

584 {
586 auto pip_energy = mField.getInterface<PipelineManager>();
587 pip_energy->getDomainRhsFE().reset();
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();
593
594 // gets the map of the internal domain entity range to get the total energy
595
596 boost::shared_ptr<std::map<int, BlockData>> intrnlDomnBlckSetPtr =
597 boost::make_shared<std::map<int, BlockData>>();
598 Range internal_domain; // range of entities marked the internal domain
600 if (bit->getName().compare(0, 10, "DOMAIN_INT") == 0) {
601 const int id = bit->getMeshsetId();
602 auto &block_data = (*intrnlDomnBlckSetPtr)[id];
603
604 CHKERR mField.get_moab().get_entities_by_dimension(
605 bit->getMeshset(), SPACE_DIM, block_data.internalDomainEnts, true);
606 internal_domain.merge(block_data.internalDomainEnts);
607 block_data.iD = id;
608 }
609 }
610 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
611 internal_domain);
612
614 pip_energy->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
615
616 auto grad_u_ptr = boost::make_shared<MatrixDouble>();
617 auto e_field_ptr = boost::make_shared<MatrixDouble>();
618
619 pip_energy->getOpDomainRhsPipeline().push_back(
621 pip_energy->getOpDomainRhsPipeline().push_back(
622 new OpElectricField(e_field_ptr, grad_u_ptr));
623
624 commonDataPtr = boost::make_shared<DataAtIntegrationPts>(mField);
625
626 pip_energy->getOpDomainRhsPipeline().push_back(
628 intrnlDomnBlckSetPtr, commonDataPtr, petscVecEnergy));
629
630 pip_energy->loopFiniteElements();
631 CHKERR VecAssemblyBegin(petscVecEnergy);
632 CHKERR VecAssemblyEnd(petscVecEnergy);
633
634 double total_energy = 0.0; // declaration for total energy
635 if (!mField.get_comm_rank()) {
636 const double *array;
637
638 CHKERR VecGetArrayRead(petscVecEnergy, &array);
639 total_energy = array[ZERO];
640 MOFEM_LOG_CHANNEL("SELF");
641 MOFEM_LOG_C("SELF", Sev::inform, "Total Energy: %6.15f", total_energy);
642 CHKERR VecRestoreArrayRead(petscVecEnergy, &array);
643 }
644
646}
@ BLOCKSET
#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.
auto bit
set bit
Managing BitRefLevels.
virtual moab::Interface & get_moab()=0
boost::shared_ptr< FEMethod > & getDomainRhsFE()
Get domain right-hand side finite element.

◆ outputResults()

MoFEMErrorCode Electrostatics::outputResults ( )
private

[Solve system]

[Output results]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 482 of file electrostatics.cpp.

482 {
484 auto pipeline_mng = mField.getInterface<PipelineManager>();
485 pipeline_mng->getDomainRhsFE().reset();
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);
490
491 // lamda function to calculate electric field
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>();
497 // add higher order operator
499 "GEOMETRY");
500 // calculate field values
501 pipeline.push_back(new OpCalculateScalarFieldValues(domainField, u_ptr));
502 pipeline.push_back(
503 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
504
505 // calculate gradient
506 pipeline.push_back(
508 // calculate electric field
509 pipeline.push_back(new OpElectricField(e_field_ptr, grad_u_ptr));
510 return boost::make_tuple(u_ptr, e_field_ptr, x_ptr);
511 };
512
513 auto [u_ptr, e_field_ptr, x_ptr] =
514 calculate_e_field(post_proc_fe->getOpPtrVector());
515
516 auto e_field_times_perm_ptr = boost::make_shared<MatrixDouble>();
517 auto energy_density_ptr = boost::make_shared<VectorDouble>();
518
519 post_proc_fe->getOpPtrVector().push_back(
520 new OpGradTimesPerm(domainField, e_field_ptr, e_field_times_perm_ptr,
522 post_proc_fe->getOpPtrVector().push_back(
523 new OpEnergyDensity(domainField, e_field_ptr, energy_density_ptr,
525
527 post_proc_fe->getOpPtrVector().push_back(new OpPPMap(
528 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
529
530 OpPPMap::DataMapVec{{"POTENTIAL", u_ptr},
531 {"ENERGY_DENSITY", energy_density_ptr}},
533 {"GEOMETRY", x_ptr},
534 {"ELECTRIC_FIELD", e_field_ptr},
535 {"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr},
536 },
538
540
541 );
542
543 pipeline_mng->getDomainRhsFE() = post_proc_fe;
544 CHKERR pipeline_mng->loopFiniteElements();
545 CHKERR post_proc_fe->writeFile("out.h5m");
546
547 if (out_skin && SPACE_DIM == 3) {
548
549 auto post_proc_skin = boost::make_shared<PostProcFaceEle>(mField);
550 auto op_loop_skin = new OpLoopSide<SideEle>(
552
553 auto [u_ptr, e_field_ptr, x_ptr] =
554 calculate_e_field(op_loop_skin->getOpPtrVector());
555
556 op_loop_skin->getOpPtrVector().push_back(
557 new OpGradTimesPerm(domainField, e_field_ptr, e_field_times_perm_ptr,
559 op_loop_skin->getOpPtrVector().push_back(
560 new OpEnergyDensity(domainField, e_field_ptr, energy_density_ptr,
562
563 // push op to boundary element
564 post_proc_skin->getOpPtrVector().push_back(op_loop_skin);
565
566 post_proc_skin->getOpPtrVector().push_back(new OpPPMap(
567 post_proc_skin->getPostProcMesh(), post_proc_skin->getMapGaussPts(),
568 OpPPMap::DataMapVec{{"POTENTIAL", u_ptr},
569 {"ENERGY_DENSITY", energy_density_ptr}},
570 OpPPMap::DataMapMat{{"ELECTRIC_FIELD", e_field_ptr},
571 {"GEOMETRY", x_ptr},
572 {"ELECTRIC_DISPLACEMENT", e_field_times_perm_ptr}},
574
576 post_proc_skin);
577 CHKERR post_proc_skin->writeFile("out_skin.h5m");
578 }
580}
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:576
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
Specialization for double precision scalar field values calculation.
Specialization for MatrixDouble vector field values calculation.
Post post-proc data at points from hash maps.
std::map< std::string, ScalarDataPtr > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat

◆ readMesh()

MoFEMErrorCode Electrostatics::readMesh ( )
private

[Read mesh]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 58 of file electrostatics.cpp.

58 {
62
64 true; // create lower dimensional element to ensure sharing of partitioed
65 // entities at the boundaries.
67 CHKERR mField.getInterface<MeshsetsManager>()->setMeshsetFromFile();
69}
Interface for managing meshsets containing materials and boundary conditions.
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
Definition Simple.cpp:191
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
bool & getAddSkeletonFE()
Get the addSkeletonFE flag.
Definition Simple.hpp:536

◆ runProgram()

MoFEMErrorCode Electrostatics::runProgram ( )

[Get Charges]

[Run program]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 766 of file electrostatics.cpp.

766 {
768
779}
MoFEMErrorCode setupProblem()
[Read mesh]
MoFEMErrorCode outputResults()
[Solve system]
MoFEMErrorCode setIntegrationRules()
[Boundary condition]
MoFEMErrorCode getElectrodeCharge()
[Get Total Energy]
MoFEMErrorCode readMesh()
[Read mesh]
MoFEMErrorCode assembleSystem()
[Set integration rules]
MoFEMErrorCode getTotalEnergy()
[Output results]
MoFEMErrorCode boundaryCondition()
[Setup problem]
MoFEMErrorCode solveSystem()
[Assemble system]

◆ setIntegrationRules()

MoFEMErrorCode Electrostatics::setIntegrationRules ( )
private

[Boundary condition]

[Set integration rules]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 334 of file electrostatics.cpp.

334 {
336
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; };
339
340 auto pipeline_mng = mField.getInterface<PipelineManager>();
341 CHKERR pipeline_mng->setDomainLhsIntegrationRule(rule_lhs);
342 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule_rhs);
343
345}
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain left-hand side finite element.

◆ setupProblem()

MoFEMErrorCode Electrostatics::setupProblem ( )
private

[Read mesh]

[Setup problem]

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 73 of file electrostatics.cpp.

73 {
75
76 Range domain_ents;
77 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, domain_ents,
78 true);
79 auto get_ents_by_dim = [&](const auto dim) {
80 if (dim == SPACE_DIM) {
81 return domain_ents;
82 } else {
83 Range ents;
84 if (dim == 0)
85 CHKERR mField.get_moab().get_connectivity(domain_ents, ents, true);
86 else
87 CHKERR mField.get_moab().get_entities_by_dimension(0, dim, ents, true);
88 return ents;
89 }
90 };
91
92 // Select base for the field based on the element type
93 auto get_base = [&]() {
94 auto domain_ents = get_ents_by_dim(SPACE_DIM);
95 if (domain_ents.empty())
97 const auto type = type_from_handle(domain_ents[0]);
98 switch (type) {
99 case MBQUAD:
101 case MBHEX:
103 case MBTRI:
105 case MBTET:
107 default:
108 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "Element type is not handled");
109 }
110 return NOBASE;
111 };
112
113 auto base = get_base();
116
117 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &oRder, PETSC_NULLPTR);
118
119 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-geom_order", &geomOrder,
120 PETSC_NULLPTR);
121
122 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atomTest,
123 PETSC_NULLPTR);
125 CHKERR simpleInterface->addDataField("GEOMETRY", H1, base, SPACE_DIM);
127
128 auto project_ho_geometry = [&]() {
129 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
130 return mField.loop_dofs("GEOMETRY", ent_method);
131 };
132
134 CHKERR project_ho_geometry();
135
136 commonDataPtr = boost::make_shared<DataAtIntegrationPts>(mField);
137 auto *json_config = mField.getInterface<JsonConfigManager>();
138
139 // gets the map of the permittivity attributes and the block sets
140 permBlockSetsPtr = boost::make_shared<std::map<int, BlockData>>();
141 Range mat_electr_ents; // range of entities with the permittivity
143 if (bit->getName().compare(0, 12, "MAT_ELECTRIC") == 0) {
144 const int id = bit->getMeshsetId();
145 auto &block_data = (*permBlockSetsPtr)[id];
146
147 CHKERR mField.get_moab().get_entities_by_dimension(
148 bit->getMeshset(), SPACE_DIM, block_data.domainEnts, true);
149 mat_electr_ents.merge(block_data.domainEnts);
150
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");
155 } else {
156 std::vector<double> attributes;
157 bit->getAttributes(attributes);
158 if (attributes.size() < 1) {
159 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
160 " At least one permittivity attributes should be given but "
161 "found %zu",
162 attributes.size());
163 }
164 block_data.epsPermit = attributes[0];
165 }
166 block_data.iD = id; // id of the block
167 }
168 }
169
170 // gets the map of the charge attributes and the block sets
171 intBlockSetsPtr = boost::make_shared<std::map<int, BlockData>>();
172 Range int_electr_ents; // range of entities with the charge
174 if (bit->getName().compare(0, 12, "INT_ELECTRIC") == 0) {
175 const int id = bit->getMeshsetId();
176 auto &block_data = (*intBlockSetsPtr)[id];
177
178 CHKERR mField.get_moab().get_entities_by_dimension(
179 bit->getMeshset(), SPACE_DIM - 1, block_data.interfaceEnts, true);
180 int_electr_ents.merge(block_data.interfaceEnts);
181
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");
186 } else {
187 std::vector<double> attributes;
188 bit->getAttributes(attributes);
189 if (attributes.size() < 1) {
190 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
191 "At least one charge attributes should be given but found %zu",
192 attributes.size());
193 }
194 block_data.chargeDensity = attributes[0];
195 }
196
197 block_data.iD = id; // id-> block ID
198 }
199 }
200 // gets the map of the electrode entity range in the block sets
201 electrodeBlockSetsPtr = boost::make_shared<std::map<int, BlockData>>();
202 Range electrode_ents; // range of entities with the electrode
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];
208 ++electrodeCount;
209
210 CHKERR mField.get_moab().get_entities_by_dimension(
211 bit->getMeshset(), SPACE_DIM - 1, block_data.electrodeEnts, true);
212 electrode_ents.merge(block_data.electrodeEnts);
213
214
215 if (electrodeCount > 2) {
216 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
217 "Three or more electrode blocksets found");
218 ;
219 }
220 }
221 }
222
223 // sync entities
224 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
225 mat_electr_ents);
226 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
227 int_electr_ents);
228 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
229 electrode_ents);
230
231 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-out_skin", &out_skin,
232 PETSC_NULLPTR);
233 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-is_partitioned", &is_partitioned,
234 PETSC_NULLPTR);
235 // get the skin entities
236 Skinner skinner(&mField.get_moab());
237 Range skin_tris;
238 CHKERR skinner.find_skin(0, mat_electr_ents, false, skin_tris);
239 Range proc_skin;
240 ParallelComm *pcomm =
241 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
242 if (is_partitioned) {
243 CHKERR pcomm->filter_pstatus(skin_tris,
244 PSTATUS_SHARED | PSTATUS_MULTISHARED,
245 PSTATUS_NOT, -1, &proc_skin);
246 } else {
247 proc_skin = skin_tris;
248 }
249 // add the skin entities to the field
252 "SKIN");
256 // add the interface entities to the field
257 CHKERR mField.add_finite_element("INTERFACE");
261 CHKERR mField.modify_finite_element_add_field_data("INTERFACE", "GEOMETRY");
262
264 SPACE_DIM - 1, "INTERFACE");
265 // add the electrode entities to the field
266 CHKERR mField.add_finite_element("ELECTRODE");
270 CHKERR mField.modify_finite_element_add_field_data("ELECTRODE", "GEOMETRY");
271
273 "ELECTRODE");
274
275 // sync field entities
276 mField.getInterface<CommInterface>()->synchroniseFieldEntities(domainField);
277 mField.getInterface<CommInterface>()->synchroniseFieldEntities("GEOMETRY");
286
290
291 DMType dm_name = "DMMOFEM";
292 CHKERR DMRegister_MoFEM(dm_name);
293
295 dm = createDM(mField.get_comm(), dm_name);
296
297 // create dm instance
298 CHKERR DMSetType(dm, dm_name);
299
301
302 // initialise petsc vector for required processor
303 int local_size;
304 if (mField.get_comm_rank() == 0) // get_comm_rank() gets processor number
305
306 local_size = LAST_ELEMENT; // last element gives size of vector
307
308 else
309 // other processors (e.g. 1, 2, 3, etc.)
310 local_size = 0; // local size of vector is zero on other processors
311
315}
std::string type
@ MF_ZERO
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ NOBASE
Definition definitions.h:59
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MYPCOMM_INDEX
default communicator number PCOMM
@ MOFEM_NOT_FOUND
Definition definitions.h:33
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
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
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.
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)
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.
PetscBool is_partitioned
virtual MPI_Comm & get_comm() const =0
Projection of edge entities with one mid-node on hierarchical basis.
MoFEMErrorCode buildProblem()
Build problem.
Definition Simple.cpp:721
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.
Definition Simple.cpp:261
MoFEMErrorCode defineFiniteElements()
Define finite elements.
Definition Simple.cpp:471
MoFEMErrorCode buildFiniteElements()
Build finite elements.
Definition Simple.cpp:659
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.
Definition Simple.cpp:355
MoFEMErrorCode buildFields()
Build fields.
Definition Simple.cpp:584
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
Definition Simple.cpp:575
MoFEMErrorCode defineProblem(const PetscBool is_partitioned=PETSC_TRUE)
define problem
Definition Simple.cpp:551
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.
Definition Simple.cpp:393
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
Definition Simple.cpp:735
intrusive_ptr for managing petsc objects

◆ solveSystem()

MoFEMErrorCode Electrostatics::solveSystem ( )
private

[Assemble system]

[Solve system]

< Null element does

Examples
mofem/tutorials/scl-12_electrostatics/electrostatics.cpp.

Definition at line 438 of file electrostatics.cpp.

438 {
440
441 auto pipeline_mng = mField.getInterface<PipelineManager>();
442
443 auto ksp_solver = pipeline_mng->createKSP();
444
445 boost::shared_ptr<ForcesAndSourcesCore> null; ///< Null element does
446 DM dm;
448
449 CHKERR DMMoFEMKSPSetComputeRHS(dm, "INTERFACE", interFaceRhsFe, null, null);
450
451 CHKERR KSPSetFromOptions(ksp_solver);
452
453 // Create RHS and solution vectors
454 auto F = createDMVector(dm);
455 auto D = vectorDuplicate(F);
456 // Solve the system
457 CHKERR KSPSetUp(ksp_solver);
458 CHKERR KSPSolve(ksp_solver, F, D);
459
460 CHKERR VecGhostUpdateBegin(F, INSERT_VALUES, SCATTER_FORWARD);
461 CHKERR VecGhostUpdateEnd(F, INSERT_VALUES, SCATTER_FORWARD);
462
463 double fnorm;
464 CHKERR VecNorm(F, NORM_2, &fnorm);
465 CHKERR PetscPrintf(PETSC_COMM_WORLD, "F norm = %9.8e\n", fnorm);
466
467 // Scatter result data on the mesh
468 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
469 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
470
471 double dnorm;
472 CHKERR VecNorm(D, NORM_2, &dnorm);
473 CHKERR PetscPrintf(PETSC_COMM_WORLD, "D norm = %9.8e\n", dnorm);
474
475 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
476
478}
@ F
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
Definition DMMoFEM.cpp:514
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
Definition DMMoFEM.cpp:627
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
SmartPetscObj< KSP > createKSP(SmartPetscObj< DM > dm=nullptr)
Create KSP (linear) solver.
double D
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.

Member Data Documentation

◆ aLpha

double Electrostatics::aLpha = 0.0
private

◆ atomTest

int Electrostatics::atomTest = 0
private

◆ bEta

double Electrostatics::bEta = 0.0
private

◆ commonDataPtr

boost::shared_ptr<DataAtIntegrationPts> Electrostatics::commonDataPtr
private

◆ domainField

std::string Electrostatics::domainField
private

◆ electrodeBlockSetsPtr

boost::shared_ptr<std::map<int, BlockData> > Electrostatics::electrodeBlockSetsPtr
private

◆ electrodeRhsFe

boost::shared_ptr<ForcesAndSourcesCore> Electrostatics::electrodeRhsFe
private

◆ geomOrder

int Electrostatics::geomOrder = 1
private

◆ intBlockSetsPtr

boost::shared_ptr<std::map<int, BlockData> > Electrostatics::intBlockSetsPtr
private

◆ interFaceRhsFe

boost::shared_ptr<ForcesAndSourcesCore> Electrostatics::interFaceRhsFe
private

◆ is_partitioned

PetscBool Electrostatics::is_partitioned = PETSC_FALSE
private

◆ mField

MoFEM::Interface& Electrostatics::mField
private

◆ oRder

int Electrostatics::oRder = 2
private

◆ out_skin

PetscBool Electrostatics::out_skin = PETSC_FALSE
private

◆ permBlockSetsPtr

boost::shared_ptr<std::map<int, BlockData> > Electrostatics::permBlockSetsPtr
private

◆ petscVec

SmartPetscObj<Vec> Electrostatics::petscVec
private

◆ petscVecEnergy

SmartPetscObj<Vec> Electrostatics::petscVecEnergy
private

◆ simpleInterface

Simple* Electrostatics::simpleInterface
private

The documentation for this struct was generated from the following file: