v0.16.3
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | 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  SolverType {
  TimeSolver , DynamicRelaxation , IncrementalOptimization , LoadFactor ,
  ShapeOptimization , TestTopologicalDerivative , TestEquilibratedMechanicalValue , TestIncrementalOptimizationLayout ,
  TestIncrementalOptimizationTransaction , TestIncrementalOptimizationObjectiveDerivative , TestIncrementalOptimizationConstraintDerivative , LastSolver
}
 

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 ()
 
MoFEMErrorCode applyTestSolverMonitorOptions (TS ts)
 
MoFEMErrorCode applyProjectionSolverMonitorOptions ()
 
std::string getStringArgumentFromJsonBlockset (const std::string &type_name, const int meshset_id, const std::string &param_name)
 
MoFEMErrorCode getStringArgumentFromJsonBlocksets (const std::string &type_name, const std::string &param_name, std::string &param_value)
 
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 resolveDissipationEntities (const EntityHandle meshset=0)
 
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 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 pushVolumeA00Ops (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 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 solveIncrementalOptimizationTAO (TS ts, Vec x, int start_step, double start_time)
 Solve the incremental constitutive optimization with TAO.
 
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 solveTestEquilibratedMechanicalValue (TS ts, Vec x, int start_step, double start_time)
 
MoFEMErrorCode solveTestIncrementalOptimizationLayout (TS ts, Vec x, int start_step, double start_time)
 
MoFEMErrorCode solveTestIncrementalOptimizationTransaction (TS ts, Vec x, int start_step, double start_time)
 
MoFEMErrorCode solveTestIncrementalOptimizationObjectiveDerivative (TS ts, Vec x, int start_step, double start_time)
 
MoFEMErrorCode solveTestIncrementalOptimizationConstraintDerivative (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={}, TS ts=PETSC_NULLPTR)
 
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 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 inv_f_log_e_quadratic (const double stretch)
 
static double inv_d_f_log_e_quadratic (const double stretch)
 
static double inv_dd_f_log_e_quadratic (const double stretch)
 
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_linear (const double v)
 
static double d_f_linear (const double)
 
static double dd_f_linear (const double)
 
static double inv_f_linear (const double v)
 
static double inv_d_f_linear (const double)
 
static double inv_dd_f_linear (const double)
 
- 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::Interface & mField
 
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
 
boost::shared_ptr< PhysicalEquations > physicalEquations
 
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
 
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeRhs
 
boost::shared_ptr< VolumeElementForcesAndSourcesCore > elasticFeLhs
 
boost::shared_ptr< FaceElementForcesAndSourcesCore > elasticBcLhs
 
boost::shared_ptr< FaceElementForcesAndSourcesCore > elasticBcRhs
 
boost::shared_ptr< ForcesAndSourcesCore > contactTreeRhs
 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.
 
SmartPetscObj< DM > dmIncrementalOptimization
 Incremental-optimization control problem.
 
SmartPetscObj< Vec > incrementalTrialControl
 
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 logDeviator = "D"
 
const std::string logJacobian = "theta"
 
const std::string auxiliaryLogStress = "Td"
 
const std::string rotAxis = "omega"
 
const std::string bubbleField = "bubble"
 
const std::string plasticFlowField = "plasticFlow"
 
const std::string plasticKappaField = "plasticKappa"
 
const std::string plasticHField = "plasticH"
 
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 alphaR = 0
 
double alphaViscousOmega = 0
 
double alphaViscousR = 0
 
double alphaRho = 0
 
double alphaTau = 0
 
double alphaTauLin = 0
 
double alphaTauBcDisp = 0
 
double alphaTauBcDisp0 = 0
 
double dynamicAtol = 0
 
double dynamicRtol = 0
 
double dynamicInitialResidual = -1
 
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< SpringBcVec > bcSpatialSpringVecPtr
 
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< double > currentCrackAreaPtr
 
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
 
boost::shared_ptr< Range > contactFaces
 
boost::shared_ptr< Range > crackFaces
 
boost::shared_ptr< Range > frontEdges
 
boost::shared_ptr< Range > frontAdjEdges
 
boost::shared_ptr< Range > frontVertices
 
boost::shared_ptr< Range > skeletonFaces
 
boost::shared_ptr< Range > maxMovedFaces
 
boost::shared_ptr< Range > interfaceFaces
 
boost::shared_ptr< Range > plasticVolumes
 
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< Tag > listTagsToTransfer
 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 RotSelector rotSelector = LARGE_ROT
 
static enum RotSelector gradApproximator = LARGE_ROT
 
static enum StretchSelector stretchSelector = LOG
 
static PetscBool setSingularity = PETSC_FALSE
 
static PetscBool physicalTimeFlg
 
static PetscBool crackingOn = PETSC_FALSE
 
static PetscBool propagateUnderCompression
 
static double crackingStartTime = 0
 
static double crackingAddTime = 0
 
static bool noCrackExtension = false
 
static int nbStepsNoCrackExtension
 
static bool potentialCrackArrest
 
static int nbJIntegralContours
 
static double finalPhysicalTime
 
static double currentPhysicalTime
 
static double physicalDt = 0
 
static int physicalMaxSteps
 
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 PetscBool plasticVolume
 
static int interfaceRemoveLevel
 
static std::string heterogeneousYoungModTagName
 
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 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 double v_max = 24
 

Protected Member Functions

MoFEMErrorCode runIncrementalOptimizationTAO (TS ts, Vec x)
 

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

◆ SolverType

Enumerator
TimeSolver 
DynamicRelaxation 
IncrementalOptimization 
LoadFactor 
ShapeOptimization 
TestTopologicalDerivative 
TestEquilibratedMechanicalValue 
TestIncrementalOptimizationLayout 
TestIncrementalOptimizationTransaction 
TestIncrementalOptimizationObjectiveDerivative 
TestIncrementalOptimizationConstraintDerivative 
LastSolver 
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 27 of file EshelbianCore.hpp.

27 {
40 };
@ TestIncrementalOptimizationConstraintDerivative
@ TestIncrementalOptimizationLayout
@ TestIncrementalOptimizationTransaction
@ TestIncrementalOptimizationObjectiveDerivative
@ TestEquilibratedMechanicalValue

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 916 of file EshelbianPlasticity.cpp.

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

◆ ~EshelbianCore()

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

Definition at line 920 of file EshelbianPlasticity.cpp.

920 {
921 auto destroy_dm = [](SmartPetscObj<DM> &dm) {
922 if (!dm)
923 return;
924
925 auto comm = PetscObjectComm(reinterpret_cast<PetscObject>(dm.get()));
926 CHKERRABORT(comm, DMMoFEMClearDMCtx(dm));
927 dm.reset();
928 };
929
930 // Sub-problems retain pointers into the parent problem. Clear their MoFEM
931 // contexts before releasing the coupled DM and before PETSc reference
932 // cycles can prevent the type-specific destroy callback from being reached.
934 destroy_dm(dmIncrementalOptimization);
935 destroy_dm(dmPrjSpatial);
936 destroy_dm(dmMaterial);
937 destroy_dm(dmElastic);
938 destroy_dm(dM);
939}
SmartPetscObj< Vec > incrementalTrialControl
SmartPetscObj< DM > dM
Coupled problem all fields.
SmartPetscObj< DM > dmMaterial
Material problem.
SmartPetscObj< DM > dmPrjSpatial
Projection spatial displacement.
SmartPetscObj< DM > dmElastic
Elastic problem.
SmartPetscObj< DM > dmIncrementalOptimization
Incremental-optimization control problem.
intrusive_ptr for managing petsc objects

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 2580 of file EshelbianPlasticity.cpp.

2580 {
2582
2583 Range meshset_ents;
2584 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
2585
2586 auto set_fe_adjacency = [&](auto fe_name) {
2589 boost::make_shared<ParentFiniteElementAdjacencyFunctionSkeleton<2>>(
2592 fe_name, MBTRI, *parentAdjSkeletonFunctionDim2);
2594 };
2595
2596 // set finite element fields
2597 auto add_field_to_fe = [this](const std::string fe,
2598 const std::string field_name) {
2607 };
2608
2610
2611 Range natural_bc_elements;
2612 if (bcSpatialDispVecPtr) {
2613 for (auto &v : *bcSpatialDispVecPtr) {
2614 natural_bc_elements.merge(v.faces);
2615 }
2616 }
2618 for (auto &v : *bcSpatialRotationVecPtr) {
2619 natural_bc_elements.merge(v.faces);
2620 }
2621 }
2623 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
2624 natural_bc_elements.merge(v.faces);
2625 }
2626 }
2628 for (auto &v : *bcSpatialSpringVecPtr) {
2629 natural_bc_elements.merge(v.faces);
2630 }
2631 }
2634 natural_bc_elements.merge(v.faces);
2635 }
2636 }
2638 for (auto &v : *bcSpatialTractionVecPtr) {
2639 natural_bc_elements.merge(v.faces);
2640 }
2641 }
2643 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
2644 natural_bc_elements.merge(v.faces);
2645 }
2646 }
2648 for (auto &v : *bcSpatialPressureVecPtr) {
2649 natural_bc_elements.merge(v.faces);
2650 }
2651 }
2652 natural_bc_elements = intersect(natural_bc_elements, meshset_ents);
2653
2655 CHKERR mField.add_ents_to_finite_element_by_type(natural_bc_elements, MBTRI,
2657 CHKERR add_field_to_fe(naturalBcElement, piolaStress);
2658 CHKERR add_field_to_fe(naturalBcElement, hybridSpatialDisp);
2659 CHKERR set_fe_adjacency(naturalBcElement);
2661 }
2662
2663 auto get_skin = [&](auto &body_ents) {
2664 Skinner skin(&mField.get_moab());
2665 Range skin_ents;
2666 CHKERR skin.find_skin(0, body_ents, false, skin_ents);
2667 return skin_ents;
2668 };
2669
2670 auto filter_true_skin = [&](auto &&skin) {
2671 Range boundary_ents;
2672 ParallelComm *pcomm =
2673 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
2674 CHKERR pcomm->filter_pstatus(skin, PSTATUS_SHARED | PSTATUS_MULTISHARED,
2675 PSTATUS_NOT, -1, &boundary_ents);
2676 return boundary_ents;
2677 };
2678
2680
2681 Range body_ents;
2682 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
2683 body_ents);
2684 auto skin = filter_true_skin(get_skin(body_ents));
2685
2693 contactDisp);
2697 }
2698
2700 if (contactFaces) {
2701 MOFEM_LOG("EP", Sev::inform)
2702 << "Contact elements " << contactFaces->size();
2706 CHKERR add_field_to_fe(contactElement, piolaStress);
2707 CHKERR add_field_to_fe(contactElement, contactDisp);
2708 CHKERR add_field_to_fe(contactElement, spatialL2Disp);
2709 CHKERR add_field_to_fe(contactElement, spatialH1Disp);
2710 CHKERR set_fe_adjacency(contactElement);
2712 }
2713 }
2714
2716 if (!skeletonFaces)
2717 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
2718 MOFEM_LOG("EP", Sev::inform)
2719 << "Skeleton elements " << skeletonFaces->size();
2723 CHKERR add_field_to_fe(skeletonElement, piolaStress);
2724 CHKERR add_field_to_fe(skeletonElement, hybridSpatialDisp);
2725 CHKERR add_field_to_fe(skeletonElement, spatialL2Disp);
2726 CHKERR add_field_to_fe(skeletonElement, spatialH1Disp);
2727 CHKERR set_fe_adjacency(skeletonElement);
2729 }
2730
2732}
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< SpringBcVec > bcSpatialSpringVecPtr
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 2112 of file EshelbianFracture.cpp.

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

4400 {
4402
4403 PetscBool debug_model = PETSC_FALSE;
4404 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_model", &debug_model,
4405 PETSC_NULLPTR);
4406 MOFEM_LOG("EP", Sev::inform)
4407 << "Debug model flag is " << (debug_model ? "ON" : "OFF");
4408
4409 if (debug_model == PETSC_TRUE) {
4410 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4411 auto post_proc = [&](TS ts, PetscReal t, Vec u, Vec u_t, Vec u_tt, Vec F,
4412 void *ctx) {
4414
4415 SNES snes;
4416 CHKERR TSGetSNES(ts, &snes);
4417 int it;
4418 CHKERR SNESGetIterationNumber(snes, &it);
4419 std::string file_name = "snes_iteration_" + std::to_string(it) + ".h5m";
4420 CHKERR postProcessResults(1, file_name, F, u_t, PETSC_NULLPTR, {}, ts);
4421
4422 // Disabled until calculateFaceMaterialForce supports the active
4423 // Neo-Hookean material model. Its adjoint path currently assumes a
4424 // Hencky tangent and dereferences an empty matD tensor.
4425#if 0
4426 std::string file_skel_name =
4427 "snes_iteration_skel_" + std::to_string(it) + ".h5m";
4428
4429 auto get_material_force_tag = [&]() {
4430 auto &moab = mField.get_moab();
4431 Tag tag;
4432 CHK_MOAB_THROW(moab.tag_get_handle("MaterialForce", tag),
4433 "can't get tag");
4434 return tag;
4435 };
4436
4438 CHKERR postProcessSkeletonResults(1, file_skel_name, F,
4439 {get_material_force_tag()}, ts);
4440#endif
4441
4443 };
4444 ts_ctx_ptr->tsDebugHook = post_proc;
4445 }
4446
4448}
@ 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 postProcessSkeletonResults(const int tag, const std::string file, Vec f_residual=PETSC_NULLPTR, std::vector< Tag > tags_to_transfer={}, TS ts=PETSC_NULLPTR)
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 calculateFaceMaterialForce(const int tag, TS ts, SmartPetscObj< Vec > *adjoint_gradient_vector=nullptr)

◆ 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 2734 of file EshelbianPlasticity.cpp.

2735 {
2737
2738 // find adjacencies between finite elements and dofs
2740
2741 // Create coupled problem
2742 dM = createDM(mField.get_comm(), "DMMOFEM");
2743 CHKERR DMMoFEMCreateMoFEM(dM, &mField, "ESHELBY_PLASTICITY", bit,
2744 BitRefLevel().set());
2745 CHKERR DMMoFEMSetDestroyProblem(dM, PETSC_TRUE);
2746 CHKERR DMMoFEMSetIsPartitioned(dM, PETSC_TRUE);
2752
2753 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_TRUE;
2754 CHKERR DMSetUp(dM);
2755 mField.getInterface<ProblemsManager>()->buildProblemFromFields = PETSC_FALSE;
2756
2757 auto remove_dofs_on_broken_skin = [&](const std::string prb_name) {
2759 for (int d : {0, 1, 2}) {
2760 std::vector<boost::weak_ptr<NumeredDofEntity>> dofs_to_remove;
2762 ->getSideDofsOnBrokenSpaceEntities(
2763 dofs_to_remove, prb_name, ROW, piolaStress,
2765 // remove piola dofs, i.e. traction free boundary
2766 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, ROW,
2767 dofs_to_remove);
2768 CHKERR mField.getInterface<ProblemsManager>()->removeDofs(prb_name, COL,
2769 dofs_to_remove);
2770 }
2772 };
2773 CHKERR remove_dofs_on_broken_skin("ESHELBY_PLASTICITY");
2774
2775 // Create elastic sub-problem
2776 dmElastic = createDM(mField.get_comm(), "DMMOFEM");
2777 CHKERR DMMoFEMCreateSubDM(dmElastic, dM, "ELASTIC_PROBLEM");
2784 for (const auto &field : physicalEquations->getMaterialFields(*this))
2795 CHKERR DMSetUp(dmElastic);
2796
2797 dmMaterial = createDM(mField.get_comm(), "DMMOFEM");
2798 CHKERR DMMoFEMCreateSubDM(dmMaterial, dM, "MATERIAL_PROBLEM");
2808 for (const auto &field : physicalEquations->getMaterialFields(*this))
2815 CHKERR DMSetUp(dmMaterial);
2816
2819 CHKERR DMMoFEMCreateSubDM(dmIncrementalOptimization, dM, "INCREMENTAL_OPTIMIZATION");
2835 CHKERR VecZeroEntries(incrementalTrialControl);
2836 }
2837
2838 auto set_zero_block = [&]() {
2840 const auto problems_manager = mField.getInterface<ProblemsManager>();
2841 auto add_empty_pair = [&](const std::string &row,
2842 const std::string &col) {
2844 if (mField.check_field(row) && mField.check_field(col)) {
2845 CHKERR problems_manager->addFieldToEmptyFieldBlocks("ELASTIC_PROBLEM",
2846 row, col);
2847 if (row != col)
2848 CHKERR problems_manager->addFieldToEmptyFieldBlocks(
2849 "ELASTIC_PROBLEM", col, row);
2850 }
2852 };
2853 for (const auto &[row, col] :
2854 physicalEquations->getMaterialEmptyBlocks(*this))
2855 CHKERR add_empty_pair(row, col);
2856 CHKERR add_empty_pair(spatialL2Disp, rotAxis);
2857 CHKERR add_empty_pair(spatialL2Disp, bubbleField);
2858
2861 };
2862
2863 auto set_section = [&]() {
2865 PetscSection section;
2866 CHKERR mField.getInterface<ISManager>()->sectionCreate("ELASTIC_PROBLEM",
2867 &section);
2868 CHKERR DMSetSection(dmElastic, section);
2869 CHKERR DMSetGlobalSection(dmElastic, section);
2870 CHKERR PetscSectionDestroy(&section);
2872 };
2873
2874 CHKERR set_zero_block();
2875 CHKERR set_section();
2876
2877 dmPrjSpatial = createDM(mField.get_comm(), "DMMOFEM");
2878 CHKERR DMMoFEMCreateSubDM(dmPrjSpatial, dM, "PROJECT_SPATIAL");
2884 CHKERR DMSetUp(dmPrjSpatial);
2885
2886 // CHKERR mField.getInterface<BcManager>()
2887 // ->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
2888 // "PROJECT_SPATIAL", spatialH1Disp, true, false);
2889
2891}
@ 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
virtual bool check_field(const std::string &name) const =0
check if field is in database
MoFEMErrorCode addFieldToEmptyFieldBlocks(const std::string problem_name, const std::string row_field, const std::string col_field) const
Add empty field blocks to optimize matrix storage.
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.
boost::shared_ptr< Range > plasticVolumes
boost::shared_ptr< TractionFreeBc > bcSpatialFreeTractionVecPtr
const std::string elementVolumeName
const std::string bubbleField
const std::string plasticFlowField
boost::shared_ptr< PhysicalEquations > physicalEquations
const std::string rotAxis
static PetscBool plasticVolume
SmartPetscObj< Vec > solTSStep
const std::string plasticKappaField
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 1588 of file EshelbianPlasticity.cpp.

1589 {
1591
1592 auto get_tets = [&]() {
1593 Range tets;
1594 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
1595 return tets;
1596 };
1597
1598 auto get_tets_skin = [&]() {
1599 Range tets_skin_part;
1600 Skinner skin(&mField.get_moab());
1601 CHKERR skin.find_skin(0, get_tets(), false, tets_skin_part);
1602 ParallelComm *pcomm =
1603 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
1604 Range tets_skin;
1605 CHKERR pcomm->filter_pstatus(tets_skin_part,
1606 PSTATUS_SHARED | PSTATUS_MULTISHARED,
1607 PSTATUS_NOT, -1, &tets_skin);
1608 return tets_skin;
1609 };
1610
1611 auto subtract_boundary_conditions = [&](auto &&tets_skin) {
1612 // That mean, that hybrid field on all faces on which traction is applied,
1613 // on other faces, or enforcing displacements as
1614 // natural boundary condition.
1616 for (auto &v : *bcSpatialTractionVecPtr) {
1617 tets_skin = subtract(tets_skin, v.faces);
1618 }
1619
1621 for (auto &v : *bcSpatialSpringVecPtr) {
1622 tets_skin = subtract(tets_skin, v.faces);
1623 }
1624
1626 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
1627 tets_skin = subtract(tets_skin, v.faces);
1628 }
1629
1631 for (auto &v : *bcSpatialPressureVecPtr) {
1632 tets_skin = subtract(tets_skin, v.faces);
1633 }
1634
1635 return tets_skin;
1636 };
1637
1638 auto subtract_blockset = [&](auto block_name, auto &&tets_skin) {
1639 auto contact_range =
1640 get_range_from_block(mField, block_name, SPACE_DIM - 1);
1641 tets_skin = subtract(tets_skin, contact_range);
1642 return tets_skin;
1643 };
1644
1645 auto get_stress_trace_faces = [&](auto &&tets_skin) {
1646 Range faces;
1647 CHKERR mField.get_moab().get_adjacencies(get_tets(), SPACE_DIM - 1, true,
1648 faces, moab::Interface::UNION);
1649 Range trace_faces = subtract(faces, tets_skin);
1650 return trace_faces;
1651 };
1652
1653 auto tets = get_tets();
1654
1655 // remove also contact faces, i.e. that is also kind of hybrid field but
1656 // named but used to enforce contact conditions
1657 auto trace_faces = get_stress_trace_faces(
1658
1659 subtract_blockset("CONTACT",
1660 subtract_boundary_conditions(get_tets_skin()))
1661
1662 );
1663
1664 contactFaces = boost::make_shared<Range>(intersect(
1665 trace_faces, get_range_from_block(mField, "CONTACT", SPACE_DIM - 1)));
1667 boost::make_shared<Range>(subtract(trace_faces, *contactFaces));
1668
1669#ifndef NDEBUG
1670 if (contactFaces->size())
1672 "contact_faces_" +
1673 std::to_string(mField.get_comm_rank()) + ".vtk",
1674 *contactFaces);
1675 if (skeletonFaces->size())
1677 "skeleton_faces_" +
1678 std::to_string(mField.get_comm_rank()) + ".vtk",
1679 *skeletonFaces);
1680#endif
1681
1683
1684 auto add_broken_hdiv_field = [this, meshset,
1685 broken_hdiv_base](const std::string field_name,
1686 const int order) {
1688
1689 const FieldApproximationBase base = broken_hdiv_base;
1690
1691 auto get_side_map_hdiv = [&]() {
1692 return std::vector<
1693
1694 std::pair<EntityType,
1696
1697 >>{
1698
1699 {MBTET,
1700 [&](BaseFunction::DofsSideMap &dofs_side_map) -> MoFEMErrorCode {
1701 return TetPolynomialBase::setDofsSideMap(HDIV, DISCONTINUOUS, base,
1702 dofs_side_map);
1703 }}
1704
1705 };
1706 };
1707
1709 get_side_map_hdiv(), MB_TAG_DENSE, MF_ZERO);
1711 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1713 };
1714
1715 auto add_l2_field = [this, meshset](const std::string field_name,
1716 const int order, const int dim) {
1719 MB_TAG_DENSE, MF_ZERO);
1721 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1723 };
1724
1725 auto add_h1_field = [this, meshset](const std::string field_name,
1726 const int order, const int dim) {
1729 MB_TAG_DENSE, MF_ZERO);
1731 CHKERR mField.set_field_order(meshset, MBVERTEX, field_name, 1);
1732 CHKERR mField.set_field_order(meshset, MBEDGE, field_name, order);
1733 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1734 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1736 };
1737
1738 auto add_l2_field_by_range = [this](const std::string field_name,
1739 const int order, const int dim,
1740 const int field_dim, Range &&r) {
1743 MB_TAG_DENSE, MF_ZERO);
1744 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(r);
1748 };
1749
1750 auto add_bubble_field = [this, meshset](const std::string field_name,
1751 const int order, const int dim) {
1753 CHKERR mField.add_field(field_name, HDIV, USER_BASE, dim, MB_TAG_DENSE,
1754 MF_ZERO);
1755 // Modify field
1756 auto field_ptr = mField.get_field_structure(field_name);
1757 auto field_order_table =
1758 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1759 auto get_cgg_bubble_order_zero = [](int p) { return 0; };
1760 auto get_cgg_bubble_order_tet = [](int p) {
1761 return NBVOLUMETET_CCG_BUBBLE(p);
1762 };
1763 field_order_table[MBVERTEX] = get_cgg_bubble_order_zero;
1764 field_order_table[MBEDGE] = get_cgg_bubble_order_zero;
1765 field_order_table[MBTRI] = get_cgg_bubble_order_zero;
1766 field_order_table[MBTET] = get_cgg_bubble_order_tet;
1768 CHKERR mField.set_field_order(meshset, MBTRI, field_name, order);
1769 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1771 };
1772
1773 auto add_user_l2_field = [this, meshset](const std::string field_name,
1774 const int order, const int dim) {
1776 CHKERR mField.add_field(field_name, L2, USER_BASE, dim, MB_TAG_DENSE,
1777 MF_ZERO);
1778 // Modify field
1779 auto field_ptr = mField.get_field_structure(field_name);
1780 auto field_order_table =
1781 const_cast<Field *>(field_ptr)->getFieldOrderTable();
1782 auto zero_dofs = [](int p) { return 0; };
1783 auto dof_l2_tet = [](int p) { return NBVOLUMETET_L2(p); };
1784 field_order_table[MBVERTEX] = zero_dofs;
1785 field_order_table[MBEDGE] = zero_dofs;
1786 field_order_table[MBTRI] = zero_dofs;
1787 field_order_table[MBTET] = dof_l2_tet;
1789 CHKERR mField.set_field_order(meshset, MBTET, field_name, order);
1791 };
1792
1793 if (!skeletonFaces)
1794 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No skeleton faces");
1795 if (!contactFaces)
1796 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "No contact faces");
1797
1798 auto get_hybridised_disp = [&]() {
1799 auto faces = *skeletonFaces;
1800 auto skin = subtract_boundary_conditions(get_tets_skin());
1801 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
1802 faces.merge(intersect(bc.faces, skin));
1803 }
1805 for (auto &bc : *bcSpatialSpringVecPtr) {
1806 faces.merge(intersect(bc.faces, skin));
1807 }
1808 return faces;
1809 };
1810
1811 auto add_spatial_fields = [&]<FieldApproximationBase Base>() {
1813 using Orders = EshelbianCore::FieldOrders<Base>;
1814 CHKERR add_broken_hdiv_field(piolaStress, Orders::stress(spaceOrder));
1815 if (add_bubble) {
1816 CHKERR add_bubble_field(bubbleField, Orders::bubble(spaceOrder), 1);
1817 }
1818 CHKERR add_l2_field(spatialL2Disp, Orders::disp(spaceOrder), 3);
1819 CHKERR add_user_l2_field(rotAxis, Orders::rot(spaceOrder), 3);
1820 for (const auto &field :
1821 physicalEquations->getMaterialFieldDefinitions(*this))
1822 CHKERR add_user_l2_field(field.name, field.order, field.coefficients);
1823 CHKERR add_l2_field_by_range(hybridSpatialDisp, Orders::hybrid(spaceOrder),
1824 2, 3, get_hybridised_disp());
1825 CHKERR add_l2_field_by_range(contactDisp, Orders::hybrid(spaceOrder), 2, 3,
1828 };
1829
1830 CHKERR withFieldOrders(add_spatial_fields);
1831
1832 // spatial displacement
1833 CHKERR add_h1_field(spatialH1Disp, spaceH1Order, 3);
1834 // material positions
1835 CHKERR add_h1_field(materialH1Positions, materialH1Order, 3);
1836 // The five-coordinate trace-free approximation of H^p is initially zero
1837 // on every volume.
1838 CHKERR add_l2_field(plasticHField, 0,
1839 plasticLogarithmicStretchCoordinateSize);
1840
1841 if (plasticVolume) {
1842 if (!plasticVolumes)
1844 "Plastic volumes have not been resolved by "
1845 "resolveDissipationEntities");
1846 // Delta H^p uses the same basis, so adding the accepted increment
1847 // preserves the trace-free approximation of H^p.
1848 CHKERR add_l2_field_by_range(
1850 plasticLogarithmicStretchCoordinateSize, Range(*plasticVolumes));
1851 // One scalar P0 layout has two deliberately separate stores: mesh field
1852 // data hold committed kappa_n, while vectors on the incremental-control
1853 // DM hold the trial Delta kappa.
1854 CHKERR add_l2_field_by_range(plasticKappaField, 0, SPACE_DIM, 1,
1856 }
1857
1859
1861}
#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
const std::string plasticHField
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.

◆ 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 2534 of file EshelbianPlasticity.cpp.

2535 {
2537
2538 // set finite element fields
2539 auto add_field_to_fe = [this](const std::string fe,
2540 const std::string field_name) {
2546 };
2547
2552
2553 CHKERR add_field_to_fe(elementVolumeName, piolaStress);
2554 if (add_bubble) {
2555 CHKERR add_field_to_fe(elementVolumeName, bubbleField);
2556 }
2557 for (const auto &field : physicalEquations->getMaterialFields(*this))
2558 CHKERR add_field_to_fe(elementVolumeName, field);
2559 CHKERR add_field_to_fe(elementVolumeName, rotAxis);
2560 CHKERR add_field_to_fe(elementVolumeName, spatialL2Disp);
2561 CHKERR add_field_to_fe(elementVolumeName, spatialH1Disp);
2562 CHKERR add_field_to_fe(elementVolumeName, contactDisp);
2566
2568 CHKERR add_field_to_fe(elementVolumeName, plasticFlowField);
2569 CHKERR add_field_to_fe(elementVolumeName, plasticKappaField);
2570 }
2571
2572 // build finite elements data structures
2574 }
2575
2577}

◆ applyProjectionSolverMonitorOptions()

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

Definition at line 990 of file EshelbianPlasticity.cpp.

990 {
992
993 PetscBool cancel_projection_ksp_monitor = PETSC_FALSE;
994 CHKERR PetscOptionsHasName(PETSC_NULLPTR, PETSC_NULLPTR,
995 "-prjspatial_ksp_monitor_cancel",
996 &cancel_projection_ksp_monitor);
997
998 if (cancel_projection_ksp_monitor) {
999 CHKERR PetscOptionsClearValue(PETSC_NULLPTR, "-prjspatial_ksp_monitor");
1000 CHKERR PetscOptionsClearValue(PETSC_NULLPTR,
1001 "-prjspatial_ksp_monitor_short");
1002 CHKERR PetscOptionsClearValue(PETSC_NULLPTR,
1003 "-prjspatial_ksp_monitor_true_residual");
1004 }
1005
1007}

◆ applyTestSolverMonitorOptions()

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

Definition at line 941 of file EshelbianPlasticity.cpp.

941 {
943
944 const char *ts_prefix = nullptr;
945 CHKERR TSGetOptionsPrefix(ts, &ts_prefix);
946 const std::string prefix = ts_prefix ? ts_prefix : "";
947 const auto make_ts_option = [&prefix](const char *name) {
948 return std::string("-") + prefix + name;
949 };
950 const auto has_ts_option = [&make_ts_option](const char *name,
951 PetscBool *found) {
952 const auto option = make_ts_option(name);
953 return PetscOptionsHasName(PETSC_NULLPTR, PETSC_NULLPTR, option.c_str(),
954 found);
955 };
956 const auto clear_ts_option = [&make_ts_option](const char *name) {
957 const auto option = make_ts_option(name);
958 return PetscOptionsClearValue(PETSC_NULLPTR, option.c_str());
959 };
960
961 PetscBool cancel_snes_monitor = PETSC_FALSE;
962 PetscBool cancel_ksp_monitor = PETSC_FALSE;
963 CHKERR has_ts_option("snes_monitor_cancel", &cancel_snes_monitor);
964 CHKERR has_ts_option("ksp_monitor_cancel", &cancel_ksp_monitor);
965
966 SNES snes;
967 CHKERR TSGetSNES(ts, &snes);
968
969 if (cancel_snes_monitor) {
970 CHKERR clear_ts_option("snes_monitor");
971 CHKERR clear_ts_option("snes_linesearch_monitor");
972 CHKERR SNESMonitorCancel(snes);
973 SNESLineSearch line_search;
974 CHKERR SNESGetLineSearch(snes, &line_search);
975 CHKERR SNESLineSearchMonitorCancel(line_search);
976 }
977
978 if (cancel_ksp_monitor) {
979 CHKERR clear_ts_option("ksp_monitor");
980 CHKERR clear_ts_option("ksp_monitor_short");
981 CHKERR clear_ts_option("ksp_monitor_true_residual");
982 KSP ksp;
983 CHKERR SNESGetKSP(snes, &ksp);
984 CHKERR KSPMonitorCancel(ksp);
985 }
986
988}

◆ calculateCrackArea()

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

Definition at line 2857 of file EshelbianFracture.cpp.

2857 {
2859
2860 if (!area_ptr) {
2861 // initialize area
2862 area_ptr = boost::shared_ptr<double>(new double(0.0));
2863 }
2864
2865 int success;
2866 *area_ptr = 0;
2867 if (mField.get_comm_rank() == 0) {
2868 MOFEM_LOG("EP", Sev::inform) << "Calculate crack area";
2869 auto crack_faces = get_range_from_block(mField, "CRACK", SPACE_DIM - 1);
2870 for (auto f : crack_faces) {
2871 *area_ptr += mField.getInterface<Tools>()->getTriArea(f);
2872 }
2873 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0, mField.get_comm());
2874 } else {
2875 success = MPI_Bcast(area_ptr.get(), 1, MPI_DOUBLE, 0, mField.get_comm());
2876 }
2877 if (success != MPI_SUCCESS) {
2879 }
2881}
@ 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));
104 CHKERR physicalEquations->pushMaterialForceFields(
105 *this, op_loop_domain_side->getOpPtrVector(), dataAtPts);
106
107 op_loop_domain_side->getOpPtrVector().push_back(
109
110 return fe_ptr;
111 };
112
113 auto integrate_face_material_force_fe = [&](auto &&face_energy_fe) {
116 dM, skeletonElement, face_energy_fe, 0, mField.get_comm_size());
117
118 auto face_exchange = CommInterface::createEntitiesPetscVector(
119 mField.get_comm(), mField.get_moab(), 2, 3, Sev::inform);
120
121 auto print_loc_size = [this](auto v, auto str, auto sev) {
123 int size;
124 CHKERR VecGetLocalSize(v.second, &size);
125 int low, high;
126 CHKERR VecGetOwnershipRange(v.second, &low, &high);
127 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( "
128 << low << " " << high << " ) ";
131 };
132 CHKERR print_loc_size(face_exchange, "material face_exchange",
133 Sev::verbose);
134
135 CHKERR CommInterface::updateEntitiesPetscVector(
136 mField.get_moab(), face_exchange, tags[ExhangeTags::MATERIALFORCE]);
137 CHKERR CommInterface::updateEntitiesPetscVector(
138 mField.get_moab(), faceExchange, tags[ExhangeTags::FACEPRESSURE]);
139
140 #ifndef NDEBUG
141 if (debug) {
143 "front_skin_faces_material_force_" +
144 std::to_string(mField.get_comm_rank()) + ".vtk",
146 }
147 #endif
148
150 };
151
152 CHKERR integrate_face_material_force_fe(get_face_material_force_fe());
153
155 };
156
157 auto get_conn = [&](auto e) {
158 Range conn;
159 CHK_MOAB_THROW(mField.get_moab().get_connectivity(&e, 1, conn, true),
160 "get connectivity");
161 return conn;
162 };
163
164 auto get_conn_range = [&](auto e) {
165 Range conn;
166 CHK_MOAB_THROW(mField.get_moab().get_connectivity(e, conn, true),
167 "get connectivity");
168 return conn;
169 };
170
171 auto get_adj = [&](auto e, auto dim) {
172 Range adj;
173 CHK_MOAB_THROW(mField.get_moab().get_adjacencies(&e, 1, dim, true, adj),
174 "get adj");
175 return adj;
176 };
177
178 auto get_adj_range = [&](auto e, auto dim) {
179 Range adj;
180 CHK_MOAB_THROW(mField.get_moab().get_adjacencies(e, dim, true, adj,
181 moab::Interface::UNION),
182 "get adj");
183 return adj;
184 };
185
186 auto get_vector_tag_data = [&](auto r, auto th) {
187 MatrixDouble tag_data(r.size(), 3, false);
189 mField.get_moab().tag_get_data(th, r, tag_data.data().data()),
190 "get vector tag data");
191 return tag_data;
192 };
193
194 auto calculate_edge_direction = [&](auto e) {
195 const EntityHandle *conn;
196 int num_nodes;
198 mField.get_moab().get_connectivity(e, conn, num_nodes, true),
199 "get connectivity");
200 std::array<double, 6> coords;
201 CHK_MOAB_THROW(mField.get_moab().get_coords(conn, num_nodes, coords.data()),
202 "get coords");
204 &coords[0], &coords[1], &coords[2]};
206 &coords[3], &coords[4], &coords[5]};
209 t_dir(i) = t_p1(i) - t_p0(i);
210 return t_dir;
211 };
212
213 auto average_vector_tag_at_edge = [&](auto th) {
215
217
218 for (auto e : *frontEdges) {
219 auto conn = get_conn(e);
220 auto data = get_vector_tag_data(conn, th);
221 auto t_node = getFTensor1FromPtr<SPACE_DIM>(data.data().data());
222 FTensor::Tensor1<double, SPACE_DIM> t_edge_material_force{0., 0., 0.};
223 for (auto n : conn) {
224 NOT_USED(n);
225 t_edge_material_force(I) += t_node(I);
226 ++t_node;
227 }
228 t_edge_material_force(I) /= conn.size();
229
230 FTensor::Tensor1<double, SPACE_DIM> t_edge_direction =
231 calculate_edge_direction(e);
232 t_edge_direction.normalize();
233
234 // Project the averaged vector to the plane normal to the front edge.
236 t_cross(K) = FTensor::levi_civita(I, J, K) * t_edge_direction(I) *
237 t_edge_material_force(J);
238 t_edge_material_force(K) =
239 FTensor::levi_civita(I, J, K) * t_edge_direction(J) * t_cross(I);
240
241 CHKERR mField.get_moab().tag_set_data(th, &e, 1,
242 &t_edge_material_force(0));
243 }
244
246 };
247
248 auto average_material_force_at_edge = [&](auto th) {
250
251 if (mField.get_comm_rank() == 0) {
252 CHKERR average_vector_tag_at_edge(th);
253
254// #ifndef NDEBUG
255// if (debug) {
256 int ts_step;
257 CHKERR TSGetStepNumber(ts, &ts_step);
259 "front_edges_material_force_" +
260 std::to_string(ts_step) + ".vtk",
261 *frontEdges);
262// }
263// #endif
264 }
265
267 };
268
269 auto calculate_force_through_node = [&](auto nb_J_integral_contours) {
271
273
274 if (mField.get_comm_rank() == 0) {
275 auto front_nodes = get_conn_range(*frontEdges);
276 Range all_skin_faces;
277
278 for (auto n : front_nodes) {
279 auto adj_tets = get_adj(n, SPACE_DIM);
280 for (int ll = 0; ll < nb_J_integral_contours; ++ll) {
281 auto conn = get_conn_range(adj_tets);
282 adj_tets = get_adj_range(conn, SPACE_DIM);
283 }
284
285 auto skin_faces = get_skin(mField, adj_tets);
286 auto material_forces =
287 get_vector_tag_data(skin_faces, tags[ExhangeTags::MATERIALFORCE]);
288
289#ifndef NDEBUG
290 if (debug) {
291 all_skin_faces.merge(skin_faces);
292 }
293#endif
294
295 auto t_face_T =
296 getFTensor1FromPtr<SPACE_DIM>(material_forces.data().data());
297 FTensor::Tensor1<double, SPACE_DIM> t_node_force{0., 0., 0.};
298 for (auto face : skin_faces) {
299
300 FTensor::Tensor1<double, SPACE_DIM> t_face_force_tmp{0., 0., 0.};
301 t_face_force_tmp(I) = t_face_T(I);
302 ++t_face_T;
303
304 auto face_tets = intersect(get_adj(face, SPACE_DIM), adj_tets);
305
306 if (face_tets.empty()) {
307 continue;
308 }
309
310 if (face_tets.size() != 1) {
312 "face_tets.size() != 1");
313 }
314
315 int side_number, sense, offset;
316 CHK_MOAB_THROW(mField.get_moab().side_number(face_tets[0], face,
317 side_number, sense,
318 offset),
319 "moab side number");
320 t_face_force_tmp(I) *= sense;
321 t_node_force(I) += t_face_force_tmp(I);
322 }
323
324 t_node_force(I) /= griffithEnergy; // scale all by griffith energy
326 mField.get_moab().tag_set_data(tags[ExhangeTags::MATERIALFORCE],
327 &n, 1, &t_node_force(0)),
328 "set data");
329 }
330
331#ifndef NDEBUG
332 if (debug) {
333 int ts_step;
334 CHKERR TSGetStepNumber(ts, &ts_step);
336 "front_skin_faces_material_force_" +
337 std::to_string(ts_step) + ".vtk",
338 all_skin_faces);
339 }
340#endif
341 }
342
344 };
345
346 auto get_adj_tets_for_contour = [&](auto n, auto nb_J_integral_contours) {
347 auto adj_tets = get_adj(n, SPACE_DIM);
348 for (int ll = 0; ll < nb_J_integral_contours; ++ll) {
349 auto conn = get_conn_range(adj_tets);
350 adj_tets = get_adj_range(conn, SPACE_DIM);
351 }
352 return adj_tets;
353 };
354
355 auto get_front_node_adj_crack_faces = [&](auto n) {
356 return intersect(get_adj(n, SPACE_DIM - 1), *crackFaces);
357 };
358
359 auto calculate_crack_area_growth_face = [&](auto nb_J_integral_contours) {
361
362 FTENSOR_INDEXES(SPACE_DIM, I, J, K, L);
363
364 if (mField.get_comm_rank() == 0) {
365 auto front_nodes = get_conn_range(*frontEdges);
366 auto body_edges = get_range_from_block(mField, "EDGES", 1);
367 Range body_ents;
368 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
369 body_ents);
370 auto body_skin = get_skin(mField, body_ents);
371 auto body_skin_conn = get_conn_range(body_skin);
372
373 auto calculate_seed_area_growth = [&](auto n, auto &adj_faces) {
374 // if skin is on body surface, project the direction on it
375 FTensor::Tensor1<double, SPACE_DIM> t_project{0., 0., 0.};
376 auto boundary_node = intersect(Range(n, n), body_skin_conn);
377 if (boundary_node.size()) {
378 auto faces = intersect(get_adj(n, SPACE_DIM - 1), body_skin);
379 for (auto f : faces) {
380 FTensor::Tensor1<double, 3> t_normal_face;
381 CHKERR mField.getInterface<Tools>()->getTriNormal(
382 f, &t_normal_face(0));
383 t_project(I) += t_normal_face(I);
384 }
385 t_project.normalize();
386 }
387
388 // calculate surface projection matrix
391 t_Q(I, J) = t_kd(I, J);
392 if (boundary_node.size()) {
393 t_Q(I, J) -= t_project(I) * t_project(J);
394 }
395
396 FTensor::Tensor1<double, 3> t_area_dir{0., 0., 0.};
397 for (auto f : adj_faces) {
398 int num_nodes;
399 const EntityHandle *conn;
400 CHKERR mField.get_moab().get_connectivity(f, conn, num_nodes, true);
401 std::array<double, 9> coords;
402 CHKERR mField.get_moab().get_coords(conn, num_nodes, coords.data());
403 FTensor::Tensor1<double, 3> t_face_normal;
405 CHKERR mField.getInterface<Tools>()->getTriNormal(
406 coords.data(), &t_face_normal(0), &t_d_normal(0, 0, 0));
407 auto n_it = std::find(conn, conn + num_nodes, n);
408 auto n_index = std::distance(conn, n_it);
409
410 FTensor::Tensor2<double, 3, 3> t_face_hessian{
411 t_d_normal(0, n_index, 0), t_d_normal(0, n_index, 1),
412 t_d_normal(0, n_index, 2),
413
414 t_d_normal(1, n_index, 0), t_d_normal(1, n_index, 1),
415 t_d_normal(1, n_index, 2),
416
417 t_d_normal(2, n_index, 0), t_d_normal(2, n_index, 1),
418 t_d_normal(2, n_index, 2)};
419
420 FTensor::Tensor2<double, 3, 3> t_projected_hessian;
421 t_projected_hessian(I, J) =
422 t_Q(I, K) * (t_face_hessian(K, L) * t_Q(L, J));
423 t_face_normal.normalize();
424 t_area_dir(K) += t_face_normal(I) * t_projected_hessian(I, K) / 2.;
425 }
426
427 return t_area_dir;
428 };
429
430 auto get_crack_area_growth_seed_nodes = [&](auto &adj_tets) {
431 // This gets all 1D edges adjacent to the current tetrahedral patch
432 // adj_tets, then keeps only edges that are either crack-front edges or
433 // special body edges from the "EDGES" block. So adj_edges is the local
434 // edge stencil relevant to crack growth near the current front node.
435 auto adj_edges = intersect(get_adj_range(adj_tets, 1),
436 unite(*frontEdges, body_edges));
437
438 // This collects all vertices/nodes connected to those edges. These are
439 // candidate seed nodes whose local crack-area growth contribution will
440 // be accumulated.
441 auto seed_n = get_conn_range(adj_edges);
442 auto skin_adj_edges = get_skin(mField, adj_edges);
443 skin_adj_edges = subtract(skin_adj_edges, body_skin_conn);
444 seed_n = subtract(seed_n, skin_adj_edges);
445
446 return std::make_pair(seed_n, skin_adj_edges);
447 };
448
449 auto calculate_front_node_area_growth = [&](auto &adj_tets) {
450 auto [seed_n, skin_adj_edges] =
451 get_crack_area_growth_seed_nodes(adj_tets);
452
453 FTensor::Tensor1<double, SPACE_DIM> t_area_dir{0., 0., 0.};
454 auto add_area_growth_direction = [&](auto sn, double weight) {
455 auto adj_faces = intersect(get_adj(sn, SPACE_DIM - 1), *crackFaces);
456 if (adj_faces.empty()) {
457 return;
458 }
459
460 auto t_area_dir_sn = calculate_seed_area_growth(sn, adj_faces);
461 t_area_dir(I) += weight * t_area_dir_sn(I);
462 };
463
464 for (auto sn : seed_n) {
465 add_area_growth_direction(sn, 1.);
466 }
467 for (auto sn : skin_adj_edges) {
468 add_area_growth_direction(sn, 0.5);
469 }
470
471 return t_area_dir;
472 };
473
474 for (auto n : front_nodes) {
475 auto front_node_adj_faces = get_front_node_adj_crack_faces(n);
476 if (front_node_adj_faces.empty()) {
477 continue;
478 }
479
480 auto adj_tets = get_adj_tets_for_contour(n, nb_J_integral_contours);
481 auto t_area_dir = calculate_front_node_area_growth(adj_tets);
482
484 mField.get_moab().tag_set_data(tags[ExhangeTags::AREAGROWTH], &n, 1,
485 &t_area_dir(0)),
486 "set data");
487 }
488 }
489
491 };
492
493 auto calculate_crack_area_growth_no_face = [&](auto nb_J_integral_contours,
494 auto material_force_tag) {
496
498
499 if (mField.get_comm_rank() == 0) {
500 auto front_nodes = get_conn_range(*frontEdges);
501 auto body_edges = get_range_from_block(mField, "EDGES", 1);
502 Range body_ents;
503 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM,
504 body_ents);
505 auto body_skin = get_skin(mField, body_ents);
506 auto body_skin_conn = get_conn_range(body_skin);
507
508 auto calculate_seed_area_growth = [&](auto n, auto &t_node_force) {
509 auto adj_edges =
510 intersect(get_adj(n, 1), unite(*frontEdges, body_edges));
511 double l = 0;
512 for (auto e : adj_edges) {
513 auto t_dir = calculate_edge_direction(e);
514 l += t_dir.l2();
515 }
516 l /= 2;
517
518 FTensor::Tensor1<double, SPACE_DIM> t_area_dir{0., 0., 0.};
520 t_node_force_tmp(I) = t_node_force(I);
521 t_node_force_tmp.normalize();
522 t_area_dir(I) = -t_node_force_tmp(I);
523 t_area_dir(I) *= l / 2;
524 return t_area_dir;
525 };
526
527 auto get_crack_area_growth_seed_nodes = [&](auto &adj_tets) {
528 auto adj_edges = intersect(get_adj_range(adj_tets, 1),
529 unite(*frontEdges, body_edges));
530 auto seed_n = get_conn_range(adj_edges);
531 auto skin_adj_edges = get_skin(mField, adj_edges);
532 skin_adj_edges = subtract(skin_adj_edges, body_skin_conn);
533 seed_n = subtract(seed_n, skin_adj_edges);
534
535 return std::make_pair(seed_n, skin_adj_edges);
536 };
537
538 auto calculate_front_node_area_growth = [&](auto &adj_tets,
539 auto &t_node_force) {
540 auto [seed_n, skin_adj_edges] =
541 get_crack_area_growth_seed_nodes(adj_tets);
542
543 FTensor::Tensor1<double, SPACE_DIM> t_area_dir{0., 0., 0.};
544 auto add_area_growth_direction = [&](auto sn, double weight) {
545 auto t_area_dir_sn = calculate_seed_area_growth(sn, t_node_force);
546 t_area_dir(I) += weight * t_area_dir_sn(I);
547 };
548
549 for (auto sn : seed_n) {
550 add_area_growth_direction(sn, 1.);
551 }
552 for (auto sn : skin_adj_edges) {
553 add_area_growth_direction(sn, 0.5);
554 }
555
556 return t_area_dir;
557 };
558
559 for (auto n : front_nodes) {
560 auto front_node_adj_faces = get_front_node_adj_crack_faces(n);
561 if (front_node_adj_faces.empty()) {
563 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &n, 1,
564 &t_node_force(0));
565
566 auto adj_tets = get_adj_tets_for_contour(n, nb_J_integral_contours);
567 auto t_area_dir =
568 calculate_front_node_area_growth(adj_tets, t_node_force);
569
571 mField.get_moab().tag_set_data(tags[ExhangeTags::AREAGROWTH], &n,
572 1, &t_area_dir(0)),
573 "set data");
574 }
575 }
576 }
577
579 };
580
581 auto update_crack_area_growth_edges = [&]() {
583
584 if (mField.get_comm_rank() == 0) {
585 CHKERR average_vector_tag_at_edge(tags[ExhangeTags::AREAGROWTH]);
586 }
587
588 auto area_growth_edge_exchange = CommInterface::createEntitiesPetscVector(
589 mField.get_comm(), mField.get_moab(), 1, 3, Sev::inform);
590 CHKERR CommInterface::updateEntitiesPetscVector(
591 mField.get_moab(), area_growth_edge_exchange,
592 tags[ExhangeTags::AREAGROWTH]);
593
595 };
596
597 auto calculate_griffith_force = [&](ExhangeTags material_force_tag,
598 ExhangeTags griffith_force_tag) {
600
602
603 if (mField.get_comm_rank() == 0) {
604 auto front_nodes = get_conn_range(*frontEdges);
605 Range all_front_faces;
606
607 for (auto n : front_nodes) {
609 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &n, 1,
610 &t_node_force(0));
612 CHKERR mField.get_moab().tag_get_data(tags[ExhangeTags::AREAGROWTH], &n,
613 1, &t_area_dir(0));
614
615 auto griffith =
616 -t_node_force(I) * t_area_dir(I) / (t_area_dir(K) * t_area_dir(K));
617 CHK_MOAB_THROW(mField.get_moab().tag_set_data(
618 tags[griffith_force_tag], &n, 1, &griffith),
619 "set data");
620 }
621
622 for (auto e : *frontEdges) {
624 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &e, 1,
625 &t_edge_force(0));
627 CHKERR mField.get_moab().tag_get_data(tags[ExhangeTags::AREAGROWTH], &e,
628 1, &t_edge_area_dir(0));
629 double griffith_energy =
630 -t_edge_force(I) * t_edge_area_dir(I) /
631 (t_edge_area_dir(K) * t_edge_area_dir(K));
632 CHKERR mField.get_moab().tag_set_data(tags[griffith_force_tag], &e, 1,
633 &griffith_energy);
634 }
635
636 for (auto e : *frontEdges) {
637 auto adj_faces = get_adj(e, SPACE_DIM - 1);
638
639 if (debug) {
640 all_front_faces.merge(adj_faces);
641 }
642
644 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &e, 1,
645 &t_edge_force(0));
646 FTensor::Tensor1<double, SPACE_DIM> t_edge_direction =
647 calculate_edge_direction(e);
648 t_edge_direction.normalize();
649
651 t_cross(K) = FTensor::levi_civita(I, J, K) * t_edge_direction(I) *
652 t_edge_force(J);
653
654 for (auto f : adj_faces) {
656 CHKERR mField.getInterface<Tools>()->getTriNormal(f, &t_normal(0));
657 t_normal.normalize();
658 int side_number, sense, offset;
659 CHKERR mField.get_moab().side_number(f, e, side_number, sense, offset);
660 auto dot = -sense * t_cross(I) * t_normal(I);
661 CHK_MOAB_THROW(mField.get_moab().tag_set_data(
662 tags[griffith_force_tag], &f, 1, &dot),
663 "set data");
664 }
665 }
666
667#ifndef NDEBUG
668 if (debug) {
669 int ts_step;
670 CHKERR TSGetStepNumber(ts, &ts_step);
672 "front_faces_material_force_" +
673 std::to_string(ts_step) + ".vtk",
674 all_front_faces);
675 }
676#endif
677 }
678
679 auto vector_edge_exchange = CommInterface::createEntitiesPetscVector(
680 mField.get_comm(), mField.get_moab(), 1, 3, Sev::inform);
681 CHKERR CommInterface::updateEntitiesPetscVector(
682 mField.get_moab(), vector_edge_exchange, tags[material_force_tag]);
683 auto &scalar_edge_exchange = edgeExchange;
684 CHKERR CommInterface::updateEntitiesPetscVector(
685 mField.get_moab(), scalar_edge_exchange, tags[griffith_force_tag]);
686
688 };
689
690 auto calculate_griffith_force_simplified = [&](auto material_force_tag,
691 auto griffith_force_tag) {
693
694 if (mField.get_comm_rank() == 0) {
695 auto front_nodes = get_conn_range(*frontEdges);
696
697 for (auto n : front_nodes) {
699 CHKERR mField.get_moab().tag_get_data(tags[material_force_tag], &n, 1,
700 &t_node_force(0));
701
702 auto adj_edges = intersect(get_adj(n, 1), *frontEdges);
703 double adj_edges_length = 0.;
704 for (auto e : adj_edges) {
705 auto t_edge_dir = calculate_edge_direction(e);
706 adj_edges_length += t_edge_dir.l2();
707 }
708
709 const double nodal_front_length = adj_edges_length / 2.;
710 if (nodal_front_length <= 0.) {
712 "Front node has zero adjacent front edge length");
713 }
714
715 double griffith_energy = t_node_force.l2() / nodal_front_length;
716 CHK_MOAB_THROW(mField.get_moab().tag_set_data(tags[griffith_force_tag],
717 &n, 1, &griffith_energy),
718 "set data");
719 }
720 }
721
723 };
724
725 auto calculate_adjoint_material_force = [&]() {
727
728 if (ts == PETSC_NULLPTR) {
730 "TS is required to calculate adjoint material force");
731 }
732
734 CHKERR VecZeroEntries(g);
735
736 // Disabled until the topological objective provides a material-compatible
737 // tangent for Neo-Hookean models. Keep g zero so the remaining exchange
738 // path cannot consume uninitialised vector data.
739 // auto topological_tao_ctx = createTopologicalTAOCtx(
740 // this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
741 // SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
742 // SmartPetscObj<TS>(ts, true));
743 // double obj_value = 0;
744 // CHKERR evaluateGradient(topological_tao_ctx.get(), &obj_value, g,
745 // ObjectiveModelType::HENCKY_MODEL);
746
747 auto set_vertex_exchange_from_gradient = [&]() {
749
750 CHKERR VecZeroEntries(vertexExchange.second);
751 CHKERR VecGhostUpdateBegin(vertexExchange.second, INSERT_VALUES,
752 SCATTER_FORWARD);
753 CHKERR VecGhostUpdateEnd(vertexExchange.second, INSERT_VALUES,
754 SCATTER_FORWARD);
755
756 auto *problem_ptr = getProblemPtr(dmMaterial);
757 auto &dofs =
758 problem_ptr->getNumeredRowDofsPtr()->get<Unique_mi_tag>();
759 const auto field_bit = mField.get_field_bit_number(materialH1Positions);
760
761 double *g_array;
762 double *exchange_array;
763 CHKERR VecGetArray(g, &g_array);
764 CHKERR VecGetArray(vertexExchange.second, &exchange_array);
765
766 auto ptr = exchange_array; // vector values are arranged as entries, That
767 // is key idea behind vertexExchange vector.
768 for (auto v : vertexExchange.first.first) {
769 std::array<double, SPACE_DIM> values = {0., 0., 0.};
770 auto lo =
771 dofs.lower_bound(DofEntity::getLoFieldEntityUId(field_bit, v));
772 auto hi =
773 dofs.upper_bound(DofEntity::getHiFieldEntityUId(field_bit, v));
774 for (; lo != hi; ++lo) {
775 if (!(*lo)->getHasLocalIndex())
776 continue;
777 const auto coeff = (*lo)->getDofCoeffIdx();
778 if (coeff < SPACE_DIM)
779 values[coeff] = g_array[(*lo)->getPetscLocalDofIdx()];
780 }
781 for (int d = 0; d != SPACE_DIM; ++d, ++ptr) {
782 *ptr = values[d];
783 }
784 }
785
786 CHKERR VecRestoreArray(vertexExchange.second, &exchange_array);
787 CHKERR VecRestoreArray(g, &g_array);
788
789 if (adjoint_gradient_vector != nullptr) {
790 (*adjoint_gradient_vector) = g;
791 }
792
794 };
795
796 CHKERR set_vertex_exchange_from_gradient();
797
798 CHKERR CommInterface::setTagFromVector(
800 tags[ExhangeTags::ADJOINT_MATERIALFORCE]);
801 CHKERR CommInterface::updateEntitiesPetscVector(
803 tags[ExhangeTags::ADJOINT_MATERIALFORCE]);
804
806 };
807
808 auto print_results = [&](auto nb_J_integral_conturs, bool print_material,
809 bool print_adjoint) {
811
812 if (!print_material && !print_adjoint) {
814 }
815
816 auto get_conn_range = [&](auto e) {
817 Range conn;
818 CHK_MOAB_THROW(mField.get_moab().get_connectivity(e, conn, true),
819 "get connectivity");
820 return conn;
821 };
822
823 auto get_tag_data = [&](auto &ents, auto tag, auto dim) {
824 std::vector<double> data(ents.size() * dim);
825 CHK_MOAB_THROW(mField.get_moab().tag_get_data(tag, ents, data.data()),
826 "get data");
827 return data;
828 };
829
830 if (mField.get_comm_rank() == 0) {
831 auto at_nodes = [&]() {
833 auto conn = get_conn_range(*frontEdges);
834 std::vector<double> material_force;
835 std::vector<double> adjoint_material_force;
836 auto area_growth = get_tag_data(conn, tags[ExhangeTags::AREAGROWTH], 3);
837 std::vector<double> griffith_force;
838 std::vector<double> adjoint_griffith_force;
839 if (print_material) {
840 material_force =
841 get_tag_data(conn, tags[ExhangeTags::MATERIALFORCE], 3);
842 griffith_force =
843 get_tag_data(conn, tags[ExhangeTags::GRIFFITHFORCE], 1);
844 }
845 if (print_adjoint) {
846 adjoint_material_force =
847 get_tag_data(conn, tags[ExhangeTags::ADJOINT_MATERIALFORCE], 3);
848 adjoint_griffith_force =
849 get_tag_data(conn, tags[ExhangeTags::ADJOINT_GRIFFITHFORCE], 1);
850 }
851 std::vector<double> coords(conn.size() * 3);
852 CHK_MOAB_THROW(mField.get_moab().get_coords(conn, coords.data()),
853 "get coords");
854 MOFEM_LOG("EPSELF", Sev::inform) << "Force results at nodes";
855 MOFEM_LOG("EPSELF", Sev::inform)
856 << std::left << std::setw(10) << "kind" << std::right
857 << std::setw(9) << "node" << std::setw(18) << "coord_x"
858 << std::setw(18) << "coord_y" << std::setw(18) << "coord_z"
859 << std::setw(18) << "force_x" << std::setw(18) << "force_y"
860 << std::setw(18) << "force_z" << std::setw(18) << "area_x"
861 << std::setw(18) << "area_y" << std::setw(18) << "area_z"
862 << std::setw(18) << "griffith" << std::setw(10) << "contour";
863
864 auto print_row = [&](const char *kind, const auto &force,
865 const auto &griffith, const size_t i) {
866 MOFEM_LOG("EPSELF", Sev::inform)
867 << std::left << std::setw(10) << kind << std::right
868 << std::setw(9) << conn[i] << std::scientific
869 << std::setprecision(10) << std::setw(18) << coords[i * 3 + 0]
870 << std::setw(18) << coords[i * 3 + 1] << std::setw(18)
871 << coords[i * 3 + 2] << std::setw(18) << force[i * 3 + 0]
872 << std::setw(18) << force[i * 3 + 1] << std::setw(18)
873 << force[i * 3 + 2] << std::setw(18) << area_growth[i * 3 + 0]
874 << std::setw(18) << area_growth[i * 3 + 1] << std::setw(18)
875 << area_growth[i * 3 + 2] << std::setw(18) << griffith[i]
876 << std::defaultfloat << std::setprecision(6) << std::setw(10)
877 << nb_J_integral_conturs;
878 };
879
880 for (size_t i = 0; i < conn.size(); ++i) {
881 if (print_material) {
882 print_row("material", material_force, griffith_force, i);
883 }
884 if (print_adjoint) {
885 print_row("adjoint", adjoint_material_force, adjoint_griffith_force,
886 i);
887 }
888 }
889
891 };
892
893 at_nodes();
894 }
896 };
897
898 CHKERR calculate_material_forces();
899
900 PetscBool all_contours = PETSC_FALSE;
901 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "",
902 "-calculate_J_integral_all_levels", &all_contours,
903 PETSC_NULLPTR); // for backward compatibility
905 PETSC_NULLPTR, "", "-calculate_J_integral_all_contours", &all_contours,
906 PETSC_NULLPTR); // new name
907
908 if (all_contours == PETSC_TRUE) {
909 for (int l = 0; l < nbJIntegralContours; ++l) {
910 CHKERR calculate_force_through_node(l);
911 CHKERR average_material_force_at_edge(tags[ExhangeTags::MATERIALFORCE]);
912 CHKERR calculate_crack_area_growth_face(l);
913 CHKERR calculate_crack_area_growth_no_face(l, ExhangeTags::MATERIALFORCE);
914 CHKERR update_crack_area_growth_edges();
915 CHKERR calculate_griffith_force(ExhangeTags::MATERIALFORCE,
916 ExhangeTags::GRIFFITHFORCE);
917 CHKERR print_results(l, true, false);
918 }
919 }
920
921 PetscBool has_nonzero_ts_solution = PETSC_FALSE;
922
923 if (ts != PETSC_NULLPTR) {
924 Vec ts_solution = PETSC_NULLPTR;
925 CHKERR TSGetSolution(ts, &ts_solution);
926 if (ts_solution != PETSC_NULLPTR) {
927 PetscReal ts_solution_norm = 0.0;
928 CHKERR VecNorm(ts_solution, NORM_2, &ts_solution_norm);
929 has_nonzero_ts_solution =
930 (ts_solution_norm > PETSC_MACHINE_EPSILON) ? PETSC_TRUE : PETSC_FALSE;
931 }
932
933 if (has_nonzero_ts_solution == PETSC_TRUE) {
934 CHKERR calculate_adjoint_material_force();
935 }
936 }
937
938 CHKERR calculate_force_through_node(nbJIntegralContours);
939 CHKERR average_material_force_at_edge(tags[ExhangeTags::MATERIALFORCE]);
940 CHKERR calculate_crack_area_growth_face(nbJIntegralContours);
941 CHKERR calculate_crack_area_growth_no_face(nbJIntegralContours,
942 ExhangeTags::MATERIALFORCE);
943 CHKERR update_crack_area_growth_edges();
944 CHKERR calculate_griffith_force(ExhangeTags::MATERIALFORCE,
945 ExhangeTags::GRIFFITHFORCE);
946 if (has_nonzero_ts_solution == PETSC_TRUE) {
947 CHKERR calculate_griffith_force(ExhangeTags::ADJOINT_MATERIALFORCE,
948 ExhangeTags::ADJOINT_GRIFFITHFORCE);
949 CHKERR calculate_griffith_force_simplified(
950 ExhangeTags::ADJOINT_MATERIALFORCE, ExhangeTags::ADJOINT_GRIFFITHFORCE);
951 }
952 CHKERR print_results(nbJIntegralContours, true, true);
953
955}
#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
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
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 957 of file EshelbianFracture.cpp.

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

2845 {
2847 auto meshset_mng = mField.getInterface<MeshsetsManager>();
2848 while (meshset_mng->checkMeshset(addCrackMeshsetId, BLOCKSET))
2850 MOFEM_LOG("EP", Sev::inform)
2851 << "Crack added surface meshset " << addCrackMeshsetId;
2852 CHKERR meshset_mng->addMeshset(BLOCKSET, addCrackMeshsetId, "CRACK_COMPUTED");
2854};

◆ 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 5937 of file EshelbianPlasticity.cpp.

5937 {
5939
5940 auto print_loc_size = [this](auto v, auto str, auto sev) {
5942 int size;
5943 CHKERR VecGetLocalSize(v.second, &size);
5944 int low, high;
5945 CHKERR VecGetOwnershipRange(v.second, &low, &high);
5946 MOFEM_LOG("EPSYNC", sev) << str << " local size " << size << " ( " << low
5947 << " " << high << " ) ";
5950 };
5951
5953 mField.get_comm(), mField.get_moab(), 3, 1, sev);
5954 CHKERR print_loc_size(volumeExchange, "volumeExchange", sev);
5956 mField.get_comm(), mField.get_moab(), 2, 1, Sev::inform);
5957 CHKERR print_loc_size(faceExchange, "faceExchange", sev);
5959 mField.get_comm(), mField.get_moab(), 1, 1, Sev::inform);
5960 CHKERR print_loc_size(edgeExchange, "edgeExchange", sev);
5962 mField.get_comm(), mField.get_moab(), 0, 3, Sev::inform);
5963 CHKERR print_loc_size(vertexExchange, "vertexExchange", sev);
5964
5966}
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  )
inlinestatic

◆ d_f_log_e()

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

◆ 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 150 of file EshelbianCore.hpp.

150 {
151 if (v > v_max) {
152 double e = static_cast<double>(std::exp(v_max));
153 double dv = v - v_max;
154 return e * dv + e;
155 } else {
156 return static_cast<double>(std::exp(v));
157 }
158 }
static constexpr double v_max

◆ dd_f_linear()

static double EshelbianCore::dd_f_linear ( const double  )
inlinestatic

◆ dd_f_log_e()

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

◆ 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 160 of file EshelbianCore.hpp.

160 {
161 if (v > v_max) {
162 return static_cast<double>(std::exp(v_max));
163 } else {
164 return static_cast<double>(std::exp(v));
165 }
166 }

◆ f_linear()

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

◆ f_log_e()

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

◆ 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 140 of file EshelbianCore.hpp.

140 {
141 if (v > v_max) {
142 double e = static_cast<double>(std::exp(v_max));
143 double dv = v - v_max;
144 return 0.5 * e * dv * dv + e * dv + e;
145 } else {
146 return static_cast<double>(std::exp(v));
147 }
148 }

◆ 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 348 of file EshelbianCore.hpp.

349 {
351 for (auto it :
352 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
353
354 (boost::format("%s(.*)") % block_name).str()
355
356 ))
357
358 ) {
359 std::vector<double> block_attributes;
360 CHKERR it->getAttributes(block_attributes);
361 if (block_attributes.size() < static_cast<size_t>(nb_attributes)) {
362 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
363 "In block %s expected %d attributes, but given %ld",
364 it->getName().c_str(), nb_attributes, block_attributes.size());
365 }
366 Range faces;
367 CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
368 true);
369 bc_vec_ptr->emplace_back(
370 it->getName(), block_attributes, faces,
371 getStringArgumentFromJsonBlockset(block_name, it->getMeshsetId(),
372 "load_history"));
373 }
375 }
std::string getStringArgumentFromJsonBlockset(const std::string &type_name, const int meshset_id, const std::string &param_name)
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 5867 of file EshelbianPlasticity.cpp.

5867 {
5869
5870 auto getExternalStrain = [&](boost::shared_ptr<ExternalStrainVec>
5871 &ext_strain_vec_ptr,
5872 const std::string block_name,
5873 const int nb_attributes) {
5875 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5876 std::regex((boost::format("(.*)%s(.*)") % block_name).str()))) {
5877 std::vector<double> block_attributes;
5878 const bool analytical_external_strain = std::regex_match(
5879 it->getName(), std::regex("(.*)ANALYTICAL_EXTERNALSTRAIN(.*)"));
5880 const std::string json_block_name =
5881 analytical_external_strain ? "ANALYTICAL_EXTERNALSTRAIN" : block_name;
5882
5883 CHKERR it->getAttributes(block_attributes);
5884
5885 if (block_attributes.size() < nb_attributes) {
5886 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5887 "In block %s expected %d attributes, but given %ld",
5888 it->getName().c_str(), nb_attributes, block_attributes.size());
5889 }
5890
5891 auto get_block_ents = [&]() {
5892 Range ents;
5893 CHKERR mField.get_moab().get_entities_by_handle(it->meshset, ents,
5894 true);
5895 return ents;
5896 };
5897
5898 std::string load_history;
5899 if (!analytical_external_strain) {
5900 load_history = getStringArgumentFromJsonBlockset(
5901 json_block_name, it->getMeshsetId(), "load_history");
5902 }
5903 ext_strain_vec_ptr->emplace_back(it->getName(), block_attributes,
5904 get_block_ents(), load_history);
5905 }
5907 };
5908
5909 externalStrainVecPtr = boost::make_shared<ExternalStrainVec>();
5910
5911 CHKERR getExternalStrain(externalStrainVecPtr, "EXTERNALSTRAIN", 2);
5912
5913 auto ts_pre_stretch = boost::make_shared<DynamicRelaxationTimeScale>(
5914 "externalstrain_history.txt");
5915 for (auto &ext_strain_block : *externalStrainVecPtr) {
5916 MOFEM_LOG("EP", Sev::noisy)
5917 << "Add time scaling external strain: " << ext_strain_block.blockName;
5918 if (!ext_strain_block.loadHistoryFile.empty()) {
5919 MOFEM_LOG("EP", Sev::inform)
5920 << "External strain load history from JSON for "
5921 << ext_strain_block.blockName << ": "
5922 << ext_strain_block.loadHistoryFile;
5923 timeScaleMap[ext_strain_block.blockName] =
5924 boost::make_shared<DynamicRelaxationTimeScale>(
5925 ext_strain_block.loadHistoryFile);
5926 } else {
5927 timeScaleMap[ext_strain_block.blockName] =
5929 ts_pre_stretch, "externalstrain_history", ".txt",
5930 ext_strain_block.blockName);
5931 }
5932 }
5933
5935}
analytical_external_strain(delta_t, t, x, y, z, block_name)
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 1009 of file EshelbianPlasticity.cpp.

1009 {
1011 // Interface initialisation applies JSON options before selecting the layout.
1013 const char *list_rots[] = {"small", "moderate", "large", "no_h1"};
1014 const char *list_release[] = {"griffith_force", "griffith_skeleton"};
1015 const char *list_stretches[] = {"linear", "log", "log_quadratic"};
1016 const char *list_broken_hdiv_bases[] = {"demkowicz", "ainsworth"};
1017 PetscInt choice_rot = EshelbianCore::rotSelector;
1018 PetscInt choice_grad = EshelbianCore::gradApproximator;
1019 PetscInt choice_release = EshelbianCore::energyReleaseSelector;
1020 PetscInt choice_stretch = StretchSelector::LOG;
1021 PetscInt choice_solver = SolverType::TimeSolver;
1022 PetscInt choice_broken_hdiv_base = 0;
1023 PetscBool l2_user_base_scale_set = PETSC_FALSE;
1026 choice_broken_hdiv_base = 0;
1027 break;
1029 choice_broken_hdiv_base = 1;
1030 break;
1031 default:
1032 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1033 "Unsupported broken HDIV base %s",
1035 }
1036 char analytical_expr_file_name[255] = "analytical_expr.py";
1037
1038 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Eshelbian plasticity", "none");
1039 CHKERR PetscOptionsInt("-space_order", "approximation oder for space", "",
1040 spaceOrder, &spaceOrder, PETSC_NULLPTR);
1041 CHKERR PetscOptionsInt("-space_h1_order", "approximation oder for space", "",
1042 spaceH1Order, &spaceH1Order, PETSC_NULLPTR);
1043 CHKERR PetscOptionsInt("-material_order", "approximation oder for material",
1044 "", materialH1Order, &materialH1Order, PETSC_NULLPTR);
1045 CHKERR PetscOptionsScalar("-viscosity_alpha_u",
1046 "Logarithmic-stretch rate viscosity", "", alphaU,
1047 &alphaU, PETSC_NULLPTR);
1048 CHKERR PetscOptionsScalar("-viscosity_alpha_w",
1049 "Spatial-displacement rate viscosity", "", alphaW,
1050 &alphaW, PETSC_NULLPTR);
1051 CHKERR PetscOptionsScalar("-alpha_omega", "H1 rotation penalty coefficient",
1052 "", alphaOmega, &alphaOmega, PETSC_NULLPTR);
1053 CHKERR PetscOptionsScalar("-alpha_r", "L2 rotation penalty coefficient", "",
1054 alphaR, &alphaR, PETSC_NULLPTR);
1055 CHKERR PetscOptionsScalar("-viscosity_alpha_omega",
1056 "H1 rotation-rate viscosity", "",
1058 PETSC_NULLPTR);
1059 CHKERR PetscOptionsScalar("-viscosity_alpha_r", "L2 rotation-rate viscosity", "",
1060 alphaViscousR, &alphaViscousR, PETSC_NULLPTR);
1061 CHKERR PetscOptionsScalar("-density_alpha_rho",
1062 "Spatial-displacement inertia density", "",
1063 alphaRho, &alphaRho, PETSC_NULLPTR);
1064 CHKERR PetscOptionsScalar("-alpha_tau",
1065 "Interior displacement-stabilisation coefficient",
1066 "", alphaTau, &alphaTau, PETSC_NULLPTR);
1067 CHKERR PetscOptionsScalar(
1068 "-alpha_tau_lin",
1069 "Coefficient multiplying the face-averaged normal-traction contribution "
1070 "to displacement stabilisation",
1071 "", alphaTauLin, &alphaTauLin, PETSC_NULLPTR);
1072 CHKERR PetscOptionsScalar("-alpha_tau_bc_disp",
1073 "Displacement-BC stabilisation coefficient", "",
1074 alphaTauBcDisp, &alphaTauBcDisp, PETSC_NULLPTR);
1075 CHKERR PetscOptionsEList("-rotations", "rotations", "", list_rots,
1076 LARGE_ROT + 1, list_rots[choice_rot], &choice_rot,
1077 PETSC_NULLPTR);
1078 CHKERR PetscOptionsEList("-grad", "gradient of defamation approximate", "",
1079 list_rots, NO_H1_CONFIGURATION + 1,
1080 list_rots[choice_grad], &choice_grad, PETSC_NULLPTR);
1081
1082 CHKERR PetscOptionsEList("-stretches", "stretches", "", list_stretches,
1083 StretchSelector::STRETCH_SELECTOR_LAST,
1084 list_stretches[choice_stretch], &choice_stretch,
1085 PETSC_NULLPTR);
1086
1087 CHKERR PetscOptionsBool("-set_singularity", "set singularity", "",
1088 setSingularity, &setSingularity, PETSC_NULLPTR);
1089 CHKERR PetscOptionsBool("-l2_user_base_scale", "streach scale", "",
1091 &l2_user_base_scale_set);
1092 CHKERR PetscOptionsEList("-broken_hdiv_base",
1093 "broken HDIV stress approximation base", "",
1094 list_broken_hdiv_bases, 2,
1095 list_broken_hdiv_bases[choice_broken_hdiv_base],
1096 &choice_broken_hdiv_base, PETSC_NULLPTR);
1097
1098 // dynamic relaxation
1099
1100 // @deprecate this option
1101 CHKERR PetscOptionsBool("-dynamic_relaxation", "dynamic time relaxation", "",
1102 physicalTimeFlg, &physicalTimeFlg, PETSC_NULLPTR);
1103 CHKERR PetscOptionsEList(
1104 "-solver_type", "solver type", "", EshelbianCore::listSolvers,
1106 EshelbianCore::listSolvers[choice_solver], &choice_solver, PETSC_NULLPTR);
1107
1108 if (choice_solver != SolverType::TimeSolver) {
1109 CHKERR PetscOptionsScalar("-physical_final_time", "physical final time", "",
1111 &EshelbianCore::finalPhysicalTime, PETSC_NULLPTR);
1112 CHKERR PetscOptionsScalar("-physical_delta_time", "physical delta time", "",
1114 PETSC_NULLPTR);
1115 CHKERR PetscOptionsInt("-physical_max_steps", "physical max iterations", "",
1117 PETSC_NULLPTR);
1118 CHKERR PetscOptionsBool(
1119 "-physical_h1_update", "update each physicalsolver step", "",
1121 }
1122
1123 // contact parameters
1124 CHKERR PetscOptionsInt("-contact_max_post_proc_ref_level", "refinement level",
1126 PETSC_NULLPTR);
1127 // cohesive interface
1128 CHKERR PetscOptionsBool("-cohesive_interface_on", "cohesive interface ON", "",
1129 interfaceCrack, &interfaceCrack, PETSC_NULLPTR);
1130 CHKERR PetscOptionsInt(
1131 "-cohesive_interface_remove_level", "cohesive interface remove level", "",
1133 CHKERR PetscOptionsBool("-plastic_volume",
1134 "restrict plasticity to the PLATIC_VOLUME block", "",
1135 plasticVolume, &plasticVolume, PETSC_NULLPTR);
1136
1137 // cracking parameters
1138 CHKERR PetscOptionsBool("-cracking_on", "cracking ON", "", crackingOn,
1139 &crackingOn, PETSC_NULLPTR);
1140 CHKERR PetscOptionsBool("-propagate_under_compression",
1141 "propagate crack under compression", "",
1143 &propagateUnderCompression, PETSC_NULLPTR);
1144 CHKERR PetscOptionsScalar("-cracking_add_time", "cracking add time", "",
1145 crackingAddTime, &crackingAddTime, PETSC_NULLPTR);
1146 CHKERR PetscOptionsScalar("-cracking_start_time", "cracking start time", "",
1148 PETSC_NULLPTR);
1149 CHKERR PetscOptionsScalar("-griffith_energy", "Griffith energy", "",
1150 griffithEnergy, &griffithEnergy, PETSC_NULLPTR);
1151
1152 CHKERR PetscOptionsScalar("-cracking_rtol", "Cracking relative tolerance", "",
1153 crackingRtol, &crackingRtol, PETSC_NULLPTR);
1154 CHKERR PetscOptionsScalar("-cracking_atol", "Cracking absolute tolerance", "",
1155 crackingAtol, &crackingAtol, PETSC_NULLPTR);
1156 CHKERR PetscOptionsEList("-energy_release_variant", "energy release variant",
1157 "", list_release, 2, list_release[choice_release],
1158 &choice_release, PETSC_NULLPTR);
1159 CHKERR PetscOptionsInt("-nb_J_integral_levels", "Number of J integarl levels",
1161 PETSC_NULLPTR); // backward compatibility
1162 CHKERR PetscOptionsInt(
1163 "-nb_J_integral_contours", "Number of J integral contours", "",
1164 nbJIntegralContours, &nbJIntegralContours, PETSC_NULLPTR);
1165
1166 // internal stress
1167 char tag_name[255] = "";
1168 CHKERR PetscOptionsString("-internal_stress_tag_name",
1169 "internal stress tag name", "", "", tag_name, 255,
1170 PETSC_NULLPTR);
1171 internalStressTagName = string(tag_name);
1172 CHKERR PetscOptionsBool("-internal_stress_voigt", "Voigt index notation", "",
1174 PETSC_NULLPTR);
1175
1176 // Heterogenous Young's modulus
1177 char tag_heterogeneous_youngs_modulus_name[255] = "";
1178 CHKERR PetscOptionsString(
1179 "-heterogeneous_youngs_modulus", "heterogeneous Young's modulus tag name",
1180 "", "", tag_heterogeneous_youngs_modulus_name, 255, PETSC_NULLPTR);
1181 heterogeneousYoungModTagName = string(tag_heterogeneous_youngs_modulus_name);
1182
1183 PetscBool has_analytical_expr_file_option = PETSC_FALSE;
1185 PETSC_NULLPTR, PETSC_NULLPTR, "-analytical_expr_file",
1186 analytical_expr_file_name, 255, &has_analytical_expr_file_option);
1187 if (!has_analytical_expr_file_option) {
1188 const auto analytical_expr_script =
1189 mField.getInterface<JsonConfigManager>()->getPythonScriptByKey(
1190 "analytical_expr");
1191 if (!analytical_expr_script.empty()) {
1192 CHKERR PetscStrncpy(analytical_expr_file_name,
1193 analytical_expr_script.c_str(),
1194 sizeof(analytical_expr_file_name));
1195 MOFEM_LOG("EP", Sev::inform)
1196 << "Using Python script 'analytical_expr' from JSON config: "
1197 << analytical_expr_file_name;
1198 }
1199 }
1200
1201 PetscOptionsEnd();
1202
1204
1205 PetscOptionsBegin(PETSC_COMM_WORLD, "mesh_transfer_", "mesh data transfer",
1206 "none");
1207 char tag_mesh_transfer_source_file_name[255] = "";
1208 CHKERR PetscOptionsString("-source_file", "source mesh file name", "",
1209 "source.h5m", tag_mesh_transfer_source_file_name,
1211 meshTransferSourceMeshFileName = string(tag_mesh_transfer_source_file_name);
1212 CHKERR PetscOptionsInt("-interp_order", "interpolation order", "", 0,
1213 &meshTransferInterpOrder, PETSC_NULLPTR);
1214 CHKERR PetscOptionsBool("-hybrid_interp", "use hybrid interpolation", "",
1216 PETSC_NULLPTR);
1217 PetscOptionsEnd();
1218
1220 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
1221 "Unsupported mesh transfer interpolation order %d",
1223 }
1224 if (!internalStressTagName.empty())
1226 if (!heterogeneousYoungModTagName.empty())
1228
1229 const PetscBool l2_user_base_scale_option = l2UserBaseScale;
1230 if (setSingularity && !l2_user_base_scale_set) {
1231 l2UserBaseScale = PETSC_TRUE;
1232 }
1233
1234 EshelbianCore::rotSelector = static_cast<RotSelector>(choice_rot);
1235 EshelbianCore::gradApproximator = static_cast<RotSelector>(choice_grad);
1236 EshelbianCore::stretchSelector = static_cast<StretchSelector>(choice_stretch);
1238 static_cast<EnergyReleaseSelector>(choice_release);
1239 switch (choice_broken_hdiv_base) {
1240 case 0:
1242 break;
1243 case 1:
1245 break;
1246 default:
1247 SETERRQ(PETSC_COMM_WORLD, MOFEM_DATA_INCONSISTENCY,
1248 "Unknown broken HDIV base option");
1249 }
1250
1252 case StretchSelector::LINEAR:
1259 break;
1260 case StretchSelector::LOG:
1267 break;
1268 case StretchSelector::LOG_QUADRATIC:
1275 break;
1276 default:
1277 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown stretch");
1278 break;
1279 };
1280
1281 const PetscBool dynamic_relaxation_option = physicalTimeFlg;
1282 if (physicalTimeFlg) {
1283 MOFEM_LOG("EP", Sev::warning)
1284 << "-dynamic_relaxation option is deprecated, use -solver_type "
1285 "dynamic_relaxation instead.";
1286 choice_solver = SolverType::DynamicRelaxation;
1287 }
1288
1289 switch (choice_solver) {
1292 break;
1296 physicalTimeFlg = PETSC_TRUE;
1297 break;
1301 physicalTimeFlg = PETSC_TRUE;
1302 break;
1305 physicalTimeFlg = PETSC_TRUE;
1306 break;
1310 break;
1314 physicalTimeFlg = PETSC_TRUE;
1315 break;
1319 physicalTimeFlg = PETSC_TRUE;
1320 break;
1324 break;
1328 physicalTimeFlg = PETSC_TRUE;
1329 break;
1332 static_cast<SolverType>(
1334 physicalTimeFlg = PETSC_TRUE;
1335 break;
1338 static_cast<SolverType>(
1340 physicalTimeFlg = PETSC_TRUE;
1341 break;
1342 default:
1343 SETERRQ(mField.get_comm(), MOFEM_DATA_INCONSISTENCY, "Unknown solver");
1344 break;
1345 };
1346
1347 // start cracking time
1349 crackingStartTime = -1;
1350 crackingAddTime = -1;
1351 MOFEM_LOG("EP", Sev::warning)
1352 << "Cracking start/add time does not apply for load factor solver.";
1353 } else {
1355 }
1356
1357 const auto yes_no = [](auto flag) { return flag ? "yes" : "no"; };
1358
1359 MOFEM_LOG("EP", Sev::inform) << "spaceOrder: -space_order " << spaceOrder;
1360 MOFEM_LOG("EP", Sev::inform)
1361 << "spaceH1Order: -space_h1_order " << spaceH1Order;
1362 MOFEM_LOG("EP", Sev::inform)
1363 << "materialH1Order: -material_order " << materialH1Order;
1364 MOFEM_LOG("EP", Sev::inform)
1365 << "alphaU (-viscosity_alpha_u), logarithmic-stretch rate viscosity: "
1366 << alphaU;
1367 MOFEM_LOG("EP", Sev::inform)
1368 << "alphaW (-viscosity_alpha_w), spatial-displacement rate viscosity: "
1369 << alphaW;
1370 MOFEM_LOG("EP", Sev::inform)
1371 << "alphaOmega (-alpha_omega), H1 rotation penalty coefficient: "
1372 << alphaOmega;
1373 MOFEM_LOG("EP", Sev::inform)
1374 << "alphaR (-alpha_r), L2 rotation penalty coefficient: " << alphaR;
1375 MOFEM_LOG("EP", Sev::inform)
1376 << "alphaViscousOmega (-viscosity_alpha_omega), H1 rotation-rate "
1377 "viscosity: "
1379 MOFEM_LOG("EP", Sev::inform)
1380 << "alphaViscousR (-viscosity_alpha_r), L2 rotation-rate viscosity: "
1381 << alphaViscousR;
1382 MOFEM_LOG("EP", Sev::inform)
1383 << "alphaRho (-density_alpha_rho), spatial-displacement inertia "
1384 "density: "
1385 << alphaRho;
1386 MOFEM_LOG("EP", Sev::inform)
1387 << "alphaTau (-alpha_tau), interior displacement-stabilisation "
1388 "coefficient: "
1389 << alphaTau;
1390 MOFEM_LOG("EP", Sev::inform)
1391 << "alphaTauLin (-alpha_tau_lin), face-averaged normal-traction "
1392 "stabilisation coefficient: "
1393 << alphaTauLin;
1394 MOFEM_LOG("EP", Sev::inform)
1395 << "alphaTauBcDisp (-alpha_tau_bc_disp), displacement-BC "
1396 "stabilisation coefficient: "
1397 << alphaTauBcDisp;
1398 MOFEM_LOG("EP", Sev::inform)
1399 << "Rotations: -rotations " << list_rots[EshelbianCore::rotSelector];
1400 MOFEM_LOG("EP", Sev::inform) << "Gradient of deformation: -grad "
1401 << list_rots[EshelbianCore::gradApproximator];
1402 MOFEM_LOG("EP", Sev::inform)
1403 << "Stretch: -stretches " << list_stretches[choice_stretch];
1404
1405 MOFEM_LOG("EP", Sev::inform) << "Dynamic relaxation: -dynamic_relaxation "
1406 << yes_no(dynamic_relaxation_option);
1407 MOFEM_LOG("EP", Sev::inform) << "Solver type: -solver_type "
1408 << EshelbianCore::listSolvers[choice_solver];
1409 if (choice_solver != SolverType::TimeSolver) {
1410 MOFEM_LOG("EP", Sev::inform)
1411 << "Physical final time: -physical_final_time " << finalPhysicalTime;
1412 MOFEM_LOG("EP", Sev::inform)
1413 << "Physical delta time: -physical_delta_time " << physicalDt;
1414 MOFEM_LOG("EP", Sev::inform)
1415 << "Physical max steps: -physical_max_steps " << physicalMaxSteps;
1416 MOFEM_LOG("EP", Sev::inform) << "Physical H1 update: -physical_h1_update "
1417 << yes_no(physicalH1Update);
1418 }
1419 MOFEM_LOG("EP", Sev::inform)
1420 << "Singularity: -set_singularity " << yes_no(setSingularity);
1421 MOFEM_LOG("EP", Sev::inform) << "L2 user base scale: -l2_user_base_scale "
1422 << yes_no(l2_user_base_scale_option);
1423 if (l2UserBaseScale != l2_user_base_scale_option) {
1424 MOFEM_LOG("EP", Sev::inform)
1425 << "Effective L2 user base scale after option processing "
1426 << yes_no(l2UserBaseScale) << " (auto-enabled by -set_singularity)";
1427 }
1428 MOFEM_LOG("EP", Sev::inform)
1429 << "Broken HDIV base: -broken_hdiv_base "
1430 << list_broken_hdiv_bases[choice_broken_hdiv_base];
1431 MOFEM_LOG("EP", Sev::inform)
1432 << "Contact max post-proc ref level: -contact_max_post_proc_ref_level "
1434
1435 MOFEM_LOG("EP", Sev::inform)
1436 << "Cracking on: -cracking_on " << yes_no(crackingOn);
1437 MOFEM_LOG("EP", Sev::inform)
1438 << "Cracking add time: -cracking_add_time " << crackingAddTime;
1439 MOFEM_LOG("EP", Sev::inform)
1440 << "Cracking start time: -cracking_start_time " << crackingStartTime;
1441 MOFEM_LOG("EP", Sev::inform)
1442 << "Griffith energy: -griffith_energy " << griffithEnergy;
1443 MOFEM_LOG("EP", Sev::inform)
1444 << "Cracking relative tolerance: -cracking_rtol " << crackingRtol;
1445 MOFEM_LOG("EP", Sev::inform)
1446 << "Cracking absolute tolerance: -cracking_atol " << crackingAtol;
1447 MOFEM_LOG("EP", Sev::inform)
1448 << "Energy release variant: -energy_release_variant "
1449 << list_release[EshelbianCore::energyReleaseSelector];
1450 MOFEM_LOG("EP", Sev::inform)
1451 << "Number of J integral contours: -nb_J_integral_contours / "
1452 "-nb_J_integral_levels "
1454 MOFEM_LOG("EP", Sev::inform)
1455 << "Cohesive interface on: -cohesive_interface_on "
1456 << ((interfaceCrack == PETSC_TRUE) ? "yes" : "no");
1457 MOFEM_LOG("EP", Sev::inform)
1458 << "Cohesive interface remove level: -cohesive_interface_remove_level "
1460 MOFEM_LOG("EP", Sev::inform)
1461 << "Plastic volume: -plastic_volume " << yes_no(plasticVolume);
1462 MOFEM_LOG("EP", Sev::inform)
1463 << "Internal stress tag name: -internal_stress_tag_name "
1465 MOFEM_LOG("EP", Sev::inform)
1466 << "Internal stress Voigt notation: -internal_stress_voigt "
1467 << yes_no(internalStressVoigt);
1468 MOFEM_LOG("EP", Sev::inform)
1469 << "Heterogeneous Young's modulus: -heterogeneous_youngs_modulus "
1471 MOFEM_LOG("EP", Sev::inform)
1472 << "Analytical expression file: -analytical_expr_file "
1473 << analytical_expr_file_name;
1475 MOFEM_LOG("EP", Sev::inform)
1476 << "Mesh transfer source file: -mesh_transfer_source_file "
1478 } else {
1479 MOFEM_LOG("EP", Sev::inform)
1480 << "Mesh transfer source file: -mesh_transfer_source_file <not set>";
1481 }
1482 MOFEM_LOG("EP", Sev::inform)
1483 << "Mesh transfer interpolation order: -mesh_transfer_interp_order "
1485 MOFEM_LOG("EP", Sev::inform)
1486 << "Mesh transfer hybrid interpolation: -mesh_transfer_hybrid_interp "
1487 << yes_no(meshTransferHybridInterp);
1488
1489#ifdef ENABLE_PYTHON_BINDING
1490 auto file_exists = [](std::string myfile) {
1491 std::ifstream file(myfile.c_str());
1492 if (file) {
1493 return true;
1494 }
1495 return false;
1496 };
1497
1498 if (file_exists(analytical_expr_file_name)) {
1499 MOFEM_LOG("EP", Sev::inform) << analytical_expr_file_name << " file found";
1500
1501 AnalyticalExprPythonPtr = boost::make_shared<AnalyticalExprPython>();
1502 CHKERR AnalyticalExprPythonPtr->analyticalExprInit(
1503 analytical_expr_file_name);
1504 AnalyticalExprPythonWeakPtr = AnalyticalExprPythonPtr;
1505 } else {
1506 MOFEM_LOG("EP", Sev::warning)
1507 << analytical_expr_file_name << " file NOT found";
1508 }
1509#endif
1510
1511 if (spaceH1Order == -1)
1513
1515}
@ 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_dd_f_linear(const double)
static double inv_f_linear(const double v)
static double dd_f_log_e_quadratic(const double v)
static double inv_d_f_linear(const double)
static double dd_f_linear(const double)
static boost::function< double(const double)> inv_dd_f
static enum SolverType solverType
static PetscBool l2UserBaseScale
static const char * listSolvers[]
static PetscBool crackingOn
static double dd_f_log_e(const double v)
static double d_f_linear(const double)
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static double inv_dd_f_log_e_quadratic(const double stretch)
static double physicalDt
static std::vector< std::string > listTagsToProject
static std::string heterogeneousYoungModTagName
static int physicalMaxSteps
static double crackingStartTime
static double inv_d_f_log_e(const double v)
static PetscBool physicalTimeFlg
static double crackingAddTime
boost::shared_ptr< AnalyticalExprPython > AnalyticalExprPythonPtr
static PetscBool meshTransferHybridInterp
static std::string internalStressTagName
static double finalPhysicalTime
static PetscBool internalStressVoigt
static double inv_dd_f_log_e(const double v)
static PetscBool setSingularity
static double d_f_log_e(const double v)
static PetscBool meshTransferSourceMeshFileSpecified
static double f_log_e_quadratic(const double v)
static double inv_f_log_e_quadratic(const double stretch)
static PetscBool interfaceCrack
static double d_f_log_e_quadratic(const double v)
static boost::function< double(const double)> dd_f
static double f_log_e(const double v)
static double inv_f_log_e(const double v)
static boost::function< double(const double)> d_f
static boost::function< double(const double)> inv_d_f
static int meshTransferInterpOrder
static double inv_d_f_log_e_quadratic(const double stretch)
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 5663 of file EshelbianPlasticity.cpp.

5663 {
5665
5666 auto bc_mng = mField.getInterface<BcManager>();
5668 "", piolaStress, false, false);
5669 CHKERR bc_mng->pushMarkDOFsOnEntities<BcDisplacementMeshsetType<BLOCKSET>>(
5670 "", piolaStress, false, false);
5671
5672 bcSpatialDispVecPtr = boost::make_shared<BcDispVec>();
5673 auto get_fix_load_history = [&](const std::string &block_name) {
5674 for (const auto type_name : {"FIX_X", "FIX_Y", "FIX_Z", "FIX_ALL"}) {
5675 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
5676 std::regex(
5677
5678 (boost::format("%s(.*)") % type_name).str()
5679
5680 ))
5681
5682 ) {
5683 if (it->getName() == block_name) {
5685 type_name, it->getMeshsetId(), "load_history");
5686 }
5687 }
5688 }
5689 return std::string();
5690 };
5691
5692 for (auto bc : bc_mng->getBcMapByBlockName()) {
5693 if (auto disp_bc = bc.second->dispBcPtr) {
5694
5695 auto [field_name, block_name] =
5697 MOFEM_LOG("EP", Sev::inform)
5698 << "Field name: " << field_name << " Block name: " << block_name;
5699 MOFEM_LOG("EP", Sev::noisy) << "Displacement BC: " << *disp_bc;
5700
5701 std::vector<double> block_attributes(6, 0.);
5702 if (disp_bc->data.flag1 == 1) {
5703 block_attributes[0] = disp_bc->data.value1;
5704 block_attributes[3] = 1;
5705 }
5706 if (disp_bc->data.flag2 == 1) {
5707 block_attributes[1] = disp_bc->data.value2;
5708 block_attributes[4] = 1;
5709 }
5710 if (disp_bc->data.flag3 == 1) {
5711 block_attributes[2] = disp_bc->data.value3;
5712 block_attributes[5] = 1;
5713 }
5714 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5715 bcSpatialDispVecPtr->emplace_back(block_name, block_attributes, faces,
5716 get_fix_load_history(block_name));
5717 }
5718 }
5719 // old way of naming blocksets for displacement BCs
5720 CHKERR getBc(bcSpatialDispVecPtr, "SPATIAL_DISP_BC", 6);
5721
5723 boost::make_shared<NormalDisplacementBcVec>();
5724 CHKERR getBc(bcSpatialNormalDisplacementVecPtr, "NORMAL_DISPLACEMENT", 1);
5725
5726 bcSpatialSpringVecPtr = boost::make_shared<SpringBcVec>();
5727 auto mesh_mng = mField.getInterface<MeshsetsManager>();
5728 for (auto it : mesh_mng->getCubitMeshsetPtr(
5729 std::regex((boost::format("(.*)%s(.*)") % "SPRING_BC").str()))) {
5730 std::vector<double> block_attributes;
5731 CHKERR it->getAttributes(block_attributes);
5732 if (block_attributes.size() < 2) {
5733 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
5734 "In block %s expected 2 attributes, but given %ld",
5735 it->getName().c_str(), block_attributes.size());
5736 }
5737 Range faces;
5738 CHKERR it->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
5739 true);
5740 MOFEM_LOG("EP", Sev::inform)
5741 << "Found spring BC on block " << it->getName();
5742 MOFEM_LOG("EP", Sev::inform)
5743 << " kn = " << block_attributes[0] << ", kt = " << block_attributes[1];
5744 MOFEM_LOG("EP", Sev::inform) << " nb. of faces " << faces.size();
5745 bcSpatialSpringVecPtr->emplace_back(it->getName(), block_attributes, faces);
5746 }
5747
5749 boost::make_shared<AnalyticalDisplacementBcVec>();
5750 CHKERR getBc(bcSpatialAnalyticalDisplacementVecPtr, "ANALYTICAL_DISPLACEMENT",
5751 3);
5752
5753 auto ts_displacement =
5754 boost::make_shared<DynamicRelaxationTimeScale>("disp_history.txt");
5755 for (auto &bc : *bcSpatialDispVecPtr) {
5756 MOFEM_LOG("EP", Sev::noisy)
5757 << "Add time scaling displacement BC: " << bc.blockName;
5758 if (!bc.loadHistoryFile.empty()) {
5759 MOFEM_LOG("EP", Sev::inform)
5760 << "Displacement load history from JSON for " << bc.blockName << ": "
5761 << bc.loadHistoryFile;
5762 timeScaleMap[bc.blockName] =
5763 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5764 } else {
5765 timeScaleMap[bc.blockName] =
5767 ts_displacement, "disp_history", ".txt", bc.blockName);
5768 }
5769 }
5770
5771 auto ts_normal_displacement =
5772 boost::make_shared<DynamicRelaxationTimeScale>("normal_disp_history.txt");
5773 for (auto &bc : *bcSpatialNormalDisplacementVecPtr) {
5774 MOFEM_LOG("EP", Sev::noisy)
5775 << "Add time scaling normal displacement BC: " << bc.blockName;
5776 if (!bc.loadHistoryFile.empty()) {
5777 MOFEM_LOG("EP", Sev::inform)
5778 << "Normal displacement load history from JSON for " << bc.blockName
5779 << ": " << bc.loadHistoryFile;
5780 timeScaleMap[bc.blockName] =
5781 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5782 } else {
5783 timeScaleMap[bc.blockName] =
5785 ts_normal_displacement, "normal_disp_history", ".txt",
5786 bc.blockName);
5787 }
5788 }
5789
5791}
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)
Template specialization for displacement boundary conditions.
Boundary condition manager for finite element problem setup.
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.
Template specialization system for type-safe boundary condition handling.

◆ getSpatialRotationBc()

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

Definition at line 379 of file EshelbianCore.hpp.

379 {
381 bcSpatialRotationVecPtr = boost::make_shared<BcRotVec>();
382 CHKERR getBc(bcSpatialRotationVecPtr, "SPATIAL_ROTATION_BC", 4);
383 CHKERR getBc(bcSpatialRotationVecPtr, "SPATIAL_ROTATION_AXIS_BC", 7);
384
385 for (auto &bc : *bcSpatialRotationVecPtr) {
386 MOFEM_LOG("EP", Sev::inform)
387 << "Found spatial rotation BC on block " << bc.blockName;
388 MOFEM_LOG("EP", Sev::inform) << " with attributes: " << bc.vals;
389 MOFEM_LOG("EP", Sev::inform) << " and rotation angle: " << bc.theta;
390 MOFEM_LOG("EP", Sev::inform) << " and nb of faces: " << bc.faces.size();
391 }
392
393 auto ts_rotation =
394 boost::make_shared<DynamicRelaxationTimeScale>("rotation_history.txt");
395 for (auto &bc : *bcSpatialRotationVecPtr) {
396 if (!bc.loadHistoryFile.empty()) {
397 MOFEM_LOG("EP", Sev::inform)
398 << "Rotation load history from JSON for " << bc.blockName << ": "
399 << bc.loadHistoryFile;
400 timeScaleMap[bc.blockName] =
401 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
402 } else {
403 timeScaleMap[bc.blockName] =
404 GetBlockScalingMethod<DynamicRelaxationTimeScale>::get(
405 ts_rotation, "rotation_history", ".txt", bc.blockName);
406 }
407 }
408
410 }

◆ 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 5793 of file EshelbianPlasticity.cpp.

5793 {
5795
5796 auto bc_mng = mField.getInterface<BcManager>();
5798 false, false);
5799
5800 bcSpatialTractionVecPtr = boost::make_shared<TractionBcVec>();
5801
5802 for (auto bc : bc_mng->getBcMapByBlockName()) {
5803 if (auto force_bc = bc.second->forceBcPtr) {
5804
5805 auto [field_name, block_name] =
5807 MOFEM_LOG("EP", Sev::inform)
5808 << "Field name: " << field_name << " Block name: " << block_name;
5809 MOFEM_LOG("EP", Sev::noisy) << "Force BC: " << *force_bc;
5810
5811 std::vector<double> block_attributes(6, 0.);
5812 block_attributes[0] = -force_bc->data.value3 * force_bc->data.value1;
5813 block_attributes[3] = 1;
5814 block_attributes[1] = -force_bc->data.value4 * force_bc->data.value1;
5815 block_attributes[4] = 1;
5816 block_attributes[2] = -force_bc->data.value5 * force_bc->data.value1;
5817 block_attributes[5] = 1;
5818 auto faces = bc.second->bcEnts.subset_by_dimension(2);
5819 bcSpatialTractionVecPtr->emplace_back(block_name, block_attributes,
5820 faces);
5821 }
5822 }
5823 CHKERR getBc(bcSpatialTractionVecPtr, "SPATIAL_TRACTION_BC", 6);
5824
5825 bcSpatialPressureVecPtr = boost::make_shared<PressureBcVec>();
5826 CHKERR getBc(bcSpatialPressureVecPtr, "PRESSURE", 1);
5827
5829 boost::make_shared<AnalyticalTractionBcVec>();
5830 CHKERR getBc(bcSpatialAnalyticalTractionVecPtr, "ANALYTICAL_TRACTION", 3);
5831
5832 auto ts_traction =
5833 boost::make_shared<DynamicRelaxationTimeScale>("traction_history.txt");
5834 for (auto &bc : *bcSpatialTractionVecPtr) {
5835 if (!bc.loadHistoryFile.empty()) {
5836 MOFEM_LOG("EP", Sev::inform)
5837 << "Traction load history from JSON for " << bc.blockName << ": "
5838 << bc.loadHistoryFile;
5839 timeScaleMap[bc.blockName] =
5840 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5841 } else {
5842 timeScaleMap[bc.blockName] =
5844 ts_traction, "traction_history", ".txt", bc.blockName);
5845 }
5846 }
5847
5848 auto ts_pressure =
5849 boost::make_shared<DynamicRelaxationTimeScale>("pressure_history.txt");
5850 for (auto &bc : *bcSpatialPressureVecPtr) {
5851 if (!bc.loadHistoryFile.empty()) {
5852 MOFEM_LOG("EP", Sev::inform)
5853 << "Pressure load history from JSON for " << bc.blockName << ": "
5854 << bc.loadHistoryFile;
5855 timeScaleMap[bc.blockName] =
5856 boost::make_shared<DynamicRelaxationTimeScale>(bc.loadHistoryFile);
5857 } else {
5858 timeScaleMap[bc.blockName] =
5860 ts_pressure, "pressure_history", ".txt", bc.blockName);
5861 }
5862 }
5863
5865}
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 429 of file EshelbianCore.hpp.

429 {
431 boost::shared_ptr<TractionFreeBc>(new TractionFreeBc());
432 return getTractionFreeBc(meshset, bcSpatialFreeTractionVecPtr, "CONTACT");
433 }
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.

◆ getStringArgumentFromJsonBlockset()

std::string EshelbianCore::getStringArgumentFromJsonBlockset ( const std::string &  type_name,
const int  meshset_id,
const std::string &  param_name 
)
inline
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 311 of file EshelbianCore.hpp.

313 {
314 const auto string_params =
315 mField.getInterface<JsonConfigManager>()->getStringParamsFromBlockset(
316 type_name, meshset_id);
317 if (const auto it = string_params.find(param_name);
318 it != string_params.end()) {
319 return it->second;
320 }
321 return "";
322 }

◆ getStringArgumentFromJsonBlocksets()

MoFEMErrorCode EshelbianCore::getStringArgumentFromJsonBlocksets ( const std::string &  type_name,
const std::string &  param_name,
std::string &  param_value 
)
inline
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 325 of file EshelbianCore.hpp.

327 {
329 param_value.clear();
330 for (auto it : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
331 std::regex((boost::format("%s(.*)") % type_name).str()))) {
332 const auto block_param = getStringArgumentFromJsonBlockset(
333 type_name, it->getMeshsetId(), param_name);
334 if (block_param.empty()) {
335 continue;
336 }
337 if (!param_value.empty() && param_value != block_param) {
338 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
339 "JSON %s blocksets specify different '%s' values",
340 type_name.c_str(), param_name.c_str());
341 }
342 param_value = block_param;
343 }
345 }

◆ 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 5596 of file EshelbianPlasticity.cpp.

5596 {
5598
5599 auto post_proc_norm_fe =
5600 boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
5601
5602 auto bubble_cache =
5603 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
5604 post_proc_norm_fe->getUserPolynomialBase() =
5605 boost::shared_ptr<BaseFunction>(new CGGUserPolynomialBase(bubble_cache));
5606 post_proc_norm_fe->getRuleHook = [](int, int, int) { return -1; };
5607 post_proc_norm_fe->setRuleHook = SetIntegrationAtFrontVolume(
5608 frontVertices, frontAdjEdges, vol_rule, bubble_cache);
5609 CHKERR EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5610 post_proc_norm_fe->getOpPtrVector(), {L2, H1, HDIV}, materialH1Positions,
5612
5613 enum NORMS { U_NORM_L2 = 0, U_NORM_H1, PIOLA_NORM, U_ERROR_L2, LAST_NORM };
5614 auto norms_vec =
5615 createVectorMPI(mField.get_comm(), LAST_NORM, PETSC_DETERMINE);
5616 CHKERR VecZeroEntries(norms_vec);
5617
5618 auto u_l2_ptr = boost::make_shared<MatrixDouble>();
5619 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5620 post_proc_norm_fe->getOpPtrVector().push_back(
5622 post_proc_norm_fe->getOpPtrVector().push_back(
5624 post_proc_norm_fe->getOpPtrVector().push_back(
5625 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_NORM_L2));
5626 post_proc_norm_fe->getOpPtrVector().push_back(
5627 new OpCalcNormL2Tensor1<SPACE_DIM>(u_h1_ptr, norms_vec, U_NORM_H1));
5628 post_proc_norm_fe->getOpPtrVector().push_back(
5629 new OpCalcNormL2Tensor1<SPACE_DIM>(u_l2_ptr, norms_vec, U_ERROR_L2,
5630 u_h1_ptr));
5631
5632 auto piola_ptr = boost::make_shared<MatrixDouble>();
5633 post_proc_norm_fe->getOpPtrVector().push_back(
5635 post_proc_norm_fe->getOpPtrVector().push_back(
5637 MBMAXTYPE));
5638
5639 post_proc_norm_fe->getOpPtrVector().push_back(
5640 new OpCalcNormL2Tensor2<3, 3>(piola_ptr, norms_vec, PIOLA_NORM));
5641
5642 TetPolynomialBase::switchCacheBaseOn<HDIV>({post_proc_norm_fe.get()});
5644 *post_proc_norm_fe);
5645 TetPolynomialBase::switchCacheBaseOff<HDIV>({post_proc_norm_fe.get()});
5646
5647 CHKERR VecAssemblyBegin(norms_vec);
5648 CHKERR VecAssemblyEnd(norms_vec);
5649 const double *norms;
5650 CHKERR VecGetArrayRead(norms_vec, &norms);
5651 MOFEM_LOG("EP", Sev::inform) << "norm_u: " << std::sqrt(norms[U_NORM_L2]);
5652 MOFEM_LOG("EP", Sev::inform) << "norm_u_h1: " << std::sqrt(norms[U_NORM_H1]);
5653 MOFEM_LOG("EP", Sev::inform)
5654 << "norm_error_u_l2: " << std::sqrt(norms[U_ERROR_L2]);
5655 MOFEM_LOG("EP", Sev::inform)
5656 << "norm_piola: " << std::sqrt(norms[PIOLA_NORM]);
5657 CHKERR VecRestoreArrayRead(norms_vec, &norms);
5658
5660}
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 3060 of file EshelbianPlasticity.cpp.

3062 {
3064
3065 // get skin from all tets
3066 Range tets;
3067 CHKERR mField.get_moab().get_entities_by_type(meshset, MBTET, tets);
3068 Range tets_skin_part;
3069 Skinner skin(&mField.get_moab());
3070 CHKERR skin.find_skin(0, tets, false, tets_skin_part);
3071 ParallelComm *pcomm =
3072 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
3073 Range tets_skin;
3074 CHKERR pcomm->filter_pstatus(tets_skin_part,
3075 PSTATUS_SHARED | PSTATUS_MULTISHARED,
3076 PSTATUS_NOT, -1, &tets_skin);
3077
3078 bc_ptr->resize(3);
3079 for (int dd = 0; dd != 3; ++dd)
3080 (*bc_ptr)[dd] = tets_skin;
3081
3082 // Do not remove dofs on which traction is applied
3084 for (auto &v : *bcSpatialDispVecPtr) {
3085 if (v.flags[0])
3086 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3087 if (v.flags[1])
3088 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3089 if (v.flags[2])
3090 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3091 }
3092
3093 // Do not remove dofs on which rotation is applied
3095 for (auto &v : *bcSpatialRotationVecPtr) {
3096 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3097 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3098 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3099 }
3100
3102 for (auto &v : *bcSpatialNormalDisplacementVecPtr) {
3103 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3104 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3105 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3106 }
3107
3110 if (v.flags[0])
3111 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3112 if (v.flags[1])
3113 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3114 if (v.flags[2])
3115 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3116 }
3117
3119 for (auto &v : *bcSpatialTractionVecPtr) {
3120 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3121 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3122 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3123 }
3124
3126 for (auto &v : *bcSpatialSpringVecPtr) {
3127 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3128 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3129 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3130 }
3131
3133 for (auto &v : *bcSpatialAnalyticalTractionVecPtr) {
3134 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3135 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3136 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3137 }
3138
3140 for (auto &v : *bcSpatialPressureVecPtr) {
3141 (*bc_ptr)[0] = subtract((*bc_ptr)[0], v.faces);
3142 (*bc_ptr)[1] = subtract((*bc_ptr)[1], v.faces);
3143 (*bc_ptr)[2] = subtract((*bc_ptr)[2], v.faces);
3144 }
3145
3146 // remove contact
3147 for (auto m : mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
3148 std::regex((boost::format("%s(.*)") % contact_set_name).str()))) {
3149 Range faces;
3150 CHKERR m->getMeshsetIdEntitiesByDimension(mField.get_moab(), 2, faces,
3151 true);
3152 (*bc_ptr)[0] = subtract((*bc_ptr)[0], faces);
3153 (*bc_ptr)[1] = subtract((*bc_ptr)[1], faces);
3154 (*bc_ptr)[2] = subtract((*bc_ptr)[2], faces);
3155 }
3156
3158}
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  )
inlinestatic

◆ inv_d_f_log_e()

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

◆ inv_d_f_log_e_quadratic()

static double EshelbianCore::inv_d_f_log_e_quadratic ( const double  stretch)
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 const double transition_stretch = std::exp(v_max);
178 if (stretch <= transition_stretch) {
179 return 1. / stretch;
180 }
181 const double root = std::sqrt(2. * stretch / transition_stretch - 1.);
182 return 1. / (transition_stretch * root);
183 }

◆ inv_dd_f_linear()

static double EshelbianCore::inv_dd_f_linear ( const double  )
inlinestatic

◆ inv_dd_f_log_e()

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

◆ inv_dd_f_log_e_quadratic()

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

Definition at line 185 of file EshelbianCore.hpp.

185 {
186 const double transition_stretch = std::exp(v_max);
187 if (stretch <= transition_stretch) {
188 return -1. / (stretch * stretch);
189 }
190 const double root = std::sqrt(2. * stretch / transition_stretch - 1.);
191 return -1. / (transition_stretch * transition_stretch * root * root * root);
192 }

◆ inv_f_linear()

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

◆ inv_f_log_e()

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

◆ inv_f_log_e_quadratic()

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

Definition at line 168 of file EshelbianCore.hpp.

168 {
169 const double transition_stretch = std::exp(v_max);
170 if (stretch <= transition_stretch) {
171 return std::log(stretch);
172 }
173 return v_max - 1. + std::sqrt(2. * stretch / transition_stretch - 1.);
174 }

◆ 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 4836 of file EshelbianPlasticity.cpp.

4837 {
4839 ParallelComm *pcomm =
4840 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
4841 // write file with only crack surfaces and full mesh
4842 if (crackingOn && !pcomm->rank()) {
4843 auto meshsets_mng = mField.getInterface<MeshsetsManager>();
4844
4845 std::vector<boost::shared_ptr<TempMeshset>> meshsets_tmp_list;
4846 auto &list = meshsets_mng->getMeshsetsMultindex();
4847 std::vector<Tag> tags_list;
4848
4849 auto meshset_ptr = get_temp_meshset_ptr(mField.get_moab());
4850
4851 for (auto &m : list) {
4852 meshsets_tmp_list.push_back(get_temp_meshset_ptr(mField.get_moab()));
4853 EntityHandle new_meshset = *meshsets_tmp_list.back();
4854 auto meshset = m.getMeshset();
4855 std::vector<Tag> tmp_tags_list;
4856 CHKERR mField.get_moab().tag_get_tags_on_entity(meshset, tmp_tags_list);
4857 Range ents;
4858 CHKERR mField.get_moab().get_entities_by_handle(meshset, ents, true);
4859 CHKERR mField.get_moab().add_entities(new_meshset, ents);
4860 for (auto t : tmp_tags_list) {
4861 void *tag_vals[1];
4862 int tag_size[1];
4863 CHKERR mField.get_moab().tag_get_by_ptr(
4864 t, &meshset, 1, (const void **)tag_vals, tag_size);
4865 CHKERR mField.get_moab().tag_set_by_ptr(t, &new_meshset, 1, tag_vals,
4866 tag_size);
4867 }
4868 std::vector<std::string> remove_tags;
4869 remove_tags.push_back("AKDTree_coord_norm");
4870 remove_tags.push_back("__PARALLEL_");
4871 remove_tags.push_back("_RefBitLevel");
4872
4873 for (auto t : tmp_tags_list) {
4874 std::string tag_name;
4875 CHKERR mField.get_moab().tag_get_name(t, tag_name);
4876 bool add = true;
4877
4878 for (auto &p : remove_tags) {
4879 if (tag_name.compare(0, p.size(), p) == 0) {
4880 add = false;
4881 break;
4882 }
4883 }
4884
4885 if (add)
4886 tags_list.push_back(t);
4887 }
4888 }
4889
4890 for (auto &m_ptr : meshsets_tmp_list) {
4891 EntityHandle m = *m_ptr;
4892 CHKERR mField.get_moab().add_entities(*meshset_ptr, &m, 1);
4893 }
4894
4895 // meshsets_tmp_list has all meshsets to write
4896 std::sort(tags_list.begin(), tags_list.end());
4897 auto new_end = std::unique(tags_list.begin(), tags_list.end());
4898 tags_list.resize(std::distance(tags_list.begin(), new_end));
4899
4900 EntityHandle save_meshset = *meshset_ptr;
4901 CHKERR mField.get_moab().write_file(file.c_str(), "MOAB", "", &save_meshset,
4902 1, &tags_list[0], tags_list.size());
4903 }
4905}
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 4908 of file EshelbianPlasticity.cpp.

4910 {
4912
4913 SmartPetscObj<Vec> f_r, v_v;
4914 if (f_residual != PETSC_NULLPTR || var_vector != PETSC_NULLPTR) {
4916 SmartPetscObj<Vec> xout;
4917 xout = createDMVector(dM);
4918 auto xin = f_residual != PETSC_NULLPTR ? f_residual : var_vector;
4919 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4920 xin, "ELASTIC_PROBLEM", RowColData::ROW, xout, "ESHELBY_PLASTICITY",
4921 RowColData::ROW, scatter);
4922 if (f_residual) {
4923 f_r = vectorDuplicate(xout);
4924 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
4925 SCATTER_FORWARD);
4926 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
4927 SCATTER_FORWARD);
4928 CHKERR VecGhostUpdateBegin(f_r, INSERT_VALUES, SCATTER_FORWARD);
4929 CHKERR VecGhostUpdateEnd(f_r, INSERT_VALUES, SCATTER_FORWARD);
4930 }
4931 if (var_vector) {
4932 v_v = createDMVector(dM);
4933 CHKERR VecScatterBegin(scatter, var_vector, v_v, INSERT_VALUES,
4934 SCATTER_FORWARD);
4935 CHKERR VecScatterEnd(scatter, var_vector, v_v, INSERT_VALUES,
4936 SCATTER_FORWARD);
4937 CHKERR VecGhostUpdateBegin(v_v, INSERT_VALUES, SCATTER_FORWARD);
4938 CHKERR VecGhostUpdateEnd(v_v, INSERT_VALUES, SCATTER_FORWARD);
4939 }
4940 }
4941
4943 if (gradient) {
4945 g = createDMVector(dM);
4946 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
4947 gradient, "MATERIAL_PROBLEM", RowColData::ROW, g, "ESHELBY_PLASTICITY",
4948 RowColData::ROW, scatter);
4949 CHKERR VecScatterBegin(scatter, gradient, g, INSERT_VALUES,
4950 SCATTER_FORWARD);
4951 CHKERR VecScatterEnd(scatter, gradient, g, INSERT_VALUES, SCATTER_FORWARD);
4952 CHKERR VecGhostUpdateBegin(g, INSERT_VALUES, SCATTER_FORWARD);
4953 CHKERR VecGhostUpdateEnd(g, INSERT_VALUES, SCATTER_FORWARD);
4954 }
4955
4956 // mark crack surface
4957 if (crackingOn) {
4958 auto get_tag = [&](auto name, auto dim) {
4959 auto &mob = mField.get_moab();
4960 Tag tag;
4961 double def_val[] = {0., 0., 0.};
4962 CHK_MOAB_THROW(mob.tag_get_handle(name, dim, MB_TYPE_DOUBLE, tag,
4963 MB_TAG_CREAT | MB_TAG_SPARSE, def_val),
4964 "create tag");
4965 return tag;
4966 };
4967 tags_to_transfer.push_back(get_tag("MaterialForce", 3));
4968 }
4969
4970 {
4971 auto get_crack_tag = [&]() {
4972 Tag th;
4973 rval = mField.get_moab().tag_get_handle("CRACK", th);
4974 if (rval == MB_SUCCESS) {
4975 MOAB_THROW(mField.get_moab().tag_delete(th));
4976 }
4977 int def_val[] = {0};
4978 MOAB_THROW(mField.get_moab().tag_get_handle(
4979 "CRACK", 1, MB_TYPE_INTEGER, th, MB_TAG_SPARSE | MB_TAG_CREAT,
4980 def_val));
4981 return th;
4982 };
4983
4984 Tag th = get_crack_tag();
4985 tags_to_transfer.push_back(th);
4986 int mark[] = {1};
4987 Range mark_faces;
4988 if (crackFaces)
4989 mark_faces.merge(*crackFaces);
4990 if (interfaceFaces)
4991 mark_faces.merge(*interfaceFaces);
4992 CHKERR mField.get_moab().tag_clear_data(th, mark_faces, mark);
4993 }
4994
4995 // add tags to transfer
4996 for (auto t : listTagsToTransfer) {
4997 std::string name;
4998 CHKERR mField.get_moab().tag_get_name(t, name);
4999 MOFEM_LOG("EP", Sev::verbose)
5000 << "Adding tag " << name << " to transfer list for post-processing";
5001 tags_to_transfer.push_back(t);
5002 }
5003
5004 if (!dataAtPts) {
5005 dataAtPts =
5006 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
5007 }
5008
5010
5011 auto get_post_proc = [&](auto &post_proc_mesh, auto sense) {
5013 auto post_proc_ptr =
5014 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
5015 mField, post_proc_mesh);
5016 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
5017 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
5019
5020 if (ts != PETSC_NULLPTR) {
5021 post_proc_ptr->data_ctx |= PetscData::CTX_SET_TIME;
5022 CHKERR TSGetTime(ts, &(post_proc_ptr->ts_t));
5023 CHKERR TSGetTimeStep(ts, &(post_proc_ptr->ts_dt));
5024 }
5025
5026 auto domain_ops = [&](auto &fe, int sense) {
5028 MaterialPostProcData material_output;
5029
5030 auto bubble_cache = boost::make_shared<CGGUserPolynomialBase::CachePhi>(
5031 0, 0, MatrixDouble());
5032 fe.getUserPolynomialBase() = boost::shared_ptr<BaseFunction>(
5033 new CGGUserPolynomialBase(bubble_cache));
5034 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5035 fe.getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions,
5037 auto piola_scale_ptr = boost::make_shared<double>(1.0);
5038 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5039 piolaStress, dataAtPts->getApproxPAtPts(), piola_scale_ptr));
5040 const bool add_bubble = mField.check_field(bubbleField);
5041 if (add_bubble) {
5042 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5043 bubbleField, dataAtPts->getApproxPAtPts(), piola_scale_ptr,
5044 SmartPetscObj<Vec>(), MBMAXTYPE));
5045 }
5046 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5047 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
5048 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
5049 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5050 piolaStress, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep));
5051 if (add_bubble) {
5052 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5053 bubbleField, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep,
5054 MBMAXTYPE));
5055 }
5056 CHKERR physicalEquations->pushMaterialFields(
5057 *this, fe.getOpPtrVector(), dataAtPts, PhysicalEquations::PREVIOUS);
5058 CHKERR physicalEquations->pushMaterialFields(
5059 *this, fe.getOpPtrVector(), dataAtPts, PhysicalEquations::CURRENT);
5060 if (var_vector) {
5061 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5062 piolaStress, dataAtPts->getVarPiolaPts(),
5063 boost::make_shared<double>(1), v_v));
5064 if (add_bubble)
5065 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5066 bubbleField, dataAtPts->getVarPiolaPts(),
5067 boost::make_shared<double>(1), v_v, MBMAXTYPE));
5068 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5069 rotAxis, dataAtPts->getVarRotAxisPts(), v_v, MBTET));
5070 CHKERR physicalEquations->pushMaterialVariation(
5071 *this, fe.getOpPtrVector(), dataAtPts, v_v, &material_output);
5072 }
5073 if (gradient) {
5074 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5075 materialH1Positions, dataAtPts->getGradientAtPts(), g));
5076 }
5077
5078 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5079 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
5080
5081 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5082 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
5083 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5084 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
5085 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
5086 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
5087 // evaluate derived quantities
5089 fe.getOpPtrVector(), plasticHField, dataAtPts->getPlasticH(),
5090 MBTET);
5091 auto plastic_flow_ptr = boost::shared_ptr<MatrixDouble>();
5092 auto plastic_kappa_ptr = boost::shared_ptr<VectorDouble>();
5093 if (plasticVolume) {
5094 plastic_flow_ptr = boost::make_shared<MatrixDouble>();
5096 fe.getOpPtrVector(), plasticFlowField, plastic_flow_ptr, MBTET);
5097 plastic_kappa_ptr = boost::make_shared<VectorDouble>();
5098 fe.getOpPtrVector().push_back(new OpCalculateScalarFieldValues(
5099 plasticKappaField, plastic_kappa_ptr, MBTET));
5100 }
5101 fe.getOpPtrVector().push_back(
5103
5104 CHKERR physicalEquations->pushPostProc(*this, fe.getOpPtrVector(),
5105 dataAtPts, material_output);
5106
5107 // // post-proc
5110 VolumeElementForcesAndSourcesCoreOnSide::UserDataOperator>;
5111
5112 OpPPMap::DataMapVec scalar_fields;
5113 if (plasticVolume)
5114 scalar_fields["PlasticKappa"] = plastic_kappa_ptr;
5115
5116 struct OpSidePPMap : public OpPPMap {
5117 OpSidePPMap(moab::Interface &post_proc_mesh,
5118 std::vector<EntityHandle> &map_gauss_pts,
5119 DataMapVec data_map_scalar, DataMapMat data_map_vec,
5120 DataMapMat data_map_mat, DataMapMat data_symm_map_mat,
5121 int sense)
5122 : OpPPMap(post_proc_mesh, map_gauss_pts, data_map_scalar,
5123 data_map_vec, data_map_mat, data_symm_map_mat),
5124 tagSense(sense) {}
5125
5126 MoFEMErrorCode doWork(int side, EntityType type,
5129
5130 if (tagSense != 0) {
5131 if (tagSense != OpPPMap::getSkeletonSense())
5133 }
5134
5135 CHKERR OpPPMap::doWork(side, type, data);
5137 }
5138
5139 private:
5140 int tagSense;
5141 };
5142
5143 OpPPMap::DataMapMat vec_fields;
5144 vec_fields["SpatialDisplacementL2"] = dataAtPts->getSmallWL2AtPts();
5145 vec_fields["SpatialDisplacementH1"] = dataAtPts->getSmallWH1AtPts();
5146 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5147 vec_fields["AngularMomentum"] = dataAtPts->getLeviKirchhoffAtPts();
5148 vec_fields["X"] = dataAtPts->getLargeXH1AtPts();
5149 if (var_vector) {
5150 vec_fields["VarOmega"] = dataAtPts->getVarRotAxisPts();
5151 vec_fields["VarSpatialDisplacementL2"] =
5152 boost::make_shared<MatrixDouble>();
5153 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5154 spatialL2Disp, vec_fields["VarSpatialDisplacementL2"], v_v, MBTET));
5155 }
5156 if (f_residual) {
5157 vec_fields["ResSpatialDisplacementL2"] =
5158 boost::make_shared<MatrixDouble>();
5159 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5160 spatialL2Disp, vec_fields["ResSpatialDisplacementL2"], f_r, MBTET));
5161 vec_fields["ResOmega"] = boost::make_shared<MatrixDouble>();
5162 fe.getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
5163 rotAxis, vec_fields["ResOmega"], f_r, MBTET));
5164 }
5165 if (gradient) {
5166 vec_fields["Gradient"] = dataAtPts->getGradientAtPts();
5167 }
5168
5169 OpPPMap::DataMapMat mat_fields;
5170 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5171 if (var_vector) {
5172 mat_fields["VarPiolaStress"] = dataAtPts->getVarPiolaPts();
5173 }
5174 if (f_residual) {
5175 mat_fields["ResPiolaStress"] = boost::make_shared<MatrixDouble>();
5176 fe.getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
5177 piolaStress, mat_fields["ResPiolaStress"],
5178 boost::make_shared<double>(1), f_r));
5179 if (add_bubble)
5180 fe.getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
5181 bubbleField, mat_fields["ResPiolaStress"],
5182 boost::make_shared<double>(1), f_r, MBMAXTYPE));
5183 }
5184 if (!internalStressTagName.empty()) {
5185 mat_fields[internalStressTagName] = dataAtPts->getInternalStressAtPts();
5186 switch (meshTransferInterpOrder) {
5187 case 0:
5188 fe.getOpPtrVector().push_back(
5190 break;
5191 case 1:
5192 fe.getOpPtrVector().push_back(
5194 break;
5195 default:
5196 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
5197 "Unsupported mesh transfer interpolation order %d, for "
5198 "internal stress",
5200 }
5201 }
5202
5203 OpPPMap::DataMapMat mat_fields_symm;
5204 if (f_residual) {
5205 CHKERR physicalEquations->pushPostProcResidual(
5206 *this, fe.getOpPtrVector(), dataAtPts, f_r, material_output);
5207 }
5208 if (plasticVolume)
5209 mat_fields_symm["PlasticHp"] = dataAtPts->getPlasticH();
5210 if (plasticVolume)
5211 mat_fields_symm["PlasticFlow"] = plastic_flow_ptr;
5212 scalar_fields.insert(material_output.scalarFields.begin(),
5213 material_output.scalarFields.end());
5214 vec_fields.insert(material_output.vectorFields.begin(),
5215 material_output.vectorFields.end());
5216 mat_fields_symm.insert(material_output.symmetricFields.begin(),
5217 material_output.symmetricFields.end());
5218
5219 fe.getOpPtrVector().push_back(
5220
5221 new OpSidePPMap(
5222
5223 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5224
5225 scalar_fields,
5226
5227 vec_fields,
5228
5229 mat_fields,
5230
5231 mat_fields_symm,
5232
5233 sense
5234
5235 )
5236
5237 );
5238
5239 fe.getOpPtrVector().push_back(new OpPostProcDataStructure(
5240 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5241 dataAtPts, sense));
5242
5244 };
5245
5246 auto X_h1_ptr = boost::make_shared<MatrixDouble>();
5247 // H1 material positions
5248 post_proc_ptr->getOpPtrVector().push_back(
5250 dataAtPts->getLargeXH1AtPts()));
5251
5252 // domain
5255 CHK_THROW_MESSAGE(domain_ops(*(op_loop_side->getSideFEPtr()), sense),
5256 "Cannot construct material postprocessing pipeline");
5257 post_proc_ptr->getOpPtrVector().push_back(op_loop_side);
5258
5259 return post_proc_ptr;
5260 };
5261
5262 // contact
5263 auto calcs_side_traction_and_displacements = [&](auto &post_proc_ptr,
5264 auto &pip) {
5266 // evaluate traction
5267 using EleOnSide =
5269 using SideEleOp = EleOnSide::UserDataOperator;
5270 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
5271 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5272 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
5273 boost::shared_ptr<BaseFunction>(
5274 new CGGUserPolynomialBase(nullptr, true));
5275 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
5276 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
5278 auto traction_ptr = boost::make_shared<MatrixDouble>();
5279 op_loop_domain_side->getOpPtrVector().push_back(
5281 piolaStress, traction_ptr, boost::make_shared<double>(1.0)));
5282
5283 pip.push_back(new OpCalculateVectorFieldValues<3>(
5284 contactDisp, dataAtPts->getContactL2AtPts()));
5285 pip.push_back(op_loop_domain_side);
5286 // evaluate contact displacement and contact conditions
5287 auto u_h1_ptr = boost::make_shared<MatrixDouble>();
5288 pip.push_back(new OpCalculateVectorFieldValues<3>(spatialH1Disp, u_h1_ptr));
5289 pip.push_back(getOpContactDetection(
5290 *this, contactTreeRhs, u_h1_ptr, traction_ptr,
5291 get_range_from_block(mField, "CONTACT", SPACE_DIM - 1),
5292 &post_proc_ptr->getPostProcMesh(), &post_proc_ptr->getMapGaussPts()));
5293
5295 using BoundaryEle =
5297 auto op_this = new OpLoopThis<BoundaryEle>(mField, contactElement);
5298 pip.push_back(op_this);
5299
5300 OpPPMap::DataMapMat vec_fields;
5301 vec_fields["ContactDisplacement"] = dataAtPts->getContactL2AtPts();
5302
5303 op_this->getOpPtrVector().push_back(
5304
5305 new OpPPMap(
5306
5307 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5308
5309 {},
5310
5311 vec_fields,
5312
5313 {},
5314
5315 {}
5316
5317 )
5318
5319 );
5320
5321 if (f_residual) {
5322
5323 auto contact_residual = boost::make_shared<MatrixDouble>();
5324 op_this->getOpPtrVector().push_back(
5326 contactDisp, contact_residual, f_r, MBTET));
5327 op_this->getOpPtrVector().push_back(
5328
5329 new OpPPMap(
5330
5331 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5332
5333 {},
5334
5335 {{"res_contact", contact_residual}},
5336
5337 {},
5338
5339 {}
5340
5341 )
5342
5343 );
5344 }
5345
5347 };
5348
5349 auto post_proc_mesh = boost::make_shared<moab::Core>();
5350 auto post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5351 auto post_proc_negative_sense_ptr =
5352 get_post_proc(post_proc_mesh, /*negative sense*/ -1);
5353 auto skin_post_proc_ptr = get_post_proc(post_proc_mesh, /*positive sense*/ 1);
5354 CHKERR calcs_side_traction_and_displacements(
5355 skin_post_proc_ptr, skin_post_proc_ptr->getOpPtrVector());
5356
5357 auto own_tets =
5359 .subset_by_dimension(SPACE_DIM);
5360 Range own_faces;
5361 CHKERR mField.get_moab().get_adjacencies(own_tets, SPACE_DIM - 1, true,
5362 own_faces, moab::Interface::UNION);
5363
5364 auto get_crack_faces = [&](auto crack_faces) {
5365 auto get_adj = [&](auto e, auto dim) {
5366 Range adj;
5367 CHKERR mField.get_moab().get_adjacencies(e, dim, true, adj,
5368 moab::Interface::UNION);
5369 return adj;
5370 };
5371 // this removes faces
5372 auto tets = get_adj(crack_faces, 3);
5373 // faces adjacent to tets not in crack_faces
5374 auto faces = subtract(get_adj(tets, 2), crack_faces);
5375 // what is left from below, are tets fully inside crack_faces
5376 tets = subtract(tets, get_adj(faces, 3));
5377 return subtract(crack_faces, get_adj(tets, 2));
5378 };
5379
5380 auto side_one_faces = [&](auto &faces) {
5381 std::pair<Range, Range> sides;
5382 for (auto f : faces) {
5383 Range adj;
5384 MOAB_THROW(mField.get_moab().get_adjacencies(&f, 1, 3, false, adj));
5385 adj = intersect(own_tets, adj);
5386 for (auto t : adj) {
5387 int side, sense, offset;
5388 MOAB_THROW(mField.get_moab().side_number(t, f, side, sense, offset));
5389 if (sense == 1) {
5390 sides.first.insert(f);
5391 } else {
5392 sides.second.insert(f);
5393 }
5394 }
5395 }
5396 return sides;
5397 };
5398
5399 auto crack_faces = unite(get_crack_faces(*crackFaces), *interfaceFaces);
5400 // VOLUME_INTERFACE faces were already merged into interfaceFaces in
5401 // resolveDissipationEntities(), after applying REMOVE_INTERFACE exclusions.
5402 auto crack_side_faces = side_one_faces(crack_faces);
5403 auto side_one_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5404 auto ent = fe_method_ptr->getFEEntityHandle();
5405 if (crack_side_faces.first.find(ent) == crack_side_faces.first.end()) {
5406 return false;
5407 }
5408 return true;
5409 };
5410 auto side_minus_crack_faces = [crack_side_faces](FEMethod *fe_method_ptr) {
5411 auto ent = fe_method_ptr->getFEEntityHandle();
5412 if (crack_side_faces.second.find(ent) == crack_side_faces.second.end()) {
5413 return false;
5414 }
5415 return true;
5416 };
5417
5418 skin_post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5419 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5420 post_proc_negative_sense_ptr->setTagsToTransfer(tags_to_transfer);
5421
5422 auto post_proc_begin =
5424 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5425 CHKERR DMoFEMLoopFiniteElements(dM, skinElement, skin_post_proc_ptr);
5426 post_proc_ptr->exeTestHook = side_one_crack_faces;
5428 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5429 post_proc_negative_sense_ptr->exeTestHook = side_minus_crack_faces;
5431 post_proc_negative_sense_ptr, 0,
5433
5434 constexpr bool debug = false;
5435 if (debug) {
5436
5437 auto get_adj_front = [&]() {
5438 auto skeleton_faces = *skeletonFaces;
5439 Range adj_front;
5440 CHKERR mField.get_moab().get_adjacencies(*frontEdges, 2, true, adj_front,
5441 moab::Interface::UNION);
5442
5443 adj_front = intersect(adj_front, skeleton_faces);
5444 adj_front = subtract(adj_front, *crackFaces);
5445 adj_front = intersect(own_faces, adj_front);
5446 return adj_front;
5447 };
5448
5449 auto adj_front = filter_owners(mField, get_adj_front());
5450 auto only_front_faces = [adj_front](FEMethod *fe_method_ptr) {
5451 auto ent = fe_method_ptr->getFEEntityHandle();
5452 if (adj_front.find(ent) == adj_front.end()) {
5453 return false;
5454 }
5455 return true;
5456 };
5457
5458 post_proc_ptr->exeTestHook = only_front_faces;
5460 dM, skeletonElement, post_proc_ptr, 0, mField.get_comm_size());
5461 post_proc_negative_sense_ptr->exeTestHook = only_front_faces;
5463 post_proc_negative_sense_ptr, 0,
5465 }
5466 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5467 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5468
5469 CHKERR post_proc_end.writeFile(file.c_str());
5471}
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.
MoFEMErrorCode addCalculatePlasticLogarithmicStretchFieldValues(boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pipeline, const std::string &field_name, boost::shared_ptr< MatrixDouble > tensor_values, const EntityType zero_type, SmartPetscObj< DM > data_dm, SmartPetscObj< Vec > data_vector)
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.
Specialization for double precision scalar field values calculation.
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, ScalarDataPtr > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
@ CTX_SET_TIME
Time value is set.
Template struct for dimension-specific finite element types.
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 = {},
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 5473 of file EshelbianPlasticity.cpp.

5475 {
5477
5479 if (f_residual != PETSC_NULLPTR) {
5481 f_r = createDMVector(dM);
5482 CHKERR mField.getInterface<VecManager>()->vecScatterCreate(
5483 f_residual, "ELASTIC_PROBLEM", RowColData::ROW, f_r,
5484 "ESHELBY_PLASTICITY", RowColData::ROW, scatter);
5485 CHKERR VecScatterBegin(scatter, f_residual, f_r, INSERT_VALUES,
5486 SCATTER_FORWARD);
5487 CHKERR VecScatterEnd(scatter, f_residual, f_r, INSERT_VALUES,
5488 SCATTER_FORWARD);
5489 CHKERR VecGhostUpdateBegin(f_r, INSERT_VALUES, SCATTER_FORWARD);
5490 CHKERR VecGhostUpdateEnd(f_r, INSERT_VALUES, SCATTER_FORWARD);
5491 }
5492
5494
5495 auto post_proc_mesh = boost::make_shared<moab::Core>();
5496 auto post_proc_ptr =
5497 boost::make_shared<PostProcBrokenMeshInMoabBaseCont<FaceEle>>(
5498 mField, post_proc_mesh);
5499 if (ts != PETSC_NULLPTR) {
5500 post_proc_ptr->data_ctx |= PetscData::CtxSetTime;
5501 CHKERR TSGetTime(ts, &post_proc_ptr->ts_t);
5502 CHKERR TSGetTimeStep(ts, &post_proc_ptr->ts_dt);
5503 }
5504 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM - 1, SPACE_DIM>::add(
5505 post_proc_ptr->getOpPtrVector(), {L2}, materialH1Positions,
5507
5508 auto hybrid_disp = boost::make_shared<MatrixDouble>();
5509 post_proc_ptr->getOpPtrVector().push_back(
5511 post_proc_ptr->getOpPtrVector().push_back(
5513 hybridSpatialDisp, dataAtPts->getGradHybridDispAtPts()));
5514
5515 auto op_loop_domain_side =
5517 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
5518 post_proc_ptr->getOpPtrVector().push_back(op_loop_domain_side);
5519
5520 MaterialPostProcData material_output;
5521 CHKERR physicalEquations->pushSkeletonEvaluation(
5522 *this, *op_loop_domain_side->getSideFEPtr(), dataAtPts, f_r,
5523 material_output);
5524
5526
5527 OpPPMap::DataMapMat vec_fields = material_output.vectorFields;
5528 vec_fields["HybridDisplacement"] = hybrid_disp;
5529 // note that grad and omega have not trace, so this is only other side value
5530 vec_fields["spatialL2Disp"] = dataAtPts->getSmallWL2AtPts();
5531 vec_fields["Omega"] = dataAtPts->getRotAxisAtPts();
5532 OpPPMap::DataMapMat mat_fields;
5533 mat_fields["PiolaStress"] = dataAtPts->getApproxPAtPts();
5534 mat_fields["HybridDisplacementGradient"] =
5535 dataAtPts->getGradHybridDispAtPts();
5536 OpPPMap::DataMapMat mat_fields_symm = material_output.symmetricFields;
5537
5538 post_proc_ptr->getOpPtrVector().push_back(
5539
5540 new OpPPMap(
5541
5542 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5543
5544 material_output.scalarFields,
5545
5546 vec_fields,
5547
5548 mat_fields,
5549
5550 mat_fields_symm
5551
5552 )
5553
5554 );
5555
5556 if (f_residual) {
5557 auto hybrid_res = boost::make_shared<MatrixDouble>();
5558 post_proc_ptr->getOpPtrVector().push_back(
5560 f_r));
5562 post_proc_ptr->getOpPtrVector().push_back(
5563
5564 new OpPPMap(
5565
5566 post_proc_ptr->getPostProcMesh(), post_proc_ptr->getMapGaussPts(),
5567
5568 {},
5569
5570 {{"res_hybrid", hybrid_res}},
5571
5572 {},
5573
5574 {}
5575
5576 )
5577
5578 );
5579 }
5580
5581 post_proc_ptr->setTagsToTransfer(tags_to_transfer);
5582
5583 auto post_proc_begin =
5585 CHKERR DMoFEMPreProcessFiniteElements(dM, post_proc_begin.getFEMethod());
5587 auto post_proc_end = PostProcBrokenMeshInMoabBaseEnd(mField, post_proc_mesh);
5588 CHKERR DMoFEMPostProcessFiniteElements(dM, post_proc_end.getFEMethod());
5589
5590 CHKERR post_proc_end.writeFile(file.c_str());
5591
5593}
static constexpr Switches CtxSetTime
Time value switch.

◆ 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 1863 of file EshelbianPlasticity.cpp.

1864 {
1866
1867 Range meshset_ents;
1868 CHKERR mField.get_moab().get_entities_by_handle(meshset, meshset_ents);
1869
1870 auto project_ho_geometry = [&](auto field) {
1872 return mField.loop_dofs(field, ent_method);
1873 };
1874 CHKERR project_ho_geometry(materialH1Positions);
1875
1876 auto get_adj_front_edges = [&](auto &front_edges) {
1877 Range front_crack_nodes;
1878 Range crack_front_edges_with_both_nodes_not_at_front;
1879
1880 if (mField.get_comm_rank() == 0) {
1881 auto &moab = mField.get_moab();
1883 moab.get_connectivity(front_edges, front_crack_nodes, true),
1884 "get_connectivity failed");
1885 Range crack_front_edges;
1886 CHK_MOAB_THROW(moab.get_adjacencies(front_crack_nodes, SPACE_DIM - 2,
1887 false, crack_front_edges,
1888 moab::Interface::UNION),
1889 "get_adjacencies failed");
1890 Range crack_front_edges_nodes;
1891 CHK_MOAB_THROW(moab.get_connectivity(crack_front_edges,
1892 crack_front_edges_nodes, true),
1893 "get_connectivity failed");
1894 // those nodes are hannging nodes
1895 crack_front_edges_nodes =
1896 subtract(crack_front_edges_nodes, front_crack_nodes);
1897 Range crack_front_edges_with_both_nodes_not_at_front;
1899 moab.get_adjacencies(crack_front_edges_nodes, 1, false,
1900 crack_front_edges_with_both_nodes_not_at_front,
1901 moab::Interface::UNION),
1902 "get_adjacencies failed");
1903 // those edges are have one node not at the crack front
1904 crack_front_edges_with_both_nodes_not_at_front = intersect(
1905 crack_front_edges, crack_front_edges_with_both_nodes_not_at_front);
1906 }
1907
1908 front_crack_nodes = send_type(mField, front_crack_nodes, MBVERTEX);
1909 crack_front_edges_with_both_nodes_not_at_front = send_type(
1910 mField, crack_front_edges_with_both_nodes_not_at_front, MBEDGE);
1911
1912 return std::make_pair(boost::make_shared<Range>(front_crack_nodes),
1913 boost::make_shared<Range>(
1914 crack_front_edges_with_both_nodes_not_at_front));
1915 };
1916
1917 if ((time - crackingAddTime) > std::numeric_limits<double>::epsilon()) {
1918 crackFaces = boost::make_shared<Range>(
1919 get_range_from_block(mField, "CRACK", SPACE_DIM - 1));
1920 } else {
1921 crackFaces = boost::make_shared<Range>();
1922 }
1923 frontEdges =
1924 boost::make_shared<Range>(get_crack_front_edges(mField, *crackFaces));
1925 auto [front_vertices, front_adj_edges] = get_adj_front_edges(*frontEdges);
1926 frontVertices = front_vertices;
1927 frontAdjEdges = front_adj_edges;
1928
1929 MOFEM_LOG("EP", Sev::inform)
1930 << "Number of crack faces: " << crackFaces->size();
1931 MOFEM_LOG("EP", Sev::inform)
1932 << "Number of front edges: " << frontEdges->size();
1933 MOFEM_LOG("EP", Sev::inform)
1934 << "Number of front vertices: " << frontVertices->size();
1935 MOFEM_LOG("EP", Sev::inform)
1936 << "Number of front adjacent edges: " << frontAdjEdges->size();
1937
1938#ifndef NDEBUG
1939 if (crackingOn) {
1940 auto rank = mField.get_comm_rank();
1941 // CHKERR save_range(mField.get_moab(),
1942 // (boost::format("meshset_ents_%d.vtk") % rank).str(),
1943 // meshset_ents);
1945 (boost::format("crack_faces_%d.vtk") % rank).str(),
1946 *crackFaces);
1948 (boost::format("front_edges_%d.vtk") % rank).str(),
1949 *frontEdges);
1950 // CHKERR save_range(mField.get_moab(),
1951 // (boost::format("front_vertices_%d.vtk") % rank).str(),
1952 // *frontVertices);
1953 // CHKERR save_range(mField.get_moab(),
1954 // (boost::format("front_adj_edges_%d.vtk") % rank).str(),
1955 // *frontAdjEdges);
1956 }
1957#endif // NDEBUG
1958
1959 auto set_singular_dofs = [&](auto &front_adj_edges, auto &front_vertices) {
1961 auto &moab = mField.get_moab();
1962
1963 double eps = 1;
1964 double beta = 0;
1965 CHKERR PetscOptionsGetScalar(PETSC_NULLPTR, "-singularity_eps", &beta,
1966 PETSC_NULLPTR);
1967 MOFEM_LOG("EP", Sev::inform) << "Singularity eps " << beta;
1968 eps -= beta;
1969
1970 auto field_blas = mField.getInterface<FieldBlas>();
1971 auto lambda =
1972 [&](boost::shared_ptr<FieldEntity> field_entity_ptr) -> MoFEMErrorCode {
1974 FTENSOR_INDEX(3, i);
1975 FTENSOR_INDEX(3, j);
1976
1977 auto nb_dofs = field_entity_ptr->getEntFieldData().size();
1978 if (nb_dofs == 0) {
1980 }
1981
1982#ifndef NDEBUG
1983 if (field_entity_ptr->getNbOfCoeffs() != 3)
1985 "Expected 3 coefficients per edge");
1986 if (nb_dofs % 3 != 0)
1988 "Expected multiple of 3 coefficients per edge");
1989#endif // NDEBUG
1990
1991 auto get_conn = [&]() {
1992 int num_nodes;
1993 const EntityHandle *conn;
1994 CHKERR moab.get_connectivity(field_entity_ptr->getEnt(), conn,
1995 num_nodes, false);
1996 return std::make_pair(conn, num_nodes);
1997 };
1998
1999 auto get_dir = [&](auto &&conn_p) {
2000 auto [conn, num_nodes] = conn_p;
2001 double coords[6];
2002 CHKERR moab.get_coords(conn, num_nodes, coords);
2003 FTensor::Tensor1<double, 3> t_edge_dir{coords[3] - coords[0],
2004 coords[4] - coords[1],
2005 coords[5] - coords[2]};
2006 return t_edge_dir;
2007 };
2008
2009 auto get_singularity_dof = [&](auto &&conn_p, auto &&t_edge_dir) {
2010 auto [conn, num_nodes] = conn_p;
2011 FTensor::Tensor1<double, 3> t_singularity_dof{0., 0., 0.};
2012 if (front_vertices.find(conn[0]) != front_vertices.end()) {
2013 t_singularity_dof(i) = t_edge_dir(i) * (-eps);
2014 } else if (front_vertices.find(conn[1]) != front_vertices.end()) {
2015 t_singularity_dof(i) = t_edge_dir(i) * eps;
2016 }
2017 return t_singularity_dof;
2018 };
2019
2020 auto t_singularity_dof =
2021 get_singularity_dof(get_conn(), get_dir(get_conn()));
2022
2023 auto field_data = field_entity_ptr->getEntFieldData();
2025 &field_data[0], &field_data[1], &field_data[2]};
2026
2027 t_dof(i) = t_singularity_dof(i);
2028 ++t_dof;
2029 for (auto n = 1; n < field_data.size() / 3; ++n) {
2030 t_dof(i) = 0;
2031 ++t_dof;
2032 }
2033
2035 };
2036
2037 CHKERR field_blas->fieldLambdaOnEntities(lambda, materialH1Positions,
2038 &front_adj_edges);
2039
2041 };
2042
2043 if (setSingularity)
2044 CHKERR set_singular_dofs(*frontAdjEdges, *frontVertices);
2045
2047}
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 2049 of file EshelbianPlasticity.cpp.

2049 {
2051#ifdef INCLUDE_MBCOUPLER
2052
2053 double toler = 5.e-10;
2054 MOFEM_LOG_CHANNEL("WORLD");
2055 MOFEM_LOG_TAG("WORLD", "mesh_data_transfer");
2057 MOFEM_LOG("WORLD", Sev::verbose)
2058 << "No source mesh specified. Skipping projection";
2060 }
2061 MOFEM_LOG("WORLD", Sev::inform)
2062 << "Projecting from source mesh: " << meshTransferSourceMeshFileName;
2063 MOFEM_LOG("WORLD", Sev::verbose)
2064 << "Interpolation Stress tag name: " << internalStressTagName;
2065 MOFEM_LOG("WORLD", Sev::verbose) << "Interpolation Young's modulus tag name: "
2067 MOFEM_LOG("WORLD", Sev::verbose)
2068 << "Interpolation order: " << meshTransferInterpOrder;
2069 MOFEM_LOG("WORLD", Sev::verbose) << "Using hybrid interpolation: "
2070 << (meshTransferHybridInterp ? "yes" : "no");
2071
2072 auto &moab = mField.get_moab();
2073
2074 // check if tag exists
2075 for (const auto &tag_name : listTagsToProject) {
2076 Tag old_interp_tag;
2077 auto rval_check_tag = moab.tag_get_handle(tag_name.c_str(), old_interp_tag);
2078 if (rval_check_tag == MB_SUCCESS) {
2079 MOFEM_LOG("WORLD", Sev::inform)
2080 << "Deleting existing tag on target mesh: " << tag_name;
2081 CHKERR moab.tag_delete(old_interp_tag);
2082 }
2083 }
2084 // make a size-1 communicator for the coupler (rank 0 only)
2085 int world_rank = -1, world_size = -1;
2086 MPI_Comm_rank(PETSC_COMM_WORLD, &world_rank);
2087 MPI_Comm_size(PETSC_COMM_WORLD, &world_size);
2088
2089 Range original_meshset_ents;
2090 CHKERR moab.get_entities_by_handle(0, original_meshset_ents);
2091
2092 MPI_Comm comm_coupler;
2093 if (world_rank == 0) {
2094 MPI_Comm_split(PETSC_COMM_WORLD, 0, 0, &comm_coupler);
2095 } else {
2096 MPI_Comm_split(PETSC_COMM_WORLD, MPI_UNDEFINED, world_rank, &comm_coupler);
2097 }
2098
2099 // build a separate ParallelComm for the coupler (rank 0 only)
2100 ParallelComm *pcomm0 = nullptr;
2101 int pcomm0_id = -1;
2102 if (world_rank == 0) {
2103 pcomm0 = new ParallelComm(&moab, comm_coupler, &pcomm0_id);
2104 }
2105
2106 Coupler::Method method;
2107 switch (meshTransferInterpOrder) {
2108 case 0:
2109 method = Coupler::CONSTANT;
2110 break;
2111 case 1:
2112 method = Coupler::LINEAR_FE;
2113 break;
2114 default:
2115 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2116 "Unsupported interpolation order");
2117 }
2118
2119 int nprocs, rank;
2120 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &nprocs);
2121 CHKERRQ(ierr);
2122 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
2123 CHKERRQ(ierr);
2124
2125 // std::string read_opts, write_opts;
2126 // read_opts = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARTITION_"
2127 // "DISTRIBUTE;PARALLEL_RESOLVE_SHARED_ENTS";
2128 // if (world_size > 1)
2129 // read_opts += ";PARALLEL_GHOSTS=3.0.1";
2130 // write_opts = (world_size > 1) ? "PARALLEL=WRITE_PART" : "";
2131
2132 // create target mesh from existing meshset
2133 EntityHandle target_root;
2134 CHKERR moab.create_meshset(MESHSET_SET, target_root);
2135 MOFEM_LOG("WORLD", Sev::inform)
2136 << "Creating target mesh from existing meshset";
2137 Range target_meshset_ents;
2138 CHKERR moab.get_entities_by_handle(0, target_meshset_ents);
2139 CHKERR moab.add_entities(target_root, target_meshset_ents);
2140
2141 // variables for tags to be broadcast later
2142 std::vector<Tag> interp_tags;
2143 std::vector<int> tag_length;
2144 std::vector<DataType> dtype;
2145 std::vector<TagType> storage;
2146
2147 // load source mesh
2148 Range targ_verts, targ_elems;
2149 if (world_rank == 0) {
2150 EntityHandle source_root;
2151 CHKERR moab.create_meshset(MESHSET_SET, source_root);
2152
2153 MOFEM_LOG("WORLD", Sev::inform) << "Loading source mesh on rank 0";
2154 auto rval_source_mesh = moab.load_file(
2155 meshTransferSourceMeshFileName.c_str(), &source_root, "");
2156 if (rval_source_mesh != MB_SUCCESS) {
2157 MOFEM_LOG("WORLD", Sev::warning) << "Error loading source mesh file: "
2159 }
2160 MOFEM_LOG("WORLD", Sev::inform) << "Source mesh loaded.";
2161
2162 Range src_elems;
2163 CHKERR moab.get_entities_by_dimension(source_root, 3, src_elems);
2164
2165 EntityHandle part_set;
2166 CHKERR pcomm0->create_part(part_set);
2167 CHKERR moab.add_entities(part_set, src_elems);
2168
2169 Range src_elems_part;
2170 CHKERR pcomm0->get_part_entities(src_elems_part, 3);
2171
2172 for (const auto &iterp_tag_name : listTagsToProject) {
2173 std::string tag_to_use = iterp_tag_name;
2174
2175 Tag interp_tag;
2176 CHKERR moab.tag_get_handle(tag_to_use.c_str(), interp_tag);
2177
2178 int interp_tag_len;
2179 CHKERR moab.tag_get_length(interp_tag, interp_tag_len);
2180
2181 if (interp_tag_len != 1 && interp_tag_len != 3 && interp_tag_len != 9) {
2182 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED,
2183 "Unsupported interpolation tag length: %d", interp_tag_len);
2184 }
2185
2186 // store tag info for later broadcast
2187 tag_length.push_back(interp_tag_len);
2188 dtype.push_back(DataType());
2189 storage.push_back(TagType());
2190 interp_tags.push_back(interp_tag);
2191 CHKERR moab.tag_get_data_type(interp_tag, dtype.back());
2192 CHKERR moab.tag_get_type(interp_tag, storage.back());
2193
2194 // coupler is collective
2195 Coupler mbc(&moab, pcomm0, src_elems_part, 0, true);
2196
2197 std::vector<double> vpos; // the positions we are interested in
2198 int num_pts = 0;
2199
2200 Range tmp_verts;
2201
2202 // First get all vertices adj to partition entities in target mesh
2203 CHKERR moab.get_entities_by_dimension(target_root, 3, targ_elems);
2204
2205 if (meshTransferInterpOrder == 0) {
2206 targ_verts = targ_elems;
2207 } else {
2208 CHKERR moab.get_adjacencies(targ_elems, 0, false, targ_verts,
2209 moab::Interface::UNION);
2210 }
2211
2212 // Then get non-owned verts and subtract
2213 CHKERR pcomm0->get_pstatus_entities(0, PSTATUS_NOT_OWNED, tmp_verts);
2214 targ_verts = subtract(targ_verts, tmp_verts);
2215
2216 // get position of these entities; these are the target points
2217 num_pts = (int)targ_verts.size();
2218 vpos.resize(3 * targ_verts.size());
2219 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2220
2221 // Locate those points in the source mesh
2222 boost::shared_ptr<TupleList> tl_ptr;
2223 tl_ptr = boost::make_shared<TupleList>();
2224 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2225 false);
2226
2227 // If some points were not located, we need to process them
2228 auto find_missing_points = [&](Range &targ_verts, int &num_pts,
2229 std::vector<double> &vpos,
2230 Range &missing_verts) {
2232 int missing_pts_num = 0;
2233 int i = 0;
2234 auto vit = targ_verts.begin();
2235 for (; vit != targ_verts.end(); i++) {
2236 if (tl_ptr->vi_rd[3 * i + 1] == -1) {
2237 missing_verts.insert(*vit);
2238 vit = targ_verts.erase(vit);
2239 missing_pts_num++;
2240 } else {
2241 vit++;
2242 }
2243 }
2244
2245 int missing_pts_num_global = 0;
2246 // MPI_Allreduce(&missing_pts_num, &missing_pts_num_global, 1, MPI_INT,
2247 // MPI_SUM, pcomm0);
2248 if (missing_pts_num_global) {
2249 MOFEM_LOG("WORLD", Sev::warning)
2250 << missing_pts_num_global
2251 << " points in target mesh were not located in source mesh. ";
2252 }
2253
2254 if (missing_pts_num) {
2255 num_pts = (int)targ_verts.size();
2256 vpos.resize(3 * targ_verts.size());
2257 CHKERR moab.get_coords(targ_verts, &vpos[0]);
2258 tl_ptr->reset();
2259 CHKERR mbc.locate_points(&vpos[0], num_pts, 0, toler, tl_ptr.get(),
2260 false);
2261 }
2263 };
2264
2265 Range missing_verts;
2266 CHKERR find_missing_points(targ_verts, num_pts, vpos, missing_verts);
2267
2268 std::vector<double> source_data(interp_tag_len * src_elems.size(), 0.0);
2269 std::vector<double> target_data(interp_tag_len * num_pts, 0.0);
2270
2271 CHKERR moab.tag_get_data(interp_tag, src_elems, &source_data[0]);
2272
2273 Tag scalar_tag, adj_count_tag;
2274 double def_scl = 0;
2275 string scalar_tag_name = string(tag_to_use) + "_COMP";
2276 CHKERR moab.tag_get_handle(scalar_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2277 scalar_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2278 &def_scl);
2279
2280 string adj_count_tag_name = "ADJ_COUNT";
2281 double def_adj = 0;
2282 CHKERR moab.tag_get_handle(adj_count_tag_name.c_str(), 1, MB_TYPE_DOUBLE,
2283 adj_count_tag, MB_TAG_CREAT | MB_TAG_DENSE,
2284 &def_adj);
2285
2286 // MBCoupler functionality supports only scalar tags. For the case of
2287 // vector or tensor tags we need to save each component as a scalar tag
2288 auto create_scalar_tags = [&](const Range &src_elems,
2289 const std::vector<double> &source_data,
2290 int itag) {
2292
2293 std::vector<double> source_data_scalar(src_elems.size());
2294 // Populate source_data_scalar
2295 for (int ielem = 0; ielem < src_elems.size(); ielem++) {
2296 source_data_scalar[ielem] =
2297 source_data[itag + ielem * interp_tag_len];
2298 }
2299
2300 // Set data on the scalar tag
2301 CHKERR moab.tag_set_data(scalar_tag, src_elems, &source_data_scalar[0]);
2302
2303 if (meshTransferInterpOrder == 1) {
2304 // Linear interpolation: compute average value of data on vertices
2305 Range src_verts;
2306 CHKERR moab.get_connectivity(src_elems, src_verts, true);
2307
2308 CHKERR moab.tag_clear_data(scalar_tag, src_verts, &def_scl);
2309 CHKERR moab.tag_clear_data(adj_count_tag, src_verts, &def_adj);
2310
2311 for (auto &tet : src_elems) {
2312 double tet_data = 0;
2313 CHKERR moab.tag_get_data(scalar_tag, &tet, 1, &tet_data);
2314
2315 Range adj_verts;
2316 CHKERR moab.get_connectivity(&tet, 1, adj_verts, true);
2317
2318 std::vector<double> adj_vert_data(adj_verts.size(), 0.0);
2319 std::vector<double> adj_vert_count(adj_verts.size(), 0.0);
2320
2321 CHKERR moab.tag_get_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2322 CHKERR moab.tag_get_data(adj_count_tag, adj_verts,
2323 &adj_vert_count[0]);
2324
2325 for (int ivert = 0; ivert < adj_verts.size(); ivert++) {
2326 adj_vert_data[ivert] += tet_data;
2327 adj_vert_count[ivert] += 1;
2328 }
2329
2330 CHKERR moab.tag_set_data(scalar_tag, adj_verts, &adj_vert_data[0]);
2331 CHKERR moab.tag_set_data(adj_count_tag, adj_verts,
2332 &adj_vert_count[0]);
2333 }
2334
2335 // Reduce tags for the parallel case
2336 std::vector<Tag> tags = {scalar_tag, adj_count_tag};
2337 pcomm0->reduce_tags(tags, tags, MPI_SUM, src_verts);
2338
2339 std::vector<double> src_vert_data(src_verts.size(), 0.0);
2340 std::vector<double> src_vert_adj_count(src_verts.size(), 0.0);
2341
2342 CHKERR moab.tag_get_data(scalar_tag, src_verts, &src_vert_data[0]);
2343 CHKERR moab.tag_get_data(adj_count_tag, src_verts,
2344 &src_vert_adj_count[0]);
2345
2346 for (int ivert = 0; ivert < src_verts.size(); ivert++) {
2347 src_vert_data[ivert] /= src_vert_adj_count[ivert];
2348 }
2349 CHKERR moab.tag_set_data(scalar_tag, src_verts, &src_vert_data[0]);
2350 }
2352 };
2353
2354 MOFEM_LOG("WORLD", Sev::inform)
2355 << "Performing interpolation for tag: " << tag_to_use;
2356 MOFEM_LOG("WORLD", Sev::inform)
2357 << "Number of target points to interpolate: " << num_pts;
2358 MOFEM_LOG("WORLD", Sev::inform)
2359 << "Interpolation method: "
2360 << (method == Coupler::CONSTANT ? "constant" : "linear FE");
2361 MOFEM_LOG("WORLD", Sev::inform)
2362 << "Number of components in tag: " << interp_tag_len;
2363
2364 MOFEM_LOG("WORLD", Sev::inform)
2365 << "Source tag data range: ["
2366 << *std::min_element(source_data.begin(), source_data.end()) << ", "
2367 << *std::max_element(source_data.begin(), source_data.end()) << "]";
2368
2369 for (int itag = 0; itag < interp_tag_len; itag++) {
2370
2371 CHKERR create_scalar_tags(src_elems, source_data, itag);
2372
2373 std::vector<double> target_data_scalar(num_pts, 0.0);
2374 CHKERR mbc.interpolate(method, scalar_tag_name, &target_data_scalar[0],
2375 tl_ptr.get());
2376
2377 for (int ielem = 0; ielem < num_pts; ielem++) {
2378 target_data[itag + ielem * interp_tag_len] =
2379 target_data_scalar[ielem];
2380 }
2381 }
2382
2383 // Use original tag
2384 CHKERR moab.tag_set_data(interp_tag, targ_verts, &target_data[0]);
2385
2386 if (missing_verts.size() && (meshTransferInterpOrder == 1) &&
2388 MOFEM_LOG("WORLD", Sev::warning)
2389 << "Using hybrid interpolation for "
2390 "missing points in the target mesh.";
2391 Range missing_adj_elems;
2392 CHKERR moab.get_adjacencies(missing_verts, 3, false, missing_adj_elems,
2393 moab::Interface::UNION);
2394
2395 int num_adj_elems = (int)missing_adj_elems.size();
2396 std::vector<double> vpos_adj_elems;
2397
2398 vpos_adj_elems.resize(3 * missing_adj_elems.size());
2399 CHKERR moab.get_coords(missing_adj_elems, &vpos_adj_elems[0]);
2400
2401 // Locate those points in the source mesh
2402 tl_ptr->reset();
2403 CHKERR mbc.locate_points(&vpos_adj_elems[0], num_adj_elems, 0, toler,
2404 tl_ptr.get(), false);
2405
2406 Range missing_tets;
2407 CHKERR find_missing_points(missing_adj_elems, num_adj_elems,
2408 vpos_adj_elems, missing_tets);
2409 if (missing_tets.size()) {
2410 MOFEM_LOG("WORLD", Sev::warning)
2411 << missing_tets.size()
2412 << " points in target mesh were not located in source mesh. ";
2413 }
2414
2415 std::vector<double> target_data_adj_elems(
2416 interp_tag_len * num_adj_elems, 0.0);
2417
2418 for (int itag = 0; itag < interp_tag_len; itag++) {
2419 CHKERR create_scalar_tags(src_elems, source_data, itag);
2420
2421 std::vector<double> target_data_adj_elems_scalar(num_adj_elems, 0.0);
2422 CHKERR mbc.interpolate(method, scalar_tag_name,
2423 &target_data_adj_elems_scalar[0],
2424 tl_ptr.get());
2425
2426 for (int ielem = 0; ielem < num_adj_elems; ielem++) {
2427 target_data_adj_elems[itag + ielem * interp_tag_len] =
2428 target_data_adj_elems_scalar[ielem];
2429 }
2430 }
2431
2432 CHKERR moab.tag_set_data(interp_tag, missing_adj_elems,
2433 &target_data_adj_elems[0]);
2434
2435 // FIXME: add implementation for parallel case
2436 for (auto &vert : missing_verts) {
2437 Range adj_elems;
2438 CHKERR moab.get_adjacencies(&vert, 1, 3, false, adj_elems,
2439 moab::Interface::UNION);
2440
2441 std::vector<double> adj_elems_data(adj_elems.size() * interp_tag_len,
2442 0.0);
2443 CHKERR moab.tag_get_data(interp_tag, adj_elems, &adj_elems_data[0]);
2444
2445 std::vector<double> vert_data(interp_tag_len, 0.0);
2446 for (int itag = 0; itag < interp_tag_len; itag++) {
2447 for (int i = 0; i < adj_elems.size(); i++) {
2448 vert_data[itag] += adj_elems_data[i * interp_tag_len + itag];
2449 }
2450 vert_data[itag] /= adj_elems.size();
2451 }
2452 CHKERR moab.tag_set_data(interp_tag, &vert, 1, &vert_data[0]);
2453 }
2454 }
2455
2456 CHKERR moab.tag_delete(scalar_tag);
2457 CHKERR moab.tag_delete(adj_count_tag);
2458 }
2459
2460 // delete source mesh after projection but keep the tags info for broadcast
2461 Range src_mesh_ents;
2462 CHKERR moab.get_entities_by_handle(source_root, src_mesh_ents);
2463 CHKERR moab.delete_entities(&source_root, 1);
2464 CHKERR moab.delete_entities(src_mesh_ents);
2465 CHKERR moab.delete_entities(&part_set, 1);
2466 }
2467
2468 // broadcast tag info to other processors
2469 int tag_size = tag_length.size();
2470 MPI_Bcast(&tag_size, 1, MPI_INT, 0, PETSC_COMM_WORLD);
2471 if (rank != 0) {
2472 interp_tags.resize(tag_size);
2473 tag_length.resize(tag_size);
2474 dtype.resize(tag_size);
2475 storage.resize(tag_size);
2476 }
2477 MPI_Bcast(interp_tags.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2478 MPI_Bcast(tag_length.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2479 MPI_Bcast(dtype.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2480 MPI_Bcast(storage.data(), tag_size, MPI_INT, 0, PETSC_COMM_WORLD);
2481
2482 // create new tag on other processors
2483 // loop over tag index to support multiple tags projection in one run
2484
2485 for (size_t index = 0; index < interp_tags.size(); index++) {
2486 // check if tag exists first
2487 if (world_rank) {
2488 Tag old_interp_tag;
2489 auto rval_check_tag =
2490 moab.tag_get_handle(listTagsToProject[index].c_str(), old_interp_tag);
2491 if (rval_check_tag == MB_SUCCESS) {
2492 MOFEM_LOG("WORLD", Sev::verbose)
2493 << "Deleting existing tag on target mesh (post-projection): "
2494 << listTagsToProject[index];
2495 CHKERR moab.tag_delete(old_interp_tag);
2496 }
2497 }
2498 Tag interp_tag_all;
2499 unsigned flags =
2500 MB_TAG_CREAT | storage[index]; // e.g., MB_TAG_DENSE or MB_TAG_SPARSE
2501 std::vector<double> def_val(tag_length[index], 0.);
2502 auto rval = moab.tag_get_handle(listTagsToProject[index].c_str(),
2503 tag_length[index], dtype[index],
2504 interp_tag_all, flags, def_val.data());
2505 if (rval != MB_SUCCESS && world_rank) {
2506 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2507 "Unable to create projection tag %s",
2508 listTagsToProject[index].c_str());
2509 }
2510
2511 MPI_Barrier(PETSC_COMM_WORLD);
2512
2513 // exchange data for all entity types across all processors
2514 auto vertex_exchange = CommInterface::createEntitiesPetscVector(
2515 mField.get_comm(), mField.get_moab(), 0, tag_length[index],
2516 Sev::inform);
2517 auto volume_exchange = CommInterface::createEntitiesPetscVector(
2518 mField.get_comm(), mField.get_moab(), 3, tag_length[index],
2519 Sev::inform);
2520
2522 mField.get_moab(), vertex_exchange, interp_tag_all);
2524 mField.get_moab(), volume_exchange, interp_tag_all);
2525 }
2526
2527 // delete target meshset but not the entities
2528 CHKERR moab.delete_entities(&target_root, 1);
2529
2530#endif // INCLUDE_MBCOUPLER
2532}
#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.

◆ 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 3334 of file EshelbianPlasticity.cpp.

3335 {
3337 fe_lhs->getOpPtrVector().push_back(
3340}
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 3323 of file EshelbianPlasticity.cpp.

3324 {
3327 fe_lhs->getOpPtrVector().push_back(
3329 fe_lhs->getOpPtrVector().push_back(
3332}
FormsIntegrators< VolUserDataOperator >::Assembly< A >::BiLinearForm< GAUSS >::OpMass< 9, 9 > OpStressGram_dBubble_dBubble
MoFEMErrorCode pushPiolaStressGramOps(boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe_lhs)

◆ pushVolumeA00Ops()

MoFEMErrorCode EshelbianCore::pushVolumeA00Ops ( 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 3291 of file EshelbianPlasticity.cpp.

3292 {
3294
3295 CHKERR physicalEquations->pushMaterialTangent(*this, fe_lhs->getOpPtrVector(),
3296 dataAtPts);
3297
3298 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dP(
3300 fe_lhs->getOpPtrVector().push_back(new OpSpatialEquilibrium_dw_dw(
3302
3303 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dP_domega(
3305 symmetrySelector == SYMMETRIC ? true : false));
3306 fe_lhs->getOpPtrVector().push_back(new OpSpatialConsistency_dBubble_domega(
3308 symmetrySelector == SYMMETRIC ? true : false));
3309
3310 if (symmetrySelector > SYMMETRIC) {
3311 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dP(
3312 rotAxis, piolaStress, dataAtPts, false));
3313 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_dBubble(
3314 rotAxis, bubbleField, dataAtPts, false));
3315 }
3316 fe_lhs->getOpPtrVector().push_back(new OpSpatialRotation_domega_domega(
3319
3321}
static constexpr enum SymmetrySelector symmetrySelector

◆ 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 898 of file EshelbianPlasticity.cpp.

899 {
900 *iface = const_cast<EshelbianCore *>(this);
901 return 0;
902}

◆ resolveDissipationEntities()

MoFEMErrorCode EshelbianCore::resolveDissipationEntities ( 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 1518 of file EshelbianPlasticity.cpp.

1518 {
1520
1521 plasticVolumes = boost::make_shared<Range>();
1522 if (plasticVolume) {
1524 }
1525 if (plasticVolumes->empty()) {
1526 CHKERR mField.get_moab().get_entities_by_dimension(meshset, SPACE_DIM,
1528 }
1529 MOFEM_LOG("EP", Sev::inform)
1530 << "Number of plastic volume elements: " << plasticVolumes->size();
1531
1532 interfaceFaces = boost::make_shared<Range>(
1533 get_range_from_block(mField, "(INTERFACE|MAT_COHESIVE)", SPACE_DIM - 1));
1534
1535 auto get_internal_interface_faces = [&](const auto block_name) {
1536 auto volume_elements = get_range_from_block(mField, block_name, SPACE_DIM);
1537 auto skin = filter_true_skin(mField, get_skin(mField, volume_elements));
1538 Range faces;
1539 CHKERR mField.get_moab().get_adjacencies(
1540 volume_elements, SPACE_DIM - 1, true, faces, moab::Interface::UNION);
1541 faces = subtract(faces, skin);
1542 MOFEM_LOG("EP", Sev::inform)
1543 << "Number of volume interface elements: " << volume_elements.size()
1544 << " and internal faces: " << faces.size();
1545 return faces;
1546 };
1547
1548 interfaceFaces->merge(
1549 get_internal_interface_faces("(VOLUME_INTERFACE|MAT_COHESIVE)"));
1550
1551 auto remove_interface_faces = [&](const auto block_name, const auto level) {
1553 Range retained_faces;
1554 if (mField.get_comm_rank() == 0) {
1555 auto entities = get_entities_by_handle(mField, block_name);
1556 for (auto l = 0; l < level; ++l) {
1557 Range adjacent_tets;
1558 CHKERR mField.get_moab().get_adjacencies(
1559 entities, SPACE_DIM, true, adjacent_tets, moab::Interface::UNION);
1560 Range adjacent_tet_faces;
1561 CHKERR mField.get_moab().get_adjacencies(adjacent_tets, SPACE_DIM - 1,
1562 true, adjacent_tet_faces,
1563 moab::Interface::UNION);
1564 entities.merge(adjacent_tet_faces);
1565 }
1566 const auto faces = entities.subset_by_dimension(SPACE_DIM - 1);
1567 if (!faces.empty()) {
1568 MOFEM_LOG("EP", Sev::inform)
1569 << "Removing " << faces.size() << " of " << interfaceFaces->size()
1570 << " interface faces";
1571 }
1572 retained_faces = subtract(*interfaceFaces, faces);
1573 MOFEM_LOG("EP", Sev::noisy)
1574 << "Interface faces after removal " << retained_faces;
1575 }
1576 auto global_retained_faces = send_type(mField, retained_faces, MBTRI);
1577 interfaceFaces->swap(global_retained_faces);
1579 };
1580 CHKERR remove_interface_faces("REMOVE_INTERFACE", interfaceRemoveLevel);
1581
1582 MOFEM_LOG("EP", Sev::inform)
1583 << "Number of interface elements: " << interfaceFaces->size();
1584
1586}
static auto get_entities_by_handle(MoFEM::Interface &m_field, const std::string block_name)

◆ runIncrementalOptimizationTAO()

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

Definition at line 748 of file PlasticIncrementalOptimization.cpp.

748 {
751 *this, SmartPetscObj<TS>(ts, true), SmartPetscObj<Vec>(state, true));
754}
boost::shared_ptr< IncrementalOptimizationContext > context
boost::shared_ptr< IncrementalOptimizationContext > createPlasticIncrementalOptimizationContext(EshelbianCore &ep, SmartPetscObj< TS > ts, SmartPetscObj< Vec > state)
MoFEMErrorCode solveIncrementalOptimizationTAO(const boost::shared_ptr< IncrementalOptimizationContext > &context, Vec state)

◆ 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 3193 of file EshelbianPlasticity.cpp.

3196 {
3198
3199 auto bubble_cache =
3200 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
3201 fe->getUserPolynomialBase() =
3202 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
3203 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3204 fe->getOpPtrVector(), {HDIV, H1, L2}, materialH1Positions, frontAdjEdges);
3205
3206 // set integration rule
3207 fe->getRuleHook = [](int, int, int) { return -1; };
3208 fe->setRuleHook = SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges,
3209 vol_rule, bubble_cache);
3210
3211 if (!dataAtPts) {
3212 dataAtPts =
3213 boost::shared_ptr<DataAtIntegrationPts>(new DataAtIntegrationPts());
3214 }
3215 dataAtPts->physicsPtr = physicalEquations;
3216
3217 // calculate fields values
3218 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
3219 piolaStress, dataAtPts->getApproxPAtPts()));
3220 if (add_bubble) {
3221 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
3222 bubbleField, dataAtPts->getApproxPAtPts(), MBMAXTYPE));
3223 }
3224 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
3225 piolaStress, dataAtPts->getDivPAtPts()));
3226 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3227 rotAxis, dataAtPts->getRotAxisAtPts(), MBTET));
3228
3229 CHKERR VecSetDM(solTSStep, PETSC_NULLPTR);
3230 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
3231 piolaStress, dataAtPts->getApproxP0AtPts(), nullptr, solTSStep));
3232 CHKERR physicalEquations->pushMaterialFields(
3233 *this, fe->getOpPtrVector(), dataAtPts, PhysicalEquations::PREVIOUS);
3234
3235 // Stress-to-stretch recovery uses the shared constitutive scratch and
3236 // tangent storage in DataAtIntegrationPts. Recover the current state last so
3237 // the Jacobian operators consume the tangent evaluated at the current P.
3238 CHKERR physicalEquations->pushMaterialFields(*this, fe->getOpPtrVector(),
3239 dataAtPts);
3240
3241 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3242 rotAxis, dataAtPts->getRotAxis0AtPts(), solTSStep, MBTET));
3243 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3244 rotAxis, dataAtPts->getRotAxisGradAtPts(), MBTET));
3245 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3246 spatialL2Disp, dataAtPts->getSmallWL2AtPts(), MBTET));
3247
3248 // H1 displacements
3249 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
3250 spatialH1Disp, dataAtPts->getSmallWH1AtPts()));
3251 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
3252 spatialH1Disp, dataAtPts->getSmallWGradH1AtPts()));
3253
3254 // velocities
3255 if (calc_rates) {
3256 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3257 spatialL2Disp, dataAtPts->getSmallWL2DotAtPts(), MBTET));
3258 CHKERR physicalEquations->pushMaterialRates(*this, fe->getOpPtrVector(),
3259 dataAtPts);
3260 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDot<3>(
3261 rotAxis, dataAtPts->getRotAxisDotAtPts(), MBTET));
3262 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradientDot<3, 3>(
3263 rotAxis, dataAtPts->getRotAxisGradDotAtPts(), MBTET));
3264
3265 // acceleration
3266 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
3267 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValuesDotDot<3>(
3268 spatialL2Disp, dataAtPts->getSmallWL2DotDotAtPts(), MBTET));
3269 }
3270 }
3271
3272 // calculate other derived quantities
3274 fe->getOpPtrVector(), plasticHField, dataAtPts->getPlasticH(), MBTET);
3277 fe->getOpPtrVector(), plasticFlowField, dataAtPts->getPlasticFlow(),
3279 fe->getOpPtrVector().push_back(new OpApplyPlasticFlowIncrement(dataAtPts));
3280 }
3281 fe->getOpPtrVector().push_back(
3283
3284 // evaluate integration points
3285 CHKERR physicalEquations->pushMaterialEvaluation(*this, fe->getOpPtrVector(),
3286 dataAtPts, do_rhs, do_lhs);
3287
3289}
Calculate divergence of tonsorial field using vectorial base.
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 4769 of file EshelbianPlasticity.cpp.

4769 {
4771
4772 auto set_block = [&](auto name, int dim) {
4773 std::map<int, Range> map;
4774 auto set_tag_impl = [&](auto name) {
4776 auto mesh_mng = mField.getInterface<MeshsetsManager>();
4777 auto bcs = mesh_mng->getCubitMeshsetPtr(
4778
4779 std::regex((boost::format("%s(.*)") % name).str())
4780
4781 );
4782 for (auto bc : bcs) {
4783 Range r;
4784 CHKERR bc->getMeshsetIdEntitiesByDimension(mField.get_moab(), dim, r,
4785 true);
4786 map[bc->getMeshsetId()] = r;
4787 MOFEM_LOG("EP", Sev::inform)
4788 << "Block " << name << " id " << bc->getMeshsetId() << " has "
4789 << r.size() << " entities";
4790 }
4792 };
4793
4794 CHKERR set_tag_impl(name);
4795
4796 return std::make_pair(name, map);
4797 };
4798
4799 auto set_skin = [&](auto &&map) {
4800 for (auto &m : map.second) {
4801 auto s = filter_true_skin(mField, get_skin(mField, m.second));
4802 m.second.swap(s);
4803 MOFEM_LOG("EP", Sev::inform)
4804 << "Skin for block " << map.first << " id " << m.first << " has "
4805 << m.second.size() << " entities";
4806 }
4807 return map;
4808 };
4809
4810 auto set_tag = [&](auto &&map) {
4811 Tag th;
4812 auto name = map.first;
4813 int def_val[] = {-1};
4815 mField.get_moab().tag_get_handle(name, 1, MB_TYPE_INTEGER, th,
4816 MB_TAG_SPARSE | MB_TAG_CREAT, def_val),
4817 "create tag");
4818 for (auto &m : map.second) {
4819 int id = m.first;
4820 CHK_MOAB_THROW(mField.get_moab().tag_clear_data(th, m.second, &id),
4821 "clear tag");
4822 }
4823 return th;
4824 };
4825
4826 listTagsToTransfer.push_back(set_tag(set_skin(set_block("BODY", 3))));
4827 listTagsToTransfer.push_back(set_tag(set_skin(set_block("MAT_ELASTIC", 3))));
4828 listTagsToTransfer.push_back(
4829 set_tag(set_skin(set_block("MAT_NEOHOOKEAN", 3))));
4830 listTagsToTransfer.push_back(set_tag(set_block("CONTACT", 2)));
4831
4833}
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 4169 of file EshelbianPlasticity.cpp.

4173 {
4175 fe_contact_tree = createContactDetectionFiniteElement(*this);
4177}
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 4179 of file EshelbianPlasticity.cpp.

4179 {
4181
4182 // Add contact operators. Note that only for rhs. THe lhs is assembled with
4183 // volume element, to enable schur complement evaluation.
4185
4188
4190}
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)

◆ 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 4192 of file EshelbianPlasticity.cpp.

4192 {
4194 boost::shared_ptr<FEMethod> null;
4195
4196 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4197
4199 null);
4201 null);
4203 null);
4205 null);
4206
4207 } else {
4209 null);
4211 null);
4213 null);
4215 null);
4216 }
4217
4219}
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 3992 of file EshelbianPlasticity.cpp.

3995 {
3997
3998 fe_rhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
3999 fe_lhs = boost::make_shared<FaceElementForcesAndSourcesCore>(mField);
4000
4001 // set integration rule
4002 // fe_rhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
4003 // fe_lhs->getRuleHook = [](int, int, int p) { return 2 * (p + 1); };
4004 fe_rhs->getRuleHook = [](int, int, int) { return -1; };
4005 fe_lhs->getRuleHook = [](int, int, int) { return -1; };
4006 fe_rhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
4007 fe_lhs->setRuleHook = SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
4008
4009 CHKERR
4010 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4011 fe_rhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
4012 CHKERR
4013 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
4014 fe_lhs->getOpPtrVector(), {L2}, materialH1Positions, frontAdjEdges);
4015
4016 if (add_elastic) {
4017
4018 auto get_broken_op_side = [this](auto &pip) {
4019 using EleOnSide =
4021 using SideEleOp = EleOnSide::UserDataOperator;
4022 // Iterate over domain FEs adjacent to boundary.
4023 auto broken_data_ptr =
4024 boost::make_shared<std::vector<BrokenBaseSideData>>();
4025 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
4026 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
4027 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
4028 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
4029 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
4030 CHKERR
4031 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
4032 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
4034 op_loop_domain_side->getOpPtrVector().push_back(
4035 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
4036 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
4037 op_loop_domain_side->getOpPtrVector().push_back(
4039 flux_mat_ptr));
4040 op_loop_domain_side->getOpPtrVector().push_back(
4041 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
4042 pip.push_back(op_loop_domain_side);
4043 return broken_data_ptr;
4044 };
4045
4046 auto set_rhs = [&]() {
4048
4049 auto broken_data_ptr = get_broken_op_side(fe_rhs->getOpPtrVector());
4050
4051 fe_rhs->getOpPtrVector().push_back(
4052 new OpDispBc(broken_data_ptr, bcSpatialDispVecPtr, timeScaleMap));
4053 fe_rhs->getOpPtrVector().push_back(new OpAnalyticalDispBc(
4055 timeScaleMap));
4056 fe_rhs->getOpPtrVector().push_back(new OpRotationBc(
4057 broken_data_ptr, bcSpatialRotationVecPtr, timeScaleMap));
4058
4059 auto piola_scale_ptr = boost::make_shared<double>(1.0);
4060 fe_rhs->getOpPtrVector().push_back(
4062 piola_scale_ptr, timeScaleMap));
4063 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
4064 // if you push gradient of L2 base to physical element, it will not work.
4065 fe_rhs->getOpPtrVector().push_back(
4067 hybridSpatialDisp, hybrid_grad_ptr));
4068 fe_rhs->getOpPtrVector().push_back(new OpBrokenPressureBc(
4070 hybrid_grad_ptr, timeScaleMap));
4071 fe_rhs->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc(
4073 timeScaleMap));
4074
4075 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
4076 fe_rhs->getOpPtrVector().push_back(
4078 hybrid_ptr));
4079 fe_rhs->getOpPtrVector().push_back(new OpNormalDispRhsBc(
4080 hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
4082 fe_rhs->getOpPtrVector().push_back(
4083 new OpSpringRhsBc(hybridSpatialDisp, hybrid_ptr, broken_data_ptr,
4085
4086 auto get_normal_disp_bc_faces = [&]() {
4087 auto faces =
4088 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
4089 return boost::make_shared<Range>(faces);
4090 };
4091
4092 auto get_spring_bc_faces = [&]() {
4093 auto faces = get_range_from_block(mField, "SPRING_BC", SPACE_DIM - 1);
4094 return boost::make_shared<Range>(faces);
4095 };
4096
4097 using BoundaryEle =
4099 using BdyEleOp = BoundaryEle::UserDataOperator;
4101 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
4102 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
4103 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
4104 get_normal_disp_bc_faces()));
4105 fe_rhs->getOpPtrVector().push_back(new OpC_dBroken(
4106 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0),
4107 get_spring_bc_faces()));
4108
4110 };
4111
4112 auto set_lhs = [&]() {
4114
4115 auto broken_data_ptr = get_broken_op_side(fe_lhs->getOpPtrVector());
4116
4117 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dU(
4119 fe_lhs->getOpPtrVector().push_back(new OpNormalDispLhsBc_dP(
4121 timeScaleMap));
4122 fe_lhs->getOpPtrVector().push_back(
4124 fe_lhs->getOpPtrVector().push_back(new OpSpringLhsBc_dP(
4125 hybridSpatialDisp, broken_data_ptr, bcSpatialSpringVecPtr));
4126
4127 auto hybrid_grad_ptr = boost::make_shared<MatrixDouble>();
4128 // if you push gradient of L2 base to physical element, it will not work.
4129 fe_lhs->getOpPtrVector().push_back(
4131 hybridSpatialDisp, hybrid_grad_ptr));
4132 fe_lhs->getOpPtrVector().push_back(new OpBrokenPressureBcLhs_dU(
4134 timeScaleMap));
4135
4136 auto get_normal_disp_bc_faces = [&]() {
4137 auto faces =
4138 get_range_from_block(mField, "NORMAL_DISPLACEMENT", SPACE_DIM - 1);
4139 return boost::make_shared<Range>(faces);
4140 };
4141
4142 auto get_spring_bc_faces = [&]() {
4143 auto faces = get_range_from_block(mField, "SPRING_BC", SPACE_DIM - 1);
4144 return boost::make_shared<Range>(faces);
4145 };
4146
4147 using BoundaryEle =
4149 using BdyEleOp = BoundaryEle::UserDataOperator;
4151 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
4152 fe_lhs->getOpPtrVector().push_back(new OpC(
4153 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
4154 true, true, get_normal_disp_bc_faces()));
4155 fe_lhs->getOpPtrVector().push_back(new OpC(
4156 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0),
4157 true, true, get_spring_bc_faces()));
4158
4160 };
4161
4162 CHKERR set_rhs();
4163 CHKERR set_lhs();
4164 }
4165
4167}
@ GAUSS
Gaussian quadrature integration.
constexpr AssemblyType A
Apply rotation boundary condition.
BoundaryEle::UserDataOperator BdyEleOp

◆ setNewFrontCoordinates()

MoFEMErrorCode EshelbianCore::setNewFrontCoordinates ( )

Definition at line 2073 of file EshelbianFracture.cpp.

2073 {
2075
2076 if (!maxMovedFaces)
2078
2079 Tag th_front_position;
2080 auto rval =
2081 mField.get_moab().tag_get_handle("FrontPosition", th_front_position);
2082 if (rval == MB_SUCCESS && maxMovedFaces) {
2083 Range verts;
2084 CHKERR mField.get_moab().get_connectivity(*maxMovedFaces, verts, true);
2085 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(verts);
2086 std::vector<double> coords(3 * verts.size());
2087 CHKERR mField.get_moab().get_coords(verts, coords.data());
2088 std::vector<double> pos(3 * verts.size());
2089 CHKERR mField.get_moab().tag_get_data(th_front_position, verts, pos.data());
2090 for (int i = 0; i != 3 * verts.size(); ++i) {
2091 coords[i] += pos[i];
2092 }
2093 CHKERR mField.get_moab().set_coords(verts, coords.data());
2094 double zero[] = {0., 0., 0.};
2095 CHKERR mField.get_moab().tag_clear_data(th_front_position, verts, zero);
2096 }
2097
2098#ifndef NDEBUG
2099 constexpr bool debug = false;
2100 if (debug) {
2101
2103 mField.get_moab(),
2104 "set_coords_faces_" +
2105 boost::lexical_cast<std::string>(mField.get_comm_rank()) + ".vtk",
2106 *maxMovedFaces);
2107 }
2108#endif
2110}

◆ 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 
)
Examples
/home/lk58p/mofem_install/vanilla_dev_release/mofem-cephas/mofem/users_modules/eshelbian_plasticity/src/impl/EshelbianPlasticity.cpp.

Definition at line 3342 of file EshelbianPlasticity.cpp.

3345 {
3347
3348 CHKERR physicalEquations->checkSetup(*this);
3349
3350 auto local_tau_sacale = boost::make_shared<double>(1.0);
3351 using BoundaryEle =
3353 using BdyEleOp = BoundaryEle::UserDataOperator;
3354 struct OpSetTauScale : public BdyEleOp {
3355 OpSetTauScale(boost::shared_ptr<double> local_tau_sacale,
3356 boost::shared_ptr<MatrixDouble> piola_stress_at_pts,
3357 double alpha_tau, double alpha_tau_lin)
3358 : BdyEleOp(NOSPACE, BdyEleOp::OPSPACE),
3359 localTauSacale(local_tau_sacale),
3360 piolaStressAtPts(piola_stress_at_pts), alphaTau(alpha_tau),
3361 alphaTauLin(alpha_tau_lin) {}
3362 MoFEMErrorCode doWork(int side, EntityType type,
3363 EntitiesFieldData::EntData &data) override {
3365 auto &coords = BdyEleOp::getCoords();
3366 auto [centre, barycenter, h] =
3367 Tools::getTricircumcenter3d(coords.data().data());
3368
3369 if (PetscUnlikely(h <= 0))
3370 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3371 "Non-positive characteristic face size");
3372
3373 double mean_normal_traction = 0;
3374 if (alphaTauLin > 0) {
3375 if (PetscUnlikely(!piolaStressAtPts))
3376 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3377 "Piola stress is not available for tau scaling");
3378
3379 const auto nb_gauss_pts = BdyEleOp::getGaussPts().size2();
3381 auto get_piola =
3384 *piolaStressAtPts, nb_gauss_pts);
3385 auto t_piola = get_piola();
3386 auto t_normal = BdyEleOp::getFTensor1NormalsAtGaussPts();
3387 auto t_w = BdyEleOp::getFTensor0IntegrationWeight();
3389
3390 double face_measure = 0;
3391 double integrated_normal_traction = 0;
3392 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
3393 const double normal_norm = t_normal.l2();
3394 if (PetscUnlikely(normal_norm <= 0))
3395 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3396 "Face normal has non-positive length");
3397
3399 t_unit_normal(i) = t_normal(i) / normal_norm;
3400 const double dA = t_w * BdyEleOp::getMeasure();
3401 face_measure += dA;
3402 integrated_normal_traction +=
3403 dA * std::abs(t_unit_normal(i) * t_piola(i, J) *
3404 t_unit_normal(J));
3405
3406 ++t_piola;
3407 ++t_normal;
3408 ++t_w;
3409 }
3410
3411 if (PetscUnlikely(face_measure <= 0))
3412 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3413 "Face has non-positive measure");
3414 mean_normal_traction = integrated_normal_traction / face_measure;
3415 }
3416
3417 *localTauSacale = (alphaTau + alphaTauLin * mean_normal_traction) / h;
3418
3420 }
3421
3422 private:
3423 boost::shared_ptr<double> localTauSacale;
3424 boost::shared_ptr<MatrixDouble> piolaStressAtPts;
3425 double alphaTau;
3426 double alphaTauLin;
3427 };
3428
3429 auto add_tau_stress_producer = [&](auto &pip) {
3430 // Freeze traction-dependent stabilisation at the last converged state.
3431 auto piola_stress_at_pts = dataAtPts->getApproxP0AtPts();
3432 if (alphaTauLin > 0)
3434 piolaStress, piola_stress_at_pts, nullptr, solTSStep));
3435 return piola_stress_at_pts;
3436 };
3437
3438 auto not_interface_face = [this](FEMethod *fe_method_ptr) {
3439 auto ent = fe_method_ptr->getFEEntityHandle();
3440 if (
3441
3442 (interfaceFaces->find(ent) != interfaceFaces->end())
3443
3444 || (crackFaces->find(ent) != crackFaces->end())
3445
3446 ) {
3447 return false;
3448 };
3449 return true;
3450 };
3451
3452 // Right hand side
3453 fe_rhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3454 CHKERR setBaseVolumeElementOps(tag, true, false, true, fe_rhs);
3455
3456 // elastic
3457 if (add_elastic) {
3458
3459 fe_rhs->getOpPtrVector().push_back(
3461 fe_rhs->getOpPtrVector().push_back(new OpSpatialRotation(
3464 CHKERR physicalEquations->pushMaterialResidual(
3465 *this, fe_rhs->getOpPtrVector(), dataAtPts);
3466 fe_rhs->getOpPtrVector().push_back(
3468 fe_rhs->getOpPtrVector().push_back(
3470 fe_rhs->getOpPtrVector().push_back(
3472
3473 auto set_hybridisation_rhs = [&](auto &pip) {
3475
3476 using BoundaryEle =
3478 using EleOnSide =
3480 using SideEleOp = EleOnSide::UserDataOperator;
3481 using BdyEleOp = BoundaryEle::UserDataOperator;
3482
3483 // First: Iterate over skeleton FEs adjacent to Domain FEs
3484 // Note: BoundaryEle, i.e. uses skeleton interation rule
3485 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3486 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3487 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3488 return -1;
3489 };
3490 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3491 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3492
3493 CHKERR EshelbianPlasticity::
3494 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3495 op_loop_skeleton_side->getOpPtrVector(), {L2},
3497
3498 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3499 // domain element.
3500 auto broken_data_ptr =
3501 boost::make_shared<std::vector<BrokenBaseSideData>>();
3502 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3503 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3504 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3505 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3506 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3507 CHKERR
3508 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3509 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3511 op_loop_domain_side->getOpPtrVector().push_back(
3512 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3513 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
3514 op_loop_domain_side->getOpPtrVector().push_back(
3516 flux_mat_ptr));
3517 op_loop_domain_side->getOpPtrVector().push_back(
3518 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
3519
3520 // Assemble on skeleton
3521 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3523 GAUSS>::OpBrokenSpaceConstrainDHybrid<SPACE_DIM>;
3525 GAUSS>::OpBrokenSpaceConstrainDFlux<SPACE_DIM>;
3526 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dHybrid(
3527 hybridSpatialDisp, broken_data_ptr, boost::make_shared<double>(1.0)));
3528 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3529 op_loop_skeleton_side->getOpPtrVector().push_back(
3531 hybrid_ptr));
3532 op_loop_skeleton_side->getOpPtrVector().push_back(new OpC_dBroken(
3533 broken_data_ptr, hybrid_ptr, boost::make_shared<double>(1.0)));
3534
3535 // Add skeleton to domain pipeline
3536 pip.push_back(op_loop_skeleton_side);
3537
3539 };
3540
3541 auto set_tau_stabilsation_rhs = [&](auto &pip, auto side_fe_name,
3542 auto hybrid_field) {
3544
3545 using BoundaryEle =
3547 using EleOnSide =
3549 using SideEleOp = EleOnSide::UserDataOperator;
3550 using BdyEleOp = BoundaryEle::UserDataOperator;
3551
3552 // First: Iterate over skeleton FEs adjacent to Domain FEs
3553 // Note: BoundaryEle, i.e. uses skeleton interation rule
3554 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3555 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3556 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3557 return -1;
3558 };
3559 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3560 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3561 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3562 CHKERR EshelbianPlasticity::
3563 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3564 op_loop_skeleton_side->getOpPtrVector(), {L2},
3566
3567 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3568 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3569 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3570 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3571 CHKERR
3572 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3573 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3575
3576 // Add stabilization operator
3577 auto broken_disp_data_ptr =
3578 boost::make_shared<std::vector<BrokenBaseSideData>>();
3579 op_loop_domain_side->getOpPtrVector().push_back(
3581 broken_disp_data_ptr));
3582 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3583 op_loop_domain_side->getOpPtrVector().push_back(
3585 disp_mat_ptr));
3586 // Set diag fluxes on skeleton side
3587 op_loop_domain_side->getOpPtrVector().push_back(
3588 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3589 auto piola_stress_at_pts =
3590 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3591 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3592 op_loop_skeleton_side->getOpPtrVector().push_back(
3593 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts, alphaTau,
3594 alphaTauLin));
3595
3596 // Add stabilization Ugamma Ugamma skeleton
3597 auto hybrid_ptr = boost::make_shared<MatrixDouble>();
3598 op_loop_skeleton_side->getOpPtrVector().push_back(
3600 hybrid_ptr));
3601
3602 // Diag u_gamma - u_gamma faces
3603 op_loop_skeleton_side->getOpPtrVector().push_back(
3605 hybrid_field, hybrid_ptr,
3606 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3607 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3608 }));
3609 // Diag L2 - L2 volumes
3610 op_loop_skeleton_side->getOpPtrVector().push_back(
3612 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3613 return (*local_tau_sacale);
3614 }));
3615 // Off-diag Ugamma - L2
3616 op_loop_skeleton_side->getOpPtrVector().push_back(
3618 hybrid_field, broken_disp_data_ptr,
3619 [local_tau_sacale](double, double, double) {
3620 return -(*local_tau_sacale);
3621 }));
3622 // Off-diag L2 - Ugamma
3623 op_loop_skeleton_side->getOpPtrVector().push_back(
3625 broken_disp_data_ptr, hybrid_ptr,
3626 [local_tau_sacale](double, double, double) {
3627 return -(*local_tau_sacale);
3628 }));
3629
3630 // Add skeleton to domain pipeline
3631 pip.push_back(op_loop_skeleton_side);
3632
3634 };
3635
3636 auto set_tau_stabilsation_disp_bc_rhs = [&](auto &pip, auto side_fe_name) {
3638
3639 using BoundaryEle =
3641 using EleOnSide =
3643 using SideEleOp = EleOnSide::UserDataOperator;
3644 using BdyEleOp = BoundaryEle::UserDataOperator;
3645
3646 // First: Iterate over skeleton FEs adjacent to Domain FEs
3647 // Note: BoundaryEle, i.e. uses skeleton interation rule
3648 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3649 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3650 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3651 return -1;
3652 };
3653 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3654 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3655 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3656 CHKERR EshelbianPlasticity::
3657 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3658 op_loop_skeleton_side->getOpPtrVector(), {L2},
3660
3661 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3662 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3663 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3664 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3665 CHKERR
3666 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3667 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3669
3670 // Add stabilization operator
3671 auto broken_disp_data_ptr =
3672 boost::make_shared<std::vector<BrokenBaseSideData>>();
3673 op_loop_domain_side->getOpPtrVector().push_back(
3675 broken_disp_data_ptr));
3676 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
3677 op_loop_domain_side->getOpPtrVector().push_back(
3679 disp_mat_ptr));
3680 // Set diag fluxes on skeleton side
3681 op_loop_domain_side->getOpPtrVector().push_back(
3682 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
3683
3684 auto piola_stress_at_pts =
3685 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3686
3687 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3688 op_loop_skeleton_side->getOpPtrVector().push_back(
3689 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts,
3691
3692 // Diag L2 - L2 volumes
3693 op_loop_skeleton_side->getOpPtrVector().push_back(
3695 broken_disp_data_ptr, bcSpatialDispVecPtr, timeScaleMap,
3696 [local_tau_sacale](double, double, double) {
3697 return (*local_tau_sacale);
3698 }));
3699 op_loop_skeleton_side->getOpPtrVector().push_back(
3701 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3702 timeScaleMap, [local_tau_sacale](double, double, double) {
3703 return (*local_tau_sacale);
3704 }));
3705 op_loop_skeleton_side->getOpPtrVector().push_back(
3707 broken_disp_data_ptr, bcSpatialRotationVecPtr, timeScaleMap,
3708 [local_tau_sacale](double, double, double) {
3709 return (*local_tau_sacale);
3710 }));
3711
3712 // Add skeleton to domain pipeline
3713 pip.push_back(op_loop_skeleton_side);
3714
3716 };
3717
3718 auto set_contact_rhs = [&](auto &pip) {
3719 return pushContactOpsRhs(*this, contactTreeRhs, pip);
3720 };
3721
3722 CHKERR set_hybridisation_rhs(fe_rhs->getOpPtrVector());
3723 CHKERR set_contact_rhs(fe_rhs->getOpPtrVector());
3724 if (alphaTau > 0.0 || alphaTauLin > 0.0) {
3725 CHKERR set_tau_stabilsation_rhs(fe_rhs->getOpPtrVector(), skeletonElement,
3727 }
3728 if (alphaTauBcDisp > 0.0 || alphaTauLin > 0.0) {
3729 CHKERR set_tau_stabilsation_disp_bc_rhs(fe_rhs->getOpPtrVector(),
3731 }
3732 // Body forces
3733 using BodyNaturalBC =
3735 Assembly<PETSC>::LinearForm<GAUSS>;
3736 using OpBodyForce =
3737 BodyNaturalBC::OpFlux<NaturalMeshsetType<BLOCKSET>, 1, 3>;
3738
3739 std::string body_force_history;
3740 CHKERR getStringArgumentFromJsonBlocksets("BODY_FORCE", "load_history",
3741 body_force_history);
3742 if (body_force_history.empty()) {
3743 body_force_history = "body_force.txt";
3744 } else {
3745 MOFEM_LOG("EP", Sev::inform)
3746 << "Body force load history from JSON: " << body_force_history;
3747 }
3748 auto body_time_scale =
3749 boost::make_shared<DynamicRelaxationTimeScale>(body_force_history);
3750 CHKERR BodyNaturalBC::AddFluxToPipeline<OpBodyForce>::add(
3751 fe_rhs->getOpPtrVector(), mField, spatialL2Disp, {body_time_scale},
3752 "BODY_FORCE", Sev::inform);
3753 }
3754
3755 // Left hand side
3756 fe_lhs = boost::make_shared<VolumeElementForcesAndSourcesCore>(mField);
3757 CHKERR setBaseVolumeElementOps(tag, true, true, true, fe_lhs);
3758
3759 // elastic
3760 if (add_elastic) {
3761
3762 CHKERR pushVolumeA00Ops(fe_lhs);
3763
3764 auto set_hybridisation_lhs = [&](auto &pip) {
3766
3767 using BoundaryEle =
3769 using EleOnSide =
3771 using SideEleOp = EleOnSide::UserDataOperator;
3772 using BdyEleOp = BoundaryEle::UserDataOperator;
3773
3774 // First: Iterate over skeleton FEs adjacent to Domain FEs
3775 // Note: BoundaryEle, i.e. uses skeleton interation rule
3776 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3777 mField, skeletonElement, SPACE_DIM - 1, Sev::noisy);
3778 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3779 return -1;
3780 };
3781 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3782 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3783 CHKERR EshelbianPlasticity::
3784 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3785 op_loop_skeleton_side->getOpPtrVector(), {L2},
3787
3788 // Second: Iterate over domain FEs adjacent to skelton, particularly one
3789 // domain element.
3790 auto broken_data_ptr =
3791 boost::make_shared<std::vector<BrokenBaseSideData>>();
3792 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3793 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3794 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3795 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3796 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3797 CHKERR
3798 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3799 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3801 op_loop_domain_side->getOpPtrVector().push_back(
3802 new OpGetBrokenBaseSideData<SideEleOp>(piolaStress, broken_data_ptr));
3803
3804 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3806 GAUSS>::OpBrokenSpaceConstrain<SPACE_DIM>;
3807 op_loop_skeleton_side->getOpPtrVector().push_back(
3808 new OpC(hybridSpatialDisp, broken_data_ptr,
3809 boost::make_shared<double>(1.0), true, false));
3810
3811 pip.push_back(op_loop_skeleton_side);
3812
3814 };
3815
3816 auto set_tau_stabilsation_lhs = [&](auto &pip, auto side_fe_name,
3817 auto hybrid_field) {
3819
3820 using BoundaryEle =
3822 using EleOnSide =
3824 using SideEleOp = EleOnSide::UserDataOperator;
3825 using BdyEleOp = BoundaryEle::UserDataOperator;
3826
3827 // First: Iterate over skeleton FEs adjacent to Domain FEs
3828 // Note: BoundaryEle, i.e. uses skeleton interation rule
3829 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3830 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3831 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3832 return -1;
3833 };
3834 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3835 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3836 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3837 CHKERR EshelbianPlasticity::
3838 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3839 op_loop_skeleton_side->getOpPtrVector(), {L2},
3841
3842 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3843 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3844 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3845 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3846 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3847 CHKERR
3848 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3849 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3851
3852 auto broken_disp_data_ptr =
3853 boost::make_shared<std::vector<BrokenBaseSideData>>();
3854 op_loop_domain_side->getOpPtrVector().push_back(
3856 broken_disp_data_ptr));
3857 auto piola_stress_at_pts =
3858 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3859 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3860 op_loop_skeleton_side->getOpPtrVector().push_back(
3861 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts, alphaTau,
3862 alphaTauLin));
3863
3864 // Diag Ugamma-Ugamma skeleton
3865 op_loop_skeleton_side->getOpPtrVector().push_back(new OpMassVectorFace(
3866 hybrid_field, hybrid_field,
3867 [local_tau_sacale, broken_disp_data_ptr](double, double, double) {
3868 return broken_disp_data_ptr->size() * (*local_tau_sacale);
3869 }));
3870 // Diag L2-L2 volumes
3871 op_loop_skeleton_side->getOpPtrVector().push_back(
3873 broken_disp_data_ptr, [local_tau_sacale](double, double, double) {
3874 return (*local_tau_sacale);
3875 }));
3876 // Off-diag Ugamma - L2
3877 op_loop_skeleton_side->getOpPtrVector().push_back(
3879 hybrid_field, broken_disp_data_ptr,
3880 [local_tau_sacale](double, double, double) {
3881 return -(*local_tau_sacale);
3882 },
3883 false, false));
3884 // Off-diag L2 - Ugamma
3885 op_loop_skeleton_side->getOpPtrVector().push_back(
3887 hybrid_field, broken_disp_data_ptr,
3888 [local_tau_sacale](double, double, double) {
3889 return -(*local_tau_sacale);
3890 },
3891 true, true));
3892
3893 pip.push_back(op_loop_skeleton_side);
3894
3896 };
3897
3898 auto set_tau_stabilsation_disp_bc_lhs = [&](auto &pip, auto side_fe_name) {
3900
3901 using BoundaryEle =
3903 using EleOnSide =
3905 using SideEleOp = EleOnSide::UserDataOperator;
3906 using BdyEleOp = BoundaryEle::UserDataOperator;
3907
3908 // First: Iterate over skeleton FEs adjacent to Domain FEs
3909 // Note: BoundaryEle, i.e. uses skeleton interation rule
3910 auto op_loop_skeleton_side = new OpLoopSide<BoundaryEle>(
3911 mField, side_fe_name, SPACE_DIM - 1, Sev::noisy);
3912 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
3913 return -1;
3914 };
3915 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
3916 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges);
3917 op_loop_skeleton_side->getSideFEPtr()->exeTestHook = not_interface_face;
3918 CHKERR EshelbianPlasticity::
3919 AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
3920 op_loop_skeleton_side->getOpPtrVector(), {L2},
3922
3923 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
3924 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
3925 mField, elementVolumeName, SPACE_DIM, Sev::noisy);
3926 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
3927 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
3928 CHKERR
3929 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
3930 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
3932
3933 auto broken_disp_data_ptr =
3934 boost::make_shared<std::vector<BrokenBaseSideData>>();
3935 op_loop_domain_side->getOpPtrVector().push_back(
3937 broken_disp_data_ptr));
3938 auto piola_stress_at_pts =
3939 add_tau_stress_producer(op_loop_domain_side->getOpPtrVector());
3940 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
3941 op_loop_skeleton_side->getOpPtrVector().push_back(
3942 new OpSetTauScale(local_tau_sacale, piola_stress_at_pts,
3944
3945 // Diag L2-L2 volumes
3946 op_loop_skeleton_side->getOpPtrVector().push_back(
3948 broken_disp_data_ptr, bcSpatialDispVecPtr,
3949 [local_tau_sacale](double, double, double) {
3950 return (*local_tau_sacale);
3951 }));
3952 op_loop_skeleton_side->getOpPtrVector().push_back(
3954 broken_disp_data_ptr, bcSpatialAnalyticalDisplacementVecPtr,
3955 [local_tau_sacale](double, double, double) {
3956 return (*local_tau_sacale);
3957 }));
3958 op_loop_skeleton_side->getOpPtrVector().push_back(
3960 broken_disp_data_ptr, bcSpatialRotationVecPtr,
3961 [local_tau_sacale](double, double, double) {
3962 return (*local_tau_sacale);
3963 }));
3964
3965 pip.push_back(op_loop_skeleton_side);
3966
3968 };
3969
3970 auto set_contact_lhs = [&](auto &pip) {
3971 return pushContactOpsLhs(*this, contactTreeRhs, pip);
3972 };
3973
3974 CHKERR set_hybridisation_lhs(fe_lhs->getOpPtrVector());
3975 CHKERR set_contact_lhs(fe_lhs->getOpPtrVector());
3976 if (alphaTau > 0.0 || alphaTauLin > 0.0) {
3977 CHKERR set_tau_stabilsation_lhs(fe_lhs->getOpPtrVector(), skeletonElement,
3979 }
3980 if (alphaTauBcDisp > 0.0 || alphaTauLin > 0.0) {
3981 CHKERR set_tau_stabilsation_disp_bc_lhs(fe_lhs->getOpPtrVector(),
3983 }
3984 }
3985
3986 if (add_material) {
3987 }
3988
3990}
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.
DataLayoutTraits< DataLayout::GaussByCoeffs > DL
Definition MatHuHu.hpp:33
decltype(GetFTensor2FromMatImpl< Tensor_Dim0, Tensor_Dim1, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2FromMatType
double h
MoFEMErrorCode pushVolumeA00Ops(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 getStringArgumentFromJsonBlocksets(const std::string &type_name, const std::string &param_name, std::string &param_value)
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

◆ 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 4617 of file EshelbianPlasticity.cpp.

4619 {
4621
4622 // Deprecated options
4623 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
4624
4625 CHKERR PetscOptionsScalar(
4626 "-dynamic_final_time", "dynamic relaxation final time", "",
4627 finalPhysicalTime, &finalPhysicalTime, PETSC_NULLPTR);
4628 CHKERR PetscOptionsScalar("-dynamic_delta_time",
4629 "dynamic relaxation final time", "", physicalDt,
4630 &physicalDt, PETSC_NULLPTR);
4631 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
4632 physicalMaxSteps, &physicalMaxSteps, PETSC_NULLPTR);
4633 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
4634 physicalH1Update, &physicalH1Update, PETSC_NULLPTR);
4635 CHKERR PetscOptionsScalar("-dynamic_atol",
4636 "stop relaxation when the zero-rate residual is "
4637 "below this value; disabled for <= 0",
4638 "", dynamicAtol, &dynamicAtol, PETSC_NULLPTR);
4639 CHKERR PetscOptionsScalar("-dynamic_rtol",
4640 "stop relaxation when the zero-rate residual is "
4641 "below this fraction of its initial value; "
4642 "disabled for <= 0",
4643 "", dynamicRtol, &dynamicRtol, PETSC_NULLPTR);
4644
4645 PetscOptionsEnd();
4646
4647 auto storage = solve_elastic_setup::setup(this, ts, x, false);
4648
4649 if (dynamicAtol > 0 || dynamicRtol > 0) {
4651 }
4652
4653 MOFEM_LOG("EP", Sev::warning)
4654 << "Following options are deprecated, use -physical prefix options "
4655 "instead";
4656 MOFEM_LOG("EP", Sev::inform)
4657 << "Dynamic relaxation final time -dynamic_final_time = "
4659 MOFEM_LOG("EP", Sev::inform)
4660 << "Dynamic relaxation delta time -dynamic_delta_time = " << physicalDt;
4661 MOFEM_LOG("EP", Sev::inform)
4662 << "Dynamic relaxation max iterations -dynamic_max_it = "
4664 MOFEM_LOG("EP", Sev::inform)
4665 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
4666 << (physicalH1Update ? "TRUE" : "FALSE");
4667 MOFEM_LOG("EP", Sev::inform)
4668 << "Dynamic relaxation absolute tolerance -dynamic_atol = "
4669 << dynamicAtol;
4670 MOFEM_LOG("EP", Sev::inform)
4671 << "Dynamic relaxation relative tolerance -dynamic_rtol = "
4672 << dynamicRtol;
4673
4675
4676 auto setup_ts_monitor = [&]() {
4677 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
4678 return monitor_ptr;
4679 };
4680 auto monitor_ptr = setup_ts_monitor();
4681
4682 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4683 {elasticFeLhs.get(), elasticFeRhs.get()});
4684 CHKERR TSSetUp(ts);
4685 CHKERR TSElasticPostStep::postStepInitialise(this);
4686
4687 double ts_delta_time;
4688 CHKERR TSGetTimeStep(ts, &ts_delta_time);
4689 CHKERR TSSetSolution(ts, x);
4690
4691 if (physicalH1Update) {
4692 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4693 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4694 } else {
4695 CHKERR TSSetPreStep(ts, PETSC_NULLPTR);
4696 CHKERR TSSetPostStep(ts, PETSC_NULLPTR);
4697 }
4698 if (dynamicAtol > 0 || dynamicRtol > 0) {
4699 CHKERR TSMonitorSet(ts, RelaxationResidualMonitor, PETSC_NULLPTR,
4700 PETSC_NULLPTR);
4701 }
4702
4703 CHKERR TSElasticPostStep::preStepFun(ts);
4704 CHKERR TSElasticPostStep::postStepFun(ts);
4705
4706 currentPhysicalTime = start_time;
4707 physicalStepNumber = start_step;
4708 monitor_ptr->ts = PETSC_NULLPTR;
4709 monitor_ptr->ts_u = PETSC_NULLPTR;
4710 monitor_ptr->ts_t = currentPhysicalTime;
4711 monitor_ptr->ts_step = physicalStepNumber;
4713
4714 if (physicalDt <= 0.) {
4716 "physicalDt must be positive, got %g", physicalDt);
4717 }
4719 MOFEM_LOG("EP", Sev::inform)
4720 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
4721 << " delta time " << physicalDt;
4722
4723 CHKERR TSSetStepNumber(ts, 0);
4724 CHKERR TSSetTime(ts, 0);
4725 CHKERR TSSetTimeStep(ts, ts_delta_time);
4726 CHKERR TSSetSolution(ts, x);
4727 if (!physicalH1Update) {
4728 CHKERR TSElasticPostStep::preStepFun(ts);
4729 }
4731 CHKERR TSSolve(ts, PETSC_NULLPTR);
4732 if (!physicalH1Update) {
4733 CHKERR TSElasticPostStep::postStepFun(ts);
4734 }
4735
4736 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
4737 SCATTER_FORWARD);
4738 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
4739 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
4740
4741 monitor_ptr->ts = PETSC_NULLPTR;
4742 monitor_ptr->ts_u = x;
4743 monitor_ptr->ts_t = currentPhysicalTime;
4744 monitor_ptr->ts_step = physicalStepNumber;
4746
4749 break;
4751 break;
4752
4753 const double remainingPhysicalTime =
4755 if (physicalDt >= remainingPhysicalTime) {
4757 } else {
4759 }
4760 }
4761
4762 CHKERR TSElasticPostStep::postStepDestroy();
4763 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4764 {elasticFeLhs.get(), elasticFeRhs.get()});
4765
4767}
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
static MoFEMErrorCode checkDynamicToleranceCompatibility(TS ts)
double dynamicInitialResidual
MoFEMErrorCode addDebugModel(TS ts)
Add debug to model.
static int physicalStepNumber
static double currentPhysicalTime

◆ 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 4450 of file EshelbianPlasticity.cpp.

4450 {
4452
4454
4455 auto storage = solve_elastic_setup::setup(this, ts, x, true);
4456
4457 if (std::abs(alphaRho) > std::numeric_limits<double>::epsilon()) {
4458 Vec xx;
4459 CHKERR VecDuplicate(x, &xx);
4460 CHKERR VecZeroEntries(xx);
4461 CHKERR TS2SetSolution(ts, x, xx);
4462 CHKERR VecDestroy(&xx);
4463 } else {
4464 CHKERR TSSetSolution(ts, x);
4465 }
4466
4467 TetPolynomialBase::switchCacheBaseOn<HDIV>(
4468 {elasticFeLhs.get(), elasticFeRhs.get()});
4469 CHKERR TSSetUp(ts);
4470 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
4471 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
4472 CHKERR TSElasticPostStep::postStepInitialise(this);
4473 CHKERR TSSolve(ts, PETSC_NULLPTR);
4474 CHKERR TSElasticPostStep::postStepDestroy();
4475 TetPolynomialBase::switchCacheBaseOff<HDIV>(
4476 {elasticFeLhs.get(), elasticFeRhs.get()});
4477
4478#ifndef NDEBUG
4479 // Make graph
4480 if (mField.get_comm_rank() == 0) {
4481 auto ts_ctx_ptr = getDMTsCtx(dmElastic);
4483 "solve_elastic_graph.dot");
4484 }
4485#endif
4486
4487 SNES snes;
4488 CHKERR TSGetSNES(ts, &snes);
4489 int lin_solver_iterations;
4490 CHKERR SNESGetLinearSolveIterations(snes, &lin_solver_iterations);
4491 MOFEM_LOG("EP", Sev::inform)
4492 << "Number of linear solver iterations " << lin_solver_iterations;
4493
4494 PetscBool test_cook_flg = PETSC_FALSE;
4495 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
4496 PETSC_NULLPTR);
4497 if (test_cook_flg) {
4498 PetscInt expected_lin_solver_iterations = 11;
4499 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "",
4500 "-test_cook_max_linear_iterations",
4501 &expected_lin_solver_iterations, PETSC_NULLPTR);
4502 if (lin_solver_iterations > expected_lin_solver_iterations)
4503 SETERRQ(
4504 PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4505 "Expected number of iterations is different than expected %d > %d",
4506 lin_solver_iterations, expected_lin_solver_iterations);
4507 }
4508
4509 PetscBool test_sslv116_flag = PETSC_FALSE;
4510 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_sslv116",
4511 &test_sslv116_flag, PETSC_NULLPTR);
4512
4513 if (test_sslv116_flag) {
4514 double max_val = 0.0;
4515 double min_val = 0.0;
4516 auto field_min_max = [&](boost::shared_ptr<FieldEntity> ent_ptr) {
4518 auto ent_type = ent_ptr->getEntType();
4519 if (ent_type == MBVERTEX) {
4520 max_val = std::max(ent_ptr->getEntFieldData()[SPACE_DIM - 1], max_val);
4521 min_val = std::min(ent_ptr->getEntFieldData()[SPACE_DIM - 1], min_val);
4522 }
4524 };
4525 CHKERR mField.getInterface<FieldBlas>()->fieldLambdaOnEntities(
4526 field_min_max, spatialH1Disp);
4527
4528 double global_max_val = 0.0;
4529 double global_min_val = 0.0;
4530 MPI_Allreduce(&max_val, &global_max_val, 1, MPI_DOUBLE, MPI_MAX,
4531 mField.get_comm());
4532 MPI_Allreduce(&min_val, &global_min_val, 1, MPI_DOUBLE, MPI_MIN,
4533 mField.get_comm());
4534 MOFEM_LOG("EP", Sev::inform)
4535 << "Max " << spatialH1Disp << " value: " << global_max_val;
4536 MOFEM_LOG("EP", Sev::inform)
4537 << "Min " << spatialH1Disp << " value: " << global_min_val;
4538
4539 double ref_max_val = 0.00767;
4540 double ref_min_val = -0.00329;
4541 if (std::abs(global_max_val - ref_max_val) > 1e-5) {
4542 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4543 "Incorrect max value of the displacement field: %f != %f",
4544 global_max_val, ref_max_val);
4545 }
4546 if (std::abs(global_min_val - ref_min_val) > 4e-5) {
4547 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
4548 "Incorrect min value of the displacement field: %f != %f",
4549 global_min_val, ref_min_val);
4550 }
4551 }
4552
4554
4556}
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
MoFEMErrorCode gettingNorms()
[Getting norms]
static MoFEMErrorCode writeTSGraphGraphviz(TsCtx *ts_ctx, std::string file_name)
TS graph to Graphviz file.

◆ solveIncrementalOptimizationTAO()

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

Solve the incremental constitutive optimization with TAO.

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 6607 of file EshelbianPlasticity.cpp.

6608 {
6610
6613 "-solver_type incremental_optimization currently supports "
6614 "-plastic_volume 1 and -cohesive_interface_on 0 only");
6616 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6620
6621 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6622 {elasticFeLhs.get(), elasticFeRhs.get()});
6623 CHKERR TSSetSolution(ts, x);
6624 CHKERR TSSetUp(ts);
6625 CHKERR TSElasticPostStep::postStepInitialise(this);
6626
6627 if (!(finalPhysicalTime > start_time))
6629 "Incremental-optimization final physical time %g must exceed "
6630 "the start time %g",
6631 finalPhysicalTime, start_time);
6632 if (!(physicalDt > 0.))
6634 "Incremental-optimization physical time step must be positive, "
6635 "got %g",
6636 physicalDt);
6637 if (physicalMaxSteps <= 0)
6639 "Incremental-optimization physical maximum steps must be "
6640 "positive, got %d",
6642
6643 PetscBool monitor_physical_steps = PETSC_TRUE;
6644 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "",
6645 "-incremental_optimization_step_monitor",
6646 &monitor_physical_steps, PETSC_NULLPTR);
6647 boost::shared_ptr<EshelbianMonitor> monitor_ptr;
6648 if (monitor_physical_steps)
6649 monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6650 auto monitor_committed_step = [&]() {
6652 if (!monitor_ptr)
6654 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6655 SCATTER_FORWARD);
6656 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6657 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6658 monitor_ptr->ts = PETSC_NULLPTR;
6659 monitor_ptr->ts_u = x;
6660 monitor_ptr->ts_t = currentPhysicalTime;
6661 monitor_ptr->ts_step = physicalStepNumber;
6664 };
6665 auto clear_incremental_control_fields = [&]() {
6667 // Preserve committed kappa in mesh storage. Only Delta H_p is a transient
6668 // post-processing field; Delta kappa exists solely in the TAO vector.
6669 CHKERR PlasticIncrementalOptimizationInternal::clearPlasticIncrementFields(
6670 *this);
6672 };
6673
6674 currentPhysicalTime = start_time;
6675 physicalStepNumber = start_step;
6676 // PlasticFlow is an increment-only post-processing field. A restart mesh
6677 // can contain the last accepted increment, which must not be reported as
6678 // the increment of the freshly initialized physical step.
6679 CHKERR clear_incremental_control_fields();
6680 CHKERR monitor_committed_step();
6681
6682 const double time_tolerance =
6683 10 * std::numeric_limits<double>::epsilon() *
6684 std::max({1., std::abs(start_time), std::abs(finalPhysicalTime)});
6685 int completed_steps = 0;
6686 while (currentPhysicalTime + time_tolerance < finalPhysicalTime &&
6687 completed_steps < physicalMaxSteps) {
6688 const double previous_time = currentPhysicalTime;
6690 std::min(previous_time + physicalDt, finalPhysicalTime);
6691 physicalStepNumber = start_step + completed_steps + 1;
6692
6693 MOFEM_LOG("EP", Sev::inform)
6694 << "Incremental-optimization load step " << physicalStepNumber
6695 << " time " << currentPhysicalTime << " delta time "
6696 << currentPhysicalTime - previous_time;
6697
6698 if (physicalH1Update) {
6699 CHKERR TSSetSolution(ts, x);
6700 CHKERR TSSetTime(ts, currentPhysicalTime);
6701 CHKERR TSElasticPostStep::preStepFun(ts);
6702 }
6703
6705
6706 if (physicalH1Update) {
6707 CHKERR TSSetSolution(ts, x);
6708 CHKERR TSSetTime(ts, currentPhysicalTime);
6709 CHKERR TSElasticPostStep::postStepFun(ts);
6710 }
6711
6712 const MoFEMErrorCode monitor_error = monitor_committed_step();
6713 const MoFEMErrorCode clear_control_error =
6714 clear_incremental_control_fields();
6715 CHKERR monitor_error;
6716 CHKERR clear_control_error;
6717 ++completed_steps;
6718 }
6719
6720 const bool reached_final_time =
6721 currentPhysicalTime + time_tolerance >= finalPhysicalTime;
6722
6723 CHKERR TSElasticPostStep::postStepDestroy();
6724 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6725 {elasticFeLhs.get(), elasticFeRhs.get()});
6726
6727 if (!reached_final_time)
6729 "Incremental optimization stopped at time %g after %d steps "
6730 "before final time %g; increase -physical_max_steps",
6731 currentPhysicalTime, completed_steps, finalPhysicalTime);
6732
6733 MOFEM_LOG("EP", Sev::inform)
6734 << "Incremental optimization completed " << completed_steps
6735 << " physical steps at time " << currentPhysicalTime;
6737}
MoFEMErrorCode validateEquilibratedMechanicalValueScope(EshelbianCore &ep)
MoFEMErrorCode applyTestSolverMonitorOptions(TS ts)
MoFEMErrorCode applyProjectionSolverMonitorOptions()
MoFEMErrorCode runIncrementalOptimizationTAO(TS ts, Vec x)

◆ 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 5968 of file EshelbianPlasticity.cpp.

5969 {
5971
5972 loadFactorTSSolveExecuted = PETSC_FALSE;
5973
5974 auto storage = solve_elastic_setup::setup(this, ts, x, false);
5975
5977
5978 auto setup_ts_monitor = [&]() {
5979 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
5980 return monitor_ptr;
5981 };
5982 auto monitor_ptr = setup_ts_monitor();
5983
5984 auto test_monitor_ptr =
5985 boost::make_shared<EshelbianTestingMonitor>(*this, monitor_ptr);
5986
5987 TetPolynomialBase::switchCacheBaseOn<HDIV>(
5988 {elasticFeLhs.get(), elasticFeRhs.get()});
5989 CHKERR TSSetUp(ts);
5990 CHKERR TSElasticPostStep::postStepInitialise(this);
5991
5992 double ts_delta_time;
5993 CHKERR TSGetTimeStep(ts, &ts_delta_time);
5994
5995 if (physicalH1Update) {
5996 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
5997 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
5998 }
5999
6000 CHKERR TSElasticPostStep::preStepFun(ts);
6001 CHKERR TSElasticPostStep::postStepFun(ts);
6002
6003 double load_factor_change_clip = 0.1;
6004
6005 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Load Factor Options", "none");
6006
6007 CHKERR PetscOptionsScalar("-initial_load_factor", "Initial load factor", "",
6008 loadFactor, &loadFactor, PETSC_NULLPTR);
6009 CHKERR PetscOptionsScalar(
6010 "-max_crack_ext_area", "Maximum crack extension area", "",
6011 maxCrackExtension, &maxCrackExtension, PETSC_NULLPTR);
6012 CHKERR PetscOptionsScalar(
6013 "-clip_load_factor_percent", "Upper bound for load factor change", "",
6014 load_factor_change_clip, &load_factor_change_clip, PETSC_NULLPTR);
6015 PetscOptionsEnd();
6016
6018 physicalStepNumber = start_step;
6019 double initial_dt = physicalDt;
6020 monitor_ptr->ts = ts;
6021 monitor_ptr->ts_u = PETSC_NULLPTR;
6022 monitor_ptr->ts_t = currentPhysicalTime;
6023 monitor_ptr->ts_step = physicalStepNumber;
6025
6026 PetscBool test_cook_flg = PETSC_FALSE;
6027 PetscInt atom_test = 0;
6028 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-test_cook", &test_cook_flg,
6029 PETSC_NULLPTR);
6030 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-atom_test", &atom_test,
6031 PETSC_NULLPTR);
6032 if (atom_test || test_cook_flg) {
6033 test_monitor_ptr->ts = ts;
6034 test_monitor_ptr->ts_u = PETSC_NULLPTR;
6035 test_monitor_ptr->ts_t = currentPhysicalTime;
6036 test_monitor_ptr->ts_step = physicalStepNumber;
6037
6039 test_monitor_ptr);
6040 }
6041
6042 MOFEM_LOG("EP", Sev::inform)
6043 << "Initial crack area: " << *currentCrackAreaPtr;
6044 MOFEM_LOG("EP", Sev::inform) << "Initial load factor: " << loadFactor;
6045 MOFEM_LOG("EP", Sev::inform)
6046 << "Initial crack front energy: " << avgGriffithsEnergy;
6047
6048 double load_factor_modifier = 1.0;
6049
6051 MOFEM_LOG("EP", Sev::inform)
6052 << "Load step " << physicalStepNumber << " Load Factor "
6053 << currentPhysicalTime << " delta load factor " << physicalDt;
6054
6058
6059 CHKERR TSSetStepNumber(ts, 0);
6060 CHKERR TSSetTime(ts, 0);
6061 CHKERR TSSetTimeStep(ts, ts_delta_time);
6062 if (!physicalH1Update) {
6063 CHKERR TSElasticPostStep::preStepFun(ts);
6064 }
6065 CHKERR TSSetSolution(ts, x);
6066 CHKERR TSSolve(ts, PETSC_NULLPTR);
6067 loadFactorTSSolveExecuted = PETSC_TRUE;
6068 if (!physicalH1Update) {
6069 CHKERR TSElasticPostStep::postStepFun(ts);
6070 }
6071
6072 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6073 SCATTER_FORWARD);
6074 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6075 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6076
6077 monitor_ptr->ts = ts;
6078 monitor_ptr->ts_u = x;
6079 monitor_ptr->ts_t = currentPhysicalTime;
6080 monitor_ptr->ts_step = physicalStepNumber;
6082
6083 if (atom_test || test_cook_flg) {
6084 test_monitor_ptr->ts = ts;
6085 test_monitor_ptr->ts_u = x;
6086 test_monitor_ptr->ts_t = currentPhysicalTime;
6087 test_monitor_ptr->ts_step = physicalStepNumber;
6089 test_monitor_ptr);
6090 }
6091
6092 if (mField.get_comm_rank() == 0) {
6093
6094 auto update_load_factor_modifier = [&](auto reason) {
6095 if (nbStepsNoCrackExtension > 1) {
6096 MOFEM_LOG("EP", Sev::warning)
6097 << reason << " for " << nbStepsNoCrackExtension
6098 << " consecutive steps. Increasing load factor range to allow "
6099 "for larger increments.";
6100 load_factor_modifier += 1.0;
6101 } else {
6102 load_factor_modifier = 1.0;
6103 }
6104 };
6105
6106 const bool crack_arrest_stops =
6108 update_load_factor_modifier(crack_arrest_stops
6109 ? "Potential crack arrest"
6110 : "No cracking occured");
6111
6112 if (crack_arrest_stops) {
6113 physicalDt = initial_dt * load_factor_modifier;
6115 MOFEM_LOG("EP", Sev::warning)
6116 << "Potential crack arrest detected. Increasing load factor by "
6117 << physicalDt << " to: " << loadFactor;
6118 } else {
6119 const double denom = 0.5 * std::abs(avgGriffithsEnergy);
6120 if (denom > 0.0) {
6121 const double updated_load_factor =
6122 oldLoadFactor * std::sqrt(griffithEnergy / denom);
6123 loadFactor = std::max(updated_load_factor, 1.0e-6);
6124 } else {
6125 MOFEM_LOG("EP", Sev::warning)
6126 << "Griffith energy is zero, cannot update load factor.";
6127 }
6128
6129 // Clip load factor.
6130 const bool is_first_step = physicalStepNumber == start_step;
6131 const double initial_step_range = 0;
6132 const double min_load_factor = 1.0e-6;
6133 const double max_load_factor =
6135 (1.0 + load_factor_change_clip * load_factor_modifier);
6136
6137 if (physicalStepNumber >= start_step + initial_step_range) {
6138 loadFactor = std::clamp(loadFactor, min_load_factor, max_load_factor);
6139 MOFEM_LOG("EP", Sev::inform)
6140 << "Allowable range for load factor [" << min_load_factor << ", "
6141 << max_load_factor << "]";
6142 }
6143
6144 // update load factor increment for next step
6146 }
6147
6148 MOFEM_LOG("EP", Sev::inform)
6149 << "Setting new load factor to: " << loadFactor;
6150 }
6151 double load_control_data[] = {physicalDt, loadFactor};
6152 CHKERR MPI_Bcast(load_control_data, 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
6153 physicalDt = load_control_data[0];
6154 loadFactor = load_control_data[1];
6155
6158 break;
6159
6160 const double remainingPhysicalTime =
6162 if (physicalDt >= remainingPhysicalTime) {
6164 } else {
6166 }
6167 }
6168
6169 CHKERR TSElasticPostStep::postStepDestroy();
6170 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6171 {elasticFeLhs.get(), elasticFeRhs.get()});
6172 MOFEM_LOG("EP", Sev::inform) << "Final load factor: " << loadFactor;
6173
6175}
PetscBool loadFactorTSSolveExecuted
static double maxCrackExtension
static int nbStepsNoCrackExtension
boost::shared_ptr< double > currentCrackAreaPtr
int atom_test
Atom test.
Definition plastic.cpp:121

◆ 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 6177 of file EshelbianPlasticity.cpp.

6179 {
6181
6182 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6183
6184 auto topological_tao_ctx = createTopologicalTAOCtx(
6185 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6186 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6187 SmartPetscObj<TS>(ts, true));
6188
6189 double final_time = 1;
6190 double delta_time = 0.1;
6191 int max_it = 10;
6192 PetscBool ts_h1_update = PETSC_FALSE;
6193
6194 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Dynamic Relaxation Options", "none");
6195
6196 CHKERR PetscOptionsScalar("-dynamic_final_time",
6197 "dynamic relaxation final time", "", final_time,
6198 &final_time, PETSC_NULLPTR);
6199 CHKERR PetscOptionsScalar("-dynamic_delta_time",
6200 "dynamic relaxation final time", "", delta_time,
6201 &delta_time, PETSC_NULLPTR);
6202 CHKERR PetscOptionsInt("-dynamic_max_it", "dynamic relaxation iterations", "",
6203 max_it, &max_it, PETSC_NULLPTR);
6204 CHKERR PetscOptionsBool("-dynamic_h1_update", "update each ts step", "",
6205 ts_h1_update, &ts_h1_update, PETSC_NULLPTR);
6206
6207 PetscOptionsEnd();
6208
6209 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6210 MOFEM_LOG("EP", Sev::inform)
6211 << "Dynamic relaxation final time -dynamic_final_time = " << final_time;
6212 MOFEM_LOG("EP", Sev::inform)
6213 << "Dynamic relaxation delta time -dynamic_delta_time = " << delta_time;
6214 MOFEM_LOG("EP", Sev::inform)
6215 << "Dynamic relaxation max iterations -dynamic_max_it = " << max_it;
6216 MOFEM_LOG("EP", Sev::inform)
6217 << "Dynamic relaxation H1 update each step -dynamic_h1_update = "
6218 << (ts_h1_update ? "TRUE" : "FALSE");
6219
6221
6222 auto setup_ts_monitor = [&]() {
6223 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6224 return monitor_ptr;
6225 };
6226 auto monitor_ptr = setup_ts_monitor();
6227
6228 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6229 {elasticFeLhs.get(), elasticFeRhs.get()});
6230 CHKERR TSSetUp(ts);
6231 CHKERR TSElasticPostStep::postStepInitialise(this);
6232
6233 double ts_delta_time;
6234 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6235
6236 if (ts_h1_update) {
6237 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6238 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6239 }
6240
6241 CHKERR TSElasticPostStep::preStepFun(ts);
6242 CHKERR TSElasticPostStep::postStepFun(ts);
6243
6244 auto tao = createTao(mField.get_comm());
6245 CHKERR TaoSetType(tao, TAOLMVM);
6248 topologicalEvaluateObjectiveAndGradient,
6249 (void *)topological_tao_ctx.get());
6250
6251 currentPhysicalTime = start_time;
6252 physicalStepNumber = start_step;
6253 monitor_ptr->ts = PETSC_NULLPTR;
6254 monitor_ptr->ts_u = PETSC_NULLPTR;
6255 monitor_ptr->ts_t = currentPhysicalTime;
6256 monitor_ptr->ts_step = physicalStepNumber;
6258
6259 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6260 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6261 SCATTER_FORWARD, RowColData::ROW);
6262 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6263 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6264
6265 int tao_sol_size, tao_sol_loc_size;
6266 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6267 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6268 MOFEM_LOG("EP", Sev::inform)
6269 << "Toplogical data vector size " << tao_sol_size << " local size "
6270 << tao_sol_loc_size << " number of interface faces "
6271 << interfaceFaces->size();
6272
6273 CHKERR TaoSetFromOptions(tao);
6274
6275 if (delta_time <= 0.) {
6277 "delta_time must be positive, got %g", delta_time);
6278 }
6279 for (; currentPhysicalTime < final_time;) {
6280 MOFEM_LOG("EP", Sev::inform)
6281 << "Load step " << physicalStepNumber << " Time " << currentPhysicalTime
6282 << " delta time " << delta_time;
6283
6284 CHKERR VecZeroEntries(tao_sol0);
6285 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6286 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6287 CHKERR TaoSetSolution(tao, tao_sol0);
6288 CHKERR TaoSolve(tao);
6289 Vec tao_sol;
6290 CHKERR TaoGetSolution(tao, &tao_sol);
6291
6292 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES,
6293 SCATTER_FORWARD);
6294 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6295 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6296 monitor_ptr->ts = PETSC_NULLPTR;
6297 monitor_ptr->ts_u = x;
6298 monitor_ptr->ts_t = currentPhysicalTime;
6299 monitor_ptr->ts_step = physicalStepNumber;
6301
6303 if (physicalStepNumber > max_it)
6304 break;
6305
6306 const double remainingPhysicalTime = final_time - currentPhysicalTime;
6307 if (delta_time >= remainingPhysicalTime) {
6308 currentPhysicalTime = final_time;
6309 } else {
6310 currentPhysicalTime += delta_time;
6311 }
6312 }
6313
6314 CHKERR TSElasticPostStep::postStepDestroy();
6315 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6316 {elasticFeLhs.get(), elasticFeRhs.get()});
6317
6319}
boost::shared_ptr< TopologicalTAOCtx > createTopologicalTAOCtx(EshelbianCore *ep, ForcesAndSourcesCore::GaussHookFun set_integration_at_interior, ForcesAndSourcesCore::GaussHookFun set_integration_at_face, SmartPetscObj< TS > time_solver)
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)

◆ solveTestEquilibratedMechanicalValue()

MoFEMErrorCode EshelbianCore::solveTestEquilibratedMechanicalValue ( 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 6445 of file EshelbianPlasticity.cpp.

6446 {
6448
6451 "The equilibrated mechanical value test requires "
6452 "-plastic_volume 1 and -cohesive_interface_on 0");
6454
6455 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6459
6460 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6461 {elasticFeLhs.get(), elasticFeRhs.get()});
6462 CHKERR TSSetSolution(ts, x);
6463 CHKERR TSSetUp(ts);
6464 CHKERR TSElasticPostStep::postStepInitialise(this);
6465
6466 const bool restart_run =
6467 start_step != 0 ||
6468 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6469 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6470 if (std::abs(currentPhysicalTime) < std::numeric_limits<double>::epsilon())
6472 "Set non-zero -physical_final_time for "
6473 "test_equilibrated_mechanical_value");
6474 physicalStepNumber = start_step;
6475
6477
6478 CHKERR TSElasticPostStep::postStepDestroy();
6479 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6480 {elasticFeLhs.get(), elasticFeRhs.get()});
6481
6483}
MoFEMErrorCode testEquilibratedMechanicalValue(EshelbianCore &ep, TS ts, Vec state)

◆ solveTestIncrementalOptimizationConstraintDerivative()

MoFEMErrorCode EshelbianCore::solveTestIncrementalOptimizationConstraintDerivative ( 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 6567 of file EshelbianPlasticity.cpp.

6568 {
6570
6573 "The incremental-optimization constraint derivative test "
6574 "requires -plastic_volume 1 and -cohesive_interface_on 0");
6576
6577 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6581
6582 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6583 {elasticFeLhs.get(), elasticFeRhs.get()});
6584 CHKERR TSSetSolution(ts, x);
6585 CHKERR TSSetUp(ts);
6586 CHKERR TSElasticPostStep::postStepInitialise(this);
6587
6588 const bool restart_run =
6589 start_step != 0 ||
6590 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6591 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6592 if (std::abs(currentPhysicalTime) <
6593 std::numeric_limits<double>::epsilon())
6595 "Set non-zero -physical_final_time for "
6596 "test_incremental_optimization_constraint_derivative");
6597 physicalStepNumber = start_step;
6598
6600
6601 CHKERR TSElasticPostStep::postStepDestroy();
6602 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6603 {elasticFeLhs.get(), elasticFeRhs.get()});
6605}
MoFEMErrorCode testIncrementalOptimizationConstraintDerivative(EshelbianCore &ep, TS ts, Vec state)

◆ solveTestIncrementalOptimizationLayout()

MoFEMErrorCode EshelbianCore::solveTestIncrementalOptimizationLayout ( TS  ts,
Vec  x,
int  start_step,
double  start_time 
)
Examples
ep.cpp, and mofem/users_modules/eshelbian_plasticity/ep.cpp.

Definition at line 2334 of file PlasticIncrementalOptimizationTests.cpp.

2337 {
2338 return testIncrementalOptimizationLayout(*this, ts, state);
2339}
MoFEMErrorCode testIncrementalOptimizationLayout(EshelbianCore &ep, TS ts, Vec state)

◆ solveTestIncrementalOptimizationObjectiveDerivative()

MoFEMErrorCode EshelbianCore::solveTestIncrementalOptimizationObjectiveDerivative ( 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 6526 of file EshelbianPlasticity.cpp.

6527 {
6529
6532 "The incremental-optimization derivative test currently requires "
6533 "-plastic_volume 1 and -cohesive_interface_on 0");
6535
6536 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6540
6541 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6542 {elasticFeLhs.get(), elasticFeRhs.get()});
6543 CHKERR TSSetSolution(ts, x);
6544 CHKERR TSSetUp(ts);
6545 CHKERR TSElasticPostStep::postStepInitialise(this);
6546
6547 const bool restart_run =
6548 start_step != 0 ||
6549 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6550 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6551 if (std::abs(currentPhysicalTime) <
6552 std::numeric_limits<double>::epsilon())
6554 "Set non-zero -physical_final_time for "
6555 "test_incremental_optimization_objective_derivative");
6556 physicalStepNumber = start_step;
6557
6559
6560 CHKERR TSElasticPostStep::postStepDestroy();
6561 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6562 {elasticFeLhs.get(), elasticFeRhs.get()});
6564}
MoFEMErrorCode testIncrementalOptimizationObjectiveDerivative(EshelbianCore &ep, TS ts, Vec state)

◆ solveTestIncrementalOptimizationTransaction()

MoFEMErrorCode EshelbianCore::solveTestIncrementalOptimizationTransaction ( 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 6486 of file EshelbianPlasticity.cpp.

6487 {
6489
6492 "The incremental-optimization transaction test currently requires "
6493 "-plastic_volume 1 and -cohesive_interface_on 0");
6495
6496 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6500
6501 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6502 {elasticFeLhs.get(), elasticFeRhs.get()});
6503 CHKERR TSSetSolution(ts, x);
6504 CHKERR TSSetUp(ts);
6505 CHKERR TSElasticPostStep::postStepInitialise(this);
6506
6507 const bool restart_run =
6508 start_step != 0 ||
6509 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6510 currentPhysicalTime = restart_run ? start_time : finalPhysicalTime;
6511 if (std::abs(currentPhysicalTime) < std::numeric_limits<double>::epsilon())
6513 "Set non-zero -physical_final_time for "
6514 "test_incremental_optimization_transaction");
6515 physicalStepNumber = start_step;
6516
6518
6519 CHKERR TSElasticPostStep::postStepDestroy();
6520 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6521 {elasticFeLhs.get(), elasticFeRhs.get()});
6523}
MoFEMErrorCode testIncrementalOptimizationTransaction(EshelbianCore &ep, TS ts, Vec state)

◆ 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 6322 of file EshelbianPlasticity.cpp.

6323 {
6325
6326 auto storage = solve_elastic_setup::setup(this, ts, x, false);
6329
6330 auto topological_tao_ctx = createTopologicalTAOCtx(
6331 this, SetIntegrationAtFrontVolume(frontVertices, frontAdjEdges),
6332 SetIntegrationAtFrontFace(frontVertices, frontAdjEdges),
6333 SmartPetscObj<TS>(ts, true));
6334
6335 EshelbianCore::physicalTimeFlg = PETSC_TRUE;
6337
6338 auto monitor_ptr = boost::make_shared<EshelbianMonitor>(*this);
6339
6340 TetPolynomialBase::switchCacheBaseOn<HDIV>(
6341 {elasticFeLhs.get(), elasticFeRhs.get()});
6342 CHKERR TSSetUp(ts);
6343 CHKERR TSElasticPostStep::postStepInitialise(this);
6344
6345 double ts_delta_time;
6346 CHKERR TSGetTimeStep(ts, &ts_delta_time);
6347
6348 if (physicalH1Update) {
6349 CHKERR TSSetPreStep(ts, TSElasticPostStep::preStepFun);
6350 CHKERR TSSetPostStep(ts, TSElasticPostStep::postStepFun);
6351 }
6352
6353 CHKERR TSElasticPostStep::preStepFun(ts);
6354 CHKERR TSElasticPostStep::postStepFun(ts);
6355
6356 const bool restart_run =
6357 start_step != 0 ||
6358 std::abs(start_time) > std::numeric_limits<double>::epsilon();
6359 const double test_time = restart_run ? start_time : finalPhysicalTime;
6360 if (!restart_run &&
6361 std::abs(test_time) < std::numeric_limits<double>::epsilon()) {
6362 SETERRQ(
6364 "Set non-zero -physical_final_time for test_topological_derivative");
6365 }
6366
6367 currentPhysicalTime = test_time;
6368 physicalStepNumber = start_step;
6369 monitor_ptr->ts = PETSC_NULLPTR;
6370 monitor_ptr->ts_u = PETSC_NULLPTR;
6371 monitor_ptr->ts_t = currentPhysicalTime;
6372 monitor_ptr->ts_step = physicalStepNumber;
6374
6375 MOFEM_LOG("EP", Sev::inform)
6376 << "Solving load step before topological derivative test: "
6377 << physicalStepNumber << " Time " << currentPhysicalTime
6378 << " TS delta time " << ts_delta_time;
6379
6380 CHKERR TSSetStepNumber(ts, 0);
6381 CHKERR TSSetTime(ts, 0);
6382 CHKERR TSSetTimeStep(ts, ts_delta_time);
6383 if (!physicalH1Update) {
6384 CHKERR TSElasticPostStep::preStepFun(ts);
6385 }
6386 CHKERR TSSetSolution(ts, x);
6387 CHKERR TSSolve(ts, PETSC_NULLPTR);
6388 if (!physicalH1Update) {
6389 CHKERR TSElasticPostStep::postStepFun(ts);
6390 }
6391
6392 CHKERR DMoFEMMeshToLocalVector(dmElastic, x, INSERT_VALUES, SCATTER_FORWARD);
6393 CHKERR VecGhostUpdateBegin(x, INSERT_VALUES, SCATTER_FORWARD);
6394 CHKERR VecGhostUpdateEnd(x, INSERT_VALUES, SCATTER_FORWARD);
6395
6396 monitor_ptr->ts = PETSC_NULLPTR;
6397 monitor_ptr->ts_u = x;
6398 monitor_ptr->ts_t = currentPhysicalTime;
6399 monitor_ptr->ts_step = physicalStepNumber;
6401
6402 auto tao_sol0 = createDMVector(dmMaterial, RowColData::ROW);
6403 CHKERR DMoFEMMeshToLocalVector(dmMaterial, tao_sol0, INSERT_VALUES,
6404 SCATTER_FORWARD, RowColData::ROW);
6405 CHKERR VecGhostUpdateBegin(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6406 CHKERR VecGhostUpdateEnd(tao_sol0, INSERT_VALUES, SCATTER_FORWARD);
6407
6408 int tao_sol_size, tao_sol_loc_size;
6409 CHKERR VecGetSize(tao_sol0, &tao_sol_size);
6410 CHKERR VecGetLocalSize(tao_sol0, &tao_sol_loc_size);
6411 MOFEM_LOG("EP", Sev::inform)
6412 << "Topological data vector size " << tao_sol_size << " local size "
6413 << tao_sol_loc_size << " number of interface faces "
6414 << interfaceFaces->size();
6415
6416 const char *list_objective_models[ObjectiveModelType::LAST_MODEL] = {
6417 "python_model", "hencky_model"};
6418#ifdef ENABLE_PYTHON_BINDING
6419 PetscInt choice_objective_model = ObjectiveModelType::PYTHON_MODEL;
6420#else
6421 PetscInt choice_objective_model = ObjectiveModelType::HENCKY_MODEL;
6422#endif
6423 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, PETSC_NULLPTR,
6424 "-objective_model_type", list_objective_models,
6425 ObjectiveModelType::LAST_MODEL,
6426 &choice_objective_model, PETSC_NULLPTR);
6427 const auto objective_model_type =
6428 static_cast<ObjectiveModelType>(choice_objective_model);
6429 MOFEM_LOG("EP", Sev::inform) << "Objective model type: -objective_model_type "
6430 << list_objective_models[objective_model_type];
6431
6433 PetscReal obj_value;
6434 CHKERR testTopologicalDerivative(topological_tao_ctx.get(), tao_sol0,
6435 &obj_value, g, objective_model_type);
6436
6437 CHKERR TSElasticPostStep::postStepDestroy();
6438 TetPolynomialBase::switchCacheBaseOff<HDIV>(
6439 {elasticFeLhs.get(), elasticFeRhs.get()});
6440
6442}
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 112 of file EshelbianCore.hpp.

112 {
116 CHKERR op.template operator()<DEMKOWICZ_JACOBI_BASE>();
117 break;
119 CHKERR op.template operator()<AINSWORTH_LEGENDRE_BASE>();
120 break;
121 default:
123 "Broken HDIV base not implemented");
124 }
126 }

Member Data Documentation

◆ a00FieldList

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

Definition at line 647 of file EshelbianCore.hpp.

◆ a00RangeList

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

Definition at line 649 of file EshelbianCore.hpp.

◆ addCrackMeshsetId

int EshelbianCore::addCrackMeshsetId = 1000
inlinestatic

Definition at line 75 of file EshelbianCore.hpp.

◆ alphaOmega

double EshelbianCore::alphaOmega = 0

◆ alphaR

double EshelbianCore::alphaR = 0

◆ alphaRho

double EshelbianCore::alphaRho = 0

◆ alphaTau

double EshelbianCore::alphaTau = 0

◆ alphaTauBcDisp

double EshelbianCore::alphaTauBcDisp = 0

◆ alphaTauBcDisp0

double EshelbianCore::alphaTauBcDisp0 = 0

Definition at line 278 of file EshelbianCore.hpp.

◆ alphaTauLin

double EshelbianCore::alphaTauLin = 0

◆ alphaU

double EshelbianCore::alphaU = 0

◆ alphaViscousOmega

double EshelbianCore::alphaViscousOmega = 0

◆ alphaViscousR

double EshelbianCore::alphaViscousR = 0

◆ alphaW

double EshelbianCore::alphaW = 0

◆ AnalyticalExprPythonPtr

boost::shared_ptr<AnalyticalExprPython> EshelbianCore::AnalyticalExprPythonPtr

◆ aoS

AO EshelbianCore::aoS = PETSC_NULLPTR

Definition at line 645 of file EshelbianCore.hpp.

◆ auxiliaryLogStress

const std::string EshelbianCore::auxiliaryLogStress = "Td"

Definition at line 249 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

◆ bcSpatialSpringVecPtr

boost::shared_ptr<SpringBcVec> EshelbianCore::bcSpatialSpringVecPtr

◆ 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 630 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 627 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 646 of file EshelbianCore.hpp.

◆ crackingAddTime

double EshelbianCore::crackingAddTime = 0
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 = 0
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

◆ dmIncrementalOptimization

SmartPetscObj<DM> EshelbianCore::dmIncrementalOptimization

◆ dmMaterial

SmartPetscObj<DM> EshelbianCore::dmMaterial

◆ dmPrjSpatial

SmartPetscObj<DM> EshelbianCore::dmPrjSpatial

◆ dynamicAtol

double EshelbianCore::dynamicAtol = 0

◆ dynamicInitialResidual

double EshelbianCore::dynamicInitialResidual = -1

◆ dynamicRtol

double EshelbianCore::dynamicRtol = 0

◆ 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

◆ 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
inlinestatic

◆ frontAdjEdges

boost::shared_ptr<Range> EshelbianCore::frontAdjEdges

◆ frontEdges

boost::shared_ptr<Range> EshelbianCore::frontEdges

◆ frontLayers

int EshelbianCore::frontLayers = 3

Definition at line 284 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

◆ heterogeneousYoungModTagName

std::string EshelbianCore::heterogeneousYoungModTagName
inlinestatic

◆ hybridSpatialDisp

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

◆ incrementalTrialControl

SmartPetscObj<Vec> EshelbianCore::incrementalTrialControl

◆ 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",
"incremental_optimization",
"load_factor",
"shape_optimization",
"test_topological_derivative",
"test_equilibrated_mechanical_value",
"test_incremental_optimization_layout",
"test_incremental_optimization_transaction",
"test_incremental_optimization_objective_derivative",
"test_incremental_optimization_constraint_derivative"}
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 EshelbianCore.hpp.

14 {
15 "time_solver",
16 "dynamic_relaxation",
17 "incremental_optimization",
18 "load_factor",
19 "shape_optimization",
20 "test_topological_derivative",
21 "test_equilibrated_mechanical_value",
22 "test_incremental_optimization_layout",
23 "test_incremental_optimization_transaction",
24 "test_incremental_optimization_objective_derivative",
25 "test_incremental_optimization_constraint_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

◆ logDeviator

const std::string EshelbianCore::logDeviator = "D"

Definition at line 247 of file EshelbianCore.hpp.

◆ logJacobian

const std::string EshelbianCore::logJacobian = "theta"

Definition at line 248 of file EshelbianCore.hpp.

◆ materialH1Order

int EshelbianCore::materialH1Order = 1

◆ materialH1Positions

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

◆ maxCrackExtension

double EshelbianCore::maxCrackExtension
inlinestatic

◆ maxMovedFaces

boost::shared_ptr<Range> EshelbianCore::maxMovedFaces

Definition at line 619 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 651 of file EshelbianCore.hpp.

◆ nbJIntegralContours

int EshelbianCore::nbJIntegralContours
inlinestatic

◆ nbStepsNoCrackExtension

int EshelbianCore::nbStepsNoCrackExtension
inlinestatic

◆ noCrackExtension

bool EshelbianCore::noCrackExtension = false
inlinestatic

Definition at line 57 of file EshelbianCore.hpp.

◆ 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
inlinestatic

◆ physicalStepNumber

int EshelbianCore::physicalStepNumber = 0
inlinestatic

◆ physicalTimeFlg

PetscBool EshelbianCore::physicalTimeFlg
inlinestatic

◆ piolaStress

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

◆ plasticFlowField

const std::string EshelbianCore::plasticFlowField = "plasticFlow"

◆ plasticHField

const std::string EshelbianCore::plasticHField = "plasticH"

◆ plasticKappaField

const std::string EshelbianCore::plasticKappaField = "plasticKappa"

◆ plasticVolume

PetscBool EshelbianCore::plasticVolume
inlinestatic

◆ plasticVolumes

boost::shared_ptr<Range> EshelbianCore::plasticVolumes

◆ potentialCrackArrest

bool EshelbianCore::potentialCrackArrest
inlinestatic

◆ propagateUnderCompression

PetscBool EshelbianCore::propagateUnderCompression
inlinestatic

◆ rotAxis

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

◆ rotSelector

enum RotSelector EshelbianCore::rotSelector = LARGE_ROT
inlinestatic

◆ S

Mat EshelbianCore::S = PETSC_NULLPTR

Definition at line 644 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.

◆ stretchSelector

enum StretchSelector EshelbianCore::stretchSelector = LOG
inlinestatic

◆ stretchTensor

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

Definition at line 246 of file EshelbianCore.hpp.

◆ symmetrySelector

constexpr enum SymmetrySelector EshelbianCore::symmetrySelector = SYMMETRIC
inlinestaticconstexpr

◆ timeScaleMap

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

◆ v_max

constexpr double EshelbianCore::v_max = 24
inlinestaticconstexpr

Definition at line 138 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: