8#ifndef __MAGNETICELEMENT_HPP__
9#define __MAGNETICELEMENT_HPP__
104 if (
bit->getName().compare(0, 9,
"NATURALBC") == 0) {
122 ParallelComm *pcomm =
126 if (
bit->getName().compare(0, 10,
"ESSENTIALBC") == 0) {
140 CHKERR skin.find_skin(0, tets,
false, skin_faces);
143 CHKERR pcomm->filter_pstatus(skin_faces,
144 PSTATUS_SHARED | PSTATUS_MULTISHARED,
145 PSTATUS_NOT, -1, &proc_skin);
166 0, 3, BitRefLevel().set(0));
206 "MESH_NODE_POSITIONS");
218 Projection10NodeCoordsOnField ent_method_material(
mField,
219 "MESH_NODE_POSITIONS");
245 "MESH_NODE_POSITIONS");
281 CHKERR DMRegister_MoFEM(
"DMMOFEM");
285 BitRefLevel().set(0));
323 auto material_grad_mat = boost::make_shared<MatrixDouble>();
324 auto material_det_vec = boost::make_shared<VectorDouble>();
325 auto material_inv_grad_mat = boost::make_shared<MatrixDouble>();
327 "MESH_NODE_POSITIONS");
334 new OpGetHONormalsOnFace(
"MESH_NODE_POSITIONS"));
336 new OpCalculateHOCoords(
"MESH_NODE_POSITIONS"));
338 new OpHOSetCovariantPiolaTransformOnFace3D(
HCURL));
350 ->createMPIAIJ<PetscGlobalIdx_mi_tag>(problem_ptr->
getName(),
371 CHKERR KSPCreate(PETSC_COMM_WORLD, &solver);
373 CHKERR KSPSetFromOptions(solver);
377 solver,
"magnetostatics");
378 CHKERR KSPDestroy(&solver);
385 if (regression_test) {
389 const double expected_value = 4.6772e+01;
390 const double tol = 1e-4;
391 if ((nrm2 - expected_value) / expected_value >
tol) {
393 "Regression test failed %6.4e != %6.4e", nrm2, expected_value);
412 PostProcBrokenMeshInMoab<VolumeElementForcesAndSourcesCore> post_proc(
415 CHKERR AddHOOps<3, 3, 3>::add(post_proc.getOpPtrVector(), {HCURL, L2},
416 "MESH_NODE_POSITIONS");
418 auto pos_ptr = boost::make_shared<MatrixDouble>();
419 auto field_val_ptr = boost::make_shared<MatrixDouble>();
421 post_proc.getOpPtrVector().push_back(
422 new OpCalculateVectorFieldValues<3>(
"MESH_NODE_POSITIONS", pos_ptr));
423 post_proc.getOpPtrVector().push_back(
426 using OpPPMap = OpPostProcMapInMoab<3, 3>;
428 post_proc.getOpPtrVector().push_back(
432 post_proc.getPostProcMesh(), post_proc.getMapGaussPts(),
436 {{
"MESH_NODE_POSITIONS", pos_ptr},
437 {blockData.fieldName, field_val_ptr}},
447 post_proc.getOpPtrVector().push_back(
new OpPostProcessCurl(
448 blockData, post_proc.getPostProcMesh(), post_proc.getMapGaussPts()));
451 CHKERR post_proc.writeFile(
"out_values.h5m");
492 MoFEMErrorCode
doWork(
int row_side,
int col_side, EntityType row_type,
494 EntitiesFieldData::EntData &row_data,
495 EntitiesFieldData::EntData &col_data) {
498 if (row_type == MBVERTEX)
500 if (col_type == MBVERTEX)
503 const int nb_row_dofs = row_data.getN().size2() / 3;
504 if (nb_row_dofs == 0)
506 const int nb_col_dofs = col_data.getN().size2() / 3;
507 if (nb_col_dofs == 0)
509 entityLocalMatrix.resize(nb_row_dofs, nb_col_dofs,
false);
510 entityLocalMatrix.clear();
512 if (nb_row_dofs !=
static_cast<int>(row_data.getFieldData().size())) {
514 "Number of base functions and DOFs on entity is different on "
516 nb_row_dofs, row_data.getFieldData().size());
518 if (nb_col_dofs !=
static_cast<int>(col_data.getFieldData().size())) {
520 "Number of base functions and DOFs on entity is different on "
522 nb_col_dofs, col_data.getFieldData().size());
525 MatrixDouble row_curl_mat, col_curl_mat;
530 const double c0 = 1. / blockData.
mU;
531 const int nb_gauss_pts = row_data.getN().size1();
532 auto t_row_curl_base = row_data.getFTensor2DiffN<3, 3>();
534 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
537 double w = getGaussPts()(3, gg) * getVolume();
540 for (
int aa = 0; aa != nb_row_dofs; aa++) {
541 t_row_curl(
i) = levi_civita(
j,
i,
k) * t_row_curl_base(
j,
k);
546 auto t_col_curl_base = col_data.getFTensor2DiffN<3, 3>(gg, 0);
547 for (
int bb = 0; bb != nb_col_dofs; bb++) {
548 t_col_curl(
i) = levi_civita(
j,
i,
k) * t_col_curl_base(
j,
k);
549 t_local_mat += c0 * w * t_row_curl(
i) * t_col_curl(
i);
558 CHKERR MatSetValues(blockData.
A, nb_row_dofs, &row_data.getIndices()[0],
559 nb_col_dofs, &col_data.getIndices()[0],
560 &entityLocalMatrix(0, 0), ADD_VALUES);
562 if (row_side != col_side || row_type != col_type) {
563 entityLocalMatrix = trans(entityLocalMatrix);
564 CHKERR MatSetValues(blockData.
A, nb_col_dofs, &col_data.getIndices()[0],
565 nb_row_dofs, &row_data.getIndices()[0],
566 &entityLocalMatrix(0, 0), ADD_VALUES);
606 MoFEMErrorCode
doWork(
int row_side,
int col_side, EntityType row_type,
608 EntitiesFieldData::EntData &row_data,
609 EntitiesFieldData::EntData &col_data) {
612 if (row_type == MBVERTEX)
614 if (col_type == MBVERTEX)
617 const int nb_row_dofs = row_data.getN().size2() / 3;
618 if (nb_row_dofs == 0)
620 const int nb_col_dofs = col_data.getN().size2() / 3;
621 if (nb_col_dofs == 0)
623 entityLocalMatrix.resize(nb_row_dofs, nb_col_dofs,
false);
624 entityLocalMatrix.clear();
626 if (nb_row_dofs !=
static_cast<int>(row_data.getFieldData().size())) {
628 "Number of base functions and DOFs on entity is different on "
630 nb_row_dofs, row_data.getFieldData().size());
632 if (nb_col_dofs !=
static_cast<int>(col_data.getFieldData().size())) {
634 "Number of base functions and DOFs on entity is different on "
636 nb_col_dofs, col_data.getFieldData().size());
639 MatrixDouble row_curl_mat, col_curl_mat;
642 const double c0 = 1. / blockData.
mU;
643 const double c1 = blockData.
ePsilon * c0;
644 const int nb_gauss_pts = row_data.getN().size1();
646 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
649 double w = getGaussPts()(3, gg) * getVolume();
652 &row_data.getVectorN<3>(gg)(0,
HVEC0),
653 &row_data.getVectorN<3>(gg)(0,
HVEC1),
654 &row_data.getVectorN<3>(gg)(0,
HVEC2), 3);
656 for (
int aa = 0; aa != nb_row_dofs; aa++) {
659 &col_data.getVectorN<3>(gg)(0,
HVEC0),
660 &col_data.getVectorN<3>(gg)(0,
HVEC1),
661 &col_data.getVectorN<3>(gg)(0,
HVEC2), 3);
662 for (
int bb = 0; bb != nb_col_dofs; bb++) {
663 t_local_mat += c1 * w * t_row_base(
i) * t_col_base(
i);
674 CHKERR MatSetValues(blockData.
A, nb_row_dofs, &row_data.getIndices()[0],
675 nb_col_dofs, &col_data.getIndices()[0],
676 &entityLocalMatrix(0, 0), ADD_VALUES);
678 if (row_side != col_side || row_type != col_type) {
679 entityLocalMatrix = trans(entityLocalMatrix);
680 CHKERR MatSetValues(blockData.
A, nb_col_dofs, &col_data.getIndices()[0],
681 nb_row_dofs, &row_data.getIndices()[0],
682 &entityLocalMatrix(0, 0), ADD_VALUES);
722 MoFEMErrorCode
doWork(
int row_side, EntityType row_type,
723 EntitiesFieldData::EntData &row_data) {
726 if (row_type == MBVERTEX)
729 const int nb_row_dofs = row_data.getN().size2() / 3;
730 if (nb_row_dofs == 0)
732 naturalBC.resize(nb_row_dofs,
false);
737 const int nb_gauss_pts = row_data.getN().size1();
738 auto t_row_base = row_data.getFTensor1N<3>();
740 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
744 area = norm_2(getNormalsAtGaussPts(gg)) * 0.5;
745 double w = getGaussPts()(2, gg) * area;
749 const double x = getCoordsAtGaussPts()(gg, 0);
750 const double y = getCoordsAtGaussPts()(gg, 1);
751 const double r = sqrt(x * x + y * y);
765 for (
int aa = 0; aa != nb_row_dofs; aa++) {
766 t_f += w * t_row_base(
i) * t_j(
i);
772 CHKERR VecSetValues(blockData.
F, row_data.getIndices().size(),
773 &row_data.getIndices()[0], &naturalBC[0], ADD_VALUES);
790 std::vector<EntityHandle> &map_gauss_pts)
793 blockData(data), postProcMesh(post_proc_mesh),
794 mapGaussPts(map_gauss_pts) {}
796 MoFEMErrorCode
doWork(
int row_side, EntityType row_type,
797 EntitiesFieldData::EntData &row_data) {
800 if (row_type == MBVERTEX)
804 double def_val[] = {0, 0, 0};
805 CHKERR postProcMesh.tag_get_handle(
"MAGNETIC_INDUCTION_FIELD", 3,
807 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
808 const int nb_row_dofs = row_data.getN().size2() / 3;
809 if (nb_row_dofs == 0)
811 const void *tags_ptr[mapGaussPts.size()];
813 if (nb_row_dofs != row_data.getFieldData().size())
815 "Wrong number of base functions and DOFs %d != %zu",
816 nb_row_dofs, row_data.getFieldData().size());
821 const int nb_gauss_pts = row_data.getN().size1();
822 if (nb_gauss_pts !=
static_cast<int>(mapGaussPts.size())) {
824 "Inconsistency number of dofs %d!=%zu", nb_gauss_pts,
827 CHKERR postProcMesh.tag_get_by_ptr(th, &mapGaussPts[0],
828 mapGaussPts.size(), tags_ptr);
829 auto t_curl_base = row_data.getFTensor2DiffN<3, 3>();
830 for (
int gg = 0; gg != nb_gauss_pts; gg++) {
833 double *ptr = &((
double *)tags_ptr[gg])[0];
837 auto t_dof = row_data.getFTensor0FieldData();
838 for (
int aa = 0; aa != nb_row_dofs; aa++) {
839 t_curl(
i) += t_dof * (levi_civita(
j,
i,
k) * t_curl_base(
j,
k));
ForcesAndSourcesCore::UserDataOperator UserDataOperator
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ HCURL
field with continuous tangents
#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_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
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 add_ents_to_finite_element_by_type(const EntityHandle entities, const EntityType type, const std::string name, const bool recursive=true)=0
add entities to finite element
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 build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
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.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
implementation of Data Operators for Forces and Sources
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
data structure storing material constants, model parameters, matrices, etc.
int oRder
approximation order
const string feNaturalBCName
double mU
magnetic constant N / A2
double ePsilon
regularization paramater
calculate and assemble CurlCurl matrix
MatrixDouble entityLocalMatrix
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
integrate matrix
OpCurlCurl(BlockData &data)
calculate essential boundary conditions
OpNaturalBC(BlockData &data)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
integrate matrix
calculate and assemble CurlCurl matrix
moab::Interface & postProcMesh
std::vector< EntityHandle > & mapGaussPts
OpPostProcessCurl(BlockData &data, moab::Interface &post_proc_mesh, std::vector< EntityHandle > &map_gauss_pts)
MoFEMErrorCode doWork(int row_side, EntityType row_type, EntitiesFieldData::EntData &row_data)
calculate and assemble stabilization matrix
MatrixDouble entityLocalMatrix
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
integrate matrix
TriFE(MoFEM::Interface &m_field)
definition of volume element
VolumeFE(MoFEM::Interface &m_field)
Implementation of magneto-static problem (basic Implementation)
MoFEMErrorCode createFields()
build problem data structures
MoFEMErrorCode createElements()
create finite elements
MoFEMErrorCode destroyProblem()
destroy Distributed mesh manager
MoFEMErrorCode postProcessResults()
post-process results, i.e. save solution on the mesh
MoFEMErrorCode createProblem()
create problem
MoFEM::Interface & mField
MoFEMErrorCode getEssentialBc()
get essential boundary conditions (only homogenous case is considered)
MoFEMErrorCode getNaturalBc()
get natural boundary conditions
MagneticElement(MoFEM::Interface &m_field)
virtual ~MagneticElement()=default
MoFEMErrorCode solveProblem(const bool regression_test=false)
solve problem
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(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_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
Deprecated interface functions.
default operator for TRI element
std::string meshPositionsFieldName
boost::ptr_deque< UserDataOperator > & getOpPtrVector()
Use to push back operator for row operator.
Post post-proc data at points from hash maps.
keeps basic data about problem
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Volume finite element base.
VolumeElementForcesAndSourcesCore(Interface &m_field)