v0.16.0
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Friends | List of all members
EshelbianCore Struct Reference

#include "users_modules/eshelbian_plasticity/src/EshelbianCore.hpp"

Inheritance diagram for EshelbianCore:
[legend]
Collaboration diagram for EshelbianCore:
[legend]

Classes

struct  DynamicRelaxationTimeScale
 
struct  FieldOrders
 
struct  FieldOrders< AINSWORTH_LEGENDRE_BASE >
 
struct  FieldOrders< DEMKOWICZ_JACOBI_BASE >
 
struct  SetUpSchur
 

Public Types

enum  MaterialModel {
  StVenantKirchhoff , MooneyRivlin , Hencky , Neohookean ,
  Meta , LastMaterial
}
 
enum  SolverType {
  TimeSolver , DynamicRelaxation , Cohesive , LoadFactor ,
  ShapeOptimization , TestTopologicalDerivative , LastSolver
}
 
enum  StretchHandling { FULL_ORDER_STREACH , NO_STREACH }
 

Public Member Functions

template<typename Op >
MoFEMErrorCode withFieldOrders (Op &&op) const
 
MoFEMErrorCode query_interface (boost::typeindex::type_index type_index, UnknownInterface **iface) const
 Getting interface of core database.
 
 EshelbianCore (MoFEM::Interface &m_field)
 
virtual ~EshelbianCore ()
 
MoFEMErrorCode getOptions ()
 
template<typename BC >
MoFEMErrorCode getBc (boost::shared_ptr< BC > &bc_vec_ptr, const std::string block_name, const int nb_attributes)
 
MoFEMErrorCode getSpatialDispBc ()
 [Getting norms]
 
MoFEMErrorCode getSpatialRotationBc ()
 
MoFEMErrorCode getSpatialTractionBc ()
 
MoFEMErrorCode getTractionFreeBc (const EntityHandle meshset, boost::shared_ptr< TractionFreeBc > &bc_ptr, const std::string contact_set_name)
 Remove all, but entities where kinematic constrains are applied.
 
MoFEMErrorCode getSpatialTractionFreeBc (const EntityHandle meshset=0)
 
MoFEMErrorCode getExternalStrain ()
 
MoFEMErrorCode createExchangeVectors (Sev sev)
 
MoFEMErrorCode addFields (const EntityHandle meshset=0, const bool add_bubble=true)
 
MoFEMErrorCode projectGeometry (const EntityHandle meshset=0, double time=0)
 
MoFEMErrorCode projectMaterialTags (const EntityHandle meshset=0)
 
MoFEMErrorCode addVolumeFiniteElement (const EntityHandle meshset=0, const bool add_bubble=true)
 
MoFEMErrorCode addBoundaryFiniteElement (const EntityHandle meshset=0)
 
MoFEMErrorCode addDMs (const BitRefLevel bit=BitRefLevel().set(0), const EntityHandle meshset=0)
 
MoFEMErrorCode addMaterial_HMHNeohookean (const int tape, const double c10, const double K)
 
MoFEMErrorCode addMaterial_Hencky (double E, double nu)
 
MoFEMErrorCode addMaterial_Core (boost::weak_ptr< MatOps::PhysicalEquations > mat_physical_equations_ptr)
 
MoFEMErrorCode setBaseVolumeElementOps (const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, const bool add_bubble=true)
 
MoFEMErrorCode setVolumeElementOps (const int tag, const bool add_elastic, const bool add_material, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_lhs)
 
MoFEMErrorCode pushNoStretchVolumeA00Ops (boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
 
MoFEMErrorCode pushStretchVolumeA00Ops (boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
 
MoFEMErrorCode pushStressGramOps (boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
 
MoFEMErrorCode pushPiolaStressGramOps (boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
 
MoFEMErrorCode setFaceElementOps (const bool add_elastic, const bool add_material, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_lhs)
 
MoFEMErrorCode setFaceInterfaceOps (const bool add_elastic, const bool add_material, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_lhs)
 
MoFEMErrorCode setContactElementRhsOps (boost::shared_ptr< ForcesAndSourcesCore > &fe_contact_tree)
 
MoFEMErrorCode setElasticElementOps (const int tag)
 
MoFEMErrorCode setElasticElementToTs (DM dm)
 
MoFEMErrorCode addDebugModel (TS ts)
 Add debug to model.
 
MoFEMErrorCode solveElastic (TS ts, Vec x)
 
MoFEMErrorCode solveDynamicRelaxation (TS ts, Vec x, int start_step, double start_time)
 Solve problem using dynamic relaxation method.
 
MoFEMErrorCode solveCohesiveCrackGrowth (TS ts, Vec x, int start_step, double start_time)
 Solve cohesive crack growth problem.
 
MoFEMErrorCode solveLoadFactor (TS ts, Vec x, int start_step, double start_time)
 Solve load factor crack growth problem.
 
MoFEMErrorCode solveSchapeOptimisation (TS ts, Vec x, int start_step, double start_time)
 Solve shape optimisation problem.
 
MoFEMErrorCode solveTestTopologicalDerivative (TS ts, Vec x, int start_step, double start_time)
 
MoFEMErrorCode setBlockTagsOnSkin ()
 
MoFEMErrorCode postProcessRestartMesh (const int tag, const std::string file, std::vector< Tag > tags_to_transfer={})
 
MoFEMErrorCode postProcessResults (const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, Vec var_vec=PETSC_NULLPTR, Vec gradient=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
 
MoFEMErrorCode postProcessSkeletonResults (const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={})
 
MoFEMErrorCode calculateCrackArea (boost::shared_ptr< double > &area_ptr)
 
MoFEMErrorCode gettingNorms ()
 [Getting norms]
 
MoFEMErrorCode calculateFaceMaterialForce (const int tag, TS ts, SmartPetscObj< Vec > *adjoint_gradient_vector=nullptr)
 
MoFEMErrorCode calculateOrientation (const int tag, bool set_orientation)
 
MoFEMErrorCode setNewFrontCoordinates ()
 
MoFEMErrorCode addCrackSurfaces (const bool debug=false)
 
MoFEMErrorCode saveOrgCoords ()
 
MoFEMErrorCode createCrackSurfaceMeshset ()
 
- Public Member Functions inherited from MoFEM::UnknownInterface
virtual MoFEMErrorCode query_interface (boost::typeindex::type_index type_index, UnknownInterface **iface) const =0
 
template<class IFACE >
MoFEMErrorCode registerInterface (bool error_if_registration_failed=true)
 Register interface.
 
template<class IFACE >
MoFEMErrorCode getInterface (IFACE *&iface) const
 Get interface reference to pointer of interface.
 
template<class IFACE >
MoFEMErrorCode getInterface (IFACE **const iface) const
 Get interface pointer to pointer of interface.
 
template<class IFACE , typename boost::enable_if< boost::is_pointer< IFACE >, int >::type = 0>
IFACE getInterface () const
 Get interface pointer to pointer of interface.
 
template<class IFACE , typename boost::enable_if< boost::is_reference< IFACE >, int >::type = 0>
IFACE getInterface () const
 Get reference to interface.
 
template<class IFACE >
IFACE * getInterface () const
 Function returning pointer to interface.
 
virtual ~UnknownInterface ()=default
 

Static Public Member Functions

static double f_log_e_quadratic (const double v)
 
static double d_f_log_e_quadratic (const double v)
 
static double dd_f_log_e_quadratic (const double v)
 
static double f_log_e (const double v)
 
static double d_f_log_e (const double v)
 
static double dd_f_log_e (const double v)
 
static double inv_f_log_e (const double v)
 
static double inv_d_f_log_e (const double v)
 
static double inv_dd_f_log_e (const double v)
 
static double f_log (const double v)
 
static double d_f_log (const double v)
 
static double dd_f_log (const double v)
 
static double inv_f_log (const double v)
 
static double inv_d_f_log (const double v)
 
static double inv_dd_f_log (const double v)
 
static double f_linear (const double v)
 
static double d_f_linear (const double v)
 
static double dd_f_linear (const double v)
 
static double inv_f_linear (const double v)
 
static double inv_d_f_linear (const double v)
 
static double inv_dd_f_linear (const double v)
 
- Static Public Member Functions inherited from MoFEM::UnknownInterface
static MoFEMErrorCode getLibVersion (Version &version)
 Get library version.
 
static MoFEMErrorCode getFileVersion (moab::Interface &moab, Version &version)
 Get database major version.
 
static MoFEMErrorCode setFileVersion (moab::Interface &moab, Version version=Version(MoFEM_VERSION_MAJOR, MoFEM_VERSION_MINOR, MoFEM_VERSION_BUILD))
 Get database major version.
 
static MoFEMErrorCode getInterfaceVersion (Version &version)
 Get database major version.
 

Public Attributes

MoFEM::InterfacemField
 
boost::shared_ptr< DataAtIntegrationPtsdataAtPts
 
boost::shared_ptr< PhysicalEquations > physicalEquations
 
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
 
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeRhs
 
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeLhs
 
boost::shared_ptr< FaceElementForcesAndSourcesCoreelasticBcLhs
 
boost::shared_ptr< FaceElementForcesAndSourcesCoreelasticBcRhs
 
boost::shared_ptr< ForcesAndSourcesCorecontactTreeRhs
 Make a contact tree.
 
SmartPetscObj< DM > dM
 Coupled problem all fields.
 
SmartPetscObj< DM > dmElastic
 Elastic problem.
 
SmartPetscObj< DM > dmMaterial
 Material problem.
 
SmartPetscObj< DM > dmPrjSpatial
 Projection spatial displacement.
 
const std::string piolaStress = "P"
 
const std::string spatialL2Disp = "wL2"
 
const std::string spatialH1Disp = "wH1"
 
const std::string materialH1Positions = "XH1"
 
const std::string hybridSpatialDisp = "hybridSpatialDisp"
 
const std::string contactDisp = "contactDisp"
 
const std::string stretchTensor = "u"
 
const std::string rotAxis = "omega"
 
const std::string bubbleField = "bubble"
 
const std::string elementVolumeName = "EP"
 
const std::string naturalBcElement = "NATURAL_BC"
 
const std::string skinElement = "SKIN"
 
const std::string skeletonElement = "SKELETON"
 
const std::string contactElement = "CONTACT"
 
int spaceOrder = 2
 
int spaceH1Order = -1
 
int materialH1Order = 1
 
double alphaU = 0
 
double alphaW = 0
 
double alphaOmega = 0
 
double alphaRho = 0
 
double alphaTau = 0
 
int contactRefinementLevels = 1
 
int frontLayers = 3
 
double loadFactor = 1.0
 
double avgGriffithsEnergy = -1
 
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
 
boost::shared_ptr< BcRotVec > bcSpatialRotationVecPtr
 
boost::shared_ptr< TractionBcVec > bcSpatialTractionVecPtr
 
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
 
boost::shared_ptr< NormalDisplacementBcVec > bcSpatialNormalDisplacementVecPtr
 
boost::shared_ptr< AnalyticalDisplacementBcVec > bcSpatialAnalyticalDisplacementVecPtr
 
boost::shared_ptr< AnalyticalTractionBcVec > bcSpatialAnalyticalTractionVecPtr
 
boost::shared_ptr< PressureBcVec > bcSpatialPressureVecPtr
 
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
 
double oldCrackArea = 0.
 
double oldStrainEnergy = 0.
 
double oldLoadFactor = 1.0
 
double strainEnergy = 0.
 
boost::shared_ptr< doublecurrentCrackAreaPtr
 
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
 
boost::shared_ptr< RangecontactFaces
 
boost::shared_ptr< RangecrackFaces
 
boost::shared_ptr< RangefrontEdges
 
boost::shared_ptr< RangefrontAdjEdges
 
boost::shared_ptr< RangefrontVertices
 
boost::shared_ptr< RangeskeletonFaces
 
boost::shared_ptr< RangemaxMovedFaces
 
boost::shared_ptr< RangeinterfaceFaces
 
boost::shared_ptr< ParentFiniteElementAdjacencyFunctionSkeleton< 2 > > parentAdjSkeletonFunctionDim2
 
BitRefLevel bitAdjParent = BitRefLevel().set()
 bit ref level for parent
 
BitRefLevel bitAdjParentMask
 bit ref level for parent parent
 
BitRefLevel bitAdjEnt = BitRefLevel().set()
 bit ref level for parent
 
BitRefLevel bitAdjEntMask
 bit ref level for parent parent
 
SmartPetscObj< Vec > solTSStep
 
PetscBool loadFactorTSSolveExecuted = PETSC_FALSE
 
CommInterface::EntitiesPetscVector volumeExchange
 
CommInterface::EntitiesPetscVector faceExchange
 
CommInterface::EntitiesPetscVector edgeExchange
 
CommInterface::EntitiesPetscVector vertexExchange
 
std::vector< TaglistTagsToTransfer
 list of tags to transfer to postprocessor
 
Mat S = PETSC_NULLPTR
 
AO aoS = PETSC_NULLPTR
 
SmartPetscObj< IS > crackHybridIs
 
std::vector< std::string > a00FieldList
 
std::vector< boost::shared_ptr< Range > > a00RangeList
 
int nbCrackFaces = 0
 

Static Public Attributes

static const char * listSolvers []
 
static constexpr enum SymmetrySelector symmetrySelector = SYMMETRIC
 
static enum SolverType solverType = TimeSolver
 
static enum MaterialModel materialModel = MooneyRivlin
 
static enum RotSelector rotSelector = LARGE_ROT
 
static enum RotSelector gradApproximator = LARGE_ROT
 
static enum StretchSelector stretchSelector = LOG
 
static enum StretchHandling stretchHandling
 
static PetscBool setSingularity = PETSC_FALSE
 
static PetscBool physicalTimeFlg
 
static PetscBool crackingOn = PETSC_FALSE
 
static double crackingStartTime = -1
 
static double crackingAddTime = -1
 
static int nbJIntegralContours
 
static double finalPhysicalTime = 0
 
static double currentPhysicalTime
 
static double physicalDt = 0
 
static int physicalMaxSteps = 20
 
static int physicalStepNumber = 0
 
static PetscBool physicalH1Update
 
static PetscBool l2UserBaseScale = PETSC_FALSE
 
static int addCrackMeshsetId = 1000
 
static double griffithEnergy = 1
 Griffith energy.
 
static double crackingRtol = 1e-10
 Cracking relative tolerance.
 
static double crackingAtol = 1e-12
 Cracking absolute tolerance.
 
static enum EnergyReleaseSelector energyReleaseSelector
 
static std::string internalStressTagName
 
static PetscBool internalStressVoigt
 
static PetscBool interfaceCrack
 
static int interfaceRemoveLevel
 
static std::string heterogeneousYoungModTagName
 
static bool hasNonHomogeneousMaterialBlock = false
 
static std::string meshTransferSourceMeshFileName
 
static int meshTransferInterpOrder
 
static PetscBool meshTransferSourceMeshFileSpecified
 
static PetscBool meshTransferHybridInterp
 
static std::vector< std::string > listTagsToProject
 
static FieldApproximationBase brokenHdivBase
 
static double maxCrackExtension
 
static double exponentBase = exp(1)
 
static boost::function< double(const double)> f = EshelbianCore::f_log_e
 
static boost::function< double(const double)> d_f
 
static boost::function< double(const double)> dd_f
 
static boost::function< double(const double)> inv_f
 
static boost::function< double(const double)> inv_d_f
 
static boost::function< double(const double)> inv_dd_f
 
static constexpr bool use_quadratic_exp = true
 
static constexpr double v_max = 24
 
static constexpr double v_min = -v_max
 

Friends

struct solve_elastic_set_up
 

Detailed Description

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 12 of file EshelbianCore.hpp.

Member Enumeration Documentation

◆ MaterialModel

Enumerator
StVenantKirchhoff 
MooneyRivlin 
Hencky 
Neohookean 
Meta 
LastMaterial 

Definition at line 14 of file EshelbianCore.hpp.

◆ SolverType

Enumerator
TimeSolver 
DynamicRelaxation 
Cohesive 
LoadFactor 
ShapeOptimization 
TestTopologicalDerivative 
LastSolver 
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 30 of file EshelbianCore.hpp.

◆ StretchHandling

Enumerator
FULL_ORDER_STREACH 
NO_STREACH 

Definition at line 40 of file EshelbianCore.hpp.

Constructor & Destructor Documentation

◆ EshelbianCore()

EshelbianCore::EshelbianCore ( MoFEM::Interface m_field)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 961 of file EshelbianPlasticity.cpp.

961 : mField(m_field) {
962 CHK_THROW_MESSAGE(getOptions(), "getOptions failed");
963}
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
MoFEM::Interface & mField
MoFEMErrorCode getOptions()

◆ ~EshelbianCore()

EshelbianCore::~EshelbianCore ( )
virtualdefault

Member Function Documentation

◆ addBoundaryFiniteElement()

MoFEMErrorCode EshelbianCore::addBoundaryFiniteElement ( const EntityHandle  meshset = 0)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 2369 of file EshelbianPlasticity.cpp.

2369 {
2371
2372 Range meshset_ents;
2373 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
2374
2375 auto set_fe_adjacency = [&](auto fe_name) {
2378 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
2381 fe_name, MBTRI, *parentAdjSkeletonFunctionDim2);
2383 };
2384
2385 // set finite element fields
2386 auto add_field_to_fe = [this](const std::string fe,
2387 const std::string field_name) {
2396 };
2397
2399
2400 Range natural_bc_elements;
2401 if (bcSpatialDispVecPtr) {
2402 for (auto &v : *bcSpatialDispVecPtr) {
2403 natural_bc_elements.merge(v.faces);
2404 }
2405 }
2407 for (auto &v : *bcSpatialRotationVecPtr) {
2408 natural_bc_elements.merge(v.faces);
2409 }
2410 }
2412 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2413 natural_bc_elements.merge(v.faces);
2414 }
2415 }
2418 natural_bc_elements.merge(v.faces);
2419 }
2420 }
2422 for (auto &v : *bcSpatialTractionVecPtr) {
2423 natural_bc_elements.merge(v.faces);
2424 }
2425 }
2427 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2428 natural_bc_elements.merge(v.faces);
2429 }
2430 }
2432 for (auto &v : *bcSpatialPressureVecPtr) {
2433 natural_bc_elements.merge(v.faces);
2434 }
2435 }
2436 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
2437
2439 CHKERR mField.add_ents_to_finite_element_by_type(natural_bc_elements, MBTRI,
2441 CHKERR add_field_to_fe(naturalBcElement, piolaStress);
2442 CHKERR add_field_to_fe(naturalBcElement, hybridSpatialDisp);
2443 CHKERR set_fe_adjacency(naturalBcElement);
2445 }
2446
2447 auto get_skin = [&](auto &body_ents) {
2448 Skinner skin(&mField.get_moab());
2449 Range skin_ents;
2450 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2451 return skin_ents;
2452 };
2453
2454 auto filter_true_skin = [&](auto &&skin) {
2455 Range boundary_ents;
2456 ParallelComm *pcomm =
2457 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2458 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2459 PSTATUS_NOT, -1, &boundary_ents);
2460 return boundary_ents;
2461 };
2462
2464
2465 Range body_ents;
2466 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
2467 body_ents);
2468 auto skin = filter_true_skin(get_skin(body_ents));
2469
2477 contactDisp);
2480
2482 }
2483
2485 if (contactFaces) {
2486 MOFEM_LOG("EP", Sev::inform)
2487 << "Contact elements " << contactFaces->size();
2491 CHKERR add_field_to_fe(contactElement, piolaStress);
2492 CHKERR add_field_to_fe(contactElement, contactDisp);
2493 CHKERR add_field_to_fe(contactElement, spatialL2Disp);
2494 CHKERR add_field_to_fe(contactElement, spatialH1Disp);
2495 CHKERR set_fe_adjacency(contactElement);
2497 }
2498 }
2499
2501 if (!skeletonFaces)
2502 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
2503 MOFEM_LOG("EP", Sev::inform)
2504 << "Skeleton elements " << skeletonFaces->size();
2508 CHKERR add_field_to_fe(skeletonElement, piolaStress);
2509 CHKERR add_field_to_fe(skeletonElement, hybridSpatialDisp);
2510 CHKERR add_field_to_fe(skeletonElement, spatialL2Disp);
2511 CHKERR add_field_to_fe(skeletonElement, spatialH1Disp);
2512 CHKERR set_fe_adjacency(skeletonElement);
2514 }
2515
2517}
static auto filter_true_skin(MoFEM::Interface &m_field, Range &&skin)
static auto get_skin(MoFEM::Interface &m_field, Range body_ents)
constexpr int SPACE_DIM
@ MF_ZERO
#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
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
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_adjacency_table(const std::string &fe_name, const EntityType type, ElementAdjacencyFunct function)=0
modify finite element table, only for advanced user
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
#define MOFEM_LOG(channel, severity)
Log.
const double v
phase velocity of light in medium (cm/ns)
constexpr auto field_name
const std::string skeletonElement
boost::shared_ptr< TractionBcVec > bcSpatialTractionVecPtr
boost::shared_ptr< Range > contactFaces
BitRefLevel bitAdjEnt
bit ref level for parent
const std::string spatialL2Disp
const std::string materialH1Positions
boost::shared_ptr< BcRotVec > bcSpatialRotationVecPtr
const std::string spatialH1Disp
boost::shared_ptr< NormalDisplacementBcVec > bcSpatialNormalDisplacementVecPtr
const std::string piolaStress
boost::shared_ptr< AnalyticalDisplacementBcVec > bcSpatialAnalyticalDisplacementVecPtr
boost::shared_ptr< ParentFiniteElementAdjacencyFunctionSkeleton< 2 > > parentAdjSkeletonFunctionDim2
boost::shared_ptr< Range > skeletonFaces
BitRefLevel bitAdjParentMask
bit ref level for parent parent
const std::string contactDisp
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
const std::string skinElement
boost::shared_ptr< AnalyticalTractionBcVec > bcSpatialAnalyticalTractionVecPtr
BitRefLevel bitAdjParent
bit ref level for parent
const std::string naturalBcElement
boost::shared_ptr< PressureBcVec > bcSpatialPressureVecPtr
const std::string hybridSpatialDisp
BitRefLevel bitAdjEntMask
bit ref level for parent parent
const std::string contactElement
virtual moab::Interface & get_moab()=0
virtual bool check_finite_element(const std::string &name) const =0
Check if finite element is in database.
virtual MPI_Comm & get_comm() const =0

◆ addCrackSurfaces()

MoFEMErrorCode EshelbianCore::addCrackSurfaces ( const bool  debug = false)

Definition at line 2100 of file EshelbianFracture.cpp.

2100 {
2102
2103 constexpr bool potential_crack_debug = false;
2104 if constexpr (potential_crack_debug) {
2105
2106 auto add_ents = get_range_from_block(mField, "POTENTIAL", SPACE_DIM - 1);
2107 Range crack_front_verts;
2108 CHKERR mField.get_moab().get_connectivity(*frontEdges, crack_front_verts,
2109 true);
2110 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
2111 crack_front_verts);
2112 Range crack_front_faces;
2113 CHKERR mField.get_moab().get_adjacencies(crack_front_verts, SPACE_DIM - 1,
2114 true, crack_front_faces,
2115 moab::Interface::UNION);
2116 crack_front_faces = intersect(crack_front_faces, add_ents);
2117 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
2118 crack_front_faces);
2119 CHKERR mField.getInterface<MeshsetsManager>()->addEntitiesToMeshset(
2120 BLOCKSET, addCrackMeshsetId, crack_front_faces);
2121 }
2122
2123 auto get_crack_faces = [&]() {
2124 if (maxMovedFaces) {
2125 return unite(*crackFaces, *maxMovedFaces);
2126 } else {
2127 return *crackFaces;
2128 }
2129 };
2130
2131 auto get_extended_crack_faces = [&]() {
2132 auto get_faces_of_crack_front_verts = [&](auto crack_faces_org) {
2133 ParallelComm *pcomm =
2134 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2135
2136 Range crack_faces;
2137
2138 if (!pcomm->rank()) {
2139
2140 auto get_nodes = [&](auto &&e) {
2141 Range nodes;
2142 CHK_MOAB_THROW(mField.get_moab().get_connectivity(e, nodes, true),
2143 "get connectivity");
2144 return nodes;
2145 };
2146
2147 auto get_adj = [&](auto &&e, auto dim,
2148 auto t = moab::Interface::UNION) {
2149 Range adj;
2151 mField.get_moab().get_adjacencies(e, dim, true, adj, t),
2152 "get adj");
2153 return adj;
2154 };
2155
2156 Range body_ents;
2157 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
2158 body_ents);
2159 auto body_skin = get_skin(mField, body_ents);
2160 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
2161 auto geometry_edges = get_range_from_block(mField, "EDGES", 1);
2162 auto front_block_edges = get_range_from_block(mField, "FRONT", 1);
2163 auto front_block_nodes = get_nodes(front_block_edges);
2164
2165 size_t s;
2166 do {
2167 s = crack_faces.size();
2168
2169 auto crack_face_nodes = get_nodes(crack_faces_org);
2170 auto crack_faces_edges =
2171 get_adj(crack_faces_org, 1, moab::Interface::UNION);
2172
2173 auto crack_skin = get_skin(mField, crack_faces_org);
2174 front_block_edges = subtract(front_block_edges, crack_skin);
2175 auto crack_skin_nodes = get_nodes(crack_skin);
2176 crack_skin_nodes.merge(front_block_nodes);
2177
2178 auto crack_skin_faces =
2179 get_adj(crack_skin, 2, moab::Interface::UNION);
2180 crack_skin_faces =
2181 subtract(subtract(crack_skin_faces, crack_faces_org), body_skin);
2182
2183 crack_faces = crack_faces_org;
2184 for (auto f : crack_skin_faces) {
2185 auto edges = intersect(
2186 get_adj(Range(f, f), 1, moab::Interface::UNION), crack_skin);
2187
2188 // if other edge is part of body skin, e.g. crack punching through
2189 // body surface
2190 if (edges.size() == 2) {
2191 edges.merge(
2192 intersect(get_adj(Range(f, f), 1, moab::Interface::UNION),
2193 body_skin_edges));
2194 }
2195
2196 if (edges.size() == 2) {
2197 auto edge_conn = get_nodes(Range(edges));
2198 auto faces = intersect(get_adj(edges, 2, moab::Interface::UNION),
2199 crack_faces_org);
2200 if (faces.size() == 2) {
2201 auto edge0_conn = get_nodes(Range(edges[0], edges[0]));
2202 auto edge1_conn = get_nodes(Range(edges[1], edges[1]));
2203 auto edges_conn = intersect(intersect(edge0_conn, edge1_conn),
2204 crack_skin_nodes); // node at apex
2205 if (edges_conn.size() == 1) {
2206
2207 auto node_edges =
2208 subtract(intersect(get_adj(edges_conn, 1,
2209 moab::Interface::INTERSECT),
2210 crack_faces_edges),
2211 crack_skin); // nodes on crack surface, but not
2212 // at the skin
2213
2214 if (node_edges.size()) {
2217 CHKERR mField.get_moab().get_coords(edges_conn, &t_v0(0));
2218
2219 auto get_t_dir = [&](auto e_conn) {
2220 auto other_node = subtract(e_conn, edges_conn);
2222 CHKERR mField.get_moab().get_coords(other_node,
2223 &t_dir(0));
2224 t_dir(i) -= t_v0(i);
2225 return t_dir;
2226 };
2227
2229 t_ave_dir(i) =
2230 get_t_dir(edge0_conn)(i) + get_t_dir(edge1_conn)(i);
2231
2232 FTensor::Tensor1<double, SPACE_DIM> t_crack_surface_ave_dir;
2233 t_crack_surface_ave_dir(i) = 0;
2234 for (auto e : node_edges) {
2235 auto e_conn = get_nodes(Range(e, e));
2236 auto t_dir = get_t_dir(e_conn);
2237 t_crack_surface_ave_dir(i) += t_dir(i);
2238 }
2239
2240 auto dot = t_ave_dir(i) * t_crack_surface_ave_dir(i);
2241 // ave edges is in opposite direction to crack surface, so
2242 // thus crack is not turning back
2243 if (dot < -std::numeric_limits<double>::epsilon()) {
2244 crack_faces.insert(f);
2245 }
2246 } else {
2247 crack_faces.insert(f);
2248 }
2249 }
2250 }
2251 } else if (edges.size() == 3) {
2252 crack_faces.insert(f);
2253 }
2254
2255 // if other edge is part of geometry edge, e.g. keyway
2256 if (edges.size() == 1) {
2257 edges.merge(
2258 intersect(get_adj(Range(f, f), 1, moab::Interface::UNION),
2259 geometry_edges));
2260 edges.merge(
2261 intersect(get_adj(Range(f, f), 1, moab::Interface::UNION),
2262 front_block_edges));
2263 if (edges.size() == 2) {
2264 crack_faces.insert(f);
2265 continue;
2266 }
2267 }
2268 }
2269
2270 crack_faces_org = crack_faces;
2271
2272 } while (s != crack_faces.size());
2273 };
2274
2275 return crack_faces; // send_type(mField, crack_faces, MBTRI);
2276 };
2277
2278 return get_faces_of_crack_front_verts(get_crack_faces());
2279 };
2280
2281 if (debug) {
2282 CHKERR save_range(mField.get_moab(), "new_crack_surface_debug.vtk",
2283 get_extended_crack_faces());
2284 }
2285
2286 auto reconstruct_crack_faces = [&](auto crack_faces) {
2287 ParallelComm *pcomm =
2288 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2289
2290 auto impl = [&]() {
2292
2293 Range new_crack_faces;
2294 if (!pcomm->rank()) {
2295
2296 auto get_nodes = [&](auto &&e) {
2297 Range nodes;
2298 CHK_MOAB_THROW(mField.get_moab().get_connectivity(e, nodes, true),
2299 "get connectivity");
2300 return nodes;
2301 };
2302
2303 auto get_adj = [&](auto &&e, auto dim,
2304 auto t = moab::Interface::UNION) {
2305 Range adj;
2307 mField.get_moab().get_adjacencies(e, dim, true, adj, t),
2308 "get adj");
2309 return adj;
2310 };
2311
2312 auto get_test_on_crack_surface = [&]() {
2313 auto crack_faces_nodes =
2314 get_nodes(crack_faces); // nodes on crac faces
2315 auto crack_faces_tets =
2316 get_adj(crack_faces_nodes, 3,
2317 moab::Interface::UNION); // adjacent
2318 // tets to
2319 // crack
2320 // faces throug nodes
2321 auto crack_faces_tets_nodes =
2322 get_nodes(crack_faces_tets); // nodes on crack faces tets
2323 crack_faces_tets_nodes =
2324 subtract(crack_faces_tets_nodes, crack_faces_nodes);
2325 crack_faces_tets =
2326 subtract(crack_faces_tets, get_adj(crack_faces_tets_nodes, 3,
2327 moab::Interface::UNION));
2328 new_crack_faces =
2329 get_adj(crack_faces_tets, 2,
2330 moab::Interface::UNION); // adjacency faces to crack
2331 // faces through tets
2332 new_crack_faces.merge(crack_faces); // add original crack faces
2333
2334 return std::make_tuple(new_crack_faces, crack_faces_tets);
2335 };
2336
2337 auto carck_faces_test_edges = [&](auto faces, auto tets) {
2338 auto adj_tets_faces = get_adj(tets, 2, moab::Interface::UNION);
2339 auto adj_faces_edges = get_adj(subtract(faces, adj_tets_faces), 1,
2340 moab::Interface::UNION);
2341 auto adj_tets_edges = get_adj(tets, 1, moab::Interface::UNION);
2342 auto geometry_edges = get_range_from_block(mField, "EDGES", 1);
2343 auto front_block_edges = get_range_from_block(mField, "FRONT", 1);
2344 adj_faces_edges.merge(geometry_edges); // geometry edges
2345 adj_faces_edges.merge(front_block_edges); // front block edges
2346
2347 auto boundary_tets_edges = intersect(adj_tets_edges, adj_faces_edges);
2348 auto boundary_test_nodes = get_nodes(boundary_tets_edges);
2349 auto boundary_test_nodes_edges =
2350 get_adj(boundary_test_nodes, 1, moab::Interface::UNION);
2351 auto boundary_test_nodes_edges_nodes = subtract(
2352 get_nodes(boundary_test_nodes_edges), boundary_test_nodes);
2353
2354 boundary_tets_edges =
2355 subtract(boundary_test_nodes_edges,
2356 get_adj(boundary_test_nodes_edges_nodes, 1,
2357 moab::Interface::UNION));
2358
2359 Range body_ents;
2360 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
2361 body_ents);
2362 auto body_skin = get_skin(mField, body_ents);
2363
2364 auto body_skin_edges = get_adj(body_skin, 1, moab::Interface::UNION);
2365 body_skin_edges = intersect(get_adj(tets, 1, moab::Interface::UNION),
2366 body_skin_edges);
2367 body_skin = intersect(body_skin, adj_tets_faces);
2368 body_skin_edges = subtract(
2369 body_skin_edges, get_adj(body_skin, 1, moab::Interface::UNION));
2370
2371 save_range(mField.get_moab(), "body_skin_edges.vtk", body_skin_edges);
2372 for (auto e : body_skin_edges) {
2373 auto adj_tet = intersect(
2374 get_adj(Range(e, e), 3, moab::Interface::INTERSECT), tets);
2375 if (adj_tet.size() == 1) {
2376 boundary_tets_edges.insert(e);
2377 }
2378 }
2379
2380 return boundary_tets_edges;
2381 };
2382
2383 auto p = get_test_on_crack_surface();
2384 auto &[new_crack_faces, crack_faces_tets] = p;
2385
2386 if (debug) {
2387 CHKERR save_range(mField.get_moab(), "hole_crack_faces_debug.vtk",
2388 crack_faces);
2389 CHKERR save_range(mField.get_moab(), "new_crack_faces_debug.vtk",
2390 new_crack_faces);
2391 CHKERR save_range(mField.get_moab(), "new_crack_tets_debug.vtk",
2392 crack_faces_tets);
2393 }
2394
2395 auto boundary_tets_edges =
2396 carck_faces_test_edges(new_crack_faces, crack_faces_tets);
2397 CHKERR save_range(mField.get_moab(), "boundary_tets_edges.vtk",
2398 boundary_tets_edges);
2399
2400 auto resolve_surface = [&](auto boundary_tets_edges,
2401 auto crack_faces_tets) {
2402 auto boundary_tets_edges_nodes = get_nodes(boundary_tets_edges);
2403 auto crack_faces_tets_faces =
2404 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
2405
2406 Range all_removed_faces;
2407 Range all_removed_tets;
2408 int counter = 0;
2409
2410 int size = 0;
2411 while (size != crack_faces_tets.size()) {
2412 auto tets_faces =
2413 get_adj(crack_faces_tets, 2, moab::Interface::UNION);
2414 auto skin_tets = get_skin(mField, crack_faces_tets);
2415 auto skin_skin =
2416 get_skin(mField, subtract(crack_faces_tets_faces, tets_faces));
2417 auto skin_skin_nodes = get_nodes(skin_skin);
2418
2419 size = crack_faces_tets.size();
2420 MOFEM_LOG("SELF", Sev::inform)
2421 << "Crack faces tets size " << crack_faces_tets.size()
2422 << " crack faces size " << crack_faces_tets_faces.size();
2423 auto skin_tets_nodes = subtract(
2424 get_nodes(skin_tets),
2425 boundary_tets_edges_nodes); // not remove tets which are
2426 // adjagasent to crack faces nodes
2427 skin_tets_nodes = subtract(skin_tets_nodes, skin_skin_nodes);
2428
2429 Range removed_nodes;
2430 Range tets_to_remove;
2431 Range faces_to_remove;
2432 for (auto n : skin_tets_nodes) {
2433 auto tets =
2434 intersect(get_adj(Range(n, n), 3, moab::Interface::INTERSECT),
2435 crack_faces_tets);
2436 if (tets.size() == 0) {
2437 continue;
2438 }
2439
2440 auto hole_detetction = [&]() {
2441 auto adj_tets =
2442 get_adj(Range(n, n), 3, moab::Interface::INTERSECT);
2443 adj_tets =
2444 subtract(adj_tets,
2445 crack_faces_tets); // tetst adjacent to the node
2446 // but not part of crack surface
2447 if (adj_tets.size() == 0) {
2448 return std::make_pair(
2449 intersect(
2450 get_adj(Range(n, n), 2, moab::Interface::INTERSECT),
2451 tets_faces),
2452 tets);
2453 }
2454
2455 std::vector<Range> tets_groups;
2456 auto test_adj_tets = adj_tets;
2457 while (test_adj_tets.size()) {
2458 auto seed_size = 0;
2459 Range seed = Range(test_adj_tets[0], test_adj_tets[0]);
2460 while (seed.size() != seed_size) {
2461 auto adj_faces =
2462 subtract(get_adj(seed, 2, moab::Interface::UNION),
2463 tets_faces); // edges which are not
2464 // part of the node
2465 seed_size = seed.size();
2466 seed.merge(
2467 intersect(get_adj(adj_faces, 3, moab::Interface::UNION),
2468 test_adj_tets));
2469 }
2470 tets_groups.push_back(seed);
2471 test_adj_tets = subtract(test_adj_tets, seed);
2472 }
2473 if (tets_groups.size() == 1) {
2474
2475 return std::make_pair(
2476 intersect(
2477 get_adj(Range(n, n), 2, moab::Interface::INTERSECT),
2478 tets_faces),
2479 tets);
2480 }
2481
2482 Range tets_to_remove;
2483 Range faces_to_remove;
2484 for (auto &r : tets_groups) {
2485 auto f = get_adj(r, 2, moab::Interface::UNION);
2486 auto t = intersect(get_adj(f, 3, moab::Interface::UNION),
2487 crack_faces_tets); // tets
2488
2489 if (f.size() > faces_to_remove.size() ||
2490 faces_to_remove.size() == 0) {
2491 faces_to_remove = f;
2492 tets_to_remove = t; // largest group of tets
2493 }
2494 }
2495 MOFEM_LOG("EPSELF", Sev::inform)
2496 << "Hole detection: faces to remove "
2497 << faces_to_remove.size() << " tets to remove "
2498 << tets_to_remove.size();
2499 return std::make_pair(faces_to_remove, tets_to_remove);
2500 };
2501
2502 if (tets.size() < tets_to_remove.size() ||
2503 tets_to_remove.size() == 0) {
2504 removed_nodes = Range(n, n);
2505 auto [h_faces_to_remove, h_tets_to_remove] =
2506 hole_detetction(); // find faces and tets to remove
2507 faces_to_remove = h_faces_to_remove;
2508 tets_to_remove = h_tets_to_remove;
2509
2510 // intersect(
2511 // get_adj(Range(n, n), 2, moab::Interface::INTERSECT),
2512 // tets_faces);
2513
2514 } // find tets which is largest adjacencty size, so that it is
2515 // removed first, and then faces are removed
2516 all_removed_faces.merge(faces_to_remove);
2517 all_removed_tets.merge(tets_to_remove);
2518 }
2519
2520 crack_faces_tets = subtract(crack_faces_tets, tets_to_remove);
2521 crack_faces_tets_faces =
2522 subtract(crack_faces_tets_faces, faces_to_remove);
2523
2524 if (debug) {
2526 "removed_nodes_" +
2527 boost::lexical_cast<std::string>(counter) + ".vtk",
2528 removed_nodes);
2530 "faces_to_remove_" +
2531 boost::lexical_cast<std::string>(counter) + ".vtk",
2532 faces_to_remove);
2534 "tets_to_remove_" +
2535 boost::lexical_cast<std::string>(counter) + ".vtk",
2536 tets_to_remove);
2538 "crack_faces_tets_faces_" +
2539 boost::lexical_cast<std::string>(counter) + ".vtk",
2540 crack_faces_tets_faces);
2542 "crack_faces_tets_" +
2543 boost::lexical_cast<std::string>(counter) + ".vtk",
2544 crack_faces_tets);
2545 }
2546 counter++;
2547 }
2548
2549 auto cese_internal_faces = [&]() {
2551 auto skin_tets = get_skin(mField, crack_faces_tets);
2552 auto adj_faces = get_adj(skin_tets, 2, moab::Interface::UNION);
2553 adj_faces =
2554 subtract(adj_faces, skin_tets); // remove skin tets faces
2555 auto adj_tets = get_adj(adj_faces, 3,
2556 moab::Interface::UNION); // tets which are
2557 // adjacent to skin
2558 crack_faces_tets =
2559 subtract(crack_faces_tets,
2560 adj_tets); // remove tets which are adjacent to
2561 // skin, so that they are not removed
2562 crack_faces_tets_faces =
2563 subtract(crack_faces_tets_faces, adj_faces);
2564
2565 all_removed_faces.merge(adj_faces);
2566 all_removed_tets.merge(adj_tets);
2567
2568 MOFEM_LOG("EPSELF", Sev::inform)
2569 << "Remove internal faces size " << adj_faces.size()
2570 << " tets size " << adj_tets.size();
2572 };
2573
2574 auto case_only_one_free_edge = [&]() {
2576
2577 for (auto t : Range(crack_faces_tets)) {
2578
2579 auto adj_faces = get_adj(
2580 Range(t, t), 2,
2581 moab::Interface::UNION); // faces of tet which can be removed
2582 auto crack_surface_edges =
2583 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
2584 adj_faces),
2585 1,
2586 moab::Interface::UNION); // edges not on the tet but
2587 // on crack surface
2588 auto adj_edges =
2589 subtract(get_adj(Range(t, t), 1, moab::Interface::INTERSECT),
2590 crack_surface_edges); // free edges
2591 adj_edges = subtract(
2592 adj_edges,
2593 boundary_tets_edges); // edges which are not part of gemetry
2594
2595 if (adj_edges.size() == 1) {
2596 crack_faces_tets =
2597 subtract(crack_faces_tets,
2598 Range(t, t)); // remove tets which are adjacent to
2599 // skin, so that they are not removed
2600
2601 auto faces_to_remove =
2602 get_adj(adj_edges, 2, moab::Interface::UNION); // faces
2603 // which can
2604 // be removed
2605 crack_faces_tets_faces =
2606 subtract(crack_faces_tets_faces, faces_to_remove);
2607
2608 all_removed_faces.merge(faces_to_remove);
2609 all_removed_tets.merge(Range(t, t));
2610
2611 MOFEM_LOG("EPSELF", Sev::inform) << "Remove free one edges ";
2612 }
2613 }
2614
2615 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
2616 crack_faces_tets_faces =
2617 subtract(crack_faces_tets_faces, all_removed_faces);
2618
2620 };
2621
2622 auto cese_flat_tet = [&](auto max_adj_edges) {
2624
2625 Range body_ents;
2626 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
2627 body_ents);
2628 auto body_skin = get_skin(mField, body_ents);
2629 auto body_skin_edges =
2630 get_adj(body_skin, 1, moab::Interface::UNION);
2631
2632 for (auto t : Range(crack_faces_tets)) {
2633
2634 auto adj_faces = get_adj(
2635 Range(t, t), 2,
2636 moab::Interface::UNION); // faces of tet which can be removed
2637 auto crack_surface_edges =
2638 get_adj(subtract(unite(crack_faces_tets_faces, crack_faces),
2639 adj_faces),
2640 1,
2641 moab::Interface::UNION); // edges not on the tet but
2642 // on crack surface
2643 auto adj_edges =
2644 subtract(get_adj(Range(t, t), 1, moab::Interface::INTERSECT),
2645 crack_surface_edges); // free edges
2646 adj_edges = subtract(adj_edges, body_skin_edges);
2647
2648 auto tet_edges = get_adj(Range(t, t), 1,
2649 moab::Interface::UNION); // edges of
2650 // tet
2651 tet_edges = subtract(tet_edges, adj_edges);
2652
2653 for (auto e : tet_edges) {
2654 constexpr int opposite_edge[] = {5, 3, 4, 1, 2, 0};
2655 auto get_side = [&](auto e) {
2656 int side, sense, offset;
2658 mField.get_moab().side_number(t, e, side, sense, offset),
2659 "get side number failed");
2660 return side;
2661 };
2662 auto get_side_ent = [&](auto side) {
2663 EntityHandle side_edge;
2665 mField.get_moab().side_element(t, 1, side, side_edge),
2666 "get side failed");
2667 return side_edge;
2668 };
2669 adj_edges.erase(get_side_ent(opposite_edge[get_side(e)]));
2670 }
2671
2672 if (adj_edges.size() <= max_adj_edges) {
2673
2674 double dot = 1;
2675 Range faces_to_remove;
2676 for (auto e : adj_edges) {
2677 auto edge_adj_faces =
2678 get_adj(Range(e, e), 2, moab::Interface::UNION);
2679 edge_adj_faces = intersect(edge_adj_faces, adj_faces);
2680 if (edge_adj_faces.size() != 2) {
2682 "Adj faces size is not 2 for edge " +
2683 boost::lexical_cast<std::string>(e));
2684 }
2685
2686 auto get_normal = [&](auto f) {
2689 mField.getInterface<Tools>()->getTriNormal(f, &t_n(0)),
2690 "get tri normal failed");
2691 return t_n;
2692 };
2693 auto t_n0 = get_normal(edge_adj_faces[0]);
2694 auto t_n1 = get_normal(edge_adj_faces[1]);
2695 auto get_sense = [&](auto f) {
2696 int side, sense, offset;
2697 CHK_MOAB_THROW(mField.get_moab().side_number(t, f, side,
2698 sense, offset),
2699 "get side number failed");
2700 return sense;
2701 };
2702 auto sense0 = get_sense(edge_adj_faces[0]);
2703 auto sense1 = get_sense(edge_adj_faces[1]);
2704 t_n0.normalize();
2705 t_n1.normalize();
2706
2708 auto dot_e = (sense0 * sense1) * t_n0(i) * t_n1(i);
2709 if (dot_e < dot || e == adj_edges[0]) {
2710 dot = dot_e;
2711 faces_to_remove = edge_adj_faces;
2712 }
2713 }
2714
2715 all_removed_faces.merge(faces_to_remove);
2716 all_removed_tets.merge(Range(t, t));
2717
2718 MOFEM_LOG("EPSELF", Sev::inform)
2719 << "Remove free edges on flat tet, with considered nb. of "
2720 "edges "
2721 << adj_edges.size();
2722 }
2723 }
2724
2725 crack_faces_tets = subtract(crack_faces_tets, all_removed_tets);
2726 crack_faces_tets_faces =
2727 subtract(crack_faces_tets_faces, all_removed_faces);
2728
2730 };
2731
2732 CHK_THROW_MESSAGE(case_only_one_free_edge(),
2733 "Case only one free edge failed");
2734 for (auto max_adj_edges : {0, 1, 2, 3}) {
2735 CHK_THROW_MESSAGE(cese_flat_tet(max_adj_edges),
2736 "Case only one free edge failed");
2737 }
2738 CHK_THROW_MESSAGE(cese_internal_faces(),
2739 "Case internal faces failed");
2740
2741 if (debug) {
2743 "crack_faces_tets_faces_" +
2744 boost::lexical_cast<std::string>(counter) + ".vtk",
2745 crack_faces_tets_faces);
2747 "crack_faces_tets_" +
2748 boost::lexical_cast<std::string>(counter) + ".vtk",
2749 crack_faces_tets);
2750 }
2751
2752 return std::make_tuple(crack_faces_tets_faces, crack_faces_tets,
2753 all_removed_faces, all_removed_tets);
2754 };
2755
2756 auto [resolved_faces, resolved_tets, all_removed_faces,
2757 all_removed_tets] =
2758 resolve_surface(boundary_tets_edges, crack_faces_tets);
2759 resolved_faces.merge(subtract(crack_faces, all_removed_faces));
2760 if (debug) {
2761 CHKERR save_range(mField.get_moab(), "resolved_faces.vtk",
2762 resolved_faces);
2763 CHKERR save_range(mField.get_moab(), "resolved_tets.vtk",
2764 resolved_tets);
2765 }
2766
2767 crack_faces = resolved_faces;
2768 }
2769
2771 };
2772
2773 CHK_THROW_MESSAGE(impl(), "resolve new crack surfaces");
2774
2775 return crack_faces; // send_type(mField, crack_faces, MBTRI);
2776 };
2777
2778 auto resolve_consisten_crack_extension = [&]() {
2780 auto crack_meshset =
2781 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
2783 auto meshset = crack_meshset->getMeshset();
2784
2785 if (!mField.get_comm_rank()) {
2786 Range old_crack_faces;
2787 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTRI,
2788 old_crack_faces);
2789 auto extendeded_crack_faces = get_extended_crack_faces();
2790 auto reconstructed_crack_faces =
2791 subtract(reconstruct_crack_faces(extendeded_crack_faces),
2792 subtract(*crackFaces, old_crack_faces));
2793 if (nbCrackFaces >= reconstructed_crack_faces.size()) {
2794 MOFEM_LOG("EPSELF", Sev::warning)
2795 << "No new crack faces to add, skipping adding to meshset";
2796 extendeded_crack_faces = subtract(
2797 extendeded_crack_faces, subtract(*crackFaces, old_crack_faces));
2798 MOFEM_LOG("EPSELF", Sev::inform)
2799 << "Number crack faces size (extended) "
2800 << extendeded_crack_faces.size();
2801 CHKERR mField.get_moab().clear_meshset(&meshset, 1);
2802 CHKERR mField.get_moab().add_entities(meshset, extendeded_crack_faces);
2803 } else {
2804 CHKERR mField.get_moab().clear_meshset(&meshset, 1);
2805 CHKERR mField.get_moab().add_entities(meshset,
2806 reconstructed_crack_faces);
2807 MOFEM_LOG("EPSELF", Sev::inform)
2808 << "Number crack faces size (reconstructed) "
2809 << reconstructed_crack_faces.size();
2810 nbCrackFaces = reconstructed_crack_faces.size();
2811 }
2812 }
2813
2814 Range crack_faces;
2815 if (!mField.get_comm_rank()) {
2816 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTRI,
2817 crack_faces);
2818 }
2819 crack_faces = send_type(mField, crack_faces, MBTRI);
2820 if (mField.get_comm_rank()) {
2821 CHKERR mField.get_moab().clear_meshset(&meshset, 1);
2822 CHKERR mField.get_moab().add_entities(meshset, crack_faces);
2823 }
2824
2826 };
2827
2828 CHKERR resolve_consisten_crack_extension();
2829
2831};
static auto send_type(MoFEM::Interface &m_field, Range r, const EntityType type)
#define FTENSOR_INDEX(DIM, I)
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
Definition adjoint.cpp:2291
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ BLOCKSET
static const bool debug
FTensor::Index< 'i', SPACE_DIM > i
const double n
refractive index of diffusive medium
constexpr double t
plate stiffness
Definition plate.cpp:58
boost::shared_ptr< Range > maxMovedFaces
static boost::function< double(const double)> f
static int addCrackMeshsetId
boost::shared_ptr< Range > crackFaces
boost::shared_ptr< Range > frontEdges
virtual int get_comm_rank() const =0
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
auto save_range

◆ addDebugModel()

MoFEMErrorCode EshelbianCore::addDebugModel ( TS  ts)

Add debug to model.

That prints information every SNES step

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 4170 of file EshelbianPlasticity.cpp.

4170 {
4172
4173 PetscBool debug_model = PETSC_FALSE;
4174 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_model", &debug_model,
4175 PETSC_NULLPTR);
4176 MOFEM_LOG("EP", Sev::inform)
4177 << "Debug model flag is " << (debug_model ? "ON" : "OFF");
4178
4179 if (debug_model == PETSC_TRUE) {
4180 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4181 auto post_proc = [&](TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, Vec F,
4182 void *ctx) {
4184
4185 SNES snes;
4186 CHKERR TSGetSNES(ts, &snes);
4187 int it;
4188 CHKERR SNESGetIterationNumber(snes, &it);
4189 std::string file_name = "snes_iteration_" + std::to_string(it) + ".h5m";
4190 CHKERR postProcessResults(1, file_name, F, u_t);
4191 std::string file_skel_name =
4192 "snes_iteration_skel_" + std::to_string(it) + ".h5m";
4193
4194 auto get_material_force_tag = [&]() {
4195 auto &moab = mField.get_moab();
4196 Tag tag;
4197 CHK_MOAB_THROW(moab.tag_get_handle("MaterialForce", tag),
4198 "can't get tag");
4199 return tag;
4200 };
4201
4203 CHKERR postProcessSkeletonResults(1, file_skel_name, F,
4204 {get_material_force_tag()});
4205
4207 };
4208 ts_ctx_ptr->tsDebugHook = post_proc;
4209 }
4210
4212}
@ F
const FTensor::Tensor2< T, Dim, Dim > Vec
auto getDMTsCtx(DM dm)
Get TS context data structure used by DM.
Definition DMMoFEM.hpp:1279
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
MoFEMErrorCode postProcessResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, Vec var_vec=PETSC_NULLPTR, Vec gradient=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
MoFEMErrorCode postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={})
MoFEMErrorCode calculateFaceMaterialForce(const int tag, TS ts, SmartPetscObj< Vec > *adjoint_gradient_vector=nullptr)
SmartPetscObj< DM > dmElastic
Elastic problem.

◆ addDMs()

MoFEMErrorCode EshelbianCore::addDMs ( const BitRefLevel  bit = BitRefLevel().set(0),
const EntityHandle  meshset = 0 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 2519 of file EshelbianPlasticity.cpp.

2520 {
2522
2523 // find adjacencies between finite elements and dofs
2525
2526 // Create coupled problem
2527 dM = createDM(mField.get_comm(), "DMMOFEM");
2528 CHKERR DMMoFEMCreateMoFEM(dM, &mField, "ESHELBY_PLASTICITY", bit,
2529 BitRefLevel().set());
2530 CHKERR DMMoFEMSetDestroyProblem(dM, PETSC_TRUE);
2531 CHKERR DMMoFEMSetIsPartitioned(dM, PETSC_TRUE);
2537
2538 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
2539 CHKERR DMSetUp(dM);
2540 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_FALSE;
2541
2542 auto remove_dofs_on_broken_skin = [&](const std::string prb_name) {
2544 for (int d : {0, 1, 2}) {
2545 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
2547 ->getSideDofsOnBrokenSpaceEntities(
2548 dofs_to_remove, prb_name, ROW, piolaStress,
2550 // remove piola dofs, i.e. traction free boundary
2551 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, ROW,
2552 dofs_to_remove);
2553 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, COL,
2554 dofs_to_remove);
2555 }
2557 };
2558 CHKERR remove_dofs_on_broken_skin("ESHELBY_PLASTICITY");
2559
2560 // Create elastic sub-problem
2561 dmElastic = createDM(mField.get_comm(), "DMMOFEM");
2562 CHKERR DMMoFEMCreateSubDM(dmElastic, dM, "ELASTIC_PROBLEM");
2568 if (stretchHandling != NO_STREACH) {
2570 }
2580 CHKERR DMSetUp(dmElastic);
2581
2582 dmMaterial = createDM(mField.get_comm(), "DMMOFEM");
2583 CHKERR DMMoFEMCreateSubDM(dmMaterial, dM, "MATERIAL_PROBLEM");
2592 if (stretchHandling != NO_STREACH) {
2594 }
2600 CHKERR DMSetUp(dmMaterial);
2601
2602 auto set_zero_block = [&]() {
2604 if (stretchHandling != NO_STREACH) {
2605 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2606 "ELASTIC_PROBLEM", spatialL2Disp, stretchTensor);
2607 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2608 "ELASTIC_PROBLEM", stretchTensor, spatialL2Disp);
2609 }
2610 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2611 "ELASTIC_PROBLEM", spatialL2Disp, rotAxis);
2612 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2613 "ELASTIC_PROBLEM", rotAxis, spatialL2Disp);
2614 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2615 "ELASTIC_PROBLEM", spatialL2Disp, bubbleField);
2616 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2617 "ELASTIC_PROBLEM", bubbleField, spatialL2Disp);
2618 if (stretchHandling != NO_STREACH) {
2619 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2620 "ELASTIC_PROBLEM", bubbleField, bubbleField);
2621 CHKERR
2622 mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2623 "ELASTIC_PROBLEM", piolaStress, piolaStress);
2624 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2625 "ELASTIC_PROBLEM", bubbleField, piolaStress);
2626 CHKERR mField.getInterface<ProblemsManager>()->addFieldToEmptyFieldBlocks(
2627 "ELASTIC_PROBLEM", piolaStress, bubbleField);
2628 }
2629
2630 auto zero_kinetic_constraints_block = [&]() {
2632 // we shoudl have sparet bloc names for this. TOPO_FIX_X, TOPO_FIX_Y,
2633 // TOPO_FIX_Z, TOPO_FIX_ALL
2634 auto bc_mng = mField.getInterface<BcManager>();
2635 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_X",
2636 materialH1Positions, 0, 0);
2637 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_Y",
2638 materialH1Positions, 1, 1);
2639 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_Z",
2640 materialH1Positions, 2, 2);
2641 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "REMOVE_ALL",
2642 materialH1Positions, 0, 3);
2643 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_X",
2644 materialH1Positions, 0, 0);
2645 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_Y",
2646 materialH1Positions, 1, 1);
2647 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_Z",
2648 materialH1Positions, 2, 2);
2649 CHKERR bc_mng->removeBlockDOFsOnEntities("MATERIAL_PROBLEM", "FIX_ALL",
2650 materialH1Positions, 0, 3);
2652 };
2653
2654 // CHKERR zero_kinetic_constraints_block();
2655
2658 };
2659
2660 auto set_section = [&]() {
2662 PetscSection section;
2663 CHKERR mField.getInterface<ISManager>()->sectionCreate("ELASTIC_PROBLEM",
2664 &section);
2665 CHKERR DMSetSection(dmElastic, section);
2666 CHKERR DMSetGlobalSection(dmElastic, section);
2667 CHKERR PetscSectionDestroy(&section);
2669 };
2670
2671 CHKERR set_zero_block();
2672 CHKERR set_section();
2673
2674 dmPrjSpatial = createDM(mField.get_comm(), "DMMOFEM");
2675 CHKERR DMMoFEMCreateSubDM(dmPrjSpatial, dM, "PROJECT_SPATIAL");
2681 CHKERR DMSetUp(dmPrjSpatial);
2682
2683 // CHKERR mField.getInterface<BcManager>()
2684 // ->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2685 // "PROJECT_SPATIAL", spatialH1Disp, true, false);
2686
2688}
@ QUIET
@ COL
@ ROW
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
Definition DMMoFEM.cpp:1113
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:215
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:450
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
Definition DMMoFEM.cpp:114
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
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
auto bit
set bit
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
Definition DMMoFEM.cpp:434
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
SmartPetscObj< DM > dM
Coupled problem all fields.
static enum StretchHandling stretchHandling
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
const std::string elementVolumeName
const std::string bubbleField
SmartPetscObj< DM > dmMaterial
Material problem.
const std::string rotAxis
SmartPetscObj< DM > dmPrjSpatial
Projection spatial displacement.
SmartPetscObj< Vec > solTSStep
const std::string stretchTensor
Boundary condition manager for finite element problem setup.
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
Problem manager is used to build and partition problems.

◆ addFields()

MoFEMErrorCode EshelbianCore::addFields ( const EntityHandle  meshset = 0,
const bool  add_bubble = true 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 1352 of file EshelbianPlasticity.cpp.

1353 {
1355
1356 auto get_tets = [&]() {
1357 Range tets;
1358 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
1359 return tets;
1360 };
1361
1362 auto get_tets_skin = [&]() {
1363 Range tets_skin_part;
1364 Skinner skin(&mField.get_moab());
1365 CHKERR skin.find_skin(0, get_tets(), false, tets_skin_part);
1366 ParallelComm *pcomm =
1367 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1368 Range tets_skin;
1369 CHKERR pcomm->filter_pstatus(tets_skin_part,
1370 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1371 PSTATUS_NOT, -1, &tets_skin);
1372 return tets_skin;
1373 };
1374
1375 auto subtract_boundary_conditions = [&](auto &&tets_skin) {
1376 // That mean, that hybrid field on all faces on which traction is applied,
1377 // on other faces, or enforcing displacements as
1378 // natural boundary condition.
1380 for (auto &v : *bcSpatialTractionVecPtr) {
1381 tets_skin = subtract(tets_skin, v.faces);
1382 }
1384 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
1385 tets_skin = subtract(tets_skin, v.faces);
1386 }
1387
1389 for (auto &v : *bcSpatialPressureVecPtr) {
1390 tets_skin = subtract(tets_skin, v.faces);
1391 }
1392
1393 return tets_skin;
1394 };
1395
1396 auto add_blockset = [&](auto block_name, auto &&tets_skin) {
1397 auto crack_faces =
1398 get_range_from_block(mField, "block_name", SPACE_DIM - 1);
1399 tets_skin.merge(crack_faces);
1400 return tets_skin;
1401 };
1402
1403 auto subtract_blockset = [&](auto block_name, auto &&tets_skin) {
1404 auto contact_range =
1405 get_range_from_block(mField, block_name, SPACE_DIM - 1);
1406 tets_skin = subtract(tets_skin, contact_range);
1407 return tets_skin;
1408 };
1409
1410 auto get_stress_trace_faces = [&](auto &&tets_skin) {
1411 Range faces;
1412 CHKERR mField.get_moab().get_adjacencies(get_tets(), SPACE_DIM - 1, true,
1413 faces, moab::Interface::UNION);
1414 Range trace_faces = subtract(faces, tets_skin);
1415 return trace_faces;
1416 };
1417
1418 auto tets = get_tets();
1419
1420 // remove also contact faces, i.e. that is also kind of hybrid field but
1421 // named but used to enforce contact conditions
1422 auto trace_faces = get_stress_trace_faces(
1423
1424 subtract_blockset("CONTACT",
1425 subtract_boundary_conditions(get_tets_skin()))
1426
1427 );
1428
1429 contactFaces = boost::make_shared<Range>(intersect(
1430 trace_faces, get_range_from_block(mField, "CONTACT", SPACE_DIM - 1)));
1432 boost::make_shared<Range>(subtract(trace_faces, *contactFaces));
1433
1434#ifndef NDEBUG
1435 if (contactFaces->size())
1437 "contact_faces_" +
1438 std::to_string(mField.get_comm_rank()) + ".vtk",
1439 *contactFaces);
1440 if (skeletonFaces->size())
1442 "skeleton_faces_" +
1443 std::to_string(mField.get_comm_rank()) + ".vtk",
1444 *skeletonFaces);
1445#endif
1446
1447 const FieldApproximationBase broken_hdiv_base =
1449
1450 auto add_broken_hdiv_field = [this, meshset, broken_hdiv_base](
1451 const std::string field_name,
1452 const int order) {
1454
1455 const FieldApproximationBase base = broken_hdiv_base;
1456
1457 auto get_side_map_hdiv = [&]() {
1458 return std::vector<
1459
1460 std::pair<EntityType,
1462
1463 >>{
1464
1465 {MBTET,
1466 [&](BaseFunction::DofsSideMap &dofs_side_map) -> MoFEMErrorCode {
1467 return TetPolynomialBase::setDofsSideMap(HDIV, DISCONTINUOUS, base,
1468 dofs_side_map);
1469 }}
1470
1471 };
1472 };
1473
1475 get_side_map_hdiv(), MB_TAG_DENSE, MF_ZERO);
1477 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1479 };
1480
1481 auto add_l2_field = [this, meshset](const std::string field_name,
1482 const int order, const int dim) {
1485 MB_TAG_DENSE, MF_ZERO);
1487 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1489 };
1490
1491 auto add_h1_field = [this, meshset](const std::string field_name,
1492 const int order, const int dim) {
1495 MB_TAG_DENSE, MF_ZERO);
1497 CHKERR mField.set_field_order(meshset, MBVERTEX, field_name, 1);
1498 CHKERR mField.set_field_order(meshset, MBEDGE, field_name, order);
1499 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1500 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1502 };
1503
1504 auto add_l2_field_by_range = [this](const std::string field_name,
1505 const int order, const int dim,
1506 const int field_dim, Range &&r) {
1509 MB_TAG_DENSE, MF_ZERO);
1510 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(r);
1514 };
1515
1516 auto add_bubble_field = [this, meshset](const std::string field_name,
1517 const int order, const int dim) {
1519 CHKERR mField.add_field(field_name, HDIV, USER_BASE, dim, MB_TAG_DENSE,
1520 MF_ZERO);
1521 // Modify field
1522 auto field_ptr = mField.get_field_structure(field_name);
1523 auto field_order_table =
1524 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1525 auto get_cgg_bubble_order_zero = [](int p) { return 0; };
1526 auto get_cgg_bubble_order_tet = [](int p) {
1527 return NBVOLUMETET_CCG_BUBBLE(p);
1528 };
1529 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1530 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1531 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1532 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1534 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1535 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1537 };
1538
1539 auto add_user_l2_field = [this, meshset](const std::string field_name,
1540 const int order, const int dim) {
1542 CHKERR mField.add_field(field_name, L2, USER_BASE, dim, MB_TAG_DENSE,
1543 MF_ZERO);
1544 // Modify field
1545 auto field_ptr = mField.get_field_structure(field_name);
1546 auto field_order_table =
1547 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1548 auto zero_dofs = [](int p) { return 0; };
1549 auto dof_l2_tet = [](int p) { return NBVOLUMETET_L2(p); };
1550 field_order_table[MBVERTEX] = zero_dofs;
1551 field_order_table[MBEDGE] = zero_dofs;
1552 field_order_table[MBTRI] = zero_dofs;
1553 field_order_table[MBTET] = dof_l2_tet;
1555 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1557 };
1558
1559 if (!skeletonFaces)
1560 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
1561 if (!contactFaces)
1562 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No contact faces");
1563
1564 auto get_hybridised_disp = [&]() {
1565 auto faces = *skeletonFaces;
1566 auto skin = subtract_boundary_conditions(get_tets_skin());
1567 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
1568 faces.merge(intersect(bc.faces, skin));
1569 }
1570 return faces;
1571 };
1572
1573 auto add_spatial_fields = [&]<FieldApproximationBase Base>() {
1575 using Orders = EshelbianCore::FieldOrders<Base>;
1576 CHKERR add_broken_hdiv_field(piolaStress, Orders::stress(spaceOrder));
1577 if (add_bubble) {
1578 CHKERR add_bubble_field(bubbleField, Orders::bubble(spaceOrder), 1);
1579 }
1580 CHKERR add_l2_field(spatialL2Disp, Orders::disp(spaceOrder), 3);
1581 CHKERR add_user_l2_field(rotAxis, Orders::rot(spaceOrder), 3);
1582 CHKERR add_user_l2_field(stretchTensor,
1584 ? Orders::stretch(spaceOrder)
1585 : -1,
1586 6);
1587 CHKERR add_l2_field_by_range(hybridSpatialDisp,
1588 Orders::hybrid(spaceOrder), 2, 3,
1589 get_hybridised_disp());
1590 CHKERR add_l2_field_by_range(contactDisp, Orders::hybrid(spaceOrder), 2, 3,
1593 };
1594
1595 CHKERR withFieldOrders(add_spatial_fields);
1596
1597 // spatial displacement
1598 CHKERR add_h1_field(spatialH1Disp, spaceH1Order, 3);
1599 // material positions
1600 CHKERR add_h1_field(materialH1Positions, materialH1Order, 3);
1601
1603
1605}
#define NBVOLUMETET_CCG_BUBBLE(P)
Bubble function for CGG H div space.
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ USER_BASE
user implemented approximation base
Definition definitions.h:68
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ HDIV
field with continuous normal traction
Definition definitions.h:87
@ DISCONTINUOUS
Broken continuity (No effect on L2 space)
constexpr int order
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode add_ents_to_field_by_dim(const Range &ents, const int dim, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
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.
#define NBVOLUMETET_L2(P)
Number of base functions on tetrahedron for L2 space.
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
int r
Definition sdf.py:205
static FieldApproximationBase brokenHdivBase
MoFEMErrorCode withFieldOrders(Op &&op) const
multi_index_container< DofsSideMapData, indexed_by< ordered_non_unique< tag< TypeSide_mi_tag >, composite_key< DofsSideMapData, member< DofsSideMapData, EntityType, &DofsSideMapData::type >, member< DofsSideMapData, int, &DofsSideMapData::side > > >, ordered_unique< tag< EntDofIdx_mi_tag >, member< DofsSideMapData, int, &DofsSideMapData::dof > > > > DofsSideMap
Map entity stype and side to element/entity dof index.
Managing BitRefLevels.
virtual MoFEMErrorCode add_broken_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const std::vector< std::pair< EntityType, std::function< MoFEMErrorCode(BaseFunction::DofsSideMap &)> > > list_dof_side_map, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
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.
Field data structure for finite element approximation.

◆ addMaterial_Core()

MoFEMErrorCode EshelbianCore::addMaterial_Core ( boost::weak_ptr< MatOps::PhysicalEquations mat_physical_equations_ptr)
Examples
ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 98 of file EshelbianMat.cpp.

99 {
101 physicalEquations = boost::make_shared<MatPhysicalEquations>(
102 mat_physical_equations_ptr.lock());
104}
boost::shared_ptr< PhysicalEquations > physicalEquations

◆ addMaterial_Hencky()

MoFEMErrorCode EshelbianCore::addMaterial_Hencky ( double  E,
double  nu 
)
Examples
ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 92 of file EshelbianMat.cpp.

92 {
94 physicalEquations = boost::make_shared<HMHHencky>(mField, E, nu);
96}

◆ addMaterial_HMHNeohookean()

MoFEMErrorCode EshelbianCore::addMaterial_HMHNeohookean ( const int  tape,
const double  c10,
const double  K 
)
Examples
ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 84 of file EshelbianMat.cpp.

86 {
88 physicalEquations = boost::make_shared<HMHNeohookean>(mField, c10, K);
90}

◆ addVolumeFiniteElement()

MoFEMErrorCode EshelbianCore::addVolumeFiniteElement ( const EntityHandle  meshset = 0,
const bool  add_bubble = true 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 2330 of file EshelbianPlasticity.cpp.

2331 {
2333
2334 // set finite element fields
2335 auto add_field_to_fe = [this](const std::string fe,
2336 const std::string field_name) {
2342 };
2343
2348
2349 CHKERR add_field_to_fe(elementVolumeName, piolaStress);
2350 if (add_bubble) {
2351 CHKERR add_field_to_fe(elementVolumeName, bubbleField);
2352 }
2354 CHKERR add_field_to_fe(elementVolumeName, stretchTensor);
2355 CHKERR add_field_to_fe(elementVolumeName, rotAxis);
2356 CHKERR add_field_to_fe(elementVolumeName, spatialL2Disp);
2357 CHKERR add_field_to_fe(elementVolumeName, spatialH1Disp);
2358 CHKERR add_field_to_fe(elementVolumeName, contactDisp);
2360
2361 // build finite elements data structures
2363 }
2364
2366}

◆ calculateCrackArea()

MoFEMErrorCode EshelbianCore::calculateCrackArea ( boost::shared_ptr< double > &  area_ptr)

Definition at line 2865 of file EshelbianFracture.cpp.

2865 {
2867
2868 if (!area_ptr) {
2869 // initialize area
2870 area_ptr = boost::shared_ptr<double>(new double(0.0));
2871 }
2872
2873 int success;
2874 *area_ptr = 0;
2875 if (mField.get_comm_rank() == 0) {
2876 MOFEM_LOG("EP", Sev::inform) << "Calculate crack area";
2877 auto crack_faces = get_range_from_block(mField, "CRACK", SPACE_DIM - 1);
2878 for (auto f : crack_faces) {
2879 *area_ptr += mField.getInterface<Tools>()->getTriArea(f);
2880 }
2881 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0, mField.get_comm());
2882 } else {
2883 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0, mField.get_comm());
2884 }
2885 if (success != MPI_SUCCESS) {
2887 }
2889}
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34

◆ calculateFaceMaterialForce()

MoFEMErrorCode EshelbianCore::calculateFaceMaterialForce ( const int  tag,
TS  ts,
SmartPetscObj< Vec > *  adjoint_gradient_vector = nullptr 
)

Create element to integration faces energies

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 14 of file EshelbianFracture.cpp.

15 {
17
18 constexpr bool debug = false;
19
20 auto get_tags_vec = [&](std::vector<std::pair<std::string, int>> names) {
21 std::vector<Tag> tags;
22 tags.reserve(names.size());
23 auto create_and_clean = [&]() {
25 for (auto n : names) {
26 tags.push_back(Tag());
27 auto &tag = tags.back();
28 auto &moab = mField.get_moab();
29 auto rval = moab.tag_get_handle(n.first.c_str(), tag);
30 if (rval == MB_SUCCESS) {
31 moab.tag_delete(tag);
32 }
33 double def_val[] = {0., 0., 0.};
34 CHKERR moab.tag_get_handle(n.first.c_str(), n.second, MB_TYPE_DOUBLE,
35 tag, MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
36 }
38 };
39 CHK_THROW_MESSAGE(create_and_clean(), "create_and_clean");
40 return tags;
41 };
42
43 enum ExhangeTags {
44 MATERIALFORCE,
45 ADJOINT_MATERIALFORCE,
46 AREAGROWTH,
47 GRIFFITHFORCE,
48 ADJOINT_GRIFFITHFORCE,
49 FACEPRESSURE
50 };
51
52 auto tags = get_tags_vec({{"MaterialForce", 3},
53 {"AdjointMaterialForce", 3},
54 {"AreaGrowth", 3},
55 {"GriffithForce", 1},
56 {"AdjointGriffithForce", 1},
57 {"FacePressure", 1}});
58
59 auto calculate_material_forces = [&]() {
61
62 /**
63 * @brief Create element to integration faces energies
64 */
65 auto get_face_material_force_fe = [&]() {
67 auto fe_ptr = boost::make_shared<FaceEle>(mField);
68 fe_ptr->getRuleHook = [](int, int, int) { return -1; };
69 fe_ptr->setRuleHook =
70 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
71 if (ts != PETSC_NULLPTR) {
72 fe_ptr->data_ctx |= PetscData::CTX_SET_TIME;
73 CHKERR TSGetTime(ts, &(fe_ptr->ts_t));
74 CHKERR TSGetTimeStep(ts, &(fe_ptr->ts_dt));
75 }
76 // hybrid disp, evaluated on face first
77 EshelbianPlasticity::AddHOOps<2, 2, 3>::add(
78 fe_ptr->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
79 fe_ptr->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
80 hybridSpatialDisp, dataAtPts->getHybridDispAtPts()));
81 fe_ptr->getOpPtrVector().push_back(
82 new OpCalculateVectorFieldGradient<SPACE_DIM, SPACE_DIM>(
83 hybridSpatialDisp, dataAtPts->getGradHybridDispAtPts()));
84 auto op_loop_domain_side =
85 new OpLoopSide<VolumeElementForcesAndSourcesCoreOnSide>(
86 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
87 fe_ptr->getOpPtrVector().push_back(op_loop_domain_side);
88 fe_ptr->getOpPtrVector().push_back(new OpFaceMaterialForce(dataAtPts));
89
90 // evaluated in side domain, that is op_loop_domain_side
91 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
92 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
93
94 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
95 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
96 materialH1Positions, frontAdjEdges, nullptr, nullptr, nullptr);
97 op_loop_domain_side->getOpPtrVector().push_back(
98 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
99 piolaStress, dataAtPts->getApproxPAtPts()));
100
101 op_loop_domain_side->getOpPtrVector().push_back(
102 new OpCalculateVectorFieldValues<SPACE_DIM>(
103 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
106 // We have to use actual strains to evaluate J integral and energy,
107 // in this case. Note actual stresses, and actual energy can only drive
108 // crack growth
109
110 op_loop_domain_side->getOpPtrVector().push_back(
111 physicalEquations->returnOpCalculateStretchFromStress(
113 } else {
114 // That will not work for problem with internal stress or strain, since
115 // we approximate mechanical stretch, not actual stretch. At some point
116 // in time we can change formulation so that actual stretch is
117 // approximated. However, the way how to do it is not clear.
118
119 op_loop_domain_side->getOpPtrVector().push_back(
120 new OpCalculateTensor2SymmetricFieldValues<SPACE_DIM>(
121 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
122 }
123
124 op_loop_domain_side->getOpPtrVector().push_back(
126
127 return fe_ptr;
128 };
129
130 auto integrate_face_material_force_fe = [&](auto &&face_energy_fe) {
133 dM, skeletonElement, face_energy_fe, 0, mField.get_comm_size());
134
135 auto face_exchange = CommInterface::createEntitiesPetscVector(
136 mField.get_comm(), mField.get_moab(), 2, 3, Sev::inform);
137
138 auto print_loc_size = [this](auto v, auto str, auto sev) {
140 int size;
141 CHKERR VecGetLocalSize(v.second, &size);
142 int low, high;
143 CHKERR VecGetOwnershipRange(v.second, &low, &high);
144 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( "
145 << low << " " << high << " ) ";
148 };
149 CHKERR print_loc_size(face_exchange, "material face_exchange",
150 Sev::verbose);
151
152 CHKERR CommInterface::updateEntitiesPetscVector(
153 mField.get_moab(), face_exchange, tags[ExhangeTags::MATERIALFORCE]);
154 CHKERR CommInterface::updateEntitiesPetscVector(
155 mField.get_moab(), faceExchange, tags[ExhangeTags::FACEPRESSURE]);
156
157 #ifndef NDEBUG
158 if (debug) {
160 "front_skin_faces_material_force_" +
161 std::to_string(mField.get_comm_rank()) + ".vtk",
163 }
164 #endif
165
167 };
168
169 CHKERR integrate_face_material_force_fe(get_face_material_force_fe());
170
172 };
173
174 auto get_conn = [&](auto e) {
175 Range conn;
176 CHK_MOAB_THROW(mField.get_moab().get_connectivity(&e, 1, conn, true),
177 "get connectivity");
178 return conn;
179 };
180
181 auto get_conn_range = [&](auto e) {
182 Range conn;
183 CHK_MOAB_THROW(mField.get_moab().get_connectivity(e, conn, true),
184 "get connectivity");
185 return conn;
186 };
187
188 auto get_adj = [&](auto e, auto dim) {
189 Range adj;
190 CHK_MOAB_THROW(mField.get_moab().get_adjacencies(&e, 1, dim, true, adj),
191 "get adj");
192 return adj;
193 };
194
195 auto get_adj_range = [&](auto e, auto dim) {
196 Range adj;
197 CHK_MOAB_THROW(mField.get_moab().get_adjacencies(e, dim, true, adj,
198 moab::Interface::UNION),
199 "get adj");
200 return adj;
201 };
202
203 auto get_vector_tag_data = [&](auto r, auto th) {
204 MatrixDouble tag_data(r.size(), 3, false);
206 mField.get_moab().tag_get_data(th, r, tag_data.data().data()),
207 "get vector tag data");
208 return tag_data;
209 };
210
211 auto calculate_edge_direction = [&](auto e) {
212 const EntityHandle *conn;
213 int num_nodes;
215 mField.get_moab().get_connectivity(e, conn, num_nodes, true),
216 "get connectivity");
217 std::array<double, 6> coords;
218 CHK_MOAB_THROW(mField.get_moab().get_coords(conn, num_nodes, coords.data()),
219 "get coords");
221 &coords[0], &coords[1], &coords[2]};
223 &coords[3], &coords[4], &coords[5]};
226 t_dir(i) = t_p1(i) - t_p0(i);
227 return t_dir;
228 };
229
230 auto average_vector_tag_at_edge = [&](auto th) {
232
234
235 for (auto e : *frontEdges) {
236 auto conn = get_conn(e);
237 auto data = get_vector_tag_data(conn, th);
238 auto t_node = getFTensor1FromPtr<SPACE_DIM>(data.data().data());
239 FTensor::Tensor1<double, SPACE_DIM> t_edge_material_force{0., 0., 0.};
240 for (auto n : conn) {
241 NOT_USED(n);
242 t_edge_material_force(I) += t_node(I);
243 ++t_node;
244 }
245 t_edge_material_force(I) /= conn.size();
246
247 FTensor::Tensor1<double, SPACE_DIM> t_edge_direction =
248 calculate_edge_direction(e);
249 t_edge_direction.normalize();
250
251 // Project the averaged vector to the plane normal to the front edge.
253 t_cross(K) = FTensor::levi_civita(I, J, K) * t_edge_direction(I) *
254 t_edge_material_force(J);
255 t_edge_material_force(K) =
256 FTensor::levi_civita(I, J, K) * t_edge_direction(J) * t_cross(I);
257
258 CHKERR mField.get_moab().tag_set_data(th, &e, 1,
259 &t_edge_material_force(0));
260 }
261
263 };
264
265 auto average_material_force_at_edge = [&](auto th) {
267
268 if (mField.get_comm_rank() == 0) {
269 CHKERR average_vector_tag_at_edge(th);
270
271// #ifndef NDEBUG
272// if (debug) {
273 int ts_step;
274 CHKERR TSGetStepNumber(ts, &ts_step);
276 "front_edges_material_force_" +
277 std::to_string(ts_step) + ".vtk",
278 *frontEdges);
279// }
280// #endif
281 }
282
284 };
285
286 auto calculate_force_through_node = [&](auto nb_J_integral_contours) {
288
290
291 if (mField.get_comm_rank() == 0) {
292 auto front_nodes = get_conn_range(*frontEdges);
293 Range all_skin_faces;
294
295 for (auto n : front_nodes) {
296 auto adj_tets = get_adj(n, SPACE_DIM);
297 for (int ll = 0; ll < nb_J_integral_contours; ++ll) {
298 auto conn = get_conn_range(adj_tets);
299 adj_tets = get_adj_range(conn, SPACE_DIM);
300 }
301
302 auto skin_faces = get_skin(mField, adj_tets);
303 auto material_forces =
304 get_vector_tag_data(skin_faces, tags[ExhangeTags::MATERIALFORCE]);
305
306#ifndef NDEBUG
307 if (debug) {
308 all_skin_faces.merge(skin_faces);
309 }
310#endif
311
312 auto t_face_T =
313 getFTensor1FromPtr<SPACE_DIM>(material_forces.data().data());
314 FTensor::Tensor1<double, SPACE_DIM> t_node_force{0., 0., 0.};
315 for (auto face : skin_faces) {
316
317 FTensor::Tensor1<double, SPACE_DIM> t_face_force_tmp{0., 0., 0.};
318 t_face_force_tmp(I) = t_face_T(I);
319 ++t_face_T;
320
321 auto face_tets = intersect(get_adj(face, SPACE_DIM), adj_tets);
322
323 if (face_tets.empty()) {
324 continue;
325 }
326
327 if (face_tets.size() != 1) {
329 "face_tets.size() != 1");
330 }
331
332 int side_number, sense, offset;
333 CHK_MOAB_THROW(mField.get_moab().side_number(face_tets[0], face,
334 side_number, sense,
335 offset),
336 "moab side number");
337 t_face_force_tmp(I) *= sense;
338 t_node_force(I) += t_face_force_tmp(I);
339 }
340
341 t_node_force(I) /= griffithEnergy; // scale all by griffith energy
343 mField.get_moab().tag_set_data(tags[ExhangeTags::MATERIALFORCE],
344 &n, 1, &t_node_force(0)),
345 "set data");
346 }
347
348#ifndef NDEBUG
349 if (debug) {
350 int ts_step;
351 CHKERR TSGetStepNumber(ts, &ts_step);
353 "front_skin_faces_material_force_" +
354 std::to_string(ts_step) + ".vtk",
355 all_skin_faces);
356 }
357#endif
358 }
359
361 };
362
363 auto get_adj_tets_for_contour = [&](auto n, auto nb_J_integral_contours) {
364 auto adj_tets = get_adj(n, SPACE_DIM);
365 for (int ll = 0; ll < nb_J_integral_contours; ++ll) {
366 auto conn = get_conn_range(adj_tets);
367 adj_tets = get_adj_range(conn, SPACE_DIM);
368 }
369 return adj_tets;
370 };
371
372 auto get_front_node_adj_crack_faces = [&](auto n) {
373 return intersect(get_adj(n, SPACE_DIM - 1), *crackFaces);
374 };
375
376 auto calculate_crack_area_growth_face = [&](auto nb_J_integral_contours) {
378
379 FTENSOR_INDEXES(SPACE_DIM, I, J, K, L);
380
381 if (mField.get_comm_rank() == 0) {
382 auto front_nodes = get_conn_range(*frontEdges);
383 auto body_edges = get_range_from_block(mField, "EDGES", 1);
384 Range body_ents;
385 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
386 body_ents);
387 auto body_skin = get_skin(mField, body_ents);
388 auto body_skin_conn = get_conn_range(body_skin);
389
390 auto calculate_seed_area_growth = [&](auto n, auto &adj_faces) {
391 // if skin is on body surface, project the direction on it
392 FTensor::Tensor1<double, SPACE_DIM> t_project{0., 0., 0.};
393 auto boundary_node = intersect(Range(n, n), body_skin_conn);
394 if (boundary_node.size()) {
395 auto faces = intersect(get_adj(n, SPACE_DIM - 1), body_skin);
396 for (auto f : faces) {
397 FTensor::Tensor1<double, 3> t_normal_face;
398 CHKERR mField.getInterface<Tools>()->getTriNormal(
399 f, &t_normal_face(0));
400 t_project(I) += t_normal_face(I);
401 }
402 t_project.normalize();
403 }
404
405 // calculate surface projection matrix
408 t_Q(I, J) = t_kd(I, J);
409 if (boundary_node.size()) {
410 t_Q(I, J) -= t_project(I) * t_project(J);
411 }
412
413 FTensor::Tensor1<double, 3> t_area_dir{0., 0., 0.};
414 for (auto f : adj_faces) {
415 int num_nodes;
416 const EntityHandle *conn;
417 CHKERR mField.get_moab().get_connectivity(f, conn, num_nodes, true);
418 std::array<double, 9> coords;
419 CHKERR mField.get_moab().get_coords(conn, num_nodes, coords.data());
420 FTensor::Tensor1<double, 3> t_face_normal;
422 CHKERR mField.getInterface<Tools>()->getTriNormal(
423 coords.data(), &t_face_normal(0), &t_d_normal(0, 0, 0));
424 auto n_it = std::find(conn, conn + num_nodes, n);
425 auto n_index = std::distance(conn, n_it);
426
427 FTensor::Tensor2<double, 3, 3> t_face_hessian{
428 t_d_normal(0, n_index, 0), t_d_normal(0, n_index, 1),
429 t_d_normal(0, n_index, 2),
430
431 t_d_normal(1, n_index, 0), t_d_normal(1, n_index, 1),
432 t_d_normal(1, n_index, 2),
433
434 t_d_normal(2, n_index, 0), t_d_normal(2, n_index, 1),
435 t_d_normal(2, n_index, 2)};
436
437 FTensor::Tensor2<double, 3, 3> t_projected_hessian;
438 t_projected_hessian(I, J) =
439 t_Q(I, K) * (t_face_hessian(K, L) * t_Q(L, J));
440 t_face_normal.normalize();
441 t_area_dir(K) += t_face_normal(I) * t_projected_hessian(I, K) / 2.;
442 }
443
444 return t_area_dir;
445 };
446
447 auto get_crack_area_growth_seed_nodes = [&](auto &adj_tets) {
448 // This gets all 1D edges adjacent to the current tetrahedral patch
449 // adj_tets, then keeps only edges that are either crack-front edges or
450 // special body edges from the "EDGES" block. So adj_edges is the local
451 // edge stencil relevant to crack growth near the current front node.
452 auto adj_edges = intersect(get_adj_range(adj_tets, 1),
453 unite(*frontEdges, body_edges));
454
455 // This collects all vertices/nodes connected to those edges. These are
456 // candidate seed nodes whose local crack-area growth contribution will
457 // be accumulated.
458 auto seed_n = get_conn_range(adj_edges);
459 auto skin_adj_edges = get_skin(mField, adj_edges);
460 skin_adj_edges = subtract(skin_adj_edges, body_skin_conn);
461 seed_n = subtract(seed_n, skin_adj_edges);
462
463 return std::make_pair(seed_n, skin_adj_edges);
464 };
465
466 auto calculate_front_node_area_growth = [&](auto &adj_tets) {
467 auto [seed_n, skin_adj_edges] =
468 get_crack_area_growth_seed_nodes(adj_tets);
469
470 FTensor::Tensor1<double, SPACE_DIM> t_area_dir{0., 0., 0.};
471 auto add_area_growth_direction = [&](auto sn, double weight) {
472 auto adj_faces = intersect(get_adj(sn, SPACE_DIM - 1), *crackFaces);
473 if (adj_faces.empty()) {
474 return;
475 }
476
477 auto t_area_dir_sn = calculate_seed_area_growth(sn, adj_faces);
478 t_area_dir(I) += weight * t_area_dir_sn(I);
479 };
480
481 for (auto sn : seed_n) {
482 add_area_growth_direction(sn, 1.);
483 }
484 for (auto sn : skin_adj_edges) {
485 add_area_growth_direction(sn, 0.5);
486 }
487
488 return t_area_dir;
489 };
490
491 for (auto n : front_nodes) {
492 auto front_node_adj_faces = get_front_node_adj_crack_faces(n);
493 if (front_node_adj_faces.empty()) {
494 continue;
495 }
496
497 auto adj_tets = get_adj_tets_for_contour(n, nb_J_integral_contours);
498 auto t_area_dir = calculate_front_node_area_growth(adj_tets);
499
501 mField.get_moab().tag_set_data(tags[ExhangeTags::AREAGROWTH], &n, 1,
502 &t_area_dir(0)),
503 "set data");
504 }
505 }
506
508 };
509
510 auto calculate_crack_area_growth_no_face = [&](auto nb_J_integral_contours,
511 auto material_force_tag) {
513
515
516 if (mField.get_comm_rank() == 0) {
517 auto front_nodes = get_conn_range(*frontEdges);
518 auto body_edges = get_range_from_block(mField, "EDGES", 1);
519 Range body_ents;
520 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
521 body_ents);
522 auto body_skin = get_skin(mField, body_ents);
523 auto body_skin_conn = get_conn_range(body_skin);
524
525 auto calculate_seed_area_growth = [&](auto n, auto &t_node_force) {
526 auto adj_edges =
527 intersect(get_adj(n, 1), unite(*frontEdges, body_edges));
528 double l = 0;
529 for (auto e : adj_edges) {
530 auto t_dir = calculate_edge_direction(e);
531 l += t_dir.l2();
532 }
533 l /= 2;
534
535 FTensor::Tensor1<double, SPACE_DIM> t_area_dir{0., 0., 0.};
537 t_node_force_tmp(I) = t_node_force(I);
538 t_node_force_tmp.normalize();
539 t_area_dir(I) = -t_node_force_tmp(I);
540 t_area_dir(I) *= l / 2;
541 return t_area_dir;
542 };
543
544 auto get_crack_area_growth_seed_nodes = [&](auto &adj_tets) {
545 auto adj_edges = intersect(get_adj_range(adj_tets, 1),
546 unite(*frontEdges, body_edges));
547 auto seed_n = get_conn_range(adj_edges);
548 auto skin_adj_edges = get_skin(mField, adj_edges);
549 skin_adj_edges = subtract(skin_adj_edges, body_skin_conn);
550 seed_n = subtract(seed_n, skin_adj_edges);
551
552 return std::make_pair(seed_n, skin_adj_edges);
553 };
554
555 auto calculate_front_node_area_growth = [&](auto &adj_tets,
556 auto &t_node_force) {
557 auto [seed_n, skin_adj_edges] =
558 get_crack_area_growth_seed_nodes(adj_tets);
559
560 FTensor::Tensor1<double, SPACE_DIM> t_area_dir{0., 0., 0.};
561 auto add_area_growth_direction = [&](auto sn, double weight) {
562 auto t_area_dir_sn = calculate_seed_area_growth(sn, t_node_force);
563 t_area_dir(I) += weight * t_area_dir_sn(I);
564 };
565
566 for (auto sn : seed_n) {
567 add_area_growth_direction(sn, 1.);
568 }
569 for (auto sn : skin_adj_edges) {
570 add_area_growth_direction(sn, 0.5);
571 }
572
573 return t_area_dir;
574 };
575
576 for (auto n : front_nodes) {
577 auto front_node_adj_faces = get_front_node_adj_crack_faces(n);
578 if (front_node_adj_faces.empty()) {
580 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &n, 1,
581 &t_node_force(0));
582
583 auto adj_tets = get_adj_tets_for_contour(n, nb_J_integral_contours);
584 auto t_area_dir =
585 calculate_front_node_area_growth(adj_tets, t_node_force);
586
588 mField.get_moab().tag_set_data(tags[ExhangeTags::AREAGROWTH], &n,
589 1, &t_area_dir(0)),
590 "set data");
591 }
592 }
593 }
594
596 };
597
598 auto update_crack_area_growth_edges = [&]() {
600
601 if (mField.get_comm_rank() == 0) {
602 CHKERR average_vector_tag_at_edge(tags[ExhangeTags::AREAGROWTH]);
603 }
604
605 auto area_growth_edge_exchange = CommInterface::createEntitiesPetscVector(
606 mField.get_comm(), mField.get_moab(), 1, 3, Sev::inform);
607 CHKERR CommInterface::updateEntitiesPetscVector(
608 mField.get_moab(), area_growth_edge_exchange,
609 tags[ExhangeTags::AREAGROWTH]);
610
612 };
613
614 auto calculate_griffith_force = [&](ExhangeTags material_force_tag,
615 ExhangeTags griffith_force_tag) {
617
619
620 if (mField.get_comm_rank() == 0) {
621 auto front_nodes = get_conn_range(*frontEdges);
622 Range all_front_faces;
623
624 for (auto n : front_nodes) {
626 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &n, 1,
627 &t_node_force(0));
629 CHKERR mField.get_moab().tag_get_data(tags[ExhangeTags::AREAGROWTH], &n,
630 1, &t_area_dir(0));
631
632 auto griffith =
633 -t_node_force(I) * t_area_dir(I) / (t_area_dir(K) * t_area_dir(K));
634 CHK_MOAB_THROW(mField.get_moab().tag_set_data(
635 tags[griffith_force_tag], &n, 1, &griffith),
636 "set data");
637 }
638
639 for (auto e : *frontEdges) {
641 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &e, 1,
642 &t_edge_force(0));
644 CHKERR mField.get_moab().tag_get_data(tags[ExhangeTags::AREAGROWTH], &e,
645 1, &t_edge_area_dir(0));
646 double griffith_energy =
647 -t_edge_force(I) * t_edge_area_dir(I) /
648 (t_edge_area_dir(K) * t_edge_area_dir(K));
649 CHKERR mField.get_moab().tag_set_data(tags[griffith_force_tag], &e, 1,
650 &griffith_energy);
651 }
652
653 for (auto e : *frontEdges) {
654 auto adj_faces = get_adj(e, SPACE_DIM - 1);
655
656 if (debug) {
657 all_front_faces.merge(adj_faces);
658 }
659
661 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &e, 1,
662 &t_edge_force(0));
663 FTensor::Tensor1<double, SPACE_DIM> t_edge_direction =
664 calculate_edge_direction(e);
665 t_edge_direction.normalize();
666
668 t_cross(K) = FTensor::levi_civita(I, J, K) * t_edge_direction(I) *
669 t_edge_force(J);
670
671 for (auto f : adj_faces) {
673 CHKERR mField.getInterface<Tools>()->getTriNormal(f, &t_normal(0));
674 t_normal.normalize();
675 int side_number, sense, offset;
676 CHKERR mField.get_moab().side_number(f, e, side_number, sense, offset);
677 auto dot = -sense * t_cross(I) * t_normal(I);
678 CHK_MOAB_THROW(mField.get_moab().tag_set_data(
679 tags[griffith_force_tag], &f, 1, &dot),
680 "set data");
681 }
682 }
683
684#ifndef NDEBUG
685 if (debug) {
686 int ts_step;
687 CHKERR TSGetStepNumber(ts, &ts_step);
689 "front_faces_material_force_" +
690 std::to_string(ts_step) + ".vtk",
691 all_front_faces);
692 }
693#endif
694 }
695
696 auto vector_edge_exchange = CommInterface::createEntitiesPetscVector(
697 mField.get_comm(), mField.get_moab(), 1, 3, Sev::inform);
698 CHKERR CommInterface::updateEntitiesPetscVector(
699 mField.get_moab(), vector_edge_exchange, tags[material_force_tag]);
700 auto &scalar_edge_exchange = edgeExchange;
701 CHKERR CommInterface::updateEntitiesPetscVector(
702 mField.get_moab(), scalar_edge_exchange, tags[griffith_force_tag]);
703
705 };
706
707 auto calculate_griffith_force_simplified = [&](auto material_force_tag,
708 auto griffith_force_tag) {
710
711 if (mField.get_comm_rank() == 0) {
712 auto front_nodes = get_conn_range(*frontEdges);
713
714 for (auto n : front_nodes) {
716 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &n, 1,
717 &t_node_force(0));
718
719 auto adj_edges = intersect(get_adj(n, 1), *frontEdges);
720 double adj_edges_length = 0.;
721 for (auto e : adj_edges) {
722 auto t_edge_dir = calculate_edge_direction(e);
723 adj_edges_length += t_edge_dir.l2();
724 }
725
726 const double nodal_front_length = adj_edges_length / 2.;
727 if (nodal_front_length <= 0.) {
729 "Front node has zero adjacent front edge length");
730 }
731
732 double griffith_energy = t_node_force.l2() / nodal_front_length;
733 CHK_MOAB_THROW(mField.get_moab().tag_set_data(tags[griffith_force_tag],
734 &n, 1, &griffith_energy),
735 "set data");
736 }
737 }
738
740 };
741
742 auto calculate_adjoint_material_force = [&]() {
744
745 if (ts == PETSC_NULLPTR) {
747 "TS is required to calculate adjoint material force");
748 }
749
750 auto topological_tao_ctx = createTopologicalTAOCtx(
751 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
752 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
753 SmartPetscObj<TS>(ts, true));
754
756 double obj_value = 0;
757 CHKERR evaluateGradient(topological_tao_ctx.get(), &obj_value, g,
758 ObjectiveModelType::HENCKY_MODEL);
759
760 auto set_vertex_exchange_from_gradient = [&]() {
762
763 CHKERR VecZeroEntries(vertexExchange.second);
764 CHKERR VecGhostUpdateBegin(vertexExchange.second, INSERT_VALUES,
765 SCATTER_FORWARD);
766 CHKERR VecGhostUpdateEnd(vertexExchange.second, INSERT_VALUES,
767 SCATTER_FORWARD);
768
769 auto *problem_ptr = getProblemPtr(dmMaterial);
770 auto &dofs =
771 problem_ptr->getNumeredRowDofsPtr()->get<Unique_mi_tag>();
772 const auto field_bit = mField.get_field_bit_number(materialH1Positions);
773
774 double *g_array;
775 double *exchange_array;
776 CHKERR VecGetArray(g, &g_array);
777 CHKERR VecGetArray(vertexExchange.second, &exchange_array);
778
779 auto ptr = exchange_array; // vector values are arranged as entries, That
780 // is key idea behind vertexExchange vector.
781 for (auto v : vertexExchange.first.first) {
782 std::array<double, SPACE_DIM> values = {0., 0., 0.};
783 auto lo =
784 dofs.lower_bound(DofEntity::getLoFieldEntityUId(field_bit, v));
785 auto hi =
786 dofs.upper_bound(DofEntity::getHiFieldEntityUId(field_bit, v));
787 for (; lo != hi; ++lo) {
788 if (!(*lo)->getHasLocalIndex())
789 continue;
790 const auto coeff = (*lo)->getDofCoeffIdx();
791 if (coeff < SPACE_DIM)
792 values[coeff] = g_array[(*lo)->getPetscLocalDofIdx()];
793 }
794 for (int d = 0; d != SPACE_DIM; ++d, ++ptr) {
795 *ptr = values[d];
796 }
797 }
798
799 CHKERR VecRestoreArray(vertexExchange.second, &exchange_array);
800 CHKERR VecRestoreArray(g, &g_array);
801
802 if (adjoint_gradient_vector != nullptr) {
803 (*adjoint_gradient_vector) = g;
804 }
805
807 };
808
809 CHKERR set_vertex_exchange_from_gradient();
810
811 CHKERR CommInterface::setTagFromVector(
813 tags[ExhangeTags::ADJOINT_MATERIALFORCE]);
814 CHKERR CommInterface::updateEntitiesPetscVector(
816 tags[ExhangeTags::ADJOINT_MATERIALFORCE]);
817
819 };
820
821 auto print_results = [&](auto nb_J_integral_conturs, bool print_material,
822 bool print_adjoint) {
824
825 if (!print_material && !print_adjoint) {
827 }
828
829 auto get_conn_range = [&](auto e) {
830 Range conn;
831 CHK_MOAB_THROW(mField.get_moab().get_connectivity(e, conn, true),
832 "get connectivity");
833 return conn;
834 };
835
836 auto get_tag_data = [&](auto &ents, auto tag, auto dim) {
837 std::vector<double> data(ents.size() * dim);
838 CHK_MOAB_THROW(mField.get_moab().tag_get_data(tag, ents, data.data()),
839 "get data");
840 return data;
841 };
842
843 if (mField.get_comm_rank() == 0) {
844 auto at_nodes = [&]() {
846 auto conn = get_conn_range(*frontEdges);
847 std::vector<double> material_force;
848 std::vector<double> adjoint_material_force;
849 auto area_growth = get_tag_data(conn, tags[ExhangeTags::AREAGROWTH], 3);
850 std::vector<double> griffith_force;
851 std::vector<double> adjoint_griffith_force;
852 if (print_material) {
853 material_force =
854 get_tag_data(conn, tags[ExhangeTags::MATERIALFORCE], 3);
855 griffith_force =
856 get_tag_data(conn, tags[ExhangeTags::GRIFFITHFORCE], 1);
857 }
858 if (print_adjoint) {
859 adjoint_material_force =
860 get_tag_data(conn, tags[ExhangeTags::ADJOINT_MATERIALFORCE], 3);
861 adjoint_griffith_force =
862 get_tag_data(conn, tags[ExhangeTags::ADJOINT_GRIFFITHFORCE], 1);
863 }
864 std::vector<double> coords(conn.size() * 3);
865 CHK_MOAB_THROW(mField.get_moab().get_coords(conn, coords.data()),
866 "get coords");
867 MOFEM_LOG("EPSELF", Sev::inform) << "Force results at nodes";
868 MOFEM_LOG("EPSELF", Sev::inform)
869 << std::left << std::setw(10) << "kind" << std::right
870 << std::setw(9) << "node" << std::setw(18) << "coord_x"
871 << std::setw(18) << "coord_y" << std::setw(18) << "coord_z"
872 << std::setw(18) << "force_x" << std::setw(18) << "force_y"
873 << std::setw(18) << "force_z" << std::setw(18) << "area_x"
874 << std::setw(18) << "area_y" << std::setw(18) << "area_z"
875 << std::setw(18) << "griffith" << std::setw(10) << "contour";
876
877 auto print_row = [&](const char *kind, const auto &force,
878 const auto &griffith, const size_t i) {
879 MOFEM_LOG("EPSELF", Sev::inform)
880 << std::left << std::setw(10) << kind << std::right
881 << std::setw(9) << conn[i] << std::scientific
882 << std::setprecision(10) << std::setw(18) << coords[i * 3 + 0]
883 << std::setw(18) << coords[i * 3 + 1] << std::setw(18)
884 << coords[i * 3 + 2] << std::setw(18) << force[i * 3 + 0]
885 << std::setw(18) << force[i * 3 + 1] << std::setw(18)
886 << force[i * 3 + 2] << std::setw(18) << area_growth[i * 3 + 0]
887 << std::setw(18) << area_growth[i * 3 + 1] << std::setw(18)
888 << area_growth[i * 3 + 2] << std::setw(18) << griffith[i]
889 << std::defaultfloat << std::setprecision(6) << std::setw(10)
890 << nb_J_integral_conturs;
891 };
892
893 for (size_t i = 0; i < conn.size(); ++i) {
894 if (print_material) {
895 print_row("material", material_force, griffith_force, i);
896 }
897 if (print_adjoint) {
898 print_row("adjoint", adjoint_material_force, adjoint_griffith_force,
899 i);
900 }
901 }
902
904 };
905
906 at_nodes();
907 }
909 };
910
911 CHKERR calculate_material_forces();
912
913 PetscBool all_contours = PETSC_FALSE;
914 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "",
915 "-calculate_J_integral_all_levels", &all_contours,
916 PETSC_NULLPTR); // for backward compatibility
918 PETSC_NULLPTR, "", "-calculate_J_integral_all_contours", &all_contours,
919 PETSC_NULLPTR); // new name
920
921 if (all_contours == PETSC_TRUE) {
922 for (int l = 0; l < nbJIntegralContours; ++l) {
923 CHKERR calculate_force_through_node(l);
924 CHKERR average_material_force_at_edge(tags[ExhangeTags::MATERIALFORCE]);
925 CHKERR calculate_crack_area_growth_face(l);
926 CHKERR calculate_crack_area_growth_no_face(l, ExhangeTags::MATERIALFORCE);
927 CHKERR update_crack_area_growth_edges();
928 CHKERR calculate_griffith_force(ExhangeTags::MATERIALFORCE,
929 ExhangeTags::GRIFFITHFORCE);
930 CHKERR print_results(l, true, false);
931 }
932 }
933
934 PetscBool has_nonzero_ts_solution = PETSC_FALSE;
935
936 if (ts != PETSC_NULLPTR) {
937 Vec ts_solution = PETSC_NULLPTR;
938 CHKERR TSGetSolution(ts, &ts_solution);
939 if (ts_solution != PETSC_NULLPTR) {
940 PetscReal ts_solution_norm = 0.0;
941 CHKERR VecNorm(ts_solution, NORM_2, &ts_solution_norm);
942 has_nonzero_ts_solution =
943 (ts_solution_norm > PETSC_MACHINE_EPSILON) ? PETSC_TRUE : PETSC_FALSE;
944 }
945
946 if (has_nonzero_ts_solution == PETSC_TRUE) {
947 CHKERR calculate_adjoint_material_force();
948 }
949 }
950
951 CHKERR calculate_force_through_node(nbJIntegralContours);
952 CHKERR average_material_force_at_edge(tags[ExhangeTags::MATERIALFORCE]);
953 CHKERR calculate_crack_area_growth_face(nbJIntegralContours);
954 CHKERR calculate_crack_area_growth_no_face(nbJIntegralContours,
955 ExhangeTags::MATERIALFORCE);
956 CHKERR update_crack_area_growth_edges();
957 CHKERR calculate_griffith_force(ExhangeTags::MATERIALFORCE,
958 ExhangeTags::GRIFFITHFORCE);
959 if (has_nonzero_ts_solution == PETSC_TRUE) {
960 CHKERR calculate_griffith_force(ExhangeTags::ADJOINT_MATERIALFORCE,
961 ExhangeTags::ADJOINT_GRIFFITHFORCE);
962 CHKERR calculate_griffith_force_simplified(
963 ExhangeTags::ADJOINT_MATERIALFORCE, ExhangeTags::ADJOINT_GRIFFITHFORCE);
964 }
965 CHKERR print_results(nbJIntegralContours, true, true);
966
968}
#define MOFEM_LOG_SEVERITY_SYNC(comm, severity)
Synchronise "SYNC" on curtain severity level.
#define FTENSOR_INDEXES(DIM,...)
Kronecker Delta class.
Tensor1< T, Tensor_Dim > normalize()
#define NOT_USED(x)
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
constexpr auto t_kd
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
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'l', 3 > l
boost::shared_ptr< TopologicalTAOCtx > createTopologicalTAOCtx(EshelbianCore *ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_interior, ForcesAndSourcesCore::GaussHookFun set_integration_at_face, SmartPetscObj< TS > time_solver)
MoFEMErrorCode evaluateGradient(TopologicalTAOCtx *ctx_ptr, double *f, Vec g, ObjectiveModelType eval_energy_model)
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
auto getProblemPtr(DM dm)
get problem pointer from DM
Definition DMMoFEM.hpp:1182
constexpr IntegrationType I
constexpr double g
boost::shared_ptr< Range > frontAdjEdges
static int nbJIntegralContours
static double griffithEnergy
Griffith energy.
CommInterface::EntitiesPetscVector vertexExchange
static enum MaterialModel materialModel
CommInterface::EntitiesPetscVector edgeExchange
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
boost::shared_ptr< Range > frontVertices
CommInterface::EntitiesPetscVector faceExchange
virtual int get_comm_size() const =0
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number

◆ calculateOrientation()

MoFEMErrorCode EshelbianCore::calculateOrientation ( const int  tag,
bool  set_orientation 
)

Iterate over front edges, get adjacent faces, find maximal face energy. Maximal face energy is stored in the edge. Maximal face energy is magnitude of edge Griffith force.

For each front edge, find maximal face energy and orientation. This is by finding angle between edge material force and maximal face normal

Definition at line 970 of file EshelbianFracture.cpp.

971 {
973
974 constexpr bool debug = false;
975 (void)debug;
976 constexpr auto sev = Sev::verbose;
977
978 Range body_ents;
979 CHKERR mField.get_moab().get_entities_by_dimension(0, 3, body_ents);
980 auto body_skin = get_skin(mField, body_ents);
981 Range body_skin_edges;
982 CHKERR mField.get_moab().get_adjacencies(body_skin, 1, false, body_skin_edges,
983 moab::Interface::UNION);
984 Range boundary_skin_verts;
985 CHKERR mField.get_moab().get_connectivity(body_skin_edges,
986 boundary_skin_verts, true);
987
988 auto geometry_edges = get_range_from_block(mField, "EDGES", 1);
989 Range geometry_edges_verts;
990 CHKERR mField.get_moab().get_connectivity(geometry_edges,
991 geometry_edges_verts, true);
992 Range crack_faces_verts;
993 CHKERR mField.get_moab().get_connectivity(*crackFaces, crack_faces_verts,
994 true);
995 Range crack_faces_edges;
996 CHKERR mField.get_moab().get_adjacencies(
997 *crackFaces, 1, true, crack_faces_edges, moab::Interface::UNION);
998 Range crack_faces_tets;
999 CHKERR mField.get_moab().get_adjacencies(
1000 *crackFaces, 3, true, crack_faces_tets, moab::Interface::UNION);
1001
1002 Range front_verts;
1003 CHKERR mField.get_moab().get_connectivity(*frontEdges, front_verts, true);
1004 Range front_faces;
1005 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2, true, front_faces,
1006 moab::Interface::UNION);
1007 Range front_verts_edges;
1008 CHKERR mField.get_moab().get_adjacencies(
1009 front_verts, 1, true, front_verts_edges, moab::Interface::UNION);
1010
1011 auto get_tags_vec = [&](auto tag_name, int dim) {
1012 std::vector<Tag> tags(1);
1013
1014 if (dim > 3)
1016
1017 auto create_and_clean = [&]() {
1019 auto &moab = mField.get_moab();
1020 auto rval = moab.tag_get_handle(tag_name, tags[0]);
1021 if (rval == MB_SUCCESS) {
1022 moab.tag_delete(tags[0]);
1023 }
1024 double def_val[] = {0., 0., 0.};
1025 CHKERR moab.tag_get_handle(tag_name, dim, MB_TYPE_DOUBLE, tags[0],
1026 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
1028 };
1029
1030 CHK_THROW_MESSAGE(create_and_clean(), "create_and_clean");
1031
1032 return tags;
1033 };
1034
1035 auto get_adj_front = [&](bool subtract_crack) {
1036 Range adj_front;
1037 CHKERR mField.get_moab().get_adjacencies(*frontEdges, SPACE_DIM - 1, true,
1038 adj_front, moab::Interface::UNION);
1039 if (subtract_crack)
1040 adj_front = subtract(adj_front, *crackFaces);
1041 return adj_front;
1042 };
1043
1044 MOFEM_LOG_CHANNEL("SELF");
1045
1046 auto th_front_position = get_tags_vec("FrontPosition", 3);
1047 auto th_max_face_energy = get_tags_vec("MaxFaceEnergy", 1);
1048
1049 if (mField.get_comm_rank() == 0) {
1050
1051 auto get_crack_adj_tets = [&](auto r) {
1052 Range crack_faces_conn;
1053 CHKERR mField.get_moab().get_connectivity(r, crack_faces_conn);
1054 Range crack_faces_conn_tets;
1055 CHKERR mField.get_moab().get_adjacencies(crack_faces_conn, SPACE_DIM,
1056 true, crack_faces_conn_tets,
1057 moab::Interface::UNION);
1058 return crack_faces_conn_tets;
1059 };
1060
1061 auto get_layers_for_sides = [&](auto &side) {
1062 std::vector<Range> layers;
1063 auto get = [&]() {
1065
1066 auto get_adj = [&](auto &r, int dim) {
1067 Range adj;
1068 CHKERR mField.get_moab().get_adjacencies(r, dim, true, adj,
1069 moab::Interface::UNION);
1070 return adj;
1071 };
1072
1073 auto get_tets = [&](auto r) { return get_adj(r, SPACE_DIM); };
1074
1075 Range front_nodes;
1076 CHKERR mField.get_moab().get_connectivity(*frontEdges, front_nodes,
1077 true);
1078 Range front_faces = get_adj(front_nodes, 2);
1079 front_faces = subtract(front_faces, *crackFaces);
1080 auto front_tets = get_tets(front_nodes);
1081 auto front_side = intersect(side, front_tets);
1082 layers.push_back(front_side);
1083 for (;;) {
1084 auto adj_faces = get_skin(mField, layers.back());
1085 adj_faces = intersect(adj_faces, front_faces);
1086 auto adj_faces_tets = get_tets(adj_faces);
1087 adj_faces_tets = intersect(adj_faces_tets, front_tets);
1088 layers.push_back(unite(layers.back(), adj_faces_tets));
1089 if (layers.back().size() == layers[layers.size() - 2].size()) {
1090 break;
1091 }
1092 }
1094 };
1095 CHK_THROW_MESSAGE(get(), "get_layers_for_sides");
1096 return layers;
1097 };
1098
1100 auto layers_top = get_layers_for_sides(sides_pair.first);
1101 auto layers_bottom = get_layers_for_sides(sides_pair.second);
1102
1103#ifndef NDEBUG
1104 if (debug) {
1106 mField.get_moab(),
1107 "crack_tets_" +
1108 boost::lexical_cast<std::string>(mField.get_comm_rank()) + ".vtk",
1109 get_crack_adj_tets(*crackFaces));
1110 CHKERR save_range(mField.get_moab(), "sides_first.vtk", sides_pair.first);
1111 CHKERR save_range(mField.get_moab(), "sides_second.vtk",
1112 sides_pair.second);
1113 MOFEM_LOG("EP", sev) << "Nb. layers " << layers_top.size();
1114 int l = 0;
1115 for (auto &r : layers_top) {
1116 MOFEM_LOG("EP", sev) << "Layer " << l << " size " << r.size();
1118 mField.get_moab(),
1119 "layers_top_" + boost::lexical_cast<std::string>(l) + ".vtk", r);
1120 ++l;
1121 }
1122
1123 l = 0;
1124 for (auto &r : layers_bottom) {
1125 MOFEM_LOG("EP", sev) << "Layer " << l << " size " << r.size();
1127 mField.get_moab(),
1128 "layers_bottom_" + boost::lexical_cast<std::string>(l) + ".vtk", r);
1129 ++l;
1130 }
1131 }
1132#endif
1133
1134 auto get_cross = [&](auto t_dir, auto f) {
1136 CHKERR mField.getInterface<Tools>()->getTriNormal(f, &t_normal(0));
1137 t_normal.normalize();
1142 t_cross(i) = FTensor::levi_civita(i, j, k) * t_normal(j) * t_dir(k);
1143 return t_cross;
1144 };
1145
1146 auto get_sense = [&](auto f, auto e) {
1147 int side, sense, offset;
1148 CHK_MOAB_THROW(mField.get_moab().side_number(f, e, side, sense, offset),
1149 "get sense");
1150 return std::make_tuple(side, sense, offset);
1151 };
1152
1153 auto calculate_edge_direction = [&](auto e, auto normalize = true) {
1154 const EntityHandle *conn;
1155 int num_nodes;
1156 CHKERR mField.get_moab().get_connectivity(e, conn, num_nodes, true);
1157 std::array<double, 6> coords;
1158 CHKERR mField.get_moab().get_coords(conn, num_nodes, coords.data());
1160 &coords[0], &coords[1], &coords[2]};
1162 &coords[3], &coords[4], &coords[5]};
1165 t_dir(i) = t_p1(i) - t_p0(i);
1166 if (normalize)
1167 t_dir.normalize();
1168 return t_dir;
1169 };
1170
1171 auto evaluate_face_energy_and_set_orientation = [&](auto front_edges,
1172 auto front_faces,
1173 auto &sides_pair,
1174 auto th_position) {
1176
1177 Tag th_face_energy;
1178 Tag th_material_force;
1179 switch (energyReleaseSelector) {
1180 case GRIFFITH_FORCE:
1181 case GRIFFITH_SKELETON:
1182 CHKERR mField.get_moab().tag_get_handle("GriffithForce",
1183 th_face_energy);
1184 // CHKERR mField.get_moab().tag_get_handle("MaterialForce",
1185 // th_material_force);
1186 CHKERR mField.get_moab().tag_get_handle("MaterialForce",
1187 th_material_force);
1188
1189 break;
1190 default:
1191 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
1192 "Unknown energy release selector");
1193 };
1194
1195 /**
1196 * Iterate over front edges, get adjacent faces, find maximal face energy.
1197 * Maximal face energy is stored in the edge. Maximal face energy is
1198 * magnitude of edge Griffith force.
1199 */
1200 auto find_maximal_face_energy = [&](auto front_edges, auto front_faces,
1201 auto &edge_face_max_energy_map) {
1203
1204 Range body_ents;
1205 CHKERR mField.get_moab().get_entities_by_dimension(0, 3, body_ents);
1206 auto body_skin = get_skin(mField, body_ents);
1207
1208 Range max_faces;
1209
1210 for (auto e : front_edges) {
1211
1212 double griffith_force;
1213 CHKERR mField.get_moab().tag_get_data(th_face_energy, &e, 1,
1214 &griffith_force);
1215
1216 Range faces;
1217 CHKERR mField.get_moab().get_adjacencies(&e, 1, 2, false, faces);
1218 faces = subtract(intersect(faces, front_faces), body_skin);
1219 std::vector<double> face_energy(faces.size());
1220 CHKERR mField.get_moab().tag_get_data(th_face_energy, faces,
1221 face_energy.data());
1222 auto max_energy_it =
1223 std::max_element(face_energy.begin(), face_energy.end());
1224 double max_energy =
1225 max_energy_it != face_energy.end() ? *max_energy_it : 0;
1226
1227 edge_face_max_energy_map[e] =
1228 std::make_tuple(faces[max_energy_it - face_energy.begin()],
1229 griffith_force, static_cast<double>(0));
1230 MOFEM_LOG("EP", Sev::inform)
1231 << "Edge " << e << " griffith force " << griffith_force
1232 << " max face energy " << max_energy << " factor "
1233 << max_energy / griffith_force;
1234
1235 max_faces.insert(faces[max_energy_it - face_energy.begin()]);
1236 }
1237
1238#ifndef NDEBUG
1239 if (debug) {
1241 mField.get_moab(),
1242 "max_faces_" +
1243 boost::lexical_cast<std::string>(mField.get_comm_rank()) +
1244 ".vtk",
1245 max_faces);
1246 }
1247#endif
1248
1250 };
1251
1252 /**
1253 * For each front edge, find maximal face energy and orientation. This is
1254 * by finding angle between edge material force and maximal face normal
1255 *
1256 */
1257 auto calculate_face_orientation = [&](auto &edge_face_max_energy_map) {
1259
1260 auto up_down_face = [&](
1261
1262 auto &face_angle_map_up,
1263 auto &face_angle_map_down
1264
1265 ) {
1267
1268 for (auto &m : edge_face_max_energy_map) {
1269 auto e = m.first;
1270 auto [max_face, energy, opt_angle] = m.second;
1271
1272 Range faces;
1273 CHKERR mField.get_moab().get_adjacencies(&e, 1, 2, false, faces);
1274 faces = intersect(faces, front_faces);
1275 Range adj_tets; // tetrahedrons adjacent to the face
1276 CHKERR mField.get_moab().get_adjacencies(&max_face, 1, SPACE_DIM,
1277 false, adj_tets,
1278 moab::Interface::UNION);
1279 if (adj_tets.size()) {
1280
1281 Range adj_tets; // tetrahedrons adjacent to the face
1282 CHKERR mField.get_moab().get_adjacencies(&max_face, 1, SPACE_DIM,
1283 false, adj_tets,
1284 moab::Interface::UNION);
1285 if (adj_tets.size()) {
1286
1287 Range adj_tets_faces;
1288 // get faces
1289 CHKERR mField.get_moab().get_adjacencies(
1290 adj_tets, SPACE_DIM - 1, false, adj_tets_faces,
1291 moab::Interface::UNION);
1292 adj_tets_faces = intersect(adj_tets_faces, faces);
1294
1295 // cross product of face normal and edge direction
1296 auto t_cross_max =
1297 get_cross(calculate_edge_direction(e, true), max_face);
1298 auto [side_max, sense_max, offset_max] = get_sense(max_face, e);
1299 t_cross_max(i) *= sense_max;
1300
1301 for (auto t : adj_tets) {
1302 Range adj_tets_faces;
1303 CHKERR mField.get_moab().get_adjacencies(
1304 &t, 1, SPACE_DIM - 1, false, adj_tets_faces);
1305 adj_tets_faces = intersect(adj_tets_faces, faces);
1306 adj_tets_faces =
1307 subtract(adj_tets_faces, Range(max_face, max_face));
1308
1309 if (adj_tets_faces.size() == 1) {
1310
1311 // cross product of adjacent face normal and edge
1312 // direction
1313 auto t_cross = get_cross(calculate_edge_direction(e, true),
1314 adj_tets_faces[0]);
1315 auto [side, sense, offset] =
1316 get_sense(adj_tets_faces[0], e);
1317 t_cross(i) *= sense;
1318 double dot = t_cross(i) * t_cross_max(i);
1319 auto angle = std::acos(dot);
1320
1321 double face_energy;
1322 CHKERR mField.get_moab().tag_get_data(
1323 th_face_energy, adj_tets_faces, &face_energy);
1324
1325 auto [side_face, sense_face, offset_face] =
1326 get_sense(t, max_face);
1327
1328 if (sense_face > 0) {
1329 face_angle_map_up[e] = std::make_tuple(face_energy, angle,
1330 adj_tets_faces[0]);
1331
1332 } else {
1333 face_angle_map_down[e] = std::make_tuple(
1334 face_energy, -angle, adj_tets_faces[0]);
1335 }
1336 }
1337 }
1338 }
1339 }
1340 }
1341
1343 };
1344
1345 auto calc_optimal_angle = [&](
1346
1347 auto &face_angle_map_up,
1348 auto &face_angle_map_down
1349
1350 ) {
1352
1353 for (auto &m : edge_face_max_energy_map) {
1354 auto e = m.first;
1355 auto &[max_face, e0, a0] = m.second;
1356
1357 if (std::abs(e0) > std::numeric_limits<double>::epsilon()) {
1358
1359 if (face_angle_map_up.find(e) == face_angle_map_up.end() ||
1360 face_angle_map_down.find(e) == face_angle_map_down.end()) {
1361 // Do nothing
1362 } else {
1363
1364 switch (energyReleaseSelector) {
1365 case GRIFFITH_FORCE:
1366 case GRIFFITH_SKELETON: {
1367
1368 Tag th_material_force;
1369 CHKERR mField.get_moab().tag_get_handle("MaterialForce",
1370 th_material_force);
1371 FTensor::Tensor1<double, SPACE_DIM> t_material_force;
1372 CHKERR mField.get_moab().tag_get_data(
1373 th_material_force, &e, 1, &t_material_force(0));
1374 auto material_force_magnitude = t_material_force.l2();
1375 if (material_force_magnitude <
1376 std::numeric_limits<double>::epsilon()) {
1377 a0 = 0;
1378
1379 } else {
1380
1381 auto t_edge_dir = calculate_edge_direction(e, true);
1382 auto t_cross_max = get_cross(t_edge_dir, max_face);
1383 auto [side, sense, offset] = get_sense(max_face, e);
1384 t_cross_max(sense) *= sense;
1385
1389
1390 t_material_force.normalize();
1391 t_cross_max.normalize();
1393 t_cross(I) = FTensor::levi_civita(I, J, K) *
1394 t_material_force(J) * t_cross_max(K);
1395 a0 = -std::asin(t_cross(I) * t_edge_dir(I));
1396
1397 MOFEM_LOG("EP", sev)
1398 << "Optimal angle " << a0 << " energy " << e0;
1399 }
1400 break;
1401 }
1402 default: {
1403
1404 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
1405 "Unknown energy release selector");
1406 }
1407 }
1408 }
1409 }
1410 }
1411
1413 };
1414
1415 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
1416 face_angle_map_up;
1417 std::map<EntityHandle, std::tuple<double, double, EntityHandle>>
1418 face_angle_map_down;
1419 CHKERR up_down_face(face_angle_map_up, face_angle_map_down);
1420 CHKERR calc_optimal_angle(face_angle_map_up, face_angle_map_down);
1421
1422#ifndef NDEBUG
1423 if (debug) {
1424 auto th_angle = get_tags_vec("Angle", 1);
1425 Range up;
1426 for (auto &m : face_angle_map_up) {
1427 auto [e, a, face] = m.second;
1428 up.insert(face);
1429 CHKERR mField.get_moab().tag_set_data(th_angle[0], &face, 1, &a);
1430 }
1431 Range down;
1432 for (auto &m : face_angle_map_down) {
1433 auto [e, a, face] = m.second;
1434 down.insert(face);
1435 CHKERR mField.get_moab().tag_set_data(th_angle[0], &face, 1, &a);
1436 }
1437
1438 Range max_energy_faces;
1439 for (auto &m : edge_face_max_energy_map) {
1440 auto [face, e, angle] = m.second;
1441 max_energy_faces.insert(face);
1442 CHKERR mField.get_moab().tag_set_data(th_angle[0], &face, 1,
1443 &angle);
1444 }
1445 if (mField.get_comm_rank() == 0) {
1446 CHKERR save_range(mField.get_moab(), "up_faces.vtk", up);
1447 CHKERR save_range(mField.get_moab(), "down_faces.vtk", down);
1448 CHKERR save_range(mField.get_moab(), "max_energy_faces.vtk",
1449 max_energy_faces);
1450 }
1451 }
1452#endif // NDEBUG
1453
1455 };
1456
1457 auto get_conn = [&](auto e) {
1458 Range conn;
1459 CHK_MOAB_THROW(mField.get_moab().get_connectivity(e, conn, true),
1460 "get conn");
1461 return conn;
1462 };
1463
1464 auto get_adj = [&](auto e, auto dim) {
1465 Range adj;
1466 CHK_MOAB_THROW(mField.get_moab().get_adjacencies(
1467 e, dim, false, adj, moab::Interface::UNION),
1468 "get adj");
1469 return adj;
1470 };
1471
1472 auto get_coords = [&](auto v) {
1474 CHK_MOAB_THROW(mField.get_moab().get_coords(v, &t_coords(0)),
1475 "get coords");
1476 return t_coords;
1477 };
1478
1479 // calculate normal of the max energy face
1480 auto get_rotated_normal = [&](auto e, auto f, auto angle) {
1483 auto t_edge_dir = calculate_edge_direction(e, true);
1484 auto [side, sense, offset] = get_sense(f, e);
1485 t_edge_dir(i) *= sense;
1486 t_edge_dir.normalize();
1487 t_edge_dir(i) *= angle;
1488 auto t_R = LieGroups::SO3::exp(t_edge_dir, angle);
1490 mField.getInterface<Tools>()->getTriNormal(f, &t_normal(0));
1491 FTensor::Tensor1<double, SPACE_DIM> t_rotated_normal;
1492 t_rotated_normal(i) = t_R(i, j) * t_normal(j);
1493 return std::make_tuple(t_normal, t_rotated_normal);
1494 };
1495
1496 auto set_coord = [&](auto v, auto &adj_vertex_tets_verts, auto &coords,
1497 auto &t_move, auto gamma) {
1498 auto index = adj_vertex_tets_verts.index(v);
1499 if (index >= 0) {
1500 for (auto ii : {0, 1, 2}) {
1501 coords[3 * index + ii] += gamma * t_move(ii);
1502 }
1503 return true;
1504 }
1505 return false;
1506 };
1507
1508 auto tets_quality = [&](auto quality, auto &adj_vertex_tets_verts,
1509 auto &adj_vertex_tets, auto &coords) {
1510 for (auto t : adj_vertex_tets) {
1511 const EntityHandle *conn;
1512 int num_nodes;
1513 CHKERR mField.get_moab().get_connectivity(t, conn, num_nodes, true);
1514 std::array<double, 12> tet_coords;
1515 for (auto n = 0; n != 4; ++n) {
1516 auto index = adj_vertex_tets_verts.index(conn[n]);
1517 if (index < 0) {
1519 }
1520 for (auto ii = 0; ii != 3; ++ii) {
1521 tet_coords[3 * n + ii] = coords[3 * index + ii];
1522 }
1523 }
1524 double q = Tools::volumeLengthQuality(tet_coords.data());
1525 if (!std::isnormal(q))
1526 q = -2;
1527 quality = std::min(quality, q);
1528 };
1529
1530 return quality;
1531 };
1532
1533 auto calculate_free_face_node_displacement =
1534 [&](auto &edge_face_max_energy_map) {
1535 // get edges adjacent to vertex along which nodes are moving
1536 auto get_vertex_edges = [&](auto vertex) {
1537 Range vertex_edges; // edges adjacent to vertex
1538
1539 auto impl = [&]() {
1541 CHKERR mField.get_moab().get_adjacencies(vertex, 1, false,
1542 vertex_edges);
1543 vertex_edges = subtract(vertex_edges, front_verts_edges);
1544
1545 if (boundary_skin_verts.size() &&
1546 boundary_skin_verts.find(vertex[0]) !=
1547 boundary_skin_verts.end()) {
1548 MOFEM_LOG("EP", sev) << "Boundary vertex";
1549 vertex_edges = intersect(vertex_edges, body_skin_edges);
1550 }
1551 if (geometry_edges_verts.size() &&
1552 geometry_edges_verts.find(vertex[0]) !=
1553 geometry_edges_verts.end()) {
1554 MOFEM_LOG("EP", sev) << "Geometry edge vertex";
1555 vertex_edges = intersect(vertex_edges, geometry_edges);
1556 }
1557 if (crack_faces_verts.size() &&
1558 crack_faces_verts.find(vertex[0]) !=
1559 crack_faces_verts.end()) {
1560 MOFEM_LOG("EP", sev) << "Crack face vertex";
1561 vertex_edges = intersect(vertex_edges, crack_faces_edges);
1562 }
1564 };
1565
1566 CHK_THROW_MESSAGE(impl(), "get_vertex_edges");
1567
1568 return vertex_edges;
1569 };
1570
1571 // vector of rotated faces, edge along node is moved, moved edge,
1572 // moved displacement, quality, cardinality, gamma
1573 using Bundle = std::vector<
1574
1577
1578 >;
1579 std::map<EntityHandle, Bundle> edge_bundle_map;
1580
1581 for (auto &m : edge_face_max_energy_map) {
1582
1583 auto edge = m.first;
1584 auto &[max_face, energy, opt_angle] = m.second;
1585
1586 // calculate rotation of max energy face
1587 auto [t_normal, t_rotated_normal] =
1588 get_rotated_normal(edge, max_face, opt_angle);
1589
1590 auto front_vertex = get_conn(Range(m.first, m.first));
1591 auto adj_tets = get_adj(Range(max_face, max_face), 3);
1592 auto adj_tets_faces = get_adj(adj_tets, 2);
1593 auto adj_front_faces = subtract(
1594 intersect(get_adj(Range(edge, edge), 2), adj_tets_faces),
1595 *crackFaces);
1596 if (adj_front_faces.size() > 3)
1598 "adj_front_faces.size()>3");
1599
1600 FTensor::Tensor1<double, SPACE_DIM> t_material_force;
1601 CHKERR mField.get_moab().tag_get_data(th_material_force, &edge, 1,
1602 &t_material_force(0));
1603 std::vector<double> griffith_energy(adj_front_faces.size());
1604 CHKERR mField.get_moab().tag_get_data(
1605 th_face_energy, adj_front_faces, griffith_energy.data());
1606
1607 auto set_edge_bundle = [&](auto min_gamma) {
1608 for (auto rotated_f : adj_front_faces) {
1609
1610 double rotated_face_energy =
1611 griffith_energy[adj_front_faces.index(rotated_f)];
1612
1613 auto vertex = subtract(get_conn(Range(rotated_f, rotated_f)),
1614 front_vertex);
1615 if (vertex.size() != 1) {
1617 "Wrong number of vertex to move");
1618 }
1619 auto front_vertex_edges_vertex = get_conn(
1620 intersect(get_adj(front_vertex, 1), crack_faces_edges));
1621 vertex = subtract(
1622 vertex, front_vertex_edges_vertex); // vertex free to move
1623 if (vertex.empty()) {
1624 continue;
1625 }
1626
1627 auto face_cardinality = [&](auto f, auto &seen_front_edges) {
1628 auto whole_front =
1629 unite(*frontEdges,
1630 subtract(body_skin_edges, crack_faces_edges));
1631 auto faces = Range(f, f);
1632 int c = 0;
1633 for (; c < 10; ++c) {
1634 auto front_edges =
1635 subtract(get_adj(faces, 1), seen_front_edges);
1636 if (front_edges.size() == 0) {
1637 return 0;
1638 }
1639 auto front_connected_edges =
1640 intersect(front_edges, whole_front);
1641 if (front_connected_edges.size()) {
1642 seen_front_edges.merge(front_connected_edges);
1643 return c;
1644 }
1645 faces.merge(get_adj(front_edges, 2));
1646 ++c;
1647 }
1648 return c;
1649 };
1650
1651 Range seen_edges = Range(edge, edge);
1652 double rotated_face_cardinality = face_cardinality(
1653 rotated_f,
1654 seen_edges); // add cardinality of max energy
1655 // face to rotated face cardinality
1656 // rotated_face_cardinality +=
1657 // face_cardinality(max_face, seen_edges);
1658 rotated_face_cardinality = std::max(rotated_face_cardinality,
1659 1.); // at least one edge
1660
1661 auto t_vertex_coords = get_coords(vertex);
1662 auto vertex_edges = get_vertex_edges(vertex);
1663
1664 EntityHandle f0 = front_vertex[0];
1665 EntityHandle f1 = front_vertex[1];
1666 FTensor::Tensor1<double, 3> t_v_e0, t_v_e1;
1667 CHKERR mField.get_moab().get_coords(&f0, 1, &t_v_e0(0));
1668 CHKERR mField.get_moab().get_coords(&f1, 1, &t_v_e1(0));
1669
1671 for (auto e_used_to_move_detection : vertex_edges) {
1672 auto edge_conn = get_conn(Range(e_used_to_move_detection,
1673 e_used_to_move_detection));
1674 edge_conn = subtract(edge_conn, vertex);
1675 // Find displacement of the edge such that dot porduct with
1676 // normal is zero.
1677 //
1678 // { (t_v0 - t_vertex_coords) + gamma * (t_v3 -
1679 // t_vertex_coords) } * n = 0
1680 // where t_v0 is the edge vertex, t_v3 is the edge end
1681 // point, n is the rotated normal of the face gamma is the
1682 // factor by which the edge is moved
1684 t_v0(i) = (t_v_e0(i) + t_v_e1(i)) / 2;
1686 CHKERR mField.get_moab().get_coords(edge_conn, &t_v3(0));
1687 auto a =
1688 (t_v0(i) - t_vertex_coords(i)) * t_rotated_normal(i);
1689 auto b =
1690 (t_v3(i) - t_vertex_coords(i)) * t_rotated_normal(i);
1691 auto gamma = a / b;
1692
1693 constexpr double eps =
1694 std::numeric_limits<double>::epsilon();
1695 if (std::isnormal(gamma) && gamma < 1.0 - eps &&
1696 gamma > -0.1) {
1698 t_move(i) = gamma * (t_v3(i) - t_vertex_coords(i));
1699
1700 auto check_rotated_face_directoon = [&]() {
1702 t_delta(i) = t_vertex_coords(i) + t_move(i) - t_v0(i);
1703 t_delta.normalize();
1704 auto dot =
1705 (t_material_force(i) / t_material_force.l2()) *
1706 t_delta(i);
1707 return -dot > 0 ? true : false;
1708 };
1709
1710 if (check_rotated_face_directoon()) {
1711
1712 MOFEM_LOG("EP", Sev::verbose)
1713 << "Crack edge " << edge << " moved face "
1714 << rotated_f
1715 << " edge: " << e_used_to_move_detection
1716 << " face direction/energy " << rotated_face_energy
1717 << " face cardinality " << rotated_face_cardinality
1718 << " gamma: " << gamma;
1719
1720 auto &bundle = edge_bundle_map[edge];
1721 bundle.emplace_back(rotated_f, e_used_to_move_detection,
1722 vertex[0], t_move, 1,
1723 rotated_face_cardinality, gamma);
1724 }
1725 }
1726 }
1727 }
1728 };
1729
1730 set_edge_bundle(std::numeric_limits<double>::epsilon());
1731 if (edge_bundle_map[edge].empty()) {
1732 set_edge_bundle(-1.);
1733 }
1734 }
1735
1736 return edge_bundle_map;
1737 };
1738
1739 auto get_sort_by_energy = [&](auto &edge_face_max_energy_map) {
1740 std::map<double, std::tuple<EntityHandle, EntityHandle, double>>
1741 sort_by_energy;
1742
1743 for (auto &m : edge_face_max_energy_map) {
1744 auto e = m.first;
1745 auto &[max_face, energy, opt_angle] = m.second;
1746 auto abs_energy = std::abs(energy);
1747 sort_by_energy[abs_energy] = std::make_tuple(e, max_face, opt_angle);
1748 }
1749
1750 return sort_by_energy;
1751 };
1752
1753 auto set_tag = [&](auto &&adj_edges_map, auto &&sort_by_energy) {
1755
1756 Tag th_face_pressure;
1758 mField.get_moab().tag_get_handle("FacePressure", th_face_pressure),
1759 "get tag");
1760 auto get_face_pressure = [&](auto face) {
1761 double pressure;
1762 CHK_MOAB_THROW(mField.get_moab().tag_get_data(th_face_pressure, &face,
1763 1, &pressure),
1764 "get rag data");
1765 return pressure;
1766 };
1767
1768 MOFEM_LOG("EPSELF", Sev::inform)
1769 << "Number of edges to check " << sort_by_energy.size();
1770
1771 enum face_energy { POSITIVE, NEGATIVE };
1772 constexpr bool skip_negative = true;
1773
1774 for (auto fe : {face_energy::POSITIVE, face_energy::NEGATIVE}) {
1775
1776 std::vector<double> energies;
1777 double max_pressure = -1;
1778 // check max energies and average all energies along the crack front
1779 // extract max pressure along the crack front
1780 for (auto it = sort_by_energy.rbegin(); it != sort_by_energy.rend();
1781 ++it) {
1782 auto energy = it->first;
1783 auto [max_edge, max_face, opt_angle] = it->second;
1784
1785 auto face_pressure = get_face_pressure(max_face);
1786 energies.push_back(energy);
1787
1788 max_pressure = std::max(max_pressure, face_pressure);
1789 }
1790
1791 double average_energy = 0;
1792 if (!energies.empty()) {
1793 average_energy =
1794 std::accumulate(energies.begin(), energies.end(), 0.) /
1795 energies.size();
1796 }
1797
1798 MOFEM_LOG("EPSELF", Sev::inform)
1799 << "Average energy Griffiths energy of crack front "
1800 << average_energy;
1801
1802 // iterate edges wih maximal energy, and make them seed. Such edges,
1803 // will most likely will have also smallest node displacement
1804 for (auto it = sort_by_energy.rbegin(); it != sort_by_energy.rend();
1805 ++it) {
1806
1807 auto energy = it->first;
1808 auto [max_edge, max_face, opt_angle] = it->second;
1809
1810 auto face_pressure = get_face_pressure(max_face);
1811 if (skip_negative) {
1812 if (fe == face_energy::POSITIVE) {
1813 if (face_pressure <
1814 -(crackingAtol + crackingRtol * std::abs(max_pressure))) {
1815 MOFEM_LOG("EPSELF", Sev::inform)
1816 << "Skip negative face " << max_face << " with energy "
1817 << energy << " and pressure " << face_pressure;
1818 continue;
1819 }
1820 }
1821 }
1822
1823 MOFEM_LOG("EPSELF", Sev::inform)
1824 << "Check face " << max_face << " edge " << max_edge
1825 << " energy " << energy << " optimal angle " << opt_angle
1826 << " face pressure " << face_pressure;
1827
1828 // store energy of max face
1829 if (!average_energy) {
1830 MOFEM_LOG("EPSELF", Sev::warning)
1831 << "Average energy is zero, setting max Griffiths energy to "
1832 "current energy "
1833 << energy;
1834 average_energy = energy;
1835 }
1836 avgGriffithsEnergy = average_energy;
1837 auto jt = adj_edges_map.find(max_edge);
1838 if (jt == adj_edges_map.end()) {
1839 MOFEM_LOG("EPSELF", Sev::warning)
1840 << "Edge " << max_edge << " not found in adj_edges_map";
1841 continue;
1842 }
1843 auto &bundle = jt->second;
1844
1845 auto find_max_in_bundle_impl = [&](auto edge, auto &bundle,
1846 auto gamma) {
1848
1849 EntityHandle vertex_max = 0;
1850 EntityHandle face_max = 0;
1851 EntityHandle move_edge_max = 0;
1852 double max_quality = -2;
1853 double max_quality_evaluated = -2;
1854 double min_cardinality = std::numeric_limits<double>::max();
1855
1856 FTensor::Tensor1<double, SPACE_DIM> t_move_last{0., 0., 0.};
1857
1858 for (auto &b : bundle) {
1859 auto &[face, move_edge, vertex, t_move, quality, cardinality,
1860 edge_gamma] = b;
1861
1862 auto adj_vertex_tets = get_adj(Range(vertex, vertex), 3);
1863 auto adj_vertex_tets_verts = get_conn(adj_vertex_tets);
1864 std::vector<double> coords(3 * adj_vertex_tets_verts.size());
1865 CHK_MOAB_THROW(mField.get_moab().get_coords(
1866 adj_vertex_tets_verts, coords.data()),
1867 "get coords");
1868
1869 set_coord(vertex, adj_vertex_tets_verts, coords, t_move, gamma);
1870 quality = tets_quality(quality, adj_vertex_tets_verts,
1871 adj_vertex_tets, coords);
1872
1873 auto eval_quality = [](auto q, auto c, auto edge_gamma) {
1874 if (q < 0) {
1875 return q;
1876 } else {
1877 return ((edge_gamma < 0) ? (q / 2) : q) / pow(c, 2);
1878 }
1879 };
1880
1881 if (eval_quality(quality, cardinality, edge_gamma) >=
1882 max_quality_evaluated) {
1883 max_quality = quality;
1884 min_cardinality = cardinality;
1885 vertex_max = vertex;
1886 face_max = face;
1887 move_edge_max = move_edge;
1888 t_move_last(i) = t_move(i);
1889 max_quality_evaluated =
1890 eval_quality(max_quality, min_cardinality, edge_gamma);
1891 }
1892 }
1893
1894 return std::make_tuple(vertex_max, face_max, t_move_last,
1895 max_quality, min_cardinality);
1896 };
1897
1898 auto find_max_in_bundle = [&](auto edge, auto &bundle) {
1899 auto b_org_bundle = bundle;
1900 auto r = find_max_in_bundle_impl(edge, bundle, 1.);
1901 auto &[vertex_max, face_max, t_move_last, max_quality,
1902 cardinality] = r;
1903 if (max_quality < 0) {
1904 for (double gamma = 0.95; gamma >= 0.45; gamma -= 0.05) {
1905 bundle = b_org_bundle;
1906 r = find_max_in_bundle_impl(edge, bundle, gamma);
1907 auto &[vertex_max, face_max, t_move_last, max_quality,
1908 cardinality] = r;
1909 MOFEM_LOG("EPSELF", Sev::warning)
1910 << "Back tracking: gamma " << gamma << " edge " << edge
1911 << " quality " << max_quality << " cardinality "
1912 << cardinality;
1913 if (max_quality > 0.01) {
1915 t_move_last(I) *= gamma;
1916 return r;
1917 }
1918 }
1920 t_move_last(I) = 0;
1921 }
1922 return r;
1923 };
1924
1925 // set tags with displacement of node and face energy
1926 auto set_tag_to_vertex_and_face = [&](auto &&r, auto &quality) {
1928 auto &[v, f, t_move, q, cardinality] = r;
1929
1930 if ((q > 0 && std::isnormal(q)) && energy > 0) {
1931
1932 MOFEM_LOG("EPSELF", Sev::inform)
1933 << "Set tag: vertex " << v << " face " << f << " "
1934 << max_edge << " move " << t_move << " energy " << energy
1935 << " quality " << q << " cardinality " << cardinality;
1936 CHKERR mField.get_moab().tag_set_data(th_position[0], &v, 1,
1937 &t_move(0));
1938 CHKERR mField.get_moab().tag_set_data(th_max_face_energy[0], &f,
1939 1, &energy);
1940 }
1941
1942 quality = q;
1944 };
1945
1946 double quality = -2;
1947 CHKERR set_tag_to_vertex_and_face(
1948
1949 find_max_in_bundle(max_edge, bundle),
1950
1951 quality
1952
1953 );
1954
1955 if (quality > 0 && std::isnormal(quality) && energy > 0) {
1956 MOFEM_LOG("EPSELF", Sev::inform)
1957 << "Crack face set with quality: " << quality;
1959 }
1960 }
1961
1962 if (!skip_negative)
1963 break;
1964 }
1965
1967 };
1968
1969 // map: {edge, {face, energy, optimal_angle}}
1970 MOFEM_LOG("EP", sev) << "Calculate orientation";
1971 std::map<EntityHandle, std::tuple<EntityHandle, double, double>>
1972 edge_face_max_energy_map;
1973 CHKERR find_maximal_face_energy(front_edges, front_faces,
1974 edge_face_max_energy_map);
1975 CHKERR calculate_face_orientation(edge_face_max_energy_map);
1976
1977 MOFEM_LOG("EP", sev) << "Calculate node positions";
1978 CHKERR set_tag(
1979
1980 calculate_free_face_node_displacement(edge_face_max_energy_map),
1981 get_sort_by_energy(edge_face_max_energy_map)
1982
1983 );
1984
1986 };
1987
1988 auto get_max_griffith_force = [&](auto r) {
1989 auto &moab = mField.get_moab();
1990 std::vector<double> gc(r.size());
1991 Tag th_gc;
1992 CHKERR moab.tag_get_handle("GriffithForce", th_gc);
1993 CHKERR moab.tag_get_data(th_gc, r, gc.data());
1994 double max_griffith_force = 0;
1995 for (size_t i = 0; i < r.size(); ++i) {
1996 max_griffith_force = std::max(max_griffith_force, std::abs(gc[i]));
1997 }
1998 return max_griffith_force;
1999 };
2000
2001 MOFEM_LOG("EP", sev) << "Front edges " << frontEdges->size();
2002 if (std::abs(get_max_griffith_force(get_adj_front(true))) >
2003 std::numeric_limits<double>::epsilon()) {
2004 CHKERR evaluate_face_energy_and_set_orientation(
2005 *frontEdges, get_adj_front(true), sides_pair, th_front_position);
2006 } else {
2007 auto adj_front = get_adj_front(true);
2008 double zero[] = {0., 0., 0.};
2009 CHKERR mField.get_moab().tag_clear_data(th_front_position[0], adj_front,
2010 zero);
2011 }
2012 }
2013
2014 // exchange positions and energies from processor zero to all other
2015 CHKERR VecZeroEntries(vertexExchange.second);
2016 CHKERR VecGhostUpdateBegin(vertexExchange.second, INSERT_VALUES,
2017 SCATTER_FORWARD);
2018 CHKERR VecGhostUpdateEnd(vertexExchange.second, INSERT_VALUES,
2019 SCATTER_FORWARD);
2020 CHKERR mField.getInterface<CommInterface>()->updateEntitiesPetscVector(
2021 mField.get_moab(), vertexExchange, th_front_position[0]);
2022 CHKERR VecZeroEntries(faceExchange.second);
2023 CHKERR VecGhostUpdateBegin(faceExchange.second, INSERT_VALUES,
2024 SCATTER_FORWARD);
2025 CHKERR VecGhostUpdateEnd(faceExchange.second, INSERT_VALUES, SCATTER_FORWARD);
2026 CHKERR mField.getInterface<CommInterface>()->updateEntitiesPetscVector(
2027 mField.get_moab(), faceExchange, th_max_face_energy[0]);
2028
2029 auto get_max_moved_faces = [&]() {
2030 Range max_moved_faces;
2031 auto adj_front = get_adj_front(false);
2032 std::vector<double> face_energy(adj_front.size());
2033 CHKERR mField.get_moab().tag_get_data(th_max_face_energy[0], adj_front,
2034 face_energy.data());
2035 for (int i = 0; i != adj_front.size(); ++i) {
2036 if (face_energy[i] > std::numeric_limits<double>::epsilon()) {
2037 max_moved_faces.insert(adj_front[i]);
2038 }
2039 }
2040
2041 return boost::make_shared<Range>(max_moved_faces);
2042 };
2043
2044 // move all faces with energy larger than 0
2045 maxMovedFaces = get_max_moved_faces();
2046 MOFEM_LOG("EP", sev) << "Number of of moved faces: " << maxMovedFaces->size();
2047
2048#ifndef NDEBUG
2049 if (debug) {
2051 mField.get_moab(),
2052 "max_moved_faces_" +
2053 boost::lexical_cast<std::string>(mField.get_comm_rank()) + ".vtk",
2054 *maxMovedFaces);
2055 }
2056#endif
2057
2059}
static auto get_two_sides_of_crack_surface(MoFEM::Interface &m_field, Range crack_faces)
constexpr double a
static const double eps
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
constexpr double a0
const double c
speed of light (cm/ns)
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
FTensor::Index< 'm', 3 > m
static double crackingAtol
Cracking absolute tolerance.
static double crackingRtol
Cracking relative tolerance.
double avgGriffithsEnergy
static enum EnergyReleaseSelector energyReleaseSelector
static auto exp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:69

◆ createCrackSurfaceMeshset()

MoFEMErrorCode EshelbianCore::createCrackSurfaceMeshset ( )
Examples
ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 2853 of file EshelbianFracture.cpp.

2853 {
2855 auto meshset_mng = mField.getInterface<MeshsetsManager>();
2856 while (meshset_mng->checkMeshset(addCrackMeshsetId, BLOCKSET))
2858 MOFEM_LOG("EP", Sev::inform)
2859 << "Crack added surface meshset " << addCrackMeshsetId;
2860 CHKERR meshset_mng->addMeshset(BLOCKSET, addCrackMeshsetId, "CRACK_COMPUTED");
2862};

◆ createExchangeVectors()

MoFEMErrorCode EshelbianCore::createExchangeVectors ( Sev  sev)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 5577 of file EshelbianPlasticity.cpp.

5577 {
5579
5580 auto print_loc_size = [this](auto v, auto str, auto sev) {
5582 int size;
5583 CHKERR VecGetLocalSize(v.second, &size);
5584 int low, high;
5585 CHKERR VecGetOwnershipRange(v.second, &low, &high);
5586 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( " << low
5587 << " " << high << " ) ";
5590 };
5591
5593 mField.get_comm(), mField.get_moab(), 3, 1, sev);
5594 CHKERR print_loc_size(volumeExchange, "volumeExchange", sev);
5596 mField.get_comm(), mField.get_moab(), 2, 1, Sev::inform);
5597 CHKERR print_loc_size(faceExchange, "faceExchange", sev);
5599 mField.get_comm(), mField.get_moab(), 1, 1, Sev::inform);
5600 CHKERR print_loc_size(edgeExchange, "edgeExchange", sev);
5602 mField.get_comm(), mField.get_moab(), 0, 3, Sev::inform);
5603 CHKERR print_loc_size(vertexExchange, "vertexExchange", sev);
5604
5606}
CommInterface::EntitiesPetscVector volumeExchange
static EntitiesPetscVector createEntitiesPetscVector(MPI_Comm comm, moab::Interface &moab, std::function< Range(Range)> get_entities_fun, const int nb_coeffs, Sev sev=Sev::verbose, int root_rank=0, bool get_vertices=true)
Create a ghost vector for exchanging data.

◆ d_f_linear()

static double EshelbianCore::d_f_linear ( const double  v)
inlinestatic

◆ d_f_log()

static double EshelbianCore::d_f_log ( const double  v)
inlinestatic

◆ d_f_log_e()

static double EshelbianCore::d_f_log_e ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 176 of file EshelbianCore.hpp.

176 {
177 if constexpr (use_quadratic_exp) {
178 return d_f_log_e_quadratic(v);
179 } else {
180 if (v > v_max)
181 return std::exp(v_max);
182 else
183 return std::exp(v);
184 }
185 }
static constexpr bool use_quadratic_exp
static constexpr double v_max
static double d_f_log_e_quadratic(const double v)

◆ d_f_log_e_quadratic()

static double EshelbianCore::d_f_log_e_quadratic ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 145 of file EshelbianCore.hpp.

145 {
146 if (v > v_max) {
147 double e = static_cast<double>(std::exp(v_max));
148 double dv = v - v_max;
149 return e * dv + e;
150 } else {
151 return static_cast<double>(std::exp(v));
152 }
153 }

◆ dd_f_linear()

static double EshelbianCore::dd_f_linear ( const double  v)
inlinestatic

◆ dd_f_log()

static double EshelbianCore::dd_f_log ( const double  v)
inlinestatic

◆ dd_f_log_e()

static double EshelbianCore::dd_f_log_e ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 186 of file EshelbianCore.hpp.

186 {
187 if constexpr (use_quadratic_exp) {
188 return dd_f_log_e_quadratic(v);
189 } else {
190 if (v > v_max)
191 return 0.;
192 else
193 return std::exp(v);
194 }
195 }
static double dd_f_log_e_quadratic(const double v)

◆ dd_f_log_e_quadratic()

static double EshelbianCore::dd_f_log_e_quadratic ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 155 of file EshelbianCore.hpp.

155 {
156 if (v > v_max) {
157 return static_cast<double>(std::exp(v_max));
158 } else {
159 return static_cast<double>(std::exp(v));
160 }
161 }

◆ f_linear()

static double EshelbianCore::f_linear ( const double  v)
inlinestatic

◆ f_log()

static double EshelbianCore::f_log ( const double  v)
inlinestatic

◆ f_log_e()

static double EshelbianCore::f_log_e ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 163 of file EshelbianCore.hpp.

163 {
164 if constexpr (use_quadratic_exp) {
165 return f_log_e_quadratic(v);
166 } else {
167 if (v > v_max)
168 // y = exp(v_max) * v + exp(v_max) * (1 - v_max);
169 // y/exp(v_max) = v + (1 - v_max);
170 // y/exp(v_max) - (1 - v_max) = v;
171 return std::exp(v_max) * v + std::exp(v_max) * (1 - v_max);
172 else
173 return std::exp(v);
174 }
175 }
static double f_log_e_quadratic(const double v)

◆ f_log_e_quadratic()

static double EshelbianCore::f_log_e_quadratic ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 135 of file EshelbianCore.hpp.

135 {
136 if (v > v_max) {
137 double e = static_cast<double>(std::exp(v_max));
138 double dv = v - v_max;
139 return 0.5 * e * dv * dv + e * dv + e;
140 } else {
141 return static_cast<double>(std::exp(v));
142 }
143 }

◆ getBc()

template<typename BC >
MoFEMErrorCode EshelbianCore::getBc ( boost::shared_ptr< BC > &  bc_vec_ptr,
const std::string  block_name,
const int  nb_attributes 
)
inline
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 331 of file EshelbianCore.hpp.

332 {
334 for (auto it :
335 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
336
337 (boost::format("%s(.*)") % block_name).str()
338
339 ))
340
341 ) {
342 std::vector<double> block_attributes;
343 CHKERR it->getAttributes(block_attributes);
344 if (block_attributes.size() < nb_attributes) {
345 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
346 "In block %s expected %d attributes, but given %ld",
347 it->getName().c_str(), nb_attributes, block_attributes.size());
348 }
349 Range faces;
350 CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
351 true);
352 bc_vec_ptr->emplace_back(it->getName(), block_attributes, faces);
353 }
355 }
IFACE getInterface() const
Get interface pointer to pointer of interface.

◆ getExternalStrain()

MoFEMErrorCode EshelbianCore::getExternalStrain ( )
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 5528 of file EshelbianPlasticity.cpp.

5528 {
5530
5531 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec>
5532 &ext_strain_vec_ptr,
5533 const std::string block_name,
5534 const int nb_attributes) {
5536 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5537 std::regex((boost::format("(.*)%s(.*)") % block_name).str()))) {
5538 std::vector<double> block_attributes;
5539 CHKERR it->getAttributes(block_attributes);
5540 if (block_attributes.size() < nb_attributes) {
5541 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5542 "In block %s expected %d attributes, but given %ld",
5543 it->getName().c_str(), nb_attributes, block_attributes.size());
5544 }
5545
5546 auto get_block_ents = [&]() {
5547 Range ents;
5548 CHKERR mField.get_moab().get_entities_by_handle(it->meshset, ents,
5549 true);
5550 return ents;
5551 };
5552 auto Ents = get_block_ents();
5553 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
5554 get_block_ents());
5555 }
5557 };
5558
5559 externalStrainVecPtr = boost::make_shared<ExternalStrainVec>();
5560
5561 CHKERR getExternalStrain(externalStrainVecPtr, "EXTERNALSTRAIN", 2);
5562
5563 auto ts_pre_stretch = boost::make_shared<DynamicRelaxationTimeScale>(
5564 "externalstrain_history.txt");
5565 for (auto &ext_strain_block : *externalStrainVecPtr) {
5566 MOFEM_LOG("EP", Sev::noisy)
5567 << "Add time scaling external strain: " << ext_strain_block.blockName;
5568 timeScaleMap[ext_strain_block.blockName] =
5570 ts_pre_stretch, "externalstrain_history", ".txt",
5571 ext_strain_block.blockName);
5572 }
5573
5575}
boost::shared_ptr< ExternalStrainVec > externalStrainVecPtr
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
MoFEMErrorCode getExternalStrain()
static boost::shared_ptr< ScalingMethod > get(boost::shared_ptr< ScalingMethod > ts, std::string file_prefix, std::string file_suffix, std::string block_name, Args &&...args)
Interface for managing meshsets containing materials and boundary conditions.

◆ getOptions()

MoFEMErrorCode EshelbianCore::getOptions ( )
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 967 of file EshelbianPlasticity.cpp.

967 {
969 const char *list_rots[] = {"small", "moderate", "large", "no_h1"};
970 const char *list_release[] = {"griffith_force", "griffith_skeleton"};
971 const char *list_stretches[] = {"linear", "log", "log_quadratic"};
972 const char *list_broken_hdiv_bases[] = {"demkowicz", "ainsworth"};
973 PetscInt choice_rot = EshelbianCore::rotSelector;
974 PetscInt choice_grad = EshelbianCore::gradApproximator;
975 PetscInt choice_release = EshelbianCore::energyReleaseSelector;
976 PetscInt choice_stretch = StretchSelector::LOG;
977 PetscInt choice_solver = SolverType::TimeSolver;
978 PetscInt choice_broken_hdiv_base = 0;
979 PetscBool l2_user_base_scale_set = PETSC_FALSE;
982 choice_broken_hdiv_base = 0;
983 break;
985 choice_broken_hdiv_base = 1;
986 break;
987 default:
988 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
989 "Unsupported broken HDIV base %s",
991 }
992 char analytical_expr_file_name[255] = "analytical_expr.py";
993 PetscBool no_stretch =
994 stretchHandling == NO_STREACH ? PETSC_TRUE : PETSC_FALSE;
995
996 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Eshelbian plasticity", "none");
997 CHKERR PetscOptionsInt("-space_order", "approximation oder for space", "",
998 spaceOrder, &spaceOrder, PETSC_NULLPTR);
999 CHKERR PetscOptionsInt("-space_h1_order", "approximation oder for space", "",
1000 spaceH1Order, &spaceH1Order, PETSC_NULLPTR);
1001 CHKERR PetscOptionsInt("-material_order", "approximation oder for material",
1002 "", materialH1Order, &materialH1Order, PETSC_NULLPTR);
1003 CHKERR PetscOptionsScalar("-viscosity_alpha_u", "viscosity", "", alphaU,
1004 &alphaU, PETSC_NULLPTR);
1005 CHKERR PetscOptionsScalar("-viscosity_alpha_w", "viscosity", "", alphaW,
1006 &alphaW, PETSC_NULLPTR);
1007 CHKERR PetscOptionsScalar("-viscosity_alpha_omega", "rot viscosity", "",
1008 alphaOmega, &alphaOmega, PETSC_NULLPTR);
1009 CHKERR PetscOptionsScalar("-density_alpha_rho", "density", "", alphaRho,
1010 &alphaRho, PETSC_NULLPTR);
1011 CHKERR PetscOptionsScalar("-alpha_tau", "tau", "", alphaTau, &alphaTau,
1012 PETSC_NULLPTR);
1013 CHKERR PetscOptionsEList("-rotations", "rotations", "", list_rots,
1014 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
1015 PETSC_NULLPTR);
1016 CHKERR PetscOptionsEList("-grad", "gradient of defamation approximate", "",
1017 list_rots, NO_H1_CONFIGURATION + 1,
1018 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
1019
1020 CHKERR PetscOptionsScalar("-exponent_base", "exponent_base", "", exponentBase,
1021 &EshelbianCore::exponentBase, PETSC_NULLPTR);
1022 CHKERR PetscOptionsEList("-stretches", "stretches", "", list_stretches,
1023 StretchSelector::STRETCH_SELECTOR_LAST,
1024 list_stretches[choice_stretch], &choice_stretch,
1025 PETSC_NULLPTR);
1026
1027 CHKERR PetscOptionsBool("-no_stretch", "do not solve for stretch", "",
1028 no_stretch, &no_stretch, PETSC_NULLPTR);
1029 CHKERR PetscOptionsBool("-set_singularity", "set singularity", "",
1030 setSingularity, &setSingularity, PETSC_NULLPTR);
1031 CHKERR PetscOptionsBool("-l2_user_base_scale", "streach scale", "",
1033 &l2_user_base_scale_set);
1034 CHKERR PetscOptionsEList(
1035 "-broken_hdiv_base", "broken HDIV stress approximation base", "",
1036 list_broken_hdiv_bases, 2,
1037 list_broken_hdiv_bases[choice_broken_hdiv_base],
1038 &choice_broken_hdiv_base, PETSC_NULLPTR);
1039
1040 // dynamic relaxation
1041
1042 // @deprecate this option
1043 CHKERR PetscOptionsBool("-dynamic_relaxation", "dynamic time relaxation", "",
1044 physicalTimeFlg, &physicalTimeFlg, PETSC_NULLPTR);
1045 CHKERR PetscOptionsEList(
1046 "-solver_type", "solver type", "", EshelbianCore::listSolvers,
1048 EshelbianCore::listSolvers[choice_solver], &choice_solver, PETSC_NULLPTR);
1049
1050 if (choice_solver != SolverType::TimeSolver) {
1051 CHKERR PetscOptionsScalar("-physical_final_time", "physical final time", "",
1053 PETSC_NULLPTR);
1054 CHKERR PetscOptionsScalar("-physical_delta_time", "physical delta time", "",
1056 PETSC_NULLPTR);
1057 CHKERR PetscOptionsInt("-physical_max_steps", "physical max iterations", "",
1059 PETSC_NULLPTR);
1060 CHKERR PetscOptionsBool(
1061 "-physical_h1_update", "update each physicalsolver step", "",
1063 }
1064
1065 // contact parameters
1066 CHKERR PetscOptionsInt("-contact_max_post_proc_ref_level", "refinement level",
1068 PETSC_NULLPTR);
1069 // cohesive interface
1070 CHKERR PetscOptionsBool("-cohesive_interface_on", "cohesive interface ON", "",
1071 interfaceCrack, &interfaceCrack, PETSC_NULLPTR);
1072 CHKERR PetscOptionsInt(
1073 "-cohesive_interface_remove_level", "cohesive interface remove level", "",
1075
1076 // cracking parameters
1077 CHKERR PetscOptionsBool("-cracking_on", "cracking ON", "", crackingOn,
1078 &crackingOn, PETSC_NULLPTR);
1079 CHKERR PetscOptionsScalar("-cracking_add_time", "cracking add time", "",
1080 crackingAddTime, &crackingAddTime, PETSC_NULLPTR);
1081 CHKERR PetscOptionsScalar("-cracking_start_time", "cracking start time", "",
1083 PETSC_NULLPTR);
1084 CHKERR PetscOptionsScalar("-griffith_energy", "Griffith energy", "",
1085 griffithEnergy, &griffithEnergy, PETSC_NULLPTR);
1086
1087 CHKERR PetscOptionsScalar("-cracking_rtol", "Cracking relative tolerance", "",
1088 crackingRtol, &crackingRtol, PETSC_NULLPTR);
1089 CHKERR PetscOptionsScalar("-cracking_atol", "Cracking absolute tolerance", "",
1090 crackingAtol, &crackingAtol, PETSC_NULLPTR);
1091 CHKERR PetscOptionsEList("-energy_release_variant", "energy release variant",
1092 "", list_release, 2, list_release[choice_release],
1093 &choice_release, PETSC_NULLPTR);
1094 CHKERR PetscOptionsInt("-nb_J_integral_levels", "Number of J integarl levels",
1096 PETSC_NULLPTR); // backward compatibility
1097 CHKERR PetscOptionsInt(
1098 "-nb_J_integral_contours", "Number of J integral contours", "",
1099 nbJIntegralContours, &nbJIntegralContours, PETSC_NULLPTR);
1100
1101 // internal stress
1102 char tag_name[255] = "";
1103 CHKERR PetscOptionsString("-internal_stress_tag_name",
1104 "internal stress tag name", "", "", tag_name, 255,
1105 PETSC_NULLPTR);
1106 internalStressTagName = string(tag_name);
1107 CHKERR PetscOptionsBool("-internal_stress_voigt", "Voigt index notation", "",
1109 PETSC_NULLPTR);
1110
1111 // Heterogenous Young's modulus
1112 char tag_heterogeneous_youngs_modulus_name[255] = "";
1113 CHKERR PetscOptionsString(
1114 "-heterogeneous_youngs_modulus", "heterogeneous Young's modulus tag name",
1115 "", "", tag_heterogeneous_youngs_modulus_name, 255, PETSC_NULLPTR);
1116 heterogeneousYoungModTagName = string(tag_heterogeneous_youngs_modulus_name);
1117
1118 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR,
1119 "-analytical_expr_file",
1120 analytical_expr_file_name, 255, PETSC_NULLPTR);
1121
1122 PetscOptionsEnd();
1123
1124 PetscOptionsBegin(PETSC_COMM_WORLD, "mesh_transfer_", "mesh data transfer",
1125 "none");
1126 char tag_mesh_transfer_source_file_name[255] = "";
1127 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
1128 "source.h5m", tag_mesh_transfer_source_file_name,
1130 meshTransferSourceMeshFileName = string(tag_mesh_transfer_source_file_name);
1131 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
1132 &meshTransferInterpOrder, PETSC_NULLPTR);
1133 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
1135 PETSC_NULLPTR);
1136 PetscOptionsEnd();
1137
1139 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1140 "Unsupported mesh transfer interpolation order %d",
1142 }
1143 if (!internalStressTagName.empty())
1145 if (!heterogeneousYoungModTagName.empty())
1147
1148 if (setSingularity && !l2_user_base_scale_set) {
1149 l2UserBaseScale = PETSC_TRUE;
1150 }
1151
1153 EshelbianCore::rotSelector = static_cast<RotSelector>(choice_rot);
1154 EshelbianCore::gradApproximator = static_cast<RotSelector>(choice_grad);
1155 EshelbianCore::stretchSelector = static_cast<StretchSelector>(choice_stretch);
1157 static_cast<EnergyReleaseSelector>(choice_release);
1158 switch (choice_broken_hdiv_base) {
1159 case 0:
1161 break;
1162 case 1:
1164 break;
1165 default:
1166 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1167 "Unknown broken HDIV base option");
1168 }
1169
1171 case StretchSelector::LINEAR:
1178 break;
1179 case StretchSelector::LOG:
1180 if (std::fabs(EshelbianCore::exponentBase - exp(1)) >
1181 std::numeric_limits<float>::epsilon()) {
1188 } else {
1195 }
1196 break;
1197 case StretchSelector::LOG_QUADRATIC:
1201 EshelbianCore::inv_f = [](const double x) {
1203 "No logarithmic quadratic stretch for this case");
1204 return 0;
1205 };
1208 break; // no stretch, do not use stretch functions
1209 default:
1210 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown stretch");
1211 break;
1212 };
1213
1214 if (physicalTimeFlg) {
1215 MOFEM_LOG("EP", Sev::warning)
1216 << "-dynamic_relaxation option is deprecated, use -solver_type "
1217 "dynamic_relaxation instead.";
1218 choice_solver = SolverType::DynamicRelaxation;
1219 }
1220
1221 switch (choice_solver) {
1224 break;
1228 physicalTimeFlg = PETSC_TRUE;
1229 break;
1232 break;
1235 physicalTimeFlg = PETSC_TRUE;
1236 break;
1240 break;
1244 physicalTimeFlg = PETSC_TRUE;
1245 break;
1246 default:
1247 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown solver");
1248 break;
1249 };
1250
1251 // start cracking after adding crack elements
1253
1254 MOFEM_LOG("EP", Sev::inform) << "spaceOrder: -space_order " << spaceOrder;
1255 MOFEM_LOG("EP", Sev::inform)
1256 << "spaceH1Order: -space_h1_order " << spaceH1Order;
1257 MOFEM_LOG("EP", Sev::inform)
1258 << "materialH1Order: -material_order " << materialH1Order;
1259 MOFEM_LOG("EP", Sev::inform) << "alphaU: -viscosity_alpha_u " << alphaU;
1260 MOFEM_LOG("EP", Sev::inform) << "alphaW: -viscosity_alpha_w " << alphaW;
1261 MOFEM_LOG("EP", Sev::inform)
1262 << "alphaOmega: -viscosity_alpha_omega " << alphaOmega;
1263 MOFEM_LOG("EP", Sev::inform) << "alphaRho: -density_alpha_rho " << alphaRho;
1264 MOFEM_LOG("EP", Sev::inform) << "alphaTau: -alpha_tau " << alphaTau;
1265 MOFEM_LOG("EP", Sev::inform)
1266 << "Rotations: -rotations " << list_rots[EshelbianCore::rotSelector];
1267 MOFEM_LOG("EP", Sev::inform) << "Gradient of deformation "
1268 << list_rots[EshelbianCore::gradApproximator];
1269 if (exponentBase != exp(1))
1270 MOFEM_LOG("EP", Sev::inform)
1271 << "Base exponent: -exponent_base " << EshelbianCore::exponentBase;
1272 else
1273 MOFEM_LOG("EP", Sev::inform) << "Base exponent e";
1274 MOFEM_LOG("EP", Sev::inform)
1275 << "Stretch: -stretches " << list_stretches[choice_stretch];
1276 MOFEM_LOG("EP", Sev::inform)
1277 << "No stretch: -no_stretch "
1278 << (stretchHandling == NO_STREACH ? "yes" : "no");
1279
1280 MOFEM_LOG("EP", Sev::inform)
1281 << "Dynamic relaxation: -dynamic_relaxation " << (physicalTimeFlg)
1282 ? "yes"
1283 : "no";
1284 MOFEM_LOG("EP", Sev::inform) << "Solver type: -solver_type "
1285 << EshelbianCore::listSolvers[choice_solver];
1286 MOFEM_LOG("EP", Sev::inform)
1287 << "Singularity: -set_singularity " << (setSingularity)
1288 ? "yes"
1289 : "no";
1290 MOFEM_LOG("EP", Sev::inform)
1291 << "L2 user base scale: -l2_user_base_scale " << (l2UserBaseScale)
1292 ? "yes"
1293 : "no";
1294 MOFEM_LOG("EP", Sev::inform)
1295 << "Broken HDIV base: -broken_hdiv_base "
1296 << list_broken_hdiv_bases[choice_broken_hdiv_base];
1297
1298 MOFEM_LOG("EP", Sev::inform) << "Cracking on: -cracking_on " << (crackingOn)
1299 ? "yes"
1300 : "no";
1301 MOFEM_LOG("EP", Sev::inform)
1302 << "Cracking add time: -cracking_add_time " << crackingAddTime;
1303 MOFEM_LOG("EP", Sev::inform)
1304 << "Cracking start time: -cracking_start_time " << crackingStartTime;
1305 MOFEM_LOG("EP", Sev::inform)
1306 << "Griffith energy: -griffith_energy " << griffithEnergy;
1307 MOFEM_LOG("EP", Sev::inform)
1308 << "Cracking relative tolerance: -cracking_rtol " << crackingRtol;
1309 MOFEM_LOG("EP", Sev::inform)
1310 << "Cracking absolute tolerance: -cracking_atol " << crackingAtol;
1311 MOFEM_LOG("EP", Sev::inform)
1312 << "Energy release variant: -energy_release_variant "
1313 << list_release[EshelbianCore::energyReleaseSelector];
1314 MOFEM_LOG("EP", Sev::inform)
1315 << "Number of J integral contours: -nb_J_integral_contours "
1317 MOFEM_LOG("EP", Sev::inform)
1318 << "Cohesive interface on: -cohesive_interface_on "
1319 << ((interfaceCrack == PETSC_TRUE) ? "yes" : "no");
1320 MOFEM_LOG("EP", Sev::inform)
1321 << "Cohesive interface remove level: -cohesive_interface_remove_level "
1323
1324#ifdef ENABLE_PYTHON_BINDING
1325 auto file_exists = [](std::string myfile) {
1326 std::ifstream file(myfile.c_str());
1327 if (file) {
1328 return true;
1329 }
1330 return false;
1331 };
1332
1333 if (file_exists(analytical_expr_file_name)) {
1334 MOFEM_LOG("EP", Sev::inform) << analytical_expr_file_name << " file found";
1335
1336 AnalyticalExprPythonPtr = boost::make_shared<AnalyticalExprPython>();
1337 CHKERR AnalyticalExprPythonPtr->analyticalExprInit(
1338 analytical_expr_file_name);
1339 AnalyticalExprPythonWeakPtr = AnalyticalExprPythonPtr;
1340 } else {
1341 MOFEM_LOG("EP", Sev::warning)
1342 << analytical_expr_file_name << " file NOT found";
1343 }
1344#endif
1345
1346 if (spaceH1Order == -1)
1348
1350}
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
static const char *const ApproximationBaseNames[]
Definition definitions.h:72
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
static PetscBool physicalH1Update
static enum StretchSelector stretchSelector
static int interfaceRemoveLevel
static double inv_f_linear(const double v)
static double dd_f_log(const double v)
static boost::function< double(const double)> inv_dd_f
static double inv_d_f_log(const double v)
static enum SolverType solverType
static PetscBool l2UserBaseScale
static const char * listSolvers[]
static PetscBool crackingOn
static double dd_f_log_e(const double v)
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static double physicalDt
static std::vector< std::string > listTagsToProject
static std::string heterogeneousYoungModTagName
static int physicalMaxSteps
static double d_f_log(const double v)
static double crackingStartTime
static PetscBool physicalTimeFlg
static double inv_f_log(const double v)
static double crackingAddTime
static double dd_f_linear(const double v)
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
static double inv_d_f_linear(const double v)
static PetscBool meshTransferHybridInterp
static double inv_dd_f_log(const double v)
static std::string internalStressTagName
static double finalPhysicalTime
static PetscBool internalStressVoigt
static double inv_dd_f_linear(const double v)
static PetscBool setSingularity
static double d_f_log_e(const double v)
static PetscBool meshTransferSourceMeshFileSpecified
static PetscBool interfaceCrack
static boost::function< double(const double)> dd_f
static double f_log_e(const double v)
static boost::function< double(const double)> d_f
static boost::function< double(const double)> inv_d_f
static double d_f_linear(const double v)
static int meshTransferInterpOrder
static double f_log(const double v)
static std::string meshTransferSourceMeshFileName
static boost::function< double(const double)> inv_f
static double f_linear(const double v)

◆ getSpatialDispBc()

MoFEMErrorCode EshelbianCore::getSpatialDispBc ( )

[Getting norms]

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 5350 of file EshelbianPlasticity.cpp.

5350 {
5352
5353 auto bc_mng = mField.getInterface<BcManager>();
5355 "", piolaStress, false, false);
5356
5357 bcSpatialDispVecPtr = boost::make_shared<BcDispVec>();
5358 for (auto bc : bc_mng->getBcMapByBlockName()) {
5359 if (auto disp_bc = bc.second->dispBcPtr) {
5360
5361 auto [field_name, block_name] =
5363 MOFEM_LOG("EP", Sev::inform)
5364 << "Field name: " << field_name << " Block name: " << block_name;
5365 MOFEM_LOG("EP", Sev::noisy) << "Displacement BC: " << *disp_bc;
5366
5367 std::vector<double> block_attributes(6, 0.);
5368 if (disp_bc->data.flag1 == 1) {
5369 block_attributes[0] = disp_bc->data.value1;
5370 block_attributes[3] = 1;
5371 }
5372 if (disp_bc->data.flag2 == 1) {
5373 block_attributes[1] = disp_bc->data.value2;
5374 block_attributes[4] = 1;
5375 }
5376 if (disp_bc->data.flag3 == 1) {
5377 block_attributes[2] = disp_bc->data.value3;
5378 block_attributes[5] = 1;
5379 }
5380 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5381 bcSpatialDispVecPtr->emplace_back(block_name, block_attributes, faces);
5382 }
5383 }
5384 // old way of naming blocksets for displacement BCs
5385 CHKERR getBc(bcSpatialDispVecPtr, "SPATIAL_DISP_BC", 6);
5386
5388 boost::make_shared<NormalDisplacementBcVec>();
5389 for (auto bc : bc_mng->getBcMapByBlockName()) {
5390 auto block_name = "(.*)NORMAL_DISPLACEMENT(.*)";
5391 std::regex reg_name(block_name);
5392 if (std::regex_match(bc.first, reg_name)) {
5393 auto [field_name, block_name] =
5395 MOFEM_LOG("EP", Sev::inform)
5396 << "Field name: " << field_name << " Block name: " << block_name;
5398 block_name, bc.second->bcAttributes,
5399 bc.second->bcEnts.subset_by_dimension(2));
5400 }
5401 }
5402
5404 boost::make_shared<AnalyticalDisplacementBcVec>();
5405
5406 for (auto bc : bc_mng->getBcMapByBlockName()) {
5407 auto block_name = "(.*)ANALYTICAL_DISPLACEMENT(.*)";
5408 std::regex reg_name(block_name);
5409 if (std::regex_match(bc.first, reg_name)) {
5410 auto [field_name, block_name] =
5412 MOFEM_LOG("EP", Sev::inform)
5413 << "Field name: " << field_name << " Block name: " << block_name;
5415 block_name, bc.second->bcAttributes,
5416 bc.second->bcEnts.subset_by_dimension(2));
5417 }
5418 }
5419
5420 auto ts_displacement =
5421 boost::make_shared<DynamicRelaxationTimeScale>("disp_history.txt");
5422 for (auto &bc : *bcSpatialDispVecPtr) {
5423 MOFEM_LOG("EP", Sev::noisy)
5424 << "Add time scaling displacement BC: " << bc.blockName;
5425 timeScaleMap[bc.blockName] =
5427 ts_displacement, "disp_history", ".txt", bc.blockName);
5428 }
5429
5430 auto ts_normal_displacement =
5431 boost::make_shared<DynamicRelaxationTimeScale>("normal_disp_history.txt");
5432 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
5433 MOFEM_LOG("EP", Sev::noisy)
5434 << "Add time scaling normal displacement BC: " << bc.blockName;
5435 timeScaleMap[bc.blockName] =
5437 ts_normal_displacement, "normal_disp_history", ".txt",
5438 bc.blockName);
5439 }
5440
5442}
MoFEMErrorCode pushMarkDOFsOnEntities(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)
Mark DOFs on block entities for boundary conditions.
MoFEMErrorCode getBc(boost::shared_ptr< BC > &bc_vec_ptr, const std::string block_name, const int nb_attributes)
static std::pair< std::string, std::string > extractStringFromBlockId(const std::string block_id, const std::string prb_name)
Extract block name and block name from block id.
Definition of the displacement bc data structure.
Definition BCData.hpp:72

◆ getSpatialRotationBc()

MoFEMErrorCode EshelbianCore::getSpatialRotationBc ( )
inline
Examples
ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 359 of file EshelbianCore.hpp.

359 {
361 bcSpatialRotationVecPtr = boost::make_shared<BcRotVec>();
362 CHKERR getBc(bcSpatialRotationVecPtr, "SPATIAL_ROTATION_BC", 4);
363 CHKERR getBc(bcSpatialRotationVecPtr, "SPATIAL_ROTATION_AXIS_BC", 7);
364
365 for (auto &bc : *bcSpatialRotationVecPtr) {
366 MOFEM_LOG("EP", Sev::inform)
367 << "Found spatial rotation BC on block " << bc.blockName;
368 MOFEM_LOG("EP", Sev::inform) << " with attributes: " << bc.vals;
369 MOFEM_LOG("EP", Sev::inform) << " and rotation angle: " << bc.theta;
370 MOFEM_LOG("EP", Sev::inform) << " and nb of faces: " << bc.faces.size();
371 }
372
373 auto ts_rotation =
374 boost::make_shared<DynamicRelaxationTimeScale>("rotation_history.txt");
375 for (auto &bc : *bcSpatialRotationVecPtr) {
376 timeScaleMap[bc.blockName] =
377 GetBlockScalingMethod<DynamicRelaxationTimeScale>::get(
378 ts_rotation, "rotation_history", ".txt", bc.blockName);
379 }
380
382 }

◆ getSpatialTractionBc()

MoFEMErrorCode EshelbianCore::getSpatialTractionBc ( )
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 5444 of file EshelbianPlasticity.cpp.

5444 {
5446
5447 auto bc_mng = mField.getInterface<BcManager>();
5449 false, false);
5450
5451 bcSpatialTractionVecPtr = boost::make_shared<TractionBcVec>();
5452
5453 for (auto bc : bc_mng->getBcMapByBlockName()) {
5454 if (auto force_bc = bc.second->forceBcPtr) {
5455
5456 auto [field_name, block_name] =
5458 MOFEM_LOG("EP", Sev::inform)
5459 << "Field name: " << field_name << " Block name: " << block_name;
5460 MOFEM_LOG("EP", Sev::noisy) << "Force BC: " << *force_bc;
5461
5462 std::vector<double> block_attributes(6, 0.);
5463 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
5464 block_attributes[3] = 1;
5465 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
5466 block_attributes[4] = 1;
5467 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
5468 block_attributes[5] = 1;
5469 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5470 bcSpatialTractionVecPtr->emplace_back(block_name, block_attributes,
5471 faces);
5472 }
5473 }
5474 CHKERR getBc(bcSpatialTractionVecPtr, "SPATIAL_TRACTION_BC", 6);
5475
5476 bcSpatialPressureVecPtr = boost::make_shared<PressureBcVec>();
5477 for (auto bc : bc_mng->getBcMapByBlockName()) {
5478 auto block_name = "(.*)PRESSURE(.*)";
5479 std::regex reg_name(block_name);
5480 if (std::regex_match(bc.first, reg_name)) {
5481
5482 auto [field_name, block_name] =
5484 MOFEM_LOG("EP", Sev::inform)
5485 << "Field name: " << field_name << " Block name: " << block_name;
5486 bcSpatialPressureVecPtr->emplace_back(
5487 block_name, bc.second->bcAttributes,
5488 bc.second->bcEnts.subset_by_dimension(2));
5489 }
5490 }
5491
5493 boost::make_shared<AnalyticalTractionBcVec>();
5494
5495 for (auto bc : bc_mng->getBcMapByBlockName()) {
5496 auto block_name = "(.*)ANALYTICAL_TRACTION(.*)";
5497 std::regex reg_name(block_name);
5498 if (std::regex_match(bc.first, reg_name)) {
5499 auto [field_name, block_name] =
5501 MOFEM_LOG("EP", Sev::inform)
5502 << "Field name: " << field_name << " Block name: " << block_name;
5504 block_name, bc.second->bcAttributes,
5505 bc.second->bcEnts.subset_by_dimension(2));
5506 }
5507 }
5508
5509 auto ts_traction =
5510 boost::make_shared<DynamicRelaxationTimeScale>("traction_history.txt");
5511 for (auto &bc : *bcSpatialTractionVecPtr) {
5512 timeScaleMap[bc.blockName] =
5514 ts_traction, "traction_history", ".txt", bc.blockName);
5515 }
5516
5517 auto ts_pressure =
5518 boost::make_shared<DynamicRelaxationTimeScale>("pressure_history.txt");
5519 for (auto &bc : *bcSpatialPressureVecPtr) {
5520 timeScaleMap[bc.blockName] =
5522 ts_pressure, "pressure_history", ".txt", bc.blockName);
5523 }
5524
5526}
Definition of the force bc data structure.
Definition BCData.hpp:135

◆ getSpatialTractionFreeBc()

MoFEMErrorCode EshelbianCore::getSpatialTractionFreeBc ( const EntityHandle  meshset = 0)
inline
Examples
ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 401 of file EshelbianCore.hpp.

401 {
403 boost::shared_ptr<TractionFreeBc>(new TractionFreeBc());
404 return getTractionFreeBc(meshset, bcSpatialFreeTractionVecPtr, "CONTACT");
405 }
std::vector< Range > TractionFreeBc
MoFEMErrorCode getTractionFreeBc(const EntityHandle meshset, boost::shared_ptr< TractionFreeBc > &bc_ptr, const std::string contact_set_name)
Remove all, but entities where kinematic constrains are applied.

◆ gettingNorms()

MoFEMErrorCode EshelbianCore::gettingNorms ( )

[Getting norms]

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 5283 of file EshelbianPlasticity.cpp.

5283 {
5285
5286 auto post_proc_norm_fe =
5287 boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
5288
5289 auto bubble_cache =
5290 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
5291 post_proc_norm_fe->getUserPolynomialBase() =
5292 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase(bubble_cache));
5293 post_proc_norm_fe->getRuleHook = [](int, int, int) { return -1; };
5294 post_proc_norm_fe->setRuleHook = SetIntegrationAtFrontVolume(
5295 frontVertices, frontAdjEdges, vol_rule, bubble_cache);
5296 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5297 post_proc_norm_fe->getOpPtrVector(), {L2, H1, HDIV}, materialH1Positions,
5299
5300 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
5301 auto norms_vec =
5302 createVectorMPI(mField.get_comm(), LAST_NORM, PETSC_DETERMINE);
5303 CHKERR VecZeroEntries(norms_vec);
5304
5305 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
5306 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5307 post_proc_norm_fe->getOpPtrVector().push_back(
5309 post_proc_norm_fe->getOpPtrVector().push_back(
5311 post_proc_norm_fe->getOpPtrVector().push_back(
5312 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_NORM_L2));
5313 post_proc_norm_fe->getOpPtrVector().push_back(
5314 new OpCalcNormL2Tensor1<SPACE_DIM>(u_h1_ptr, norms_vec, U_NORM_H1));
5315 post_proc_norm_fe->getOpPtrVector().push_back(
5316 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_ERROR_L2,
5317 u_h1_ptr));
5318
5319 auto piola_ptr = boost::make_shared<MatrixDouble>();
5320 post_proc_norm_fe->getOpPtrVector().push_back(
5322 post_proc_norm_fe->getOpPtrVector().push_back(
5324 MBMAXTYPE));
5325
5326 post_proc_norm_fe->getOpPtrVector().push_back(
5327 new OpCalcNormL2Tensor2<3, 3>(piola_ptr, norms_vec, PIOLA_NORM));
5328
5329 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
5331 *post_proc_norm_fe);
5332 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
5333
5334 CHKERR VecAssemblyBegin(norms_vec);
5335 CHKERR VecAssemblyEnd(norms_vec);
5336 const double *norms;
5337 CHKERR VecGetArrayRead(norms_vec, &norms);
5338 MOFEM_LOG("EP", Sev::inform) << "norm_u: " << std::sqrt(norms[U_NORM_L2]);
5339 MOFEM_LOG("EP", Sev::inform) << "norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
5340 MOFEM_LOG("EP", Sev::inform)
5341 << "norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
5342 MOFEM_LOG("EP", Sev::inform)
5343 << "norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
5344 CHKERR VecRestoreArrayRead(norms_vec, &norms);
5345
5347}
virtual MoFEMErrorCode loop_finite_elements(const std::string problem_name, const std::string &fe_name, FEMethod &method, boost::shared_ptr< NumeredEntFiniteElement_multiIndex > fe_ptr=nullptr, MoFEMTypes bh=MF_EXIST, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr(), int verb=DEFAULT_VERBOSITY)=0
Make a loop over finite elements.
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
CGG User Polynomial Base.
Get norm of input MatrixDouble for Tensor1.
Get norm of input MatrixDouble for Tensor2.
Calculate tenor field using tensor base, i.e. Hdiv/Hcurl.
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
Specialization for MatrixDouble vector field values calculation.

◆ getTractionFreeBc()

MoFEMErrorCode EshelbianCore::getTractionFreeBc ( const EntityHandle  meshset,
boost::shared_ptr< TractionFreeBc > &  bc_ptr,
const std::string  contact_set_name 
)

Remove all, but entities where kinematic constrains are applied.

Parameters
meshset
bc_ptr
disp_block_set_name
rot_block_set_name
contact_set_name
Returns
MoFEMErrorCode
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 2840 of file EshelbianPlasticity.cpp.

2842 {
2844
2845 // get skin from all tets
2846 Range tets;
2847 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
2848 Range tets_skin_part;
2849 Skinner skin(&mField.get_moab());
2850 CHKERR skin.find_skin(0, tets, false, tets_skin_part);
2851 ParallelComm *pcomm =
2852 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2853 Range tets_skin;
2854 CHKERR pcomm->filter_pstatus(tets_skin_part,
2855 PSTATUS_SHARED | PSTATUS_MULTISHARED,
2856 PSTATUS_NOT, -1, &tets_skin);
2857
2858 bc_ptr->resize(3);
2859 for (int dd = 0; dd != 3; ++dd)
2860 (*bc_ptr)[dd] = tets_skin;
2861
2862 // Do not remove dofs on which traction is applied
2864 for (auto &v : *bcSpatialDispVecPtr) {
2865 if (v.flags[0])
2866 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2867 if (v.flags[1])
2868 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2869 if (v.flags[2])
2870 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2871 }
2872
2873 // Do not remove dofs on which rotation is applied
2875 for (auto &v : *bcSpatialRotationVecPtr) {
2876 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2877 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2878 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2879 }
2880
2882 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2883 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2884 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2885 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2886 }
2887
2890 if (v.flags[0])
2891 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2892 if (v.flags[1])
2893 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2894 if (v.flags[2])
2895 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2896 }
2897
2899 for (auto &v : *bcSpatialTractionVecPtr) {
2900 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2901 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2902 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2903 }
2904
2906 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2907 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2908 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2909 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2910 }
2911
2913 for (auto &v : *bcSpatialPressureVecPtr) {
2914 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
2915 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
2916 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
2917 }
2918
2919 // remove contact
2920 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
2921 std::regex((boost::format("%s(.*)") % contact_set_name).str()))) {
2922 Range faces;
2923 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
2924 true);
2925 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
2926 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
2927 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
2928 }
2929
2931}
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition ddTensor0.hpp:33

◆ inv_d_f_linear()

static double EshelbianCore::inv_d_f_linear ( const double  v)
inlinestatic

◆ inv_d_f_log()

static double EshelbianCore::inv_d_f_log ( const double  v)
inlinestatic

◆ inv_d_f_log_e()

static double EshelbianCore::inv_d_f_log_e ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 205 of file EshelbianCore.hpp.

205 {
206 if (v > std::exp(v_min))
207 return 1. / v;
208 else
209 return 1. / exp(v_min);
210 }
static constexpr double v_min

◆ inv_dd_f_linear()

static double EshelbianCore::inv_dd_f_linear ( const double  v)
inlinestatic

◆ inv_dd_f_log()

static double EshelbianCore::inv_dd_f_log ( const double  v)
inlinestatic

◆ inv_dd_f_log_e()

static double EshelbianCore::inv_dd_f_log_e ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 211 of file EshelbianCore.hpp.

211 {
212 if (v > std::exp(v_min))
213 return -1. / (v * v);
214 else
215 return 0.;
216 }

◆ inv_f_linear()

static double EshelbianCore::inv_f_linear ( const double  v)
inlinestatic

◆ inv_f_log()

static double EshelbianCore::inv_f_log ( const double  v)
inlinestatic

◆ inv_f_log_e()

static double EshelbianCore::inv_f_log_e ( const double  v)
inlinestatic
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 196 of file EshelbianCore.hpp.

196 {
197 if (v > std::exp(v_min))
198 return std::log(v);
199 else
200 // y = exp(v_min) * v + exp(v_min) * (1 - v_min);
201 // y/exp(v_min) = v + (1 - v_min);
202 // y/exp(v_min) - (1 - v_min) = v;
203 return v / exp(v_min) - (1 - v_min);
204 }

◆ postProcessRestartMesh()

MoFEMErrorCode EshelbianCore::postProcessRestartMesh ( const int  tag,
const std::string  file,
std::vector< Tag tags_to_transfer = {} 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 4508 of file EshelbianPlasticity.cpp.

4509 {
4511 ParallelComm *pcomm =
4512 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
4513 // write file with only crack surfaces and full mesh
4514 if (crackingOn && !pcomm->rank()) {
4515 auto meshsets_mng = mField.getInterface<MeshsetsManager>();
4516
4517 std::vector<boost::shared_ptr<TempMeshset>> meshsets_tmp_list;
4518 auto &list = meshsets_mng->getMeshsetsMultindex();
4519 std::vector<Tag> tags_list;
4520
4521 auto meshset_ptr = get_temp_meshset_ptr(mField.get_moab());
4522
4523 for (auto &m : list) {
4524 meshsets_tmp_list.push_back(get_temp_meshset_ptr(mField.get_moab()));
4525 EntityHandle new_meshset = *meshsets_tmp_list.back();
4526 auto meshset = m.getMeshset();
4527 std::vector<Tag> tmp_tags_list;
4528 CHKERR mField.get_moab().tag_get_tags_on_entity(meshset, tmp_tags_list);
4529 Range ents;
4530 CHKERR mField.get_moab().get_entities_by_handle(meshset, ents, true);
4531 CHKERR mField.get_moab().add_entities(new_meshset, ents);
4532 for (auto t : tmp_tags_list) {
4533 void *tag_vals[1];
4534 int tag_size[1];
4535 CHKERR mField.get_moab().tag_get_by_ptr(
4536 t, &meshset, 1, (const void **)tag_vals, tag_size);
4537 CHKERR mField.get_moab().tag_set_by_ptr(t, &new_meshset, 1, tag_vals,
4538 tag_size);
4539 }
4540 std::vector<std::string> remove_tags;
4541 remove_tags.push_back("AKDTree_coord_norm");
4542 remove_tags.push_back("__PARALLEL_");
4543 remove_tags.push_back("_RefBitLevel");
4544
4545 for (auto t : tmp_tags_list) {
4546 std::string tag_name;
4547 CHKERR mField.get_moab().tag_get_name(t, tag_name);
4548 bool add = true;
4549
4550 for (auto &p : remove_tags) {
4551 if (tag_name.compare(0, p.size(), p) == 0) {
4552 add = false;
4553 break;
4554 }
4555 }
4556
4557 if (add)
4558 tags_list.push_back(t);
4559 }
4560 }
4561
4562 for (auto &m_ptr : meshsets_tmp_list) {
4563 EntityHandle m = *m_ptr;
4564 CHKERR mField.get_moab().add_entities(*meshset_ptr, &m, 1);
4565 }
4566
4567 // meshsets_tmp_list has all meshsets to write
4568 std::sort(tags_list.begin(), tags_list.end());
4569 auto new_end = std::unique(tags_list.begin(), tags_list.end());
4570 tags_list.resize(std::distance(tags_list.begin(), new_end));
4571
4572 EntityHandle save_meshset = *meshset_ptr;
4573 CHKERR mField.get_moab().write_file(file.c_str(), "MOAB", "", &save_meshset,
4574 1, &tags_list[0], tags_list.size());
4575 }
4577}
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
CubitMeshSet_multiIndex & getMeshsetsMultindex()

◆ postProcessResults()

MoFEMErrorCode EshelbianCore::postProcessResults ( const int  tag,
const std::string  file,
Vec  f_residual = PETSC_NULLPTR,
Vec  var_vec = PETSC_NULLPTR,
Vec  gradient = PETSC_NULLPTR,
std::vector< Tag tags_to_transfer = {},
TS  ts = PETSC_NULLPTR 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 4580 of file EshelbianPlasticity.cpp.

4582 {
4584
4585 SmartPetscObj<Vec> f_r, v_v;
4586 if (f_residual != PETSC_NULLPTR || var_vector != PETSC_NULLPTR) {
4588 SmartPetscObj<Vec> xout;
4589 xout = createDMVector(dM);
4590 auto xin = f_residual != PETSC_NULLPTR ? f_residual : var_vector;
4591 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4592 xin, "ELASTIC_PROBLEM", RowColData::ROW, xout, "ESHELBY_PLASTICITY",
4593 RowColData::ROW, scatter);
4594 if (f_residual) {
4595 f_r = vectorDuplicate(xout);
4596 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
4597 SCATTER_FORWARD);
4598 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
4599 SCATTER_FORWARD);
4600 CHKERR VecGhostUpdateBegin(f_r, INSERT_VALUES, SCATTER_FORWARD);
4601 CHKERR VecGhostUpdateEnd(f_r, INSERT_VALUES, SCATTER_FORWARD);
4602 }
4603 if (var_vector) {
4604 v_v = createDMVector(dM);
4605 CHKERR VecScatterBegin(scatter, var_vector, v_v, INSERT_VALUES,
4606 SCATTER_FORWARD);
4607 CHKERR VecScatterEnd(scatter, var_vector, v_v, INSERT_VALUES,
4608 SCATTER_FORWARD);
4609 CHKERR VecGhostUpdateBegin(v_v, INSERT_VALUES, SCATTER_FORWARD);
4610 CHKERR VecGhostUpdateEnd(v_v, INSERT_VALUES, SCATTER_FORWARD);
4611 }
4612 }
4613
4615 if (gradient) {
4617 g = createDMVector(dM);
4618 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4619 gradient, "MATERIAL_PROBLEM", RowColData::ROW, g, "ESHELBY_PLASTICITY",
4620 RowColData::ROW, scatter);
4621 CHKERR VecScatterBegin(scatter, gradient, g, INSERT_VALUES,
4622 SCATTER_FORWARD);
4623 CHKERR VecScatterEnd(scatter, gradient, g, INSERT_VALUES, SCATTER_FORWARD);
4624 CHKERR VecGhostUpdateBegin(g, INSERT_VALUES, SCATTER_FORWARD);
4625 CHKERR VecGhostUpdateEnd(g, INSERT_VALUES, SCATTER_FORWARD);
4626 }
4627
4628 // mark crack surface
4629 if (crackingOn) {
4630 auto get_tag = [&](auto name, auto dim) {
4631 auto &mob = mField.get_moab();
4632 Tag tag;
4633 double def_val[] = {0., 0., 0.};
4634 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4635 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4636 "create tag");
4637 return tag;
4638 };
4639 tags_to_transfer.push_back(get_tag("MaterialForce", 3));
4640 }
4641
4642 {
4643 auto get_crack_tag = [&]() {
4644 Tag th;
4645 rval = mField.get_moab().tag_get_handle("CRACK", th);
4646 if (rval == MB_SUCCESS) {
4647 MOAB_THROW(mField.get_moab().tag_delete(th));
4648 }
4649 int def_val[] = {0};
4650 MOAB_THROW(mField.get_moab().tag_get_handle(
4651 "CRACK", 1, MB_TYPE_INTEGER, th, MB_TAG_SPARSE | MB_TAG_CREAT,
4652 def_val));
4653 return th;
4654 };
4655
4656 Tag th = get_crack_tag();
4657 tags_to_transfer.push_back(th);
4658 int mark[] = {1};
4659 Range mark_faces;
4660 if (crackFaces)
4661 mark_faces.merge(*crackFaces);
4662 if (interfaceFaces)
4663 mark_faces.merge(*interfaceFaces);
4664 CHKERR mField.get_moab().tag_clear_data(th, mark_faces, mark);
4665 }
4666
4667 // add tags to transfer
4668 for (auto t : listTagsToTransfer) {
4669 std::string name;
4670 CHKERR mField.get_moab().tag_get_name(t, name);
4671 MOFEM_LOG("EP", Sev::verbose)
4672 << "Adding tag " << name << " to transfer list for post-processing";
4673 tags_to_transfer.push_back(t);
4674 }
4675
4676 if (!dataAtPts) {
4677 dataAtPts =
4678 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
4679 }
4680
4682
4683 auto get_post_proc = [&](auto &post_proc_mesh, auto sense) {
4685 auto post_proc_ptr =
4686 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
4687 mField, post_proc_mesh);
4688 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4689 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
4691
4692 if (ts != PETSC_NULLPTR) {
4693 post_proc_ptr->data_ctx |= PetscData::CTX_SET_TIME;
4694 CHKERR TSGetTime(ts, &(post_proc_ptr->ts_t));
4695 CHKERR TSGetTimeStep(ts, &(post_proc_ptr->ts_dt));
4696 }
4697
4698 auto domain_ops = [&](auto &fe, int sense) {
4700
4701 auto bubble_cache = boost::make_shared<CGGUserPolynomialBase::CachePhi>(
4702 0, 0, MatrixDouble());
4703 fe.getUserPolynomialBase() = boost::shared_ptr<BaseFunction>(
4704 new CGGUserPolynomialBase(bubble_cache));
4705 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4706 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
4708 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4709 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4710 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
4711 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4712 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
4713 SmartPetscObj<Vec>(), MBMAXTYPE));
4714 if (stretchHandling == NO_STREACH) {
4715 fe.getOpPtrVector().push_back(
4716 physicalEquations->returnOpCalculateStretchFromStress(
4718 } else {
4719 fe.getOpPtrVector().push_back(
4721 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
4722 }
4723 if (var_vector) {
4724 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4725 piolaStress, dataAtPts->getVarPiolaPts(),
4726 boost::make_shared<double>(1), v_v));
4727 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4728 bubbleField, dataAtPts->getVarPiolaPts(),
4729 boost::make_shared<double>(1), v_v, MBMAXTYPE));
4730 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4731 rotAxis, dataAtPts->getVarRotAxisPts(), v_v, MBTET));
4732 if (stretchHandling == NO_STREACH) {
4733 fe.getOpPtrVector().push_back(
4734 physicalEquations->returnOpCalculateVarStretchFromStress(
4736 } else {
4737 fe.getOpPtrVector().push_back(
4739 stretchTensor, dataAtPts->getVarLogStreachPts(), v_v, MBTET));
4740 }
4741 }
4742 if (gradient) {
4743 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4744 materialH1Positions, dataAtPts->getGradientAtPts(), g));
4745 }
4746
4747 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4748 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
4749 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4750 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
4751
4752 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4753 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
4754 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4755 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
4756 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
4757 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
4758 // evaluate derived quantities
4759 fe.getOpPtrVector().push_back(
4761
4762 // evaluate integration points
4763 fe.getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
4764 true, false, dataAtPts, physicalEquations));
4765 if (auto op =
4766 physicalEquations->returnOpCalculateEnergy(dataAtPts, nullptr)) {
4767 fe.getOpPtrVector().push_back(op);
4768 fe.getOpPtrVector().push_back(new OpCalculateEshelbyStress(dataAtPts));
4769 }
4770
4771 // // post-proc
4774 VolumeElementForcesAndSourcesCoreOnSide::UserDataOperator>;
4775
4776 struct OpSidePPMap : public OpPPMap {
4777 OpSidePPMap(moab::Interface &post_proc_mesh,
4778 std::vector<EntityHandle> &map_gauss_pts,
4779 DataMapVec data_map_scalar, DataMapMat data_map_vec,
4780 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
4781 int sense)
4782 : OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
4783 data_map_vec, data_map_mat, data_symm_map_mat),
4784 tagSense(sense) {}
4785
4786 MoFEMErrorCode doWork(int side, EntityType type,
4789
4790 if (tagSense != 0) {
4791 if (tagSense != OpPPMap::getSkeletonSense())
4793 }
4794
4795 CHKERR OpPPMap::doWork(side, type, data);
4797 }
4798
4799 private:
4800 int tagSense;
4801 };
4802
4803 OpPPMap::DataMapMat vec_fields;
4804 vec_fields["SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
4805 vec_fields["SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
4806 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
4807 vec_fields["AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
4808 vec_fields["X"] = dataAtPts->getLargeXH1AtPts();
4809 if (stretchHandling != NO_STREACH) {
4810 vec_fields["EiegnLogStreach"] = dataAtPts->getEigenVals();
4811 }
4812 if (var_vector) {
4813 vec_fields["VarOmega"] = dataAtPts->getVarRotAxisPts();
4814 vec_fields["VarSpatialDisplacementL2"] =
4815 boost::make_shared<MatrixDouble>();
4816 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4817 spatialL2Disp, vec_fields["VarSpatialDisplacementL2"], v_v, MBTET));
4818 }
4819 if (f_residual) {
4820 vec_fields["ResSpatialDisplacementL2"] =
4821 boost::make_shared<MatrixDouble>();
4822 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4823 spatialL2Disp, vec_fields["ResSpatialDisplacementL2"], f_r, MBTET));
4824 vec_fields["ResOmega"] = boost::make_shared<MatrixDouble>();
4825 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
4826 rotAxis, vec_fields["ResOmega"], f_r, MBTET));
4827 }
4828 if (gradient) {
4829 vec_fields["Gradient"] = dataAtPts->getGradientAtPts();
4830 }
4831
4832 OpPPMap::DataMapMat mat_fields;
4833 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
4834 if (var_vector) {
4835 mat_fields["VarPiolaStress"] = dataAtPts->getVarPiolaPts();
4836 }
4837 if (f_residual) {
4838 mat_fields["ResPiolaStress"] = boost::make_shared<MatrixDouble>();
4839 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
4840 piolaStress, mat_fields["ResPiolaStress"],
4841 boost::make_shared<double>(1), f_r));
4842 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
4843 bubbleField, mat_fields["ResPiolaStress"],
4844 boost::make_shared<double>(1), f_r, MBMAXTYPE));
4845 }
4846 if (!internalStressTagName.empty()) {
4847 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
4848 switch (meshTransferInterpOrder) {
4849 case 0:
4850 fe.getOpPtrVector().push_back(
4852 break;
4853 case 1:
4854 fe.getOpPtrVector().push_back(
4856 break;
4857 default:
4858 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
4859 "Unsupported mesh transfer interpolation order %d, for "
4860 "internal stress",
4862 }
4863 }
4864
4865 OpPPMap::DataMapMat mat_fields_symm;
4866 mat_fields_symm["LogSpatialStretch"] =
4867 dataAtPts->getLogStretchTensorAtPts();
4868 mat_fields_symm["SpatialStretch"] = dataAtPts->getStretchTensorAtPts();
4869 if (var_vector) {
4870 mat_fields_symm["VarLogSpatialStretch"] =
4871 dataAtPts->getVarLogStreachPts();
4872 }
4873 if (f_residual) {
4874 if (stretchHandling != NO_STREACH) {
4875 mat_fields_symm["ResLogSpatialStretch"] =
4876 boost::make_shared<MatrixDouble>();
4877 fe.getOpPtrVector().push_back(
4879 stretchTensor, mat_fields_symm["ResLogSpatialStretch"], f_r,
4880 MBTET));
4881 }
4882 }
4883
4884 fe.getOpPtrVector().push_back(
4885
4886 new OpSidePPMap(
4887
4888 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4889
4890 {},
4891
4892 vec_fields,
4893
4894 mat_fields,
4895
4896 mat_fields_symm,
4897
4898 sense
4899
4900 )
4901
4902 );
4903
4904 fe.getOpPtrVector().push_back(new OpPostProcDataStructure(
4905 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4906 dataAtPts, sense));
4907
4909 };
4910
4911 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
4912 // H1 material positions
4913 post_proc_ptr->getOpPtrVector().push_back(
4915 dataAtPts->getLargeXH1AtPts()));
4916
4917 // domain
4920 domain_ops(*(op_loop_side->getSideFEPtr()), sense);
4921 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
4922
4923 return post_proc_ptr;
4924 };
4925
4926 // contact
4927 auto calcs_side_traction_and_displacements = [&](auto &post_proc_ptr,
4928 auto &pip) {
4930 // evaluate traction
4931 using EleOnSide =
4933 using SideEleOp = EleOnSide::UserDataOperator;
4934 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
4935 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4936 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4937 boost::shared_ptr<BaseFunction>(
4938 new CGGUserPolynomialBase(nullptr, true));
4939 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4940 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4942 auto traction_ptr = boost::make_shared<MatrixDouble>();
4943 op_loop_domain_side->getOpPtrVector().push_back(
4945 piolaStress, traction_ptr, boost::make_shared<double>(1.0)));
4946
4947 pip.push_back(new OpCalculateVectorFieldValues<3>(
4948 contactDisp, dataAtPts->getContactL2AtPts()));
4949 pip.push_back(op_loop_domain_side);
4950 // evaluate contact displacement and contact conditions
4951 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
4952 pip.push_back(new OpCalculateVectorFieldValues<3>(spatialH1Disp, u_h1_ptr));
4953 pip.push_back(getOpContactDetection(
4954 *this, contactTreeRhs, u_h1_ptr, traction_ptr,
4955 get_range_from_block(mField, "CONTACT", SPACE_DIM - 1),
4956 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
4957
4959 using BoundaryEle =
4961 auto op_this = new OpLoopThis<BoundaryEle>(mField, contactElement);
4962 pip.push_back(op_this);
4963
4964 op_this->getOpPtrVector().push_back(
4965
4966 new OpPPMap(
4967
4968 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4969
4970 {},
4971
4972 {{"ContactDisplacement", dataAtPts->getContactL2AtPts()}},
4973
4974 {},
4975
4976 {}
4977
4978 )
4979
4980 );
4981
4982 if (f_residual) {
4983
4984 auto contact_residual = boost::make_shared<MatrixDouble>();
4985 op_this->getOpPtrVector().push_back(
4987 contactDisp, contact_residual, f_r, MBTET));
4988 op_this->getOpPtrVector().push_back(
4989
4990 new OpPPMap(
4991
4992 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
4993
4994 {},
4995
4996 {{"res_contact", contact_residual}},
4997
4998 {},
4999
5000 {}
5001
5002 )
5003
5004 );
5005 }
5006
5008 };
5009
5010 auto post_proc_mesh = boost::make_shared<moab::Core>();
5011 auto post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5012 auto post_proc_negative_sense_ptr =
5013 get_post_proc(post_proc_mesh, /*negative sense*/ -1);
5014 auto skin_post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5015 CHKERR calcs_side_traction_and_displacements(
5016 skin_post_proc_ptr, skin_post_proc_ptr->getOpPtrVector());
5017
5018 auto own_tets =
5020 .subset_by_dimension(SPACE_DIM);
5021 Range own_faces;
5022 CHKERR mField.get_moab().get_adjacencies(own_tets, SPACE_DIM - 1, true,
5023 own_faces, moab::Interface::UNION);
5024
5025 auto get_crack_faces = [&](auto crack_faces) {
5026 auto get_adj = [&](auto e, auto dim) {
5027 Range adj;
5028 CHKERR mField.get_moab().get_adjacencies(e, dim, true, adj,
5029 moab::Interface::UNION);
5030 return adj;
5031 };
5032 // this removes faces
5033 auto tets = get_adj(crack_faces, 3);
5034 // faces adjacent to tets not in crack_faces
5035 auto faces = subtract(get_adj(tets, 2), crack_faces);
5036 // what is left from below, are tets fully inside crack_faces
5037 tets = subtract(tets, get_adj(faces, 3));
5038 return subtract(crack_faces, get_adj(tets, 2));
5039 };
5040
5041 auto side_one_faces = [&](auto &faces) {
5042 std::pair<Range, Range> sides;
5043 for (auto f : faces) {
5044 Range adj;
5045 MOAB_THROW(mField.get_moab().get_adjacencies(&f, 1, 3, false, adj));
5046 adj = intersect(own_tets, adj);
5047 for (auto t : adj) {
5048 int side, sense, offset;
5049 MOAB_THROW(mField.get_moab().side_number(t, f, side, sense, offset));
5050 if (sense == 1) {
5051 sides.first.insert(f);
5052 } else {
5053 sides.second.insert(f);
5054 }
5055 }
5056 }
5057 return sides;
5058 };
5059
5060 auto get_interface_from_block = [&](auto block_name) {
5061 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
5062 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
5063 Range faces;
5064 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
5065 faces, moab::Interface::UNION);
5066 faces = subtract(faces, skin);
5067 return faces;
5068 };
5069
5070 auto crack_faces = unite(get_crack_faces(*crackFaces), *interfaceFaces);
5071 // VOLUME_INTERFACE faces were already merged into interfaceFaces in
5072 // projectGeometry(), after applying REMOVE_INTERFACE exclusions.
5073 auto crack_side_faces = side_one_faces(crack_faces);
5074 auto side_one_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5075 auto ent = fe_method_ptr->getFEEntityHandle();
5076 if (crack_side_faces.first.find(ent) == crack_side_faces.first.end()) {
5077 return false;
5078 }
5079 return true;
5080 };
5081 auto side_minus_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5082 auto ent = fe_method_ptr->getFEEntityHandle();
5083 if (crack_side_faces.second.find(ent) == crack_side_faces.second.end()) {
5084 return false;
5085 }
5086 return true;
5087 };
5088
5089 skin_post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5090 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5091 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
5092
5093 auto post_proc_begin =
5095 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5096 CHKERR DMoFEMLoopFiniteElements(dM, skinElement, skin_post_proc_ptr);
5097 post_proc_ptr->exeTestHook = side_one_crack_faces;
5099 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5100 post_proc_negative_sense_ptr->exeTestHook = side_minus_crack_faces;
5102 post_proc_negative_sense_ptr, 0,
5104
5105 constexpr bool debug = false;
5106 if (debug) {
5107
5108 auto get_adj_front = [&]() {
5109 auto skeleton_faces = *skeletonFaces;
5110 Range adj_front;
5111 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2, true, adj_front,
5112 moab::Interface::UNION);
5113
5114 adj_front = intersect(adj_front, skeleton_faces);
5115 adj_front = subtract(adj_front, *crackFaces);
5116 adj_front = intersect(own_faces, adj_front);
5117 return adj_front;
5118 };
5119
5120 auto adj_front = filter_owners(mField, get_adj_front());
5121 auto only_front_faces = [adj_front](FEMethod *fe_method_ptr) {
5122 auto ent = fe_method_ptr->getFEEntityHandle();
5123 if (adj_front.find(ent) == adj_front.end()) {
5124 return false;
5125 }
5126 return true;
5127 };
5128
5129 post_proc_ptr->exeTestHook = only_front_faces;
5131 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5132 post_proc_negative_sense_ptr->exeTestHook = only_front_faces;
5134 post_proc_negative_sense_ptr, 0,
5136 }
5137 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5138 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5139
5140 CHKERR post_proc_end.writeFile(file.c_str());
5142}
static auto filter_owners(MoFEM::Interface &m_field, Range skin)
std::string type
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
#define MOAB_THROW(err)
Check error code of MoAB function and throw MoFEM exception.
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:546
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
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:536
ForcesAndSourcesCore::UserDataOperator * getOpContactDetection(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::shared_ptr< MatrixDouble > u_h1_ptr, boost::shared_ptr< MatrixDouble > contact_traction_ptr, Range r, moab::Interface *post_proc_mesh_ptr, std::vector< EntityHandle > *map_gauss_pts_ptr)
Push operator for contact detection.
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PostProcBrokenMeshInMoabBaseEndImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseEnd
Enable to run stack of post-processing elements. Use this to end stack.
PostProcBrokenMeshInMoabBaseBeginImpl< PostProcBrokenMeshInMoabBase< ForcesAndSourcesCore > > PostProcBrokenMeshInMoabBaseBegin
Enable to run stack of post-processing elements. Use this to begin stack.
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::FaceSideEle EleOnSide
std::vector< Tag > listTagsToTransfer
list of tags to transfer to postprocessor
boost::shared_ptr< Range > interfaceFaces
boost::shared_ptr< ForcesAndSourcesCore > contactTreeRhs
Make a contact tree.
static Range getPartEntities(moab::Interface &moab, int part)
Data on single entity (This is passed as argument to DataOperator::doWork)
Structure for user loop methods on finite elements.
Calculate trace of vector (Hdiv/Hcurl) space.
Calculate symmetric tensor field values at integration pts.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Element used to execute operators on side of the element.
Execute "this" element in the operator.
Post post-proc data at points from hash maps.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
@ CTX_SET_TIME
Time value is set.
Template struct for dimension-specific finite element types.
intrusive_ptr for managing petsc objects
Vector manager is used to create vectors \mofem_vectors.

◆ postProcessSkeletonResults()

MoFEMErrorCode EshelbianCore::postProcessSkeletonResults ( const int  tag,
const std::string  file,
Vec  f_residual = PETSC_NULLPTR,
std::vector< Tag tags_to_transfer = {} 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 5145 of file EshelbianPlasticity.cpp.

5147 {
5149
5151 if (f_residual != PETSC_NULLPTR) {
5153 f_r = createDMVector(dM);
5154 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
5155 f_residual, "ELASTIC_PROBLEM", RowColData::ROW, f_r,
5156 "ESHELBY_PLASTICITY", RowColData::ROW, scatter);
5157 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
5158 SCATTER_FORWARD);
5159 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
5160 SCATTER_FORWARD);
5161 }
5162
5164
5165 auto post_proc_mesh = boost::make_shared<moab::Core>();
5166 auto post_proc_ptr =
5167 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
5168 mField, post_proc_mesh);
5169 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
5170 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
5172
5173 auto hybrid_disp = boost::make_shared<MatrixDouble>();
5174 post_proc_ptr->getOpPtrVector().push_back(
5176 post_proc_ptr->getOpPtrVector().push_back(
5178 hybridSpatialDisp, dataAtPts->getGradHybridDispAtPts()));
5179
5180 auto op_loop_domain_side =
5182 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5183 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
5184
5185 // evaluated in side domain, that is op_loop_domain_side
5186 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
5187 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
5188 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5189 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
5191 op_loop_domain_side->getOpPtrVector().push_back(
5193 piolaStress, dataAtPts->getApproxPAtPts()));
5194 op_loop_domain_side->getOpPtrVector().push_back(
5196 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
5197 op_loop_domain_side->getOpPtrVector().push_back(
5199 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
5200
5201 if (stretchHandling == NO_STREACH) {
5202 op_loop_domain_side->getOpPtrVector().push_back(
5203 physicalEquations->returnOpCalculateStretchFromStress(
5205 } else {
5206 op_loop_domain_side->getOpPtrVector().push_back(
5208 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
5209 }
5210
5212
5213 OpPPMap::DataMapMat vec_fields;
5214 vec_fields["HybridDisplacement"] = hybrid_disp;
5215 // note that grad and omega have not trace, so this is only other side value
5216 vec_fields["spatialL2Disp"] = dataAtPts->getSmallWL2AtPts();
5217 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5218 OpPPMap::DataMapMat mat_fields;
5219 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5220 mat_fields["HybridDisplacementGradient"] =
5221 dataAtPts->getGradHybridDispAtPts();
5222 OpPPMap::DataMapMat mat_fields_symm;
5223 mat_fields_symm["LogSpatialStretch"] = dataAtPts->getLogStretchTensorAtPts();
5224
5225 post_proc_ptr->getOpPtrVector().push_back(
5226
5227 new OpPPMap(
5228
5229 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5230
5231 {},
5232
5233 vec_fields,
5234
5235 mat_fields,
5236
5237 mat_fields_symm
5238
5239 )
5240
5241 );
5242
5243 if (f_residual) {
5244 auto hybrid_res = boost::make_shared<MatrixDouble>();
5245 post_proc_ptr->getOpPtrVector().push_back(
5247 f_r));
5249 post_proc_ptr->getOpPtrVector().push_back(
5250
5251 new OpPPMap(
5252
5253 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5254
5255 {},
5256
5257 {{"res_hybrid", hybrid_res}},
5258
5259 {},
5260
5261 {}
5262
5263 )
5264
5265 );
5266 }
5267
5268 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5269
5270 auto post_proc_begin =
5272 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5274 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5275 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5276
5277 CHKERR post_proc_end.writeFile(file.c_str());
5278
5280}

◆ projectGeometry()

MoFEMErrorCode EshelbianCore::projectGeometry ( const EntityHandle  meshset = 0,
double  time = 0 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 1607 of file EshelbianPlasticity.cpp.

1608 {
1610
1611 Range meshset_ents;
1612 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
1613
1614 auto project_ho_geometry = [&](auto field) {
1616 return mField.loop_dofs(field, ent_method);
1617 };
1618 CHKERR project_ho_geometry(materialH1Positions);
1619
1620 auto get_adj_front_edges = [&](auto &front_edges) {
1621 Range front_crack_nodes;
1622 Range crack_front_edges_with_both_nodes_not_at_front;
1623
1624 if (mField.get_comm_rank() == 0) {
1625 auto &moab = mField.get_moab();
1627 moab.get_connectivity(front_edges, front_crack_nodes, true),
1628 "get_connectivity failed");
1629 Range crack_front_edges;
1630 CHK_MOAB_THROW(moab.get_adjacencies(front_crack_nodes, SPACE_DIM - 2,
1631 false, crack_front_edges,
1632 moab::Interface::UNION),
1633 "get_adjacencies failed");
1634 Range crack_front_edges_nodes;
1635 CHK_MOAB_THROW(moab.get_connectivity(crack_front_edges,
1636 crack_front_edges_nodes, true),
1637 "get_connectivity failed");
1638 // those nodes are hannging nodes
1639 crack_front_edges_nodes =
1640 subtract(crack_front_edges_nodes, front_crack_nodes);
1641 Range crack_front_edges_with_both_nodes_not_at_front;
1643 moab.get_adjacencies(crack_front_edges_nodes, 1, false,
1644 crack_front_edges_with_both_nodes_not_at_front,
1645 moab::Interface::UNION),
1646 "get_adjacencies failed");
1647 // those edges are have one node not at the crack front
1648 crack_front_edges_with_both_nodes_not_at_front = intersect(
1649 crack_front_edges, crack_front_edges_with_both_nodes_not_at_front);
1650 }
1651
1652 front_crack_nodes = send_type(mField, front_crack_nodes, MBVERTEX);
1653 crack_front_edges_with_both_nodes_not_at_front = send_type(
1654 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1655
1656 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1657 boost::make_shared<Range>(
1658 crack_front_edges_with_both_nodes_not_at_front));
1659 };
1660
1661 if ((time - crackingAddTime) > std::numeric_limits<double>::epsilon()) {
1662 crackFaces = boost::make_shared<Range>(
1663 get_range_from_block(mField, "CRACK", SPACE_DIM - 1));
1664 } else {
1665 crackFaces = boost::make_shared<Range>();
1666 }
1667 frontEdges =
1668 boost::make_shared<Range>(get_crack_front_edges(mField, *crackFaces));
1669 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*frontEdges);
1670 frontVertices = front_vertices;
1671 frontAdjEdges = front_adj_edges;
1672
1673 MOFEM_LOG("EP", Sev::inform)
1674 << "Number of crack faces: " << crackFaces->size();
1675 MOFEM_LOG("EP", Sev::inform)
1676 << "Number of front edges: " << frontEdges->size();
1677 MOFEM_LOG("EP", Sev::inform)
1678 << "Number of front vertices: " << frontVertices->size();
1679 MOFEM_LOG("EP", Sev::inform)
1680 << "Number of front adjacent edges: " << frontAdjEdges->size();
1681
1682#ifndef NDEBUG
1683 if (crackingOn) {
1684 auto rank = mField.get_comm_rank();
1685 // CHKERR save_range(mField.get_moab(),
1686 // (boost::format("meshset_ents_%d.vtk") % rank).str(),
1687 // meshset_ents);
1689 (boost::format("crack_faces_%d.vtk") % rank).str(),
1690 *crackFaces);
1692 (boost::format("front_edges_%d.vtk") % rank).str(),
1693 *frontEdges);
1694 // CHKERR save_range(mField.get_moab(),
1695 // (boost::format("front_vertices_%d.vtk") % rank).str(),
1696 // *frontVertices);
1697 // CHKERR save_range(mField.get_moab(),
1698 // (boost::format("front_adj_edges_%d.vtk") % rank).str(),
1699 // *frontAdjEdges);
1700 }
1701#endif // NDEBUG
1702
1703 auto set_singular_dofs = [&](auto &front_adj_edges, auto &front_vertices) {
1705 auto &moab = mField.get_moab();
1706
1707 double eps = 1;
1708 double beta = 0;
1709 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "-singularity_eps", &beta,
1710 PETSC_NULLPTR);
1711 MOFEM_LOG("EP", Sev::inform) << "Singularity eps " << beta;
1712 eps -= beta;
1713
1714 auto field_blas = mField.getInterface<FieldBlas>();
1715 auto lambda =
1716 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) -> MoFEMErrorCode {
1718 FTENSOR_INDEX(3, i);
1719 FTENSOR_INDEX(3, j);
1720
1721 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1722 if (nb_dofs == 0) {
1724 }
1725
1726#ifndef NDEBUG
1727 if (field_entity_ptr->getNbOfCoeffs() != 3)
1729 "Expected 3 coefficients per edge");
1730 if (nb_dofs % 3 != 0)
1732 "Expected multiple of 3 coefficients per edge");
1733#endif // NDEBUG
1734
1735 auto get_conn = [&]() {
1736 int num_nodes;
1737 const EntityHandle *conn;
1738 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1739 num_nodes, false);
1740 return std::make_pair(conn, num_nodes);
1741 };
1742
1743 auto get_dir = [&](auto &&conn_p) {
1744 auto [conn, num_nodes] = conn_p;
1745 double coords[6];
1746 CHKERR moab.get_coords(conn, num_nodes, coords);
1747 FTensor::Tensor1<double, 3> t_edge_dir{coords[3] - coords[0],
1748 coords[4] - coords[1],
1749 coords[5] - coords[2]};
1750 return t_edge_dir;
1751 };
1752
1753 auto get_singularity_dof = [&](auto &&conn_p, auto &&t_edge_dir) {
1754 auto [conn, num_nodes] = conn_p;
1755 FTensor::Tensor1<double, 3> t_singularity_dof{0., 0., 0.};
1756 if (front_vertices.find(conn[0]) != front_vertices.end()) {
1757 t_singularity_dof(i) = t_edge_dir(i) * (-eps);
1758 } else if (front_vertices.find(conn[1]) != front_vertices.end()) {
1759 t_singularity_dof(i) = t_edge_dir(i) * eps;
1760 }
1761 return t_singularity_dof;
1762 };
1763
1764 auto t_singularity_dof =
1765 get_singularity_dof(get_conn(), get_dir(get_conn()));
1766
1767 auto field_data = field_entity_ptr->getEntFieldData();
1769 &field_data[0], &field_data[1], &field_data[2]};
1770
1771 t_dof(i) = t_singularity_dof(i);
1772 ++t_dof;
1773 for (auto n = 1; n < field_data.size() / 3; ++n) {
1774 t_dof(i) = 0;
1775 ++t_dof;
1776 }
1777
1779 };
1780
1781 CHKERR field_blas->fieldLambdaOnEntities(lambda, materialH1Positions,
1782 &front_adj_edges);
1783
1785 };
1786
1787 if (setSingularity)
1788 CHKERR set_singular_dofs(*frontAdjEdges, *frontVertices);
1789
1790 interfaceFaces = boost::make_shared<Range>(
1791 get_range_from_block(mField, "INTERFACE", SPACE_DIM - 1));
1792 MOFEM_LOG("EP", Sev::inform)
1793 << "Number of interface elements: " << interfaceFaces->size();
1794
1795 auto get_interface_from_block = [&](auto block_name) {
1796 auto vol_eles = get_range_from_block(mField, block_name, SPACE_DIM);
1797 auto skin = filter_true_skin(mField, get_skin(mField, vol_eles));
1798 Range faces;
1799 CHKERR mField.get_moab().get_adjacencies(vol_eles, SPACE_DIM - 1, true,
1800 faces, moab::Interface::UNION);
1801 faces = subtract(faces, skin);
1802 MOFEM_LOG("EP", Sev::inform)
1803 << "Number of vol interface elements: " << vol_eles.size()
1804 << " and faces: " << faces.size();
1805 return faces;
1806 };
1807
1808 interfaceFaces->merge(get_interface_from_block("VOLUME_INTERFACE"));
1809
1810 auto remove_interface_from_block = [&](auto block_name, auto level) {
1812 Range intreface_faces;
1813 if (mField.get_comm_rank() == 0) {
1814 auto ents = get_entities_by_handle(mField, block_name);
1815 for (auto l = 0; l < level; ++l) {
1816 Range adj_tets;
1817 CHKERR mField.get_moab().get_adjacencies(
1818 ents, SPACE_DIM, true, adj_tets, moab::Interface::UNION);
1819 Range adj_tets_faces;
1820 CHKERR mField.get_moab().get_adjacencies(adj_tets, SPACE_DIM - 1, true,
1821 adj_tets_faces,
1822 moab::Interface::UNION);
1823 ents.merge(adj_tets_faces);
1824 }
1825 auto faces = ents.subset_by_dimension(SPACE_DIM - 1);
1826 if (faces.size()) {
1827 MOFEM_LOG("EP", Sev::inform)
1828 << "Removed ents " << faces.size()
1829 << " interface faces: " << interfaceFaces->size();
1830 }
1831 intreface_faces = subtract(*interfaceFaces, faces);
1832 MOFEM_LOG("EP", Sev::noisy)
1833 << "Interface faces after remove " << intreface_faces;
1834 }
1835 auto intreface_faces_global = send_type(mField, intreface_faces, MBTRI);
1836 interfaceFaces->swap(intreface_faces_global);
1838 };
1839 CHKERR remove_interface_from_block("REMOVE_INTERFACE", interfaceRemoveLevel);
1840
1842}
static auto get_entities_by_handle(MoFEM::Interface &m_field, const std::string block_name)
static auto get_crack_front_edges(MoFEM::Interface &m_field, Range crack_faces)
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.
static double lambda
PetscErrorCode PetscOptionsGetScalar(PetscOptions *, const char pre[], const char name[], PetscScalar *dval, PetscBool *set)
Basic algebra on fields.
Definition FieldBlas.hpp:21
Projection of edge entities with one mid-node on hierarchical basis.

◆ projectMaterialTags()

MoFEMErrorCode EshelbianCore::projectMaterialTags ( const EntityHandle  meshset = 0)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 1844 of file EshelbianPlasticity.cpp.

1844 {
1846#ifdef INCLUDE_MBCOUPLER
1847
1848 double toler = 5.e-10;
1849 MOFEM_LOG_CHANNEL("WORLD");
1850 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
1852 MOFEM_LOG("WORLD", Sev::verbose)
1853 << "No source mesh specified. Skipping projection";
1855 }
1856 MOFEM_LOG("WORLD", Sev::inform)
1857 << "Projecting from source mesh: " << meshTransferSourceMeshFileName;
1858 MOFEM_LOG("WORLD", Sev::verbose)
1859 << "Interpolation Stress tag name: " << internalStressTagName;
1860 MOFEM_LOG("WORLD", Sev::verbose) << "Interpolation Young's modulus tag name: "
1862 MOFEM_LOG("WORLD", Sev::verbose)
1863 << "Interpolation order: " << meshTransferInterpOrder;
1864 MOFEM_LOG("WORLD", Sev::verbose) << "Using hybrid interpolation: "
1865 << (meshTransferHybridInterp ? "yes" : "no");
1866
1867 auto &moab = mField.get_moab();
1868
1869 // check if tag exists
1870 for (const auto &tag_name : listTagsToProject) {
1871 Tag old_interp_tag;
1872 auto rval_check_tag = moab.tag_get_handle(tag_name.c_str(), old_interp_tag);
1873 if (rval_check_tag == MB_SUCCESS) {
1874 MOFEM_LOG("WORLD", Sev::inform)
1875 << "Deleting existing tag on target mesh: " << tag_name;
1876 CHKERR moab.tag_delete(old_interp_tag);
1877 }
1878 }
1879 // make a size-1 communicator for the coupler (rank 0 only)
1880 int world_rank = -1, world_size = -1;
1881 MPI_Comm_rank(PETSC_COMM_WORLD, &world_rank);
1882 MPI_Comm_size(PETSC_COMM_WORLD, &world_size);
1883
1884 Range original_meshset_ents;
1885 CHKERR moab.get_entities_by_handle(0, original_meshset_ents);
1886
1887 MPI_Comm comm_coupler;
1888 if (world_rank == 0) {
1889 MPI_Comm_split(PETSC_COMM_WORLD, 0, 0, &comm_coupler);
1890 } else {
1891 MPI_Comm_split(PETSC_COMM_WORLD, MPI_UNDEFINED, world_rank, &comm_coupler);
1892 }
1893
1894 // build a separate ParallelComm for the coupler (rank 0 only)
1895 ParallelComm *pcomm0 = nullptr;
1896 int pcomm0_id = -1;
1897 if (world_rank == 0) {
1898 pcomm0 = new ParallelComm(&moab, comm_coupler, &pcomm0_id);
1899 }
1900
1901 Coupler::Method method;
1902 switch (meshTransferInterpOrder) {
1903 case 0:
1904 method = Coupler::CONSTANT;
1905 break;
1906 case 1:
1907 method = Coupler::LINEAR_FE;
1908 break;
1909 default:
1910 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1911 "Unsupported interpolation order");
1912 }
1913
1914 int nprocs, rank;
1915 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &nprocs);
1916 CHKERRQ(ierr);
1917 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
1918 CHKERRQ(ierr);
1919
1920 // std::string read_opts, write_opts;
1921 // read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
1922 // "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
1923 // if (world_size > 1)
1924 // read_opts += ";PARALLEL_GHOSTS=3.0.1";
1925 // write_opts = (world_size > 1) ? "PARALLEL=WRITE_PART" : "";
1926
1927 // create target mesh from existing meshset
1928 EntityHandle target_root;
1929 CHKERR moab.create_meshset(MESHSET_SET, target_root);
1930 MOFEM_LOG("WORLD", Sev::inform)
1931 << "Creating target mesh from existing meshset";
1932 Range target_meshset_ents;
1933 CHKERR moab.get_entities_by_handle(0, target_meshset_ents);
1934 CHKERR moab.add_entities(target_root, target_meshset_ents);
1935
1936 // variables for tags to be broadcast later
1937 std::vector<Tag> interp_tags;
1938 std::vector<int> tag_length;
1939 std::vector<DataType> dtype;
1940 std::vector<TagType> storage;
1941
1942 // load source mesh
1943 Range targ_verts, targ_elems;
1944 if (world_rank == 0) {
1945 EntityHandle source_root;
1946 CHKERR moab.create_meshset(MESHSET_SET, source_root);
1947
1948 MOFEM_LOG("WORLD", Sev::inform) << "Loading source mesh on rank 0";
1949 auto rval_source_mesh = moab.load_file(
1950 meshTransferSourceMeshFileName.c_str(), &source_root, "");
1951 if (rval_source_mesh != MB_SUCCESS) {
1952 MOFEM_LOG("WORLD", Sev::warning) << "Error loading source mesh file: "
1954 }
1955 MOFEM_LOG("WORLD", Sev::inform) << "Source mesh loaded.";
1956
1957 Range src_elems;
1958 CHKERR moab.get_entities_by_dimension(source_root, 3, src_elems);
1959
1960 EntityHandle part_set;
1961 CHKERR pcomm0->create_part(part_set);
1962 CHKERR moab.add_entities(part_set, src_elems);
1963
1964 Range src_elems_part;
1965 CHKERR pcomm0->get_part_entities(src_elems_part, 3);
1966
1967 for (const auto &iterp_tag_name : listTagsToProject) {
1968 std::string tag_to_use = iterp_tag_name;
1969
1970 Tag interp_tag;
1971 CHKERR moab.tag_get_handle(tag_to_use.c_str(), interp_tag);
1972
1973 int interp_tag_len;
1974 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
1975
1976 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
1977 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1978 "Unsupported interpolation tag length: %d", interp_tag_len);
1979 }
1980
1981 // store tag info for later broadcast
1982 tag_length.push_back(interp_tag_len);
1983 dtype.push_back(DataType());
1984 storage.push_back(TagType());
1985 interp_tags.push_back(interp_tag);
1986 CHKERR moab.tag_get_data_type(interp_tag, dtype.back());
1987 CHKERR moab.tag_get_type(interp_tag, storage.back());
1988
1989 // coupler is collective
1990 Coupler mbc(&moab, pcomm0, src_elems_part, 0, true);
1991
1992 std::vector<double> vpos; // the positions we are interested in
1993 int num_pts = 0;
1994
1995 Range tmp_verts;
1996
1997 // First get all vertices adj to partition entities in target mesh
1998 CHKERR moab.get_entities_by_dimension(target_root, 3, targ_elems);
1999
2000 if (meshTransferInterpOrder == 0) {
2001 targ_verts = targ_elems;
2002 } else {
2003 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
2004 moab::Interface::UNION);
2005 }
2006
2007 // Then get non-owned verts and subtract
2008 CHKERR pcomm0->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
2009 targ_verts = subtract(targ_verts, tmp_verts);
2010
2011 // get position of these entities; these are the target points
2012 num_pts = (int)targ_verts.size();
2013 vpos.resize(3 * targ_verts.size());
2014 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2015
2016 // Locate those points in the source mesh
2017 boost::shared_ptr<TupleList> tl_ptr;
2018 tl_ptr = boost::make_shared<TupleList>();
2019 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2020 false);
2021
2022 // If some points were not located, we need to process them
2023 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
2024 std::vector<double> &vpos,
2025 Range &missing_verts) {
2027 int missing_pts_num = 0;
2028 int i = 0;
2029 auto vit = targ_verts.begin();
2030 for (; vit != targ_verts.end(); i++) {
2031 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
2032 missing_verts.insert(*vit);
2033 vit = targ_verts.erase(vit);
2034 missing_pts_num++;
2035 } else {
2036 vit++;
2037 }
2038 }
2039
2040 int missing_pts_num_global = 0;
2041 // MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
2042 // MPI_SUM, pcomm0);
2043 if (missing_pts_num_global) {
2044 MOFEM_LOG("WORLD", Sev::warning)
2045 << missing_pts_num_global
2046 << " points in target mesh were not located in source mesh. ";
2047 }
2048
2049 if (missing_pts_num) {
2050 num_pts = (int)targ_verts.size();
2051 vpos.resize(3 * targ_verts.size());
2052 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2053 tl_ptr->reset();
2054 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2055 false);
2056 }
2058 };
2059
2060 Range missing_verts;
2061 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
2062
2063 std::vector<double> source_data(interp_tag_len * src_elems.size(), 0.0);
2064 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
2065
2066 CHKERR moab.tag_get_data(interp_tag, src_elems, &source_data[0]);
2067
2068 Tag scalar_tag, adj_count_tag;
2069 double def_scl = 0;
2070 string scalar_tag_name = string(tag_to_use) + "_COMP";
2071 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2072 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2073 &def_scl);
2074
2075 string adj_count_tag_name = "ADJ_COUNT";
2076 double def_adj = 0;
2077 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2078 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2079 &def_adj);
2080
2081 // MBCoupler functionality supports only scalar tags. For the case of
2082 // vector or tensor tags we need to save each component as a scalar tag
2083 auto create_scalar_tags = [&](const Range &src_elems,
2084 const std::vector<double> &source_data,
2085 int itag) {
2087
2088 std::vector<double> source_data_scalar(src_elems.size());
2089 // Populate source_data_scalar
2090 for (int ielem = 0; ielem < src_elems.size(); ielem++) {
2091 source_data_scalar[ielem] =
2092 source_data[itag + ielem * interp_tag_len];
2093 }
2094
2095 // Set data on the scalar tag
2096 CHKERR moab.tag_set_data(scalar_tag, src_elems, &source_data_scalar[0]);
2097
2098 if (meshTransferInterpOrder == 1) {
2099 // Linear interpolation: compute average value of data on vertices
2100 Range src_verts;
2101 CHKERR moab.get_connectivity(src_elems, src_verts, true);
2102
2103 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
2104 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
2105
2106 for (auto &tet : src_elems) {
2107 double tet_data = 0;
2108 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
2109
2110 Range adj_verts;
2111 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
2112
2113 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
2114 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
2115
2116 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2117 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
2118 &adj_vert_count[0]);
2119
2120 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
2121 adj_vert_data[ivert] += tet_data;
2122 adj_vert_count[ivert] += 1;
2123 }
2124
2125 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2126 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
2127 &adj_vert_count[0]);
2128 }
2129
2130 // Reduce tags for the parallel case
2131 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
2132 pcomm0->reduce_tags(tags, tags, MPI_SUM, src_verts);
2133
2134 std::vector<double> src_vert_data(src_verts.size(), 0.0);
2135 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
2136
2137 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
2138 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
2139 &src_vert_adj_count[0]);
2140
2141 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
2142 src_vert_data[ivert] /= src_vert_adj_count[ivert];
2143 }
2144 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
2145 }
2147 };
2148
2149 MOFEM_LOG("WORLD", Sev::inform)
2150 << "Performing interpolation for tag: " << tag_to_use;
2151 MOFEM_LOG("WORLD", Sev::inform)
2152 << "Number of target points to interpolate: " << num_pts;
2153 MOFEM_LOG("WORLD", Sev::inform)
2154 << "Interpolation method: "
2155 << (method == Coupler::CONSTANT ? "constant" : "linear FE");
2156 MOFEM_LOG("WORLD", Sev::inform)
2157 << "Number of components in tag: " << interp_tag_len;
2158
2159 MOFEM_LOG("WORLD", Sev::inform)
2160 << "Source tag data range: ["
2161 << *std::min_element(source_data.begin(), source_data.end()) << ", "
2162 << *std::max_element(source_data.begin(), source_data.end()) << "]";
2163
2164 for (int itag = 0; itag < interp_tag_len; itag++) {
2165
2166 CHKERR create_scalar_tags(src_elems, source_data, itag);
2167
2168 std::vector<double> target_data_scalar(num_pts, 0.0);
2169 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
2170 tl_ptr.get());
2171
2172 for (int ielem = 0; ielem < num_pts; ielem++) {
2173 target_data[itag + ielem * interp_tag_len] =
2174 target_data_scalar[ielem];
2175 }
2176 }
2177
2178 // Use original tag
2179 CHKERR moab.tag_set_data(interp_tag, targ_verts, &target_data[0]);
2180
2181 if (missing_verts.size() && (meshTransferInterpOrder == 1) &&
2183 MOFEM_LOG("WORLD", Sev::warning)
2184 << "Using hybrid interpolation for "
2185 "missing points in the target mesh.";
2186 Range missing_adj_elems;
2187 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
2188 moab::Interface::UNION);
2189
2190 int num_adj_elems = (int)missing_adj_elems.size();
2191 std::vector<double> vpos_adj_elems;
2192
2193 vpos_adj_elems.resize(3 * missing_adj_elems.size());
2194 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
2195
2196 // Locate those points in the source mesh
2197 tl_ptr->reset();
2198 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
2199 tl_ptr.get(), false);
2200
2201 Range missing_tets;
2202 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
2203 vpos_adj_elems, missing_tets);
2204 if (missing_tets.size()) {
2205 MOFEM_LOG("WORLD", Sev::warning)
2206 << missing_tets.size()
2207 << " points in target mesh were not located in source mesh. ";
2208 }
2209
2210 std::vector<double> target_data_adj_elems(
2211 interp_tag_len * num_adj_elems, 0.0);
2212
2213 for (int itag = 0; itag < interp_tag_len; itag++) {
2214 CHKERR create_scalar_tags(src_elems, source_data, itag);
2215
2216 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
2217 CHKERR mbc.interpolate(method, scalar_tag_name,
2218 &target_data_adj_elems_scalar[0],
2219 tl_ptr.get());
2220
2221 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
2222 target_data_adj_elems[itag + ielem * interp_tag_len] =
2223 target_data_adj_elems_scalar[ielem];
2224 }
2225 }
2226
2227 CHKERR moab.tag_set_data(interp_tag, missing_adj_elems,
2228 &target_data_adj_elems[0]);
2229
2230 // FIXME: add implementation for parallel case
2231 for (auto &vert : missing_verts) {
2232 Range adj_elems;
2233 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
2234 moab::Interface::UNION);
2235
2236 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
2237 0.0);
2238 CHKERR moab.tag_get_data(interp_tag, adj_elems, &adj_elems_data[0]);
2239
2240 std::vector<double> vert_data(interp_tag_len, 0.0);
2241 for (int itag = 0; itag < interp_tag_len; itag++) {
2242 for (int i = 0; i < adj_elems.size(); i++) {
2243 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
2244 }
2245 vert_data[itag] /= adj_elems.size();
2246 }
2247 CHKERR moab.tag_set_data(interp_tag, &vert, 1, &vert_data[0]);
2248 }
2249 }
2250
2251 CHKERR moab.tag_delete(scalar_tag);
2252 CHKERR moab.tag_delete(adj_count_tag);
2253 }
2254
2255 // delete source mesh after projection but keep the tags info for broadcast
2256 Range src_mesh_ents;
2257 CHKERR moab.get_entities_by_handle(source_root, src_mesh_ents);
2258 CHKERR moab.delete_entities(&source_root, 1);
2259 CHKERR moab.delete_entities(src_mesh_ents);
2260 CHKERR moab.delete_entities(&part_set, 1);
2261 }
2262
2263 // broadcast tag info to other processors
2264 int tag_size = tag_length.size();
2265 MPI_Bcast(&tag_size, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2266 if (rank != 0) {
2267 interp_tags.resize(tag_size);
2268 tag_length.resize(tag_size);
2269 dtype.resize(tag_size);
2270 storage.resize(tag_size);
2271 }
2272 MPI_Bcast(interp_tags.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2273 MPI_Bcast(tag_length.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2274 MPI_Bcast(dtype.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2275 MPI_Bcast(storage.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2276
2277 // create new tag on other processors
2278 // loop over tag index to support multiple tags projection in one run
2279
2280 for (size_t index = 0; index < interp_tags.size(); index++) {
2281 // check if tag exists first
2282 if (world_rank) {
2283 Tag old_interp_tag;
2284 auto rval_check_tag =
2285 moab.tag_get_handle(listTagsToProject[index].c_str(), old_interp_tag);
2286 if (rval_check_tag == MB_SUCCESS) {
2287 MOFEM_LOG("WORLD", Sev::verbose)
2288 << "Deleting existing tag on target mesh (post-projection): "
2289 << listTagsToProject[index];
2290 CHKERR moab.tag_delete(old_interp_tag);
2291 }
2292 }
2293 Tag interp_tag_all;
2294 unsigned flags =
2295 MB_TAG_CREAT | storage[index]; // e.g., MB_TAG_DENSE or MB_TAG_SPARSE
2296 std::vector<double> def_val(tag_length[index], 0.);
2297 auto rval = moab.tag_get_handle(listTagsToProject[index].c_str(),
2298 tag_length[index], dtype[index],
2299 interp_tag_all, flags, def_val.data());
2300 if (rval != MB_SUCCESS && world_rank) {
2301 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2302 "Unable to create projection tag %s",
2303 listTagsToProject[index].c_str());
2304 }
2305
2306 MPI_Barrier(PETSC_COMM_WORLD);
2307
2308 // exchange data for all entity types across all processors
2309 auto vertex_exchange = CommInterface::createEntitiesPetscVector(
2310 mField.get_comm(), mField.get_moab(), 0, tag_length[index],
2311 Sev::inform);
2312 auto volume_exchange = CommInterface::createEntitiesPetscVector(
2313 mField.get_comm(), mField.get_moab(), 3, tag_length[index],
2314 Sev::inform);
2315
2317 mField.get_moab(), vertex_exchange, interp_tag_all);
2319 mField.get_moab(), volume_exchange, interp_tag_all);
2320 }
2321
2322 // delete target meshset but not the entities
2323 CHKERR moab.delete_entities(&target_root, 1);
2324
2325#endif // INCLUDE_MBCOUPLER
2327}
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
static MoFEMErrorCode updateEntitiesPetscVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag, UpdateGhosts update_gosts=defaultUpdateGhosts)
Exchange data between vector and data.

◆ pushNoStretchVolumeA00Ops()

MoFEMErrorCode EshelbianCore::pushNoStretchVolumeA00Ops ( boost::shared_ptr< VolumeElementForcesAndSourcesCore fe_lhs)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3054 of file EshelbianPlasticity.cpp.

3055 {
3057
3058 bool has_nonhomogeneous_mat_block =
3060 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_dP(
3061 piolaStress, piolaStress, dataAtPts, has_nonhomogeneous_mat_block));
3062 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dP(
3063 bubbleField, piolaStress, dataAtPts, has_nonhomogeneous_mat_block));
3064 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_dBubble(
3065 bubbleField, bubbleField, dataAtPts, has_nonhomogeneous_mat_block));
3066
3067 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3069 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3071
3072 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3074 symmetrySelector == SYMMETRIC ? true : false));
3075 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3077 symmetrySelector == SYMMETRIC ? true : false));
3078
3079 if (symmetrySelector > SYMMETRIC) {
3080 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3081 rotAxis, piolaStress, dataAtPts, false));
3082 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3083 rotAxis, bubbleField, dataAtPts, false));
3084 }
3085 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3087
3089}
static constexpr enum SymmetrySelector symmetrySelector
static bool hasNonHomogeneousMaterialBlock

◆ pushPiolaStressGramOps()

MoFEMErrorCode EshelbianCore::pushPiolaStressGramOps ( boost::shared_ptr< VolumeElementForcesAndSourcesCore fe_lhs)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3143 of file EshelbianPlasticity.cpp.

3144 {
3146 fe_lhs->getOpPtrVector().push_back(
3149}
FormsIntegrators< VolUserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 3, 9 > OpStressGram_dP_dP

◆ pushStressGramOps()

MoFEMErrorCode EshelbianCore::pushStressGramOps ( boost::shared_ptr< VolumeElementForcesAndSourcesCore fe_lhs)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3132 of file EshelbianPlasticity.cpp.

3133 {
3136 fe_lhs->getOpPtrVector().push_back(
3138 fe_lhs->getOpPtrVector().push_back(new OpStressGram_dBubble_dBubble(
3141}
FormsIntegrators< VolUserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 9, 9 > OpStressGram_dBubble_dBubble
MoFEMErrorCode pushPiolaStressGramOps(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)

◆ pushStretchVolumeA00Ops()

MoFEMErrorCode EshelbianCore::pushStretchVolumeA00Ops ( boost::shared_ptr< VolumeElementForcesAndSourcesCore fe_lhs)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3091 of file EshelbianPlasticity.cpp.

3092 {
3094
3095 fe_lhs->getOpPtrVector().push_back(
3096 physicalEquations->returnOpSpatialPhysical_du_du(
3098 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dP(
3100 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_dBubble(
3102 fe_lhs->getOpPtrVector().push_back(new OpSpatialPhysical_du_domega(
3104 symmetrySelector == SYMMETRIC ? true : false));
3105
3106 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3108 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3110
3111 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3113 symmetrySelector == SYMMETRIC ? true : false));
3114 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3116 symmetrySelector == SYMMETRIC ? true : false));
3117
3118 if (symmetrySelector > SYMMETRIC) {
3119 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_du(
3120 rotAxis, stretchTensor, dataAtPts, false));
3121 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3122 rotAxis, piolaStress, dataAtPts, false));
3123 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3124 rotAxis, bubbleField, dataAtPts, false));
3125 }
3126 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3128
3130}

◆ query_interface()

MoFEMErrorCode EshelbianCore::query_interface ( boost::typeindex::type_index  type_index,
UnknownInterface **  iface 
) const

Getting interface of core database.

Parameters
uuidunique ID of interface
ifacereturned pointer to interface
Returns
error code
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 943 of file EshelbianPlasticity.cpp.

944 {
945 *iface = const_cast<EshelbianCore *>(this);
946 return 0;
947}

◆ saveOrgCoords()

MoFEMErrorCode EshelbianCore::saveOrgCoords ( )

Definition at line 2833 of file EshelbianFracture.cpp.

2833 {
2835 auto crack_faces =
2836 get_range_from_block(mField, "CRACK_COMPUTED", SPACE_DIM - 1);
2837 Range conn;
2838 CHKERR mField.get_moab().get_connectivity(crack_faces, conn, true);
2839 Range verts;
2840 CHKERR mField.get_moab().get_entities_by_type(0, MBVERTEX, verts);
2841 verts = subtract(verts, conn);
2842 std::vector<double> coords(3 * verts.size());
2843 CHKERR mField.get_moab().get_coords(verts, coords.data());
2844 double def_coords[] = {0., 0., 0.};
2845 Tag th_org_coords;
2846 CHKERR mField.get_moab().tag_get_handle(
2847 "ORG_COORDS", 3, MB_TYPE_DOUBLE, th_org_coords,
2848 MB_TAG_CREAT | MB_TAG_DENSE, def_coords);
2849 CHKERR mField.get_moab().tag_set_data(th_org_coords, verts, coords.data());
2851}

◆ setBaseVolumeElementOps()

MoFEMErrorCode EshelbianCore::setBaseVolumeElementOps ( const int  tag,
const bool  do_rhs,
const bool  do_lhs,
const bool  calc_rates,
boost::shared_ptr< VolumeElementForcesAndSourcesCore fe,
const bool  add_bubble = true 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 2954 of file EshelbianPlasticity.cpp.

2957 {
2959
2960 auto bubble_cache =
2961 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
2962 fe->getUserPolynomialBase() =
2963 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
2964 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
2965 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
2966
2967 // set integration rule
2968 fe->getRuleHook = [](int, int, int) { return -1; };
2969 // auto vol_rule = (SMALL_ROT > 0) ? vol_rule_lin : vol_rule_no_lin;
2970 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges,
2971 vol_rule, bubble_cache);
2972 // fe->getRuleHook = VolRule();
2973
2974 if (!dataAtPts) {
2975 dataAtPts =
2976 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
2977 dataAtPts->physicsPtr = physicalEquations;
2978 }
2979
2980 // calculate fields values
2981 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
2982 piolaStress, dataAtPts->getApproxPAtPts()));
2983 if (add_bubble) {
2984 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
2985 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
2986 }
2987 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
2988 piolaStress, dataAtPts->getDivPAtPts()));
2989
2990 if (stretchHandling == NO_STREACH) {
2991 fe->getOpPtrVector().push_back(
2992 physicalEquations->returnOpCalculateStretchFromStress(
2994 } else {
2995 fe->getOpPtrVector().push_back(
2997 stretchTensor, dataAtPts->getLogStretchTensorAtPts(), MBTET));
2998 }
2999
3000 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3001 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3002 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
3003 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3004 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3005 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3006 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3007
3008 // H1 displacements
3009 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3010 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3011 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3012 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3013
3014 // velocities
3015 if (calc_rates) {
3016 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3017 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
3018 if (stretchHandling == NO_STREACH) {
3019 } else {
3020 fe->getOpPtrVector().push_back(
3022 stretchTensor, dataAtPts->getLogStretchDotTensorAtPts(), MBTET));
3023 fe->getOpPtrVector().push_back(
3025 stretchTensor, dataAtPts->getGradLogStretchDotTensorAtPts(),
3026 MBTET));
3027 }
3028 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3029 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
3030 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradientDot<3, 3>(
3031 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
3032
3033 // acceleration
3034 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3035 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDotDot<3>(
3036 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
3037 }
3038 }
3039
3040 // calculate other derived quantities
3041 fe->getOpPtrVector().push_back(new OpCalculateRotationAndSpatialGradient(
3042 dataAtPts, ((do_rhs || do_lhs) && calc_rates) ? alphaOmega : 0.));
3043
3044 // evaluate integration points
3045 if (stretchHandling == NO_STREACH) {
3046 } else {
3047 fe->getOpPtrVector().push_back(physicalEquations->returnOpJacobian(
3048 do_rhs, do_lhs, dataAtPts, physicalEquations));
3049 }
3050
3052}
Calculate divergence of tonsorial field using vectorial base.
Calculate symmetric tensor field rates ant integratio pts.
Get field gradients time derivative at integration pts for scalar field rank 0, i....
Approximate field values for given petsc vector.

◆ setBlockTagsOnSkin()

MoFEMErrorCode EshelbianCore::setBlockTagsOnSkin ( )
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 4441 of file EshelbianPlasticity.cpp.

4441 {
4443
4444 auto set_block = [&](auto name, int dim) {
4445 std::map<int, Range> map;
4446 auto set_tag_impl = [&](auto name) {
4448 auto mesh_mng = mField.getInterface<MeshsetsManager>();
4449 auto bcs = mesh_mng->getCubitMeshsetPtr(
4450
4451 std::regex((boost::format("%s(.*)") % name).str())
4452
4453 );
4454 for (auto bc : bcs) {
4455 Range r;
4456 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
4457 true);
4458 map[bc->getMeshsetId()] = r;
4459 MOFEM_LOG("EP", Sev::inform)
4460 << "Block " << name << " id " << bc->getMeshsetId() << " has "
4461 << r.size() << " entities";
4462 }
4464 };
4465
4466 CHKERR set_tag_impl(name);
4467
4468 return std::make_pair(name, map);
4469 };
4470
4471 auto set_skin = [&](auto &&map) {
4472 for (auto &m : map.second) {
4473 auto s = filter_true_skin(mField, get_skin(mField, m.second));
4474 m.second.swap(s);
4475 MOFEM_LOG("EP", Sev::inform)
4476 << "Skin for block " << map.first << " id " << m.first << " has "
4477 << m.second.size() << " entities";
4478 }
4479 return map;
4480 };
4481
4482 auto set_tag = [&](auto &&map) {
4483 Tag th;
4484 auto name = map.first;
4485 int def_val[] = {-1};
4487 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER, th,
4488 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
4489 "create tag");
4490 for (auto &m : map.second) {
4491 int id = m.first;
4492 CHK_MOAB_THROW(mField.get_moab().tag_clear_data(th, m.second, &id),
4493 "clear tag");
4494 }
4495 return th;
4496 };
4497
4498 listTagsToTransfer.push_back(set_tag(set_skin(set_block("BODY", 3))));
4499 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_ELASTIC", 3))));
4500 listTagsToTransfer.push_back(
4501 set_tag(set_skin(set_block("MAT_NEOHOOKEAN", 3))));
4502 listTagsToTransfer.push_back(set_tag(set_block("CONTACT", 2)));
4503
4505}
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset

◆ setContactElementRhsOps()

MoFEMErrorCode EshelbianCore::setContactElementRhsOps ( boost::shared_ptr< ForcesAndSourcesCore > &  fe_contact_tree)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3963 of file EshelbianPlasticity.cpp.

3967 {
3969 fe_contact_tree = createContactDetectionFiniteElement(*this);
3971}
boost::shared_ptr< ForcesAndSourcesCore > createContactDetectionFiniteElement(EshelbianCore &ep)
Create a Contact Tree finite element.

◆ setElasticElementOps()

MoFEMErrorCode EshelbianCore::setElasticElementOps ( const int  tag)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 3973 of file EshelbianPlasticity.cpp.

3973 {
3975
3976 // Add contact operators. Note that only for rhs. THe lhs is assembled with
3977 // volume element, to enable schur complement evaluation.
3979
3982
3983 auto adj_cache =
3984 boost::make_shared<ForcesAndSourcesCore::UserDataOperator::AdjCache>();
3985
3986 auto get_op_contact_bc = [&]() {
3988 auto op_loop_side = new OpLoopSide<SideEle>(
3989 mField, contactElement, SPACE_DIM - 1, Sev::noisy, adj_cache);
3990 return op_loop_side;
3991 };
3992
3994}
boost::shared_ptr< FaceElementForcesAndSourcesCore > elasticBcRhs
boost::shared_ptr< FaceElementForcesAndSourcesCore > elasticBcLhs
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeRhs
MoFEMErrorCode setVolumeElementOps(const int tag, const bool add_elastic, const bool add_material, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< VolumeElementForcesAndSourcesCore > &fe_lhs)
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeLhs
MoFEMErrorCode setFaceElementOps(const bool add_elastic, const bool add_material, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_rhs, boost::shared_ptr< FaceElementForcesAndSourcesCore > &fe_lhs)
MoFEMErrorCode setContactElementRhsOps(boost::shared_ptr< ForcesAndSourcesCore > &fe_contact_tree)
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:62

◆ setElasticElementToTs()

MoFEMErrorCode EshelbianCore::setElasticElementToTs ( DM  dm)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 3996 of file EshelbianPlasticity.cpp.

3996 {
3998 boost::shared_ptr<FEMethod> null;
3999
4000 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4001
4003 null);
4005 null);
4007 null);
4009 null);
4010
4011 } else {
4013 null);
4015 null);
4017 null);
4019 null);
4020 }
4021
4023}
PetscErrorCode DMMoFEMTSSetIFunction(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set TS implicit function evaluation function
Definition DMMoFEM.cpp:790
PetscErrorCode DMMoFEMTSSetIJacobian(DM dm, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
set TS Jacobian evaluation function
Definition DMMoFEM.cpp:843
PetscErrorCode DMMoFEMTSSetI2Jacobian(DM dm, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
set TS Jacobian evaluation function
Definition DMMoFEM.cpp:1007
PetscErrorCode DMMoFEMTSSetI2Function(DM dm, const std::string fe_name, boost::shared_ptr< MoFEM::FEMethod > method, boost::shared_ptr< MoFEM::BasicMethod > pre_only, boost::shared_ptr< MoFEM::BasicMethod > post_only)
set TS implicit function evaluation function
Definition DMMoFEM.cpp:965

◆ setFaceElementOps()

MoFEMErrorCode EshelbianCore::setFaceElementOps ( const bool  add_elastic,
const bool  add_material,
boost::shared_ptr< FaceElementForcesAndSourcesCore > &  fe_rhs,
boost::shared_ptr< FaceElementForcesAndSourcesCore > &  fe_lhs 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3801 of file EshelbianPlasticity.cpp.

3804 {
3806
3807 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3808 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3809
3810 // set integration rule
3811 // fe_rhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3812 // fe_lhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
3813 fe_rhs->getRuleHook = [](int, int, int) { return -1; };
3814 fe_lhs->getRuleHook = [](int, int, int) { return -1; };
3815 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3816 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3817
3818 CHKERR
3819 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3820 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3821 CHKERR
3822 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3823 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
3824
3825 if (add_elastic) {
3826
3827 auto get_broken_op_side = [this](auto &pip) {
3828 using EleOnSide =
3830 using SideEleOp = EleOnSide::UserDataOperator;
3831 // Iterate over domain FEs adjacent to boundary.
3832 auto broken_data_ptr =
3833 boost::make_shared<std::vector<BrokenBaseSideData>>();
3834 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3835 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
3836 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3837 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3838 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3839 CHKERR
3840 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3841 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3843 op_loop_domain_side->getOpPtrVector().push_back(
3844 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3845 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3846 op_loop_domain_side->getOpPtrVector().push_back(
3848 flux_mat_ptr));
3849 op_loop_domain_side->getOpPtrVector().push_back(
3850 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3851 pip.push_back(op_loop_domain_side);
3852 return broken_data_ptr;
3853 };
3854
3855 auto set_rhs = [&]() {
3857
3858 auto broken_data_ptr = get_broken_op_side(fe_rhs->getOpPtrVector());
3859
3860 fe_rhs->getOpPtrVector().push_back(
3861 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
3862 fe_rhs->getOpPtrVector().push_back(new OpAnalyticalDispBc(
3864 timeScaleMap));
3865 fe_rhs->getOpPtrVector().push_back(new OpRotationBc(
3866 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
3867
3868 auto piola_scale_ptr = boost::make_shared<double>(1.0);
3869 fe_rhs->getOpPtrVector().push_back(
3871 piola_scale_ptr, timeScaleMap));
3872 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3873 // if you push gradient of L2 base to physical element, it will not work.
3874 fe_rhs->getOpPtrVector().push_back(
3876 hybridSpatialDisp, hybrid_grad_ptr));
3877 fe_rhs->getOpPtrVector().push_back(new OpBrokenPressureBc(
3879 hybrid_grad_ptr, timeScaleMap));
3880 fe_rhs->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc(
3882 timeScaleMap));
3883
3884 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3885 fe_rhs->getOpPtrVector().push_back(
3887 hybrid_ptr));
3888 fe_rhs->getOpPtrVector().push_back(new OpNormalDispRhsBc(
3889 hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
3891
3892 auto get_normal_disp_bc_faces = [&]() {
3893 auto faces =
3894 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3895 return boost::make_shared<Range>(faces);
3896 };
3897
3898 using BoundaryEle =
3900 using BdyEleOp = BoundaryEle::UserDataOperator;
3902 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3903 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
3904 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
3905 get_normal_disp_bc_faces()));
3906
3908 };
3909
3910 auto set_lhs = [&]() {
3912
3913 auto broken_data_ptr = get_broken_op_side(fe_lhs->getOpPtrVector());
3914
3915 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dU(
3917 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dP(
3919 timeScaleMap));
3920
3921 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
3922 // if you push gradient of L2 base to physical element, it will not work.
3923 fe_lhs->getOpPtrVector().push_back(
3925 hybridSpatialDisp, hybrid_grad_ptr));
3926 fe_lhs->getOpPtrVector().push_back(new OpBrokenPressureBcLhs_dU(
3928 timeScaleMap));
3929
3930 auto get_normal_disp_bc_faces = [&]() {
3931 auto faces =
3932 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
3933 return boost::make_shared<Range>(faces);
3934 };
3935
3936 using BoundaryEle =
3938 using BdyEleOp = BoundaryEle::UserDataOperator;
3940 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3941 fe_lhs->getOpPtrVector().push_back(new OpC(
3942 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
3943 true, true, get_normal_disp_bc_faces()));
3944
3946 };
3947
3948 CHKERR set_rhs();
3949 CHKERR set_lhs();
3950 }
3951
3953}
@ GAUSS
Gaussian quadrature integration.
constexpr AssemblyType A
Apply rotation boundary condition.
BoundaryEle::UserDataOperator BdyEleOp

◆ setFaceInterfaceOps()

MoFEMErrorCode EshelbianCore::setFaceInterfaceOps ( const bool  add_elastic,
const bool  add_material,
boost::shared_ptr< FaceElementForcesAndSourcesCore > &  fe_rhs,
boost::shared_ptr< FaceElementForcesAndSourcesCore > &  fe_lhs 
)

◆ setNewFrontCoordinates()

MoFEMErrorCode EshelbianCore::setNewFrontCoordinates ( )

Definition at line 2061 of file EshelbianFracture.cpp.

2061 {
2063
2064 if (!maxMovedFaces)
2066
2067 Tag th_front_position;
2068 auto rval =
2069 mField.get_moab().tag_get_handle("FrontPosition", th_front_position);
2070 if (rval == MB_SUCCESS && maxMovedFaces) {
2071 Range verts;
2072 CHKERR mField.get_moab().get_connectivity(*maxMovedFaces, verts, true);
2073 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(verts);
2074 std::vector<double> coords(3 * verts.size());
2075 CHKERR mField.get_moab().get_coords(verts, coords.data());
2076 std::vector<double> pos(3 * verts.size());
2077 CHKERR mField.get_moab().tag_get_data(th_front_position, verts, pos.data());
2078 for (int i = 0; i != 3 * verts.size(); ++i) {
2079 coords[i] += pos[i];
2080 }
2081 CHKERR mField.get_moab().set_coords(verts, coords.data());
2082 double zero[] = {0., 0., 0.};
2083 CHKERR mField.get_moab().tag_clear_data(th_front_position, verts, zero);
2084 }
2085
2086#ifndef NDEBUG
2087 constexpr bool debug = false;
2088 if (debug) {
2089
2091 mField.get_moab(),
2092 "set_coords_faces_" +
2093 boost::lexical_cast<std::string>(mField.get_comm_rank()) + ".vtk",
2094 *maxMovedFaces);
2095 }
2096#endif
2098}

◆ setVolumeElementOps()

MoFEMErrorCode EshelbianCore::setVolumeElementOps ( const int  tag,
const bool  add_elastic,
const bool  add_material,
boost::shared_ptr< VolumeElementForcesAndSourcesCore > &  fe_rhs,
boost::shared_ptr< VolumeElementForcesAndSourcesCore > &  fe_lhs 
)

Contact requires that body is marked

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3151 of file EshelbianPlasticity.cpp.

3154 {
3156
3157 /** Contact requires that body is marked */
3158 auto get_body_range = [this](auto name, int dim) {
3159 std::map<int, Range> map;
3160
3161 for (auto m_ptr :
3162 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
3163
3164 (boost::format("%s(.*)") % name).str()
3165
3166 ))
3167
3168 ) {
3169 Range ents;
3170 CHK_MOAB_THROW(m_ptr->getMeshsetIdEntitiesByDimension(mField.get_moab(),
3171 dim, ents, true),
3172 "by dim");
3173 map[m_ptr->getMeshsetId()] = ents;
3174 }
3175
3176 return map;
3177 };
3178
3179 auto local_tau_sacale = boost::make_shared<double>(1.0);
3180 using BoundaryEle =
3182 using BdyEleOp = BoundaryEle::UserDataOperator;
3183 struct OpSetTauScale : public BdyEleOp {
3184 OpSetTauScale(boost::shared_ptr<double> local_tau_sacale, double alphaTau)
3185 : BdyEleOp(NOSPACE, BdyEleOp::OPSPACE),
3186 localTauSacale(local_tau_sacale), alphaTau(alphaTau) {}
3187 MoFEMErrorCode doWork(int side, EntityType type,
3188 EntitiesFieldData::EntData &data) override {
3190 auto &coords = BdyEleOp::getCoords();
3191 auto [centre, barycenter, h] =
3192 Tools::getTricircumcenter3d(coords.data().data());
3193 *localTauSacale = (alphaTau / h);
3195 }
3196
3197 private:
3198 boost::shared_ptr<double> localTauSacale;
3199 double alphaTau;
3200 };
3201
3202 auto not_interface_face = [this](FEMethod *fe_method_ptr) {
3203 auto ent = fe_method_ptr->getFEEntityHandle();
3204 if (
3205
3206 (interfaceFaces->find(ent) != interfaceFaces->end())
3207
3208 || (crackFaces->find(ent) != crackFaces->end())
3209
3210 ) {
3211 return false;
3212 };
3213 return true;
3214 };
3215
3216 // Right hand side
3217 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3218 CHKERR setBaseVolumeElementOps(tag, true, false, true, fe_rhs);
3219
3220 // elastic
3221 if (add_elastic) {
3222
3223 fe_rhs->getOpPtrVector().push_back(
3225 fe_rhs->getOpPtrVector().push_back(
3227 if (stretchHandling == NO_STREACH) {
3228 // do nothing - no stretch approximation
3229 } else {
3230 if (!internalStressTagName.empty()) {
3231 switch (meshTransferInterpOrder) {
3232 case 0:
3233 fe_rhs->getOpPtrVector().push_back(
3235 break;
3236 case 1:
3237 fe_rhs->getOpPtrVector().push_back(
3239 break;
3240 default:
3241 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3242 "Unsupported mesh transfer interpolation order %d, for "
3243 "internal stress",
3245 }
3246 // set default time scaling for interal stresses to constant
3247 TimeScale::ScalingFun def_scaling_fun = [](double time) { return 1; };
3248 auto ts_internal_stress =
3249 boost::make_shared<DynamicRelaxationTimeScale>(
3250 "internal_stress_history.txt", false, def_scaling_fun);
3251 if (internalStressVoigt) {
3252 fe_rhs->getOpPtrVector().push_back(
3254 stretchTensor, dataAtPts, ts_internal_stress));
3255 } else {
3256 fe_rhs->getOpPtrVector().push_back(
3258 stretchTensor, dataAtPts, ts_internal_stress));
3259 }
3260 }
3261 if (auto op = physicalEquations->returnOpSpatialPhysicalExternalStrain(
3263 fe_rhs->getOpPtrVector().push_back(op);
3264 } else if (externalStrainVecPtr && !externalStrainVecPtr->empty()) {
3265 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
3266 "OpSpatialPhysicalExternalStrain not implemented for this "
3267 "material");
3268 }
3269
3270 fe_rhs->getOpPtrVector().push_back(
3271 physicalEquations->returnOpSpatialPhysical(stretchTensor, dataAtPts,
3272 alphaU));
3273 }
3274 fe_rhs->getOpPtrVector().push_back(
3276 fe_rhs->getOpPtrVector().push_back(
3278 fe_rhs->getOpPtrVector().push_back(
3280
3281 auto set_hybridisation_rhs = [&](auto &pip) {
3283
3284 using BoundaryEle =
3286 using EleOnSide =
3288 using SideEleOp = EleOnSide::UserDataOperator;
3289 using BdyEleOp = BoundaryEle::UserDataOperator;
3290
3291 // First: Iterate over skeleton FEs adjacent to Domain FEs
3292 // Note: BoundaryEle, i.e. uses skeleton interation rule
3293 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3294 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3295 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3296 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3297 return -1;
3298 };
3299 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3300 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3301
3302 CHKERR EshelbianPlasticity::
3303 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3304 op_loop_skeleton_side->getOpPtrVector(), {L2},
3306
3307 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3308 // domain element.
3309 auto broken_data_ptr =
3310 boost::make_shared<std::vector<BrokenBaseSideData>>();
3311 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3312 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3313 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3314 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3315 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3316 CHKERR
3317 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3318 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3320 op_loop_domain_side->getOpPtrVector().push_back(
3321 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3322 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3323 op_loop_domain_side->getOpPtrVector().push_back(
3325 flux_mat_ptr));
3326 op_loop_domain_side->getOpPtrVector().push_back(
3327 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3328
3329 // Assemble on skeleton
3330 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3332 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
3334 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3335 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dHybrid(
3336 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
3337 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3338 op_loop_skeleton_side->getOpPtrVector().push_back(
3340 hybrid_ptr));
3341 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dBroken(
3342 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
3343
3344 // Add skeleton to domain pipeline
3345 pip.push_back(op_loop_skeleton_side);
3346
3348 };
3349
3350 auto set_tau_stabilsation_rhs = [&](auto &pip, auto side_fe_name,
3351 auto hybrid_field) {
3353
3354 using BoundaryEle =
3356 using EleOnSide =
3358 using SideEleOp = EleOnSide::UserDataOperator;
3359 using BdyEleOp = BoundaryEle::UserDataOperator;
3360
3361 // First: Iterate over skeleton FEs adjacent to Domain FEs
3362 // Note: BoundaryEle, i.e. uses skeleton interation rule
3363 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3364 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3365 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3366 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3367 return -1;
3368 };
3369 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3370 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3371 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3372 CHKERR EshelbianPlasticity::
3373 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3374 op_loop_skeleton_side->getOpPtrVector(), {L2},
3376
3377 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3378 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3379 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3380 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3381 CHKERR
3382 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3383 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3385
3386 // Add stabilization operator
3387 auto broken_disp_data_ptr =
3388 boost::make_shared<std::vector<BrokenBaseSideData>>();
3389 op_loop_domain_side->getOpPtrVector().push_back(
3391 broken_disp_data_ptr));
3392 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3393 op_loop_domain_side->getOpPtrVector().push_back(
3395 disp_mat_ptr));
3396 // Set diag fluxes on skeleton side
3397 op_loop_domain_side->getOpPtrVector().push_back(
3398 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3399
3400 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3401 op_loop_skeleton_side->getOpPtrVector().push_back(
3402 new OpSetTauScale(local_tau_sacale, alphaTau));
3403
3404 // Add stabilization Ugamma Ugamma skeleton
3405 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3406 op_loop_skeleton_side->getOpPtrVector().push_back(
3408 hybrid_ptr));
3409
3410 // Diag u_gamma - u_gamma faces
3411 op_loop_skeleton_side->getOpPtrVector().push_back(
3413 hybrid_field, hybrid_ptr,
3414 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3415 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3416 }));
3417 // Diag L2 - L2 volumes
3418 op_loop_skeleton_side->getOpPtrVector().push_back(
3420 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3421 return (*local_tau_sacale);
3422 }));
3423 // Off-diag Ugamma - L2
3424 op_loop_skeleton_side->getOpPtrVector().push_back(
3426 hybrid_field, broken_disp_data_ptr,
3427 [local_tau_sacale](double, double, double) {
3428 return -(*local_tau_sacale);
3429 }));
3430 // Off-diag L2 - Ugamma
3431 op_loop_skeleton_side->getOpPtrVector().push_back(
3433 broken_disp_data_ptr, hybrid_ptr,
3434 [local_tau_sacale](double, double, double) {
3435 return -(*local_tau_sacale);
3436 }));
3437
3438 // Add skeleton to domain pipeline
3439 pip.push_back(op_loop_skeleton_side);
3440
3442 };
3443
3444 auto set_tau_stabilsation_disp_bc_rhs = [&](auto &pip, auto side_fe_name) {
3446
3447 using BoundaryEle =
3449 using EleOnSide =
3451 using SideEleOp = EleOnSide::UserDataOperator;
3452 using BdyEleOp = BoundaryEle::UserDataOperator;
3453
3454 // First: Iterate over skeleton FEs adjacent to Domain FEs
3455 // Note: BoundaryEle, i.e. uses skeleton interation rule
3456 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3457 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3458 // op_loop_skeleton_side->getSideFEPtr()->getRuleHook = FaceRule();
3459 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3460 return -1;
3461 };
3462 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3463 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3464 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3465 CHKERR EshelbianPlasticity::
3466 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3467 op_loop_skeleton_side->getOpPtrVector(), {L2},
3469
3470 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3471 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3472 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3473 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3474 CHKERR
3475 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3476 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3478
3479 // Add stabilization operator
3480 auto broken_disp_data_ptr =
3481 boost::make_shared<std::vector<BrokenBaseSideData>>();
3482 op_loop_domain_side->getOpPtrVector().push_back(
3484 broken_disp_data_ptr));
3485 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3486 op_loop_domain_side->getOpPtrVector().push_back(
3488 disp_mat_ptr));
3489 // Set diag fluxes on skeleton side
3490 op_loop_domain_side->getOpPtrVector().push_back(
3491 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3492
3493 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3494 op_loop_skeleton_side->getOpPtrVector().push_back(
3495 new OpSetTauScale(local_tau_sacale, alphaTau));
3496
3497 // Diag L2 - L2 volumes
3498 op_loop_skeleton_side->getOpPtrVector().push_back(
3500 broken_disp_data_ptr, bcSpatialDispVecPtr, timeScaleMap,
3501 [local_tau_sacale](double, double, double) {
3502 return (*local_tau_sacale);
3503 }));
3504 op_loop_skeleton_side->getOpPtrVector().push_back(
3506 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3507 timeScaleMap, [local_tau_sacale](double, double, double) {
3508 return (*local_tau_sacale);
3509 }));
3510 op_loop_skeleton_side->getOpPtrVector().push_back(
3512 broken_disp_data_ptr, bcSpatialRotationVecPtr, timeScaleMap,
3513 [local_tau_sacale](double, double, double) {
3514 return (*local_tau_sacale);
3515 }));
3516
3517 // Add skeleton to domain pipeline
3518 pip.push_back(op_loop_skeleton_side);
3519
3521 };
3522
3523 auto set_contact_rhs = [&](auto &pip) {
3524 return pushContactOpsRhs(*this, contactTreeRhs, pip);
3525 };
3526
3527 auto set_cohesive_rhs = [&](auto &pip) {
3528 return pushCohesiveOpsRhs(
3529 *this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
3530 interfaceFaces, pip);
3531 };
3532
3533 CHKERR set_hybridisation_rhs(fe_rhs->getOpPtrVector());
3534 CHKERR set_contact_rhs(fe_rhs->getOpPtrVector());
3535 if (alphaTau > 0.0) {
3536 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), skeletonElement,
3538 CHKERR set_tau_stabilsation_disp_bc_rhs(fe_rhs->getOpPtrVector(),
3540 }
3541 if (interfaceCrack == PETSC_TRUE) {
3542 CHKERR set_cohesive_rhs(fe_rhs->getOpPtrVector());
3543 }
3544
3545 // Body forces
3546 using BodyNaturalBC =
3548 Assembly<PETSC>::LinearForm<GAUSS>;
3549 using OpBodyForce =
3550 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
3551
3552 auto body_time_scale =
3553 boost::make_shared<DynamicRelaxationTimeScale>("body_force.txt");
3554 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
3555 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
3556 "BODY_FORCE", Sev::inform);
3557 }
3558
3559 // Left hand side
3560 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3561 CHKERR setBaseVolumeElementOps(tag, true, true, true, fe_lhs);
3562
3563 // elastic
3564 if (add_elastic) {
3565
3566 if (stretchHandling == NO_STREACH) {
3568 } else {
3570 }
3571
3572 auto set_hybridisation_lhs = [&](auto &pip) {
3574
3575 using BoundaryEle =
3577 using EleOnSide =
3579 using SideEleOp = EleOnSide::UserDataOperator;
3580 using BdyEleOp = BoundaryEle::UserDataOperator;
3581
3582 // First: Iterate over skeleton FEs adjacent to Domain FEs
3583 // Note: BoundaryEle, i.e. uses skeleton interation rule
3584 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3585 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3586 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3587 return -1;
3588 };
3589 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3590 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3591 CHKERR EshelbianPlasticity::
3592 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3593 op_loop_skeleton_side->getOpPtrVector(), {L2},
3595
3596 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3597 // domain element.
3598 auto broken_data_ptr =
3599 boost::make_shared<std::vector<BrokenBaseSideData>>();
3600 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3601 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3602 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3603 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3604 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3605 CHKERR
3606 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3607 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3609 op_loop_domain_side->getOpPtrVector().push_back(
3610 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3611
3612 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3614 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3615 op_loop_skeleton_side->getOpPtrVector().push_back(
3616 new OpC(hybridSpatialDisp, broken_data_ptr,
3617 boost::make_shared<double>(1.0), true, false));
3618
3619 pip.push_back(op_loop_skeleton_side);
3620
3622 };
3623
3624 auto set_tau_stabilsation_lhs = [&](auto &pip, auto side_fe_name,
3625 auto hybrid_field) {
3627
3628 using BoundaryEle =
3630 using EleOnSide =
3632 using SideEleOp = EleOnSide::UserDataOperator;
3633 using BdyEleOp = BoundaryEle::UserDataOperator;
3634
3635 // First: Iterate over skeleton FEs adjacent to Domain FEs
3636 // Note: BoundaryEle, i.e. uses skeleton interation rule
3637 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3638 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3639 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3640 return -1;
3641 };
3642 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3643 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3644 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3645 CHKERR EshelbianPlasticity::
3646 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3647 op_loop_skeleton_side->getOpPtrVector(), {L2},
3649
3650 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3651 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3652 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3653 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3654 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3655 CHKERR
3656 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3657 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3659
3660 auto broken_disp_data_ptr =
3661 boost::make_shared<std::vector<BrokenBaseSideData>>();
3662 op_loop_domain_side->getOpPtrVector().push_back(
3664 broken_disp_data_ptr));
3665 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3666 op_loop_skeleton_side->getOpPtrVector().push_back(
3667 new OpSetTauScale(local_tau_sacale, alphaTau));
3668
3669 // Diag Ugamma-Ugamma skeleton
3670 op_loop_skeleton_side->getOpPtrVector().push_back(new OpMassVectorFace(
3671 hybrid_field, hybrid_field,
3672 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3673 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3674 }));
3675 // Diag L2-L2 volumes
3676 op_loop_skeleton_side->getOpPtrVector().push_back(
3678 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3679 return (*local_tau_sacale);
3680 }));
3681 // Off-diag Ugamma - L2
3682 op_loop_skeleton_side->getOpPtrVector().push_back(
3684 hybrid_field, broken_disp_data_ptr,
3685 [local_tau_sacale](double, double, double) {
3686 return -(*local_tau_sacale);
3687 },
3688 false, false));
3689 // Off-diag L2 - Ugamma
3690 op_loop_skeleton_side->getOpPtrVector().push_back(
3692 hybrid_field, broken_disp_data_ptr,
3693 [local_tau_sacale](double, double, double) {
3694 return -(*local_tau_sacale);
3695 },
3696 true, true));
3697
3698 pip.push_back(op_loop_skeleton_side);
3699
3701 };
3702
3703 auto set_tau_stabilsation_disp_bc_lhs = [&](auto &pip, auto side_fe_name) {
3705
3706 using BoundaryEle =
3708 using EleOnSide =
3710 using SideEleOp = EleOnSide::UserDataOperator;
3711 using BdyEleOp = BoundaryEle::UserDataOperator;
3712
3713 // First: Iterate over skeleton FEs adjacent to Domain FEs
3714 // Note: BoundaryEle, i.e. uses skeleton interation rule
3715 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3716 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3717 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3718 return -1;
3719 };
3720 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3721 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3722 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3723 CHKERR EshelbianPlasticity::
3724 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3725 op_loop_skeleton_side->getOpPtrVector(), {L2},
3727
3728 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3729 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3730 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3731 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3732 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3733 CHKERR
3734 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3735 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3737
3738 auto broken_disp_data_ptr =
3739 boost::make_shared<std::vector<BrokenBaseSideData>>();
3740 op_loop_domain_side->getOpPtrVector().push_back(
3742 broken_disp_data_ptr));
3743 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3744 op_loop_skeleton_side->getOpPtrVector().push_back(
3745 new OpSetTauScale(local_tau_sacale, alphaTau));
3746
3747 // Diag L2-L2 volumes
3748 op_loop_skeleton_side->getOpPtrVector().push_back(
3750 broken_disp_data_ptr, bcSpatialDispVecPtr,
3751 [local_tau_sacale](double, double, double) {
3752 return (*local_tau_sacale);
3753 }));
3754 op_loop_skeleton_side->getOpPtrVector().push_back(
3756 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3757 [local_tau_sacale](double, double, double) {
3758 return (*local_tau_sacale);
3759 }));
3760 op_loop_skeleton_side->getOpPtrVector().push_back(
3762 broken_disp_data_ptr, bcSpatialRotationVecPtr,
3763 [local_tau_sacale](double, double, double) {
3764 return (*local_tau_sacale);
3765 }));
3766
3767 pip.push_back(op_loop_skeleton_side);
3768
3770 };
3771
3772 auto set_contact_lhs = [&](auto &pip) {
3773 return pushContactOpsLhs(*this, contactTreeRhs, pip);
3774 };
3775
3776 auto set_cohesive_lhs = [&](auto &pip) {
3777 return pushCohesiveOpsLhs(
3778 *this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
3779 interfaceFaces, pip);
3780 };
3781
3782 CHKERR set_hybridisation_lhs(fe_lhs->getOpPtrVector());
3783 CHKERR set_contact_lhs(fe_lhs->getOpPtrVector());
3784 if (alphaTau > 0.0) {
3785 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), skeletonElement,
3787 CHKERR set_tau_stabilsation_disp_bc_lhs(fe_lhs->getOpPtrVector(),
3789 }
3790 if (interfaceCrack == PETSC_TRUE) {
3791 CHKERR set_cohesive_lhs(fe_lhs->getOpPtrVector());
3792 }
3793 }
3794
3795 if (add_material) {
3796 }
3797
3799}
FormsIntegrators< FaceElementForcesAndSourcesCore::UserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMassVectorFace
@ NOSPACE
Definition definitions.h:83
MoFEMErrorCode pushContactOpsRhs(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Push contact operations to the right-hand side.
MoFEMErrorCode pushContactOpsLhs(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > contact_tree_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Push contact operations to the left-hand side.
MoFEMErrorCode pushCohesiveOpsLhs(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
MoFEMErrorCode pushCohesiveOpsRhs(EshelbianCore &ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, boost::shared_ptr< Range > interface_range_ptr, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
double h
MoFEMErrorCode pushNoStretchVolumeA00Ops(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
MoFEMErrorCode setBaseVolumeElementOps(const int tag, const bool do_rhs, const bool do_lhs, const bool calc_rates, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, const bool add_bubble=true)
MoFEMErrorCode pushStretchVolumeA00Ops(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)
Natural boundary conditions.
Definition Natural.hpp:57
Operator for broken loop side.
static std::tuple< std::array< double, 3 >, std::array< double, 2 >, double > getTricircumcenter3d(double *coords_ptr)
Calculate triangle circumcenter in 3d.
Definition Tools.cpp:878

◆ solveCohesiveCrackGrowth()

MoFEMErrorCode EshelbianCore::solveCohesiveCrackGrowth ( TS  ts,
Vec  x,
int  start_step,
double  start_time 
)

Solve cohesive crack growth problem.

Parameters
ts
x
Returns
* MoFEMErrorCode
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 5608 of file EshelbianPlasticity.cpp.

5610 {
5612
5613 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5614
5615 auto cohesive_tao_ctx = createCohesiveTAOCtx(
5616 this, SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
5617 SmartPetscObj<TS>(ts, true));
5618
5619 // Deprecated options
5620 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
5621
5622 CHKERR PetscOptionsScalar("-dynamic_final_time",
5623 "dynamic relaxation final time", "",
5624 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
5625 CHKERR PetscOptionsScalar("-dynamic_delta_time",
5626 "dynamic relaxation final time", "", physicalDt,
5627 &physicalDt, PETSC_NULLPTR);
5628 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
5629 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
5630 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
5631 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
5632
5633 PetscOptionsEnd();
5634
5635 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
5636 MOFEM_LOG("EP", Sev::inform)
5637 << "Dynamic relaxation final time -dynamic_final_time = "
5639 MOFEM_LOG("EP", Sev::inform)
5640 << "Dynamic relaxation delta time -dynamic_delta_time = "
5641 << physicalDt;
5642 MOFEM_LOG("EP", Sev::inform)
5643 << "Dynamic relaxation max iterations -dynamic_max_it = " << physicalMaxSteps;
5644 MOFEM_LOG("EP", Sev::inform)
5645 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
5646 << (physicalH1Update ? "TRUE" : "FALSE");
5647
5650
5651 auto setup_ts_monitor = [&]() {
5652 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5653 return monitor_ptr;
5654 };
5655 auto monitor_ptr = setup_ts_monitor();
5656
5657 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5658 {elasticFeLhs.get(), elasticFeRhs.get()});
5659 CHKERR TSSetUp(ts);
5660 CHKERR TSElasticPostStep::postStepInitialise(this);
5661
5662 double ts_delta_time;
5663 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5664
5665 if (physicalH1Update) {
5666 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5667 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5668 }
5669
5670 auto tao = createTao(mField.get_comm());
5671 CHKERR TaoSetType(tao, TAOLMVM);
5672 auto g = cohesive_tao_ctx->duplicateGradientVec();
5674 cohesiveEvaluateObjectiveAndGradient,
5675 (void *)cohesive_tao_ctx.get());
5676
5677 currentPhysicalTime = start_time;
5678 physicalStepNumber = start_step;
5679 monitor_ptr->ts = PETSC_NULLPTR;
5680 monitor_ptr->ts_u = PETSC_NULLPTR;
5681 monitor_ptr->ts_t = currentPhysicalTime;
5682 monitor_ptr->ts_step = physicalStepNumber;
5684
5685 auto tao_sol0 = cohesive_tao_ctx->duplicateKappaVec();
5686 int tao_sol_size, tao_sol_loc_size;
5687 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
5688 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
5689 MOFEM_LOG("EP", Sev::inform)
5690 << "Cohesive crack growth initial kappa vector size " << tao_sol_size
5691 << " local size " << tao_sol_loc_size << " number of interface faces "
5692 << interfaceFaces->size();
5693
5694 CHKERR TaoSetFromOptions(tao);
5695
5696 auto xl = vectorDuplicate(tao_sol0);
5697 auto xu = vectorDuplicate(tao_sol0);
5698 CHKERR VecSet(xl, 0.0);
5699 CHKERR VecSet(xu, PETSC_INFINITY);
5700 CHKERR TaoSetVariableBounds(tao, xl, xu);
5701
5702 if (physicalDt <= 0.) {
5704 "physicalDt must be positive, got %g", physicalDt);
5705 }
5707 MOFEM_LOG("EP", Sev::inform)
5708 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
5709 << " delta time " << physicalDt;
5710
5711 CHKERR VecZeroEntries(tao_sol0);
5712 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5713 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
5714 CHKERR TaoSetSolution(tao, tao_sol0);
5715
5716 if (!physicalH1Update && physicalStepNumber > start_step) {
5717 CHKERR TSElasticPostStep::preStepFun(ts);
5718 }
5719 CHKERR TaoSolve(tao);
5720
5721 Vec tao_sol;
5722 CHKERR TaoGetSolution(tao, &tao_sol);
5723
5724 // add solution increment to kappa vec/tags
5725 auto &kappa_vec = cohesive_tao_ctx->getKappaVec();
5728 CHKERR VecAXPY(kappa_vec.second, 1.0, tao_sol);
5729 CHKERR VecGhostUpdateBegin(kappa_vec.second, INSERT_VALUES,
5730 SCATTER_FORWARD);
5731 CHKERR VecGhostUpdateEnd(kappa_vec.second, INSERT_VALUES, SCATTER_FORWARD);
5734
5735 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
5736 SCATTER_FORWARD);
5737 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
5738 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
5739 monitor_ptr->ts = PETSC_NULLPTR;
5740 monitor_ptr->ts_u = x;
5741 monitor_ptr->ts_t = currentPhysicalTime;
5742 monitor_ptr->ts_step = physicalStepNumber;
5744
5745 if (!physicalH1Update) {
5746 CHKERR TSElasticPostStep::postStepFun(ts);
5747 }
5748
5751 break;
5752
5753 const double remainingPhysicalTime =
5755 if (physicalDt >= remainingPhysicalTime) {
5757 } else {
5759 }
5760 }
5761
5762 CHKERR TSElasticPostStep::postStepDestroy();
5763 TetPolynomialBase::switchCacheBaseOff<HDIV>(
5764 {elasticFeLhs.get(), elasticFeRhs.get()});
5765
5767}
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
boost::shared_ptr< CohesiveTAOCtx > createCohesiveTAOCtx(EshelbianCore *ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_front_face, SmartPetscObj< TS > time_solver)
Tag get_kappa_tag(moab::Interface &moab)
MoFEMErrorCode initializeCohesiveKappaField(EshelbianCore &ep)
PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
Sets the objective function value and gradient for a TAO optimization solver.
Definition TaoCtx.cpp:178
auto createTao(MPI_Comm comm)
MoFEMErrorCode addDebugModel(TS ts)
Add debug to model.
static int physicalStepNumber
static double currentPhysicalTime
static MoFEMErrorCode setVectorFromTag(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Vector From Tag object.
static MoFEMErrorCode setTagFromVector(moab::Interface &moab, EntitiesPetscVector &vec, Tag tag)
Set the Tag From Vector object.

◆ solveDynamicRelaxation()

MoFEMErrorCode EshelbianCore::solveDynamicRelaxation ( TS  ts,
Vec  x,
int  start_step,
double  start_time 
)

Solve problem using dynamic relaxation method.

Parameters
tssolver time stepper
xsolution vector
start_stepstarting step number
start_timestarting time
Returns
MoFEMErrorCode
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 4319 of file EshelbianPlasticity.cpp.

4321 {
4323
4324 auto storage = solve_elastic_setup::setup(this, ts, x, false);
4325
4326 // Deprecated options
4327 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
4328
4329 CHKERR PetscOptionsScalar("-dynamic_final_time",
4330 "dynamic relaxation final time", "",
4331 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
4332 CHKERR PetscOptionsScalar("-dynamic_delta_time",
4333 "dynamic relaxation final time", "", physicalDt,
4334 &physicalDt, PETSC_NULLPTR);
4335 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
4336 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
4337 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
4338 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
4339
4340 PetscOptionsEnd();
4341
4342 MOFEM_LOG("EP", Sev::warning)
4343 << "Following options are deprecated, use -physical prefix options "
4344 "instead";
4345 MOFEM_LOG("EP", Sev::inform)
4346 << "Dynamic relaxation final time -dynamic_final_time = "
4348 MOFEM_LOG("EP", Sev::inform)
4349 << "Dynamic relaxation delta time -dynamic_delta_time = "
4350 << physicalDt;
4351 MOFEM_LOG("EP", Sev::inform)
4352 << "Dynamic relaxation max iterations -dynamic_max_it = " << physicalMaxSteps;
4353 MOFEM_LOG("EP", Sev::inform)
4354 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
4355 << (physicalH1Update ? "TRUE" : "FALSE");
4356
4358
4359 auto setup_ts_monitor = [&]() {
4360 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
4361 return monitor_ptr;
4362 };
4363 auto monitor_ptr = setup_ts_monitor();
4364
4365 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4366 {elasticFeLhs.get(), elasticFeRhs.get()});
4367 CHKERR TSSetUp(ts);
4368 CHKERR TSElasticPostStep::postStepInitialise(this);
4369
4370 double ts_delta_time;
4371 CHKERR TSGetTimeStep(ts, &ts_delta_time);
4372
4373 if (physicalH1Update) {
4374 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4375 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4376 }
4377
4378 CHKERR TSElasticPostStep::preStepFun(ts);
4379 CHKERR TSElasticPostStep::postStepFun(ts);
4380
4381 currentPhysicalTime = start_time;
4382 physicalStepNumber = start_step;
4383 monitor_ptr->ts = PETSC_NULLPTR;
4384 monitor_ptr->ts_u = PETSC_NULLPTR;
4385 monitor_ptr->ts_t = currentPhysicalTime;
4386 monitor_ptr->ts_step = physicalStepNumber;
4388
4389 if (physicalDt <= 0.) {
4391 "physicalDt must be positive, got %g", physicalDt);
4392 }
4394 MOFEM_LOG("EP", Sev::inform)
4395 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
4396 << " delta time " << physicalDt;
4397
4398 CHKERR TSSetStepNumber(ts, 0);
4399 CHKERR TSSetTime(ts, 0);
4400 CHKERR TSSetTimeStep(ts, ts_delta_time);
4401 if (!physicalH1Update) {
4402 CHKERR TSElasticPostStep::preStepFun(ts);
4403 }
4404 CHKERR TSSetSolution(ts, x);
4405 CHKERR TSSolve(ts, PETSC_NULLPTR);
4406 if (!physicalH1Update) {
4407 CHKERR TSElasticPostStep::postStepFun(ts);
4408 }
4409
4410 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
4411 SCATTER_FORWARD);
4412 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4413 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4414
4415 monitor_ptr->ts = PETSC_NULLPTR;
4416 monitor_ptr->ts_u = x;
4417 monitor_ptr->ts_t = currentPhysicalTime;
4418 monitor_ptr->ts_step = physicalStepNumber;
4420
4423 break;
4424
4425 const double remainingPhysicalTime =
4427 if (physicalDt >= remainingPhysicalTime) {
4429 } else {
4431 }
4432 }
4433
4434 CHKERR TSElasticPostStep::postStepDestroy();
4435 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4436 {elasticFeLhs.get(), elasticFeRhs.get()});
4437
4439}

◆ solveElastic()

MoFEMErrorCode EshelbianCore::solveElastic ( TS  ts,
Vec  x 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 4214 of file EshelbianPlasticity.cpp.

4214 {
4216
4218
4219 auto storage = solve_elastic_setup::setup(this, ts, x, true);
4220
4221 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4222 Vec xx;
4223 CHKERR VecDuplicate(x, &xx);
4224 CHKERR VecZeroEntries(xx);
4225 CHKERR TS2SetSolution(ts, x, xx);
4226 CHKERR VecDestroy(&xx);
4227 } else {
4228 CHKERR TSSetSolution(ts, x);
4229 }
4230
4231 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4232 {elasticFeLhs.get(), elasticFeRhs.get()});
4233 CHKERR TSSetUp(ts);
4234 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4235 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4236 CHKERR TSElasticPostStep::postStepInitialise(this);
4237 CHKERR TSSolve(ts, PETSC_NULLPTR);
4238 CHKERR TSElasticPostStep::postStepDestroy();
4239 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4240 {elasticFeLhs.get(), elasticFeRhs.get()});
4241
4242#ifndef NDEBUG
4243 // Make graph
4244 if (mField.get_comm_rank() == 0) {
4245 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4247 "solve_elastic_graph.dot");
4248 }
4249#endif
4250
4251 SNES snes;
4252 CHKERR TSGetSNES(ts, &snes);
4253 int lin_solver_iterations;
4254 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
4255 MOFEM_LOG("EP", Sev::inform)
4256 << "Number of linear solver iterations " << lin_solver_iterations;
4257
4258 PetscBool test_cook_flg = PETSC_FALSE;
4259 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
4260 PETSC_NULLPTR);
4261 if (test_cook_flg) {
4262 constexpr int expected_lin_solver_iterations = 11;
4263 if (lin_solver_iterations > expected_lin_solver_iterations)
4264 SETERRQ(
4265 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4266 "Expected number of iterations is different than expected %d > %d",
4267 lin_solver_iterations, expected_lin_solver_iterations);
4268 }
4269
4270 PetscBool test_sslv116_flag = PETSC_FALSE;
4271 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_sslv116",
4272 &test_sslv116_flag, PETSC_NULLPTR);
4273
4274 if (test_sslv116_flag) {
4275 double max_val = 0.0;
4276 double min_val = 0.0;
4277 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
4279 auto ent_type = ent_ptr->getEntType();
4280 if (ent_type == MBVERTEX) {
4281 max_val = std::max(ent_ptr->getEntFieldData()[SPACE_DIM - 1], max_val);
4282 min_val = std::min(ent_ptr->getEntFieldData()[SPACE_DIM - 1], min_val);
4283 }
4285 };
4286 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(
4287 field_min_max, spatialH1Disp);
4288
4289 double global_max_val = 0.0;
4290 double global_min_val = 0.0;
4291 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
4292 mField.get_comm());
4293 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
4294 mField.get_comm());
4295 MOFEM_LOG("EP", Sev::inform)
4296 << "Max " << spatialH1Disp << " value: " << global_max_val;
4297 MOFEM_LOG("EP", Sev::inform)
4298 << "Min " << spatialH1Disp << " value: " << global_min_val;
4299
4300 double ref_max_val = 0.00767;
4301 double ref_min_val = -0.00329;
4302 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
4303 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4304 "Incorrect max value of the displacement field: %f != %f",
4305 global_max_val, ref_max_val);
4306 }
4307 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
4308 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4309 "Incorrect min value of the displacement field: %f != %f",
4310 global_min_val, ref_min_val);
4311 }
4312 }
4313
4315
4317}
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
MoFEMErrorCode gettingNorms()
[Getting norms]
static MoFEMErrorCode writeTSGraphGraphviz(TsCtx *ts_ctx, std::string file_name)
TS graph to Graphviz file.

◆ solveLoadFactor()

MoFEMErrorCode EshelbianCore::solveLoadFactor ( TS  ts,
Vec  x,
int  start_step,
double  start_time 
)

Solve load factor crack growth problem.

Parameters
ts
x
Returns
* MoFEMErrorCode
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 5769 of file EshelbianPlasticity.cpp.

5770 {
5772
5773 loadFactorTSSolveExecuted = PETSC_FALSE;
5774
5775 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5776
5778
5779 auto setup_ts_monitor = [&]() {
5780 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5781 return monitor_ptr;
5782 };
5783 auto monitor_ptr = setup_ts_monitor();
5784
5785 auto test_monitor_ptr =
5786 boost::make_shared<EshelbianTestingMonitor>(*this, monitor_ptr);
5787
5788 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5789 {elasticFeLhs.get(), elasticFeRhs.get()});
5790 CHKERR TSSetUp(ts);
5791 CHKERR TSElasticPostStep::postStepInitialise(this);
5792
5793 double ts_delta_time;
5794 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5795
5796 if (physicalH1Update) {
5797 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5798 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5799 }
5800
5801 CHKERR TSElasticPostStep::preStepFun(ts);
5802 CHKERR TSElasticPostStep::postStepFun(ts);
5803
5804 double load_factor_change_clip = 0.1;
5805
5806 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Load Factor Options", "none");
5807
5808 CHKERR PetscOptionsScalar("-initial_load_factor", "Initial load factor", "",
5809 loadFactor, &loadFactor, PETSC_NULLPTR);
5810 CHKERR PetscOptionsScalar("-max_crack_ext_area",
5811 "Maximum crack extension area", "",
5813 PETSC_NULLPTR);
5814 CHKERR PetscOptionsScalar("-clip_load_factor_percent",
5815 "Upper bound for load factor change", "",
5816 load_factor_change_clip,
5817 &load_factor_change_clip, PETSC_NULLPTR);
5818 PetscOptionsEnd();
5819
5820 currentPhysicalTime = start_time;
5821 physicalStepNumber = start_step;
5822 monitor_ptr->ts = ts;
5823 monitor_ptr->ts_u = PETSC_NULLPTR;
5824 monitor_ptr->ts_t = currentPhysicalTime;
5825 monitor_ptr->ts_step = physicalStepNumber;
5827
5828 PetscBool test_cook_flg = PETSC_FALSE;
5829 PetscInt atom_test = 0;
5830 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
5831 PETSC_NULLPTR);
5832 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
5833 PETSC_NULLPTR);
5834 if (atom_test || test_cook_flg) {
5835 test_monitor_ptr->ts = ts;
5836 test_monitor_ptr->ts_u = PETSC_NULLPTR;
5837 test_monitor_ptr->ts_t = currentPhysicalTime;
5838 test_monitor_ptr->ts_step = physicalStepNumber;
5839
5841 test_monitor_ptr);
5842 }
5843
5844 MOFEM_LOG("EP", Sev::inform)
5845 << "Initial crack area: " << *currentCrackAreaPtr;
5846 MOFEM_LOG("EP", Sev::inform) << "Initial load factor: " << loadFactor;
5847 MOFEM_LOG("EP", Sev::inform)
5848 << "Initial crack front energy: " << avgGriffithsEnergy;
5849
5851 MOFEM_LOG("EP", Sev::inform)
5852 << "Load step " << physicalStepNumber << " Load Factor "
5853 << currentPhysicalTime << " delta load factor " << physicalDt;
5854
5858
5859 CHKERR TSSetStepNumber(ts, 0);
5860 CHKERR TSSetTime(ts, 0);
5861 CHKERR TSSetTimeStep(ts, ts_delta_time);
5862 if (!physicalH1Update) {
5863 CHKERR TSElasticPostStep::preStepFun(ts);
5864 }
5865 CHKERR TSSetSolution(ts, x);
5866 CHKERR TSSolve(ts, PETSC_NULLPTR);
5867 loadFactorTSSolveExecuted = PETSC_TRUE;
5868 if (!physicalH1Update) {
5869 CHKERR TSElasticPostStep::postStepFun(ts);
5870 }
5871
5872 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
5873 SCATTER_FORWARD);
5874 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
5875 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
5876
5877 monitor_ptr->ts = ts;
5878 monitor_ptr->ts_u = x;
5879 monitor_ptr->ts_t = currentPhysicalTime;
5880 monitor_ptr->ts_step = physicalStepNumber;
5882
5883 if (atom_test || test_cook_flg) {
5884 test_monitor_ptr->ts = ts;
5885 test_monitor_ptr->ts_u = x;
5886 test_monitor_ptr->ts_t = currentPhysicalTime;
5887 test_monitor_ptr->ts_step = physicalStepNumber;
5889 test_monitor_ptr);
5890 }
5891
5892 if (mField.get_comm_rank() == 0) {
5893 const double delta_area = *currentCrackAreaPtr - oldCrackArea;
5894 const bool has_crack_extension = delta_area > 0.0;
5895
5896 if (has_crack_extension) {
5897 const double denom = 0.5 * std::abs(avgGriffithsEnergy);
5898 if (denom > 0.0) {
5899 const double updated_load_factor =
5900 oldLoadFactor * std::sqrt(griffithEnergy / denom);
5901 loadFactor = std::max(updated_load_factor, 1.0e-6);
5902 }
5903 }
5904
5905 const bool is_first_step = physicalStepNumber == start_step;
5906 const double initial_step_range = 5;
5907 const double min_load_factor = 1.0e-6;
5908 const double max_load_factor =
5909 oldLoadFactor * (1.0 + load_factor_change_clip);
5910
5911 if (physicalStepNumber >= start_step + initial_step_range) {
5912 loadFactor = std::clamp(loadFactor, min_load_factor, max_load_factor);
5913 MOFEM_LOG("EP", Sev::inform)
5914 << "Allowable range for load factor [" << min_load_factor << ", "
5915 << max_load_factor << "]";
5916 }
5917
5918 const double previous_load_factor = is_first_step ? 0. : oldLoadFactor;
5919 physicalDt = loadFactor - previous_load_factor;
5920
5921 MOFEM_LOG("EP", Sev::inform)
5922 << "Setting new load factor to: " << loadFactor;
5923 }
5924 double load_control_data[] = {physicalDt, loadFactor};
5925 CHKERR MPI_Bcast(load_control_data, 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
5926 physicalDt = load_control_data[0];
5927 loadFactor = load_control_data[1];
5928
5931 break;
5932
5933 const double remainingPhysicalTime =
5935 if (physicalDt >= remainingPhysicalTime) {
5937 } else {
5939 }
5940 }
5941
5942 CHKERR TSElasticPostStep::postStepDestroy();
5943 TetPolynomialBase::switchCacheBaseOff<HDIV>(
5944 {elasticFeLhs.get(), elasticFeRhs.get()});
5945 MOFEM_LOG("EP", Sev::inform) << "Final load factor: " << loadFactor;
5946
5948}
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscBool loadFactorTSSolveExecuted
static double maxCrackExtension
boost::shared_ptr< double > currentCrackAreaPtr
int atom_test
Atom test.
Definition plastic.cpp:122

◆ solveSchapeOptimisation()

MoFEMErrorCode EshelbianCore::solveSchapeOptimisation ( TS  ts,
Vec  x,
int  start_step,
double  start_time 
)

Solve shape optimisation problem.

Parameters
ts
x
Returns
* MoFEMErrorCode
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 5950 of file EshelbianPlasticity.cpp.

5952 {
5954
5955 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5956
5957 auto topological_tao_ctx = createTopologicalTAOCtx(
5958 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
5959 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
5960 SmartPetscObj<TS>(ts, true));
5961
5962 double final_time = 1;
5963 double delta_time = 0.1;
5964 int max_it = 10;
5965 PetscBool ts_h1_update = PETSC_FALSE;
5966
5967 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
5968
5969 CHKERR PetscOptionsScalar("-dynamic_final_time",
5970 "dynamic relaxation final time", "", final_time,
5971 &final_time, PETSC_NULLPTR);
5972 CHKERR PetscOptionsScalar("-dynamic_delta_time",
5973 "dynamic relaxation final time", "", delta_time,
5974 &delta_time, PETSC_NULLPTR);
5975 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
5976 max_it, &max_it, PETSC_NULLPTR);
5977 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
5978 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
5979
5980 PetscOptionsEnd();
5981
5982 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
5983 MOFEM_LOG("EP", Sev::inform)
5984 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
5985 MOFEM_LOG("EP", Sev::inform)
5986 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
5987 MOFEM_LOG("EP", Sev::inform)
5988 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
5989 MOFEM_LOG("EP", Sev::inform)
5990 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
5991 << (ts_h1_update ? "TRUE" : "FALSE");
5992
5994
5995 auto setup_ts_monitor = [&]() {
5996 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5997 return monitor_ptr;
5998 };
5999 auto monitor_ptr = setup_ts_monitor();
6000
6001 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6002 {elasticFeLhs.get(), elasticFeRhs.get()});
6003 CHKERR TSSetUp(ts);
6004 CHKERR TSElasticPostStep::postStepInitialise(this);
6005
6006 double ts_delta_time;
6007 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6008
6009 if (ts_h1_update) {
6010 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6011 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6012 }
6013
6014 CHKERR TSElasticPostStep::preStepFun(ts);
6015 CHKERR TSElasticPostStep::postStepFun(ts);
6016
6017 auto tao = createTao(mField.get_comm());
6018 CHKERR TaoSetType(tao, TAOLMVM);
6021 topologicalEvaluateObjectiveAndGradient,
6022 (void *)topological_tao_ctx.get());
6023
6024 currentPhysicalTime = start_time;
6025 physicalStepNumber = start_step;
6026 monitor_ptr->ts = PETSC_NULLPTR;
6027 monitor_ptr->ts_u = PETSC_NULLPTR;
6028 monitor_ptr->ts_t = currentPhysicalTime;
6029 monitor_ptr->ts_step = physicalStepNumber;
6031
6032 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6033 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6034 SCATTER_FORWARD, RowColData::ROW);
6035 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6036 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6037
6038 int tao_sol_size, tao_sol_loc_size;
6039 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6040 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6041 MOFEM_LOG("EP", Sev::inform)
6042 << "Toplogical data vector size " << tao_sol_size << " local size "
6043 << tao_sol_loc_size << " number of interface faces "
6044 << interfaceFaces->size();
6045
6046 CHKERR TaoSetFromOptions(tao);
6047
6048 if (delta_time <= 0.) {
6050 "delta_time must be positive, got %g", delta_time);
6051 }
6052 for (; currentPhysicalTime < final_time;) {
6053 MOFEM_LOG("EP", Sev::inform)
6054 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
6055 << " delta time " << delta_time;
6056
6057 CHKERR VecZeroEntries(tao_sol0);
6058 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6059 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6060 CHKERR TaoSetSolution(tao, tao_sol0);
6061 CHKERR TaoSolve(tao);
6062 Vec tao_sol;
6063 CHKERR TaoGetSolution(tao, &tao_sol);
6064
6065 // // add solution increment to kappa vec/tags
6066 // auto &kappa_vec = topological_tao_ctx->getKappaVec();
6067 // CHKERR CommInterface::setVectorFromTag(mField.get_moab(), kappa_vec,
6068 // get_kappa_tag(mField.get_moab()));
6069 // CHKERR VecAXPY(kappa_vec.second, 1.0, tao_sol);
6070 // CHKERR VecGhostUpdateBegin(kappa_vec.second, INSERT_VALUES,
6071 // SCATTER_FORWARD);
6072 // CHKERR VecGhostUpdateEnd(kappa_vec.second, INSERT_VALUES, SCATTER_FORWARD);
6073 // CHKERR CommInterface::setTagFromVector(mField.get_moab(), kappa_vec,
6074 // get_kappa_tag(mField.get_moab()));
6075
6076
6077 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6078 SCATTER_FORWARD);
6079 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6080 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6081 monitor_ptr->ts = PETSC_NULLPTR;
6082 monitor_ptr->ts_u = x;
6083 monitor_ptr->ts_t = currentPhysicalTime;
6084 monitor_ptr->ts_step = physicalStepNumber;
6086
6088 if (physicalStepNumber > max_it)
6089 break;
6090
6091 const double remainingPhysicalTime = final_time - currentPhysicalTime;
6092 if (delta_time >= remainingPhysicalTime) {
6093 currentPhysicalTime = final_time;
6094 } else {
6095 currentPhysicalTime += delta_time;
6096 }
6097 }
6098
6099 CHKERR TSElasticPostStep::postStepDestroy();
6100 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6101 {elasticFeLhs.get(), elasticFeRhs.get()});
6102
6104}

◆ solveTestTopologicalDerivative()

MoFEMErrorCode EshelbianCore::solveTestTopologicalDerivative ( TS  ts,
Vec  x,
int  start_step,
double  start_time 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp, ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 6106 of file EshelbianPlasticity.cpp.

6108 {
6110
6111 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6112
6113 auto topological_tao_ctx = createTopologicalTAOCtx(
6114 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6115 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6116 SmartPetscObj<TS>(ts, true));
6117
6118 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6120
6121 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6122
6123 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6124 {elasticFeLhs.get(), elasticFeRhs.get()});
6125 CHKERR TSSetUp(ts);
6126 CHKERR TSElasticPostStep::postStepInitialise(this);
6127
6128 double ts_delta_time;
6129 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6130
6131 if (physicalH1Update) {
6132 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6133 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6134 }
6135
6136 CHKERR TSElasticPostStep::preStepFun(ts);
6137 CHKERR TSElasticPostStep::postStepFun(ts);
6138
6139 const bool restart_run =
6140 start_step != 0 ||
6141 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6142 const double test_time = restart_run ? start_time : finalPhysicalTime;
6143 if (!restart_run &&
6144 std::abs(test_time) < std::numeric_limits<double>::epsilon()) {
6146 "Set non-zero -physical_final_time for test_topological_derivative");
6147 }
6148
6149 currentPhysicalTime = test_time;
6150 physicalStepNumber = start_step;
6151 monitor_ptr->ts = PETSC_NULLPTR;
6152 monitor_ptr->ts_u = PETSC_NULLPTR;
6153 monitor_ptr->ts_t = currentPhysicalTime;
6154 monitor_ptr->ts_step = physicalStepNumber;
6156
6157 MOFEM_LOG("EP", Sev::inform)
6158 << "Solving load step before topological derivative test: "
6159 << physicalStepNumber << " Time " << currentPhysicalTime
6160 << " TS delta time " << ts_delta_time;
6161
6162 CHKERR TSSetStepNumber(ts, 0);
6163 CHKERR TSSetTime(ts, 0);
6164 CHKERR TSSetTimeStep(ts, ts_delta_time);
6165 if (!physicalH1Update) {
6166 CHKERR TSElasticPostStep::preStepFun(ts);
6167 }
6168 CHKERR TSSetSolution(ts, x);
6169 CHKERR TSSolve(ts, PETSC_NULLPTR);
6170 if (!physicalH1Update) {
6171 CHKERR TSElasticPostStep::postStepFun(ts);
6172 }
6173
6174 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6175 SCATTER_FORWARD);
6176 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6177 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6178
6179 monitor_ptr->ts = PETSC_NULLPTR;
6180 monitor_ptr->ts_u = x;
6181 monitor_ptr->ts_t = currentPhysicalTime;
6182 monitor_ptr->ts_step = physicalStepNumber;
6184
6185 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6186 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6187 SCATTER_FORWARD, RowColData::ROW);
6188 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6189 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6190
6191 int tao_sol_size, tao_sol_loc_size;
6192 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6193 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6194 MOFEM_LOG("EP", Sev::inform)
6195 << "Topological data vector size " << tao_sol_size << " local size "
6196 << tao_sol_loc_size << " number of interface faces "
6197 << interfaceFaces->size();
6198
6199 const char *list_objective_models[ObjectiveModelType::LAST_MODEL] = {
6200 "python_model", "hencky_model"};
6201#ifdef ENABLE_PYTHON_BINDING
6202 PetscInt choice_objective_model = ObjectiveModelType::PYTHON_MODEL;
6203#else
6204 PetscInt choice_objective_model = ObjectiveModelType::HENCKY_MODEL;
6205#endif
6207 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_model_type",
6208 list_objective_models, ObjectiveModelType::LAST_MODEL,
6209 &choice_objective_model, PETSC_NULLPTR);
6210 const auto objective_model_type =
6211 static_cast<ObjectiveModelType>(choice_objective_model);
6212 MOFEM_LOG("EP", Sev::inform)
6213 << "Objective model type: -objective_model_type "
6214 << list_objective_models[objective_model_type];
6215
6217 PetscReal obj_value;
6218 CHKERR testTopologicalDerivative(topological_tao_ctx.get(), tao_sol0,
6219 &obj_value, g, objective_model_type);
6220
6221 CHKERR TSElasticPostStep::postStepDestroy();
6222 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6223 {elasticFeLhs.get(), elasticFeRhs.get()});
6224
6226}
MoFEMErrorCode testTopologicalDerivative(TopologicalTAOCtx *ctx_ptr, Vec sol, PetscReal *f, Vec g, ObjectiveModelType eval_energy_model)
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)

◆ withFieldOrders()

template<typename Op >
MoFEMErrorCode EshelbianCore::withFieldOrders ( Op &&  op) const
inline
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 104 of file EshelbianCore.hpp.

104 {
108 CHKERR op.template operator()<DEMKOWICZ_JACOBI_BASE>();
109 break;
111 CHKERR op.template operator()<AINSWORTH_LEGENDRE_BASE>();
112 break;
113 default:
115 "Broken HDIV base not implemented");
116 }
118 }

Friends And Related Symbol Documentation

◆ solve_elastic_set_up

friend struct solve_elastic_set_up
friend

Definition at line 480 of file EshelbianCore.hpp.

Member Data Documentation

◆ a00FieldList

std::vector<std::string> EshelbianCore::a00FieldList

Definition at line 615 of file EshelbianCore.hpp.

◆ a00RangeList

std::vector<boost::shared_ptr<Range> > EshelbianCore::a00RangeList

Definition at line 617 of file EshelbianCore.hpp.

◆ addCrackMeshsetId

int EshelbianCore::addCrackMeshsetId = 1000
inlinestatic

Definition at line 69 of file EshelbianCore.hpp.

◆ alphaOmega

double EshelbianCore::alphaOmega = 0

◆ alphaRho

double EshelbianCore::alphaRho = 0

◆ alphaTau

double EshelbianCore::alphaTau = 0

◆ alphaU

double EshelbianCore::alphaU = 0

◆ alphaW

double EshelbianCore::alphaW = 0

◆ AnalyticalExprPythonPtr

boost::shared_ptr<AnalyticalExprPython> EshelbianCore::AnalyticalExprPythonPtr

◆ aoS

AO EshelbianCore::aoS = PETSC_NULLPTR

Definition at line 613 of file EshelbianCore.hpp.

◆ avgGriffithsEnergy

double EshelbianCore::avgGriffithsEnergy = -1

◆ bcSpatialAnalyticalDisplacementVecPtr

boost::shared_ptr<AnalyticalDisplacementBcVec> EshelbianCore::bcSpatialAnalyticalDisplacementVecPtr

◆ bcSpatialAnalyticalTractionVecPtr

boost::shared_ptr<AnalyticalTractionBcVec> EshelbianCore::bcSpatialAnalyticalTractionVecPtr

◆ bcSpatialDispVecPtr

boost::shared_ptr<BcDispVec> EshelbianCore::bcSpatialDispVecPtr

◆ bcSpatialFreeTractionVecPtr

boost::shared_ptr<TractionFreeBc> EshelbianCore::bcSpatialFreeTractionVecPtr

◆ bcSpatialNormalDisplacementVecPtr

boost::shared_ptr<NormalDisplacementBcVec> EshelbianCore::bcSpatialNormalDisplacementVecPtr

◆ bcSpatialPressureVecPtr

boost::shared_ptr<PressureBcVec> EshelbianCore::bcSpatialPressureVecPtr

◆ bcSpatialRotationVecPtr

boost::shared_ptr<BcRotVec> EshelbianCore::bcSpatialRotationVecPtr

◆ bcSpatialTractionVecPtr

boost::shared_ptr<TractionBcVec> EshelbianCore::bcSpatialTractionVecPtr

◆ bitAdjEnt

BitRefLevel EshelbianCore::bitAdjEnt = BitRefLevel().set()

◆ bitAdjEntMask

BitRefLevel EshelbianCore::bitAdjEntMask
Initial value:
=
BitRefLevel().set()

bit ref level for parent parent

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 598 of file EshelbianCore.hpp.

◆ bitAdjParent

BitRefLevel EshelbianCore::bitAdjParent = BitRefLevel().set()

◆ bitAdjParentMask

BitRefLevel EshelbianCore::bitAdjParentMask
Initial value:
=
BitRefLevel().set()

bit ref level for parent parent

Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 595 of file EshelbianCore.hpp.

◆ brokenHdivBase

FieldApproximationBase EshelbianCore::brokenHdivBase
inlinestatic

◆ bubbleField

const std::string EshelbianCore::bubbleField = "bubble"

◆ contactDisp

const std::string EshelbianCore::contactDisp = "contactDisp"

◆ contactElement

const std::string EshelbianCore::contactElement = "CONTACT"

◆ contactFaces

boost::shared_ptr<Range> EshelbianCore::contactFaces

◆ contactRefinementLevels

int EshelbianCore::contactRefinementLevels = 1

◆ contactTreeRhs

boost::shared_ptr<ForcesAndSourcesCore> EshelbianCore::contactTreeRhs

◆ crackFaces

boost::shared_ptr<Range> EshelbianCore::crackFaces

◆ crackHybridIs

SmartPetscObj<IS> EshelbianCore::crackHybridIs

Definition at line 614 of file EshelbianCore.hpp.

◆ crackingAddTime

double EshelbianCore::crackingAddTime = -1
inlinestatic

◆ crackingAtol

double EshelbianCore::crackingAtol = 1e-12
inlinestatic

◆ crackingOn

PetscBool EshelbianCore::crackingOn = PETSC_FALSE
inlinestatic

◆ crackingRtol

double EshelbianCore::crackingRtol = 1e-10
inlinestatic

◆ crackingStartTime

double EshelbianCore::crackingStartTime = -1
inlinestatic

◆ currentCrackAreaPtr

boost::shared_ptr<double> EshelbianCore::currentCrackAreaPtr

◆ currentPhysicalTime

double EshelbianCore::currentPhysicalTime
inlinestatic

◆ d_f

boost::function< double(const double)> EshelbianCore::d_f
static

◆ dataAtPts

boost::shared_ptr<DataAtIntegrationPts> EshelbianCore::dataAtPts

◆ dd_f

boost::function< double(const double)> EshelbianCore::dd_f
static

◆ dM

SmartPetscObj<DM> EshelbianCore::dM

◆ dmElastic

SmartPetscObj<DM> EshelbianCore::dmElastic

◆ dmMaterial

SmartPetscObj<DM> EshelbianCore::dmMaterial

◆ dmPrjSpatial

SmartPetscObj<DM> EshelbianCore::dmPrjSpatial

◆ edgeExchange

CommInterface::EntitiesPetscVector EshelbianCore::edgeExchange

◆ elasticBcLhs

boost::shared_ptr<FaceElementForcesAndSourcesCore> EshelbianCore::elasticBcLhs

◆ elasticBcRhs

boost::shared_ptr<FaceElementForcesAndSourcesCore> EshelbianCore::elasticBcRhs

◆ elasticFeLhs

boost::shared_ptr<VolumeElementForcesAndSourcesCore> EshelbianCore::elasticFeLhs

◆ elasticFeRhs

boost::shared_ptr<VolumeElementForcesAndSourcesCore> EshelbianCore::elasticFeRhs

◆ elementVolumeName

const std::string EshelbianCore::elementVolumeName = "EP"

◆ energyReleaseSelector

enum EnergyReleaseSelector EshelbianCore::energyReleaseSelector
inlinestatic

◆ exponentBase

double EshelbianCore::exponentBase = exp(1)
static

◆ externalStrainVecPtr

boost::shared_ptr<ExternalStrainVec> EshelbianCore::externalStrainVecPtr

◆ f

boost::function< double(const double)> EshelbianCore::f = EshelbianCore::f_log_e
static

◆ faceExchange

CommInterface::EntitiesPetscVector EshelbianCore::faceExchange

◆ finalPhysicalTime

double EshelbianCore::finalPhysicalTime = 0
inlinestatic

◆ frontAdjEdges

boost::shared_ptr<Range> EshelbianCore::frontAdjEdges

◆ frontEdges

boost::shared_ptr<Range> EshelbianCore::frontEdges

◆ frontLayers

int EshelbianCore::frontLayers = 3

Definition at line 306 of file EshelbianCore.hpp.

◆ frontVertices

boost::shared_ptr<Range> EshelbianCore::frontVertices

◆ gradApproximator

enum RotSelector EshelbianCore::gradApproximator = LARGE_ROT
inlinestatic

◆ griffithEnergy

double EshelbianCore::griffithEnergy = 1
inlinestatic

◆ hasNonHomogeneousMaterialBlock

bool EshelbianCore::hasNonHomogeneousMaterialBlock = false
inlinestatic

◆ heterogeneousYoungModTagName

std::string EshelbianCore::heterogeneousYoungModTagName
inlinestatic

◆ hybridSpatialDisp

const std::string EshelbianCore::hybridSpatialDisp = "hybridSpatialDisp"

◆ interfaceCrack

PetscBool EshelbianCore::interfaceCrack
inlinestatic

◆ interfaceFaces

boost::shared_ptr<Range> EshelbianCore::interfaceFaces

◆ interfaceRemoveLevel

int EshelbianCore::interfaceRemoveLevel
inlinestatic

◆ internalStressTagName

std::string EshelbianCore::internalStressTagName
inlinestatic

◆ internalStressVoigt

PetscBool EshelbianCore::internalStressVoigt
inlinestatic

◆ inv_d_f

boost::function< double(const double)> EshelbianCore::inv_d_f
static

◆ inv_dd_f

boost::function< double(const double)> EshelbianCore::inv_dd_f
static

◆ inv_f

boost::function< double(const double)> EshelbianCore::inv_f
static

◆ l2UserBaseScale

PetscBool EshelbianCore::l2UserBaseScale = PETSC_FALSE
inlinestatic

◆ listSolvers

const char* EshelbianCore::listSolvers[]
inlinestatic
Initial value:
= {"time_solver",
"dynamic_relaxation",
"cohesive",
"load_factor",
"shape_optimization",
"test_topological_derivative"}
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 23 of file EshelbianCore.hpp.

23 {"time_solver",
24 "dynamic_relaxation",
25 "cohesive",
26 "load_factor",
27 "shape_optimization",
28 "test_topological_derivative"};

◆ listTagsToProject

std::vector<std::string> EshelbianCore::listTagsToProject
inlinestatic

◆ listTagsToTransfer

std::vector<Tag> EshelbianCore::listTagsToTransfer

◆ loadFactor

double EshelbianCore::loadFactor = 1.0

◆ loadFactorTSSolveExecuted

PetscBool EshelbianCore::loadFactorTSSolveExecuted = PETSC_FALSE

◆ materialH1Order

int EshelbianCore::materialH1Order = 1

◆ materialH1Positions

const std::string EshelbianCore::materialH1Positions = "XH1"

◆ materialModel

enum MaterialModel EshelbianCore::materialModel = MooneyRivlin
inlinestatic

◆ maxCrackExtension

double EshelbianCore::maxCrackExtension
inlinestatic

◆ maxMovedFaces

boost::shared_ptr<Range> EshelbianCore::maxMovedFaces

Definition at line 588 of file EshelbianCore.hpp.

◆ meshTransferHybridInterp

PetscBool EshelbianCore::meshTransferHybridInterp
inlinestatic

◆ meshTransferInterpOrder

int EshelbianCore::meshTransferInterpOrder
inlinestatic

◆ meshTransferSourceMeshFileName

std::string EshelbianCore::meshTransferSourceMeshFileName
inlinestatic

◆ meshTransferSourceMeshFileSpecified

PetscBool EshelbianCore::meshTransferSourceMeshFileSpecified
inlinestatic

◆ mField

MoFEM::Interface& EshelbianCore::mField

◆ naturalBcElement

const std::string EshelbianCore::naturalBcElement = "NATURAL_BC"

◆ nbCrackFaces

int EshelbianCore::nbCrackFaces = 0

Definition at line 619 of file EshelbianCore.hpp.

◆ nbJIntegralContours

int EshelbianCore::nbJIntegralContours
inlinestatic

◆ oldCrackArea

double EshelbianCore::oldCrackArea = 0.

◆ oldLoadFactor

double EshelbianCore::oldLoadFactor = 1.0

◆ oldStrainEnergy

double EshelbianCore::oldStrainEnergy = 0.

◆ parentAdjSkeletonFunctionDim2

boost::shared_ptr<ParentFiniteElementAdjacencyFunctionSkeleton<2> > EshelbianCore::parentAdjSkeletonFunctionDim2

◆ physicalDt

double EshelbianCore::physicalDt = 0
inlinestatic

◆ physicalEquations

boost::shared_ptr<PhysicalEquations> EshelbianCore::physicalEquations

◆ physicalH1Update

PetscBool EshelbianCore::physicalH1Update
inlinestatic

◆ physicalMaxSteps

int EshelbianCore::physicalMaxSteps = 20
inlinestatic

◆ physicalStepNumber

int EshelbianCore::physicalStepNumber = 0
inlinestatic

◆ physicalTimeFlg

PetscBool EshelbianCore::physicalTimeFlg
inlinestatic

◆ piolaStress

const std::string EshelbianCore::piolaStress = "P"

◆ rotAxis

const std::string EshelbianCore::rotAxis = "omega"

◆ rotSelector

enum RotSelector EshelbianCore::rotSelector = LARGE_ROT
inlinestatic

◆ S

Mat EshelbianCore::S = PETSC_NULLPTR

Definition at line 612 of file EshelbianCore.hpp.

◆ setSingularity

PetscBool EshelbianCore::setSingularity = PETSC_FALSE
inlinestatic

◆ skeletonElement

const std::string EshelbianCore::skeletonElement = "SKELETON"

◆ skeletonFaces

boost::shared_ptr<Range> EshelbianCore::skeletonFaces

◆ skinElement

const std::string EshelbianCore::skinElement = "SKIN"

◆ solTSStep

SmartPetscObj<Vec> EshelbianCore::solTSStep

◆ solverType

enum SolverType EshelbianCore::solverType = TimeSolver
inlinestatic

◆ spaceH1Order

int EshelbianCore::spaceH1Order = -1

◆ spaceOrder

int EshelbianCore::spaceOrder = 2

◆ spatialH1Disp

const std::string EshelbianCore::spatialH1Disp = "wH1"

◆ spatialL2Disp

const std::string EshelbianCore::spatialL2Disp = "wL2"

◆ strainEnergy

double EshelbianCore::strainEnergy = 0.

◆ stretchHandling

enum StretchHandling EshelbianCore::stretchHandling
inlinestatic

◆ stretchSelector

enum StretchSelector EshelbianCore::stretchSelector = LOG
inlinestatic

◆ stretchTensor

const std::string EshelbianCore::stretchTensor = "u"

◆ symmetrySelector

constexpr enum SymmetrySelector EshelbianCore::symmetrySelector = SYMMETRIC
inlinestaticconstexpr

◆ timeScaleMap

std::map<std::string, boost::shared_ptr<ScalingMethod> > EshelbianCore::timeScaleMap

◆ use_quadratic_exp

constexpr bool EshelbianCore::use_quadratic_exp = true
inlinestaticconstexpr

Definition at line 131 of file EshelbianCore.hpp.

◆ v_max

constexpr double EshelbianCore::v_max = 24
inlinestaticconstexpr

Definition at line 132 of file EshelbianCore.hpp.

◆ v_min

constexpr double EshelbianCore::v_min = -v_max
inlinestaticconstexpr

Definition at line 133 of file EshelbianCore.hpp.

◆ vertexExchange

CommInterface::EntitiesPetscVector EshelbianCore::vertexExchange

◆ volumeExchange

CommInterface::EntitiesPetscVector EshelbianCore::volumeExchange

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