v0.16.3
Loading...
Searching...
No Matches
TSElasticPostStep.cpp
Go to the documentation of this file.
1/** @file TSElasticPostStep.cpp
2 * @brief
3 * @date 2023-05-13
4 *
5 * @license{This project is released under the MIT License.}
6 *
7 */
8
9#define SINGULARITY
10#include <MoFEM.hpp>
11using namespace MoFEM;
12
14
15#include <boost/math/constants/constants.hpp>
16#include <boost/math/special_functions/lambert_w.hpp>
17
18#include <TSElasticPostStep.hpp>
19
20namespace EshelbianPlasticity {
21
22namespace {
23
24MoFEMErrorCode resetIncrementalKinematics(EshelbianCore *ep_ptr,
25 Vec solution) {
27
28 auto zero_field = [&](const std::string &field_name) {
30 auto is_mng = ep_ptr->mField.getInterface<ISManager>();
32 CHKERR is_mng->isCreateProblemFieldAndRankLocal(
33 "ELASTIC_PROBLEM", ROW, field_name, 0, MAX_DOFS_ON_ENTITY, is);
34 const int *index_ptr;
35 CHKERR ISGetIndices(is, &index_ptr);
36 int size;
37 CHKERR ISGetLocalSize(is, &size);
38 double *array;
39 CHKERR VecGetArray(solution, &array);
40 for (int ii = 0; ii != size; ++ii) {
41 array[index_ptr[ii]] = 0;
42 }
43 CHKERR VecRestoreArray(solution, &array);
44 CHKERR ISRestoreIndices(is, &index_ptr);
46 };
47
50 break;
51 case LARGE_ROT:
52 case MODERATE_ROT:
53 case SMALL_ROT:
54 MOFEM_LOG("EP", Sev::verbose)
55 << "Resetting incremental stretch and rotation after H1 transfer";
56 CHKERR zero_field(ep_ptr->stretchTensor);
57 CHKERR zero_field(ep_ptr->rotAxis);
58 CHKERR VecGhostUpdateBegin(solution, INSERT_VALUES, SCATTER_FORWARD);
59 CHKERR VecGhostUpdateEnd(solution, INSERT_VALUES, SCATTER_FORWARD);
60 break;
61 }
62
64}
65
66} // namespace
67
70
71 epPtr = ep_ptr;
72
73 auto create_post_step_ksp = [&]() {
74 auto ksp = createKSP(epPtr->mField.get_comm());
75
76 auto set_up = [&]() {
79 using DomainEleOp = DomainEle::UserDataOperator;
83 GAUSS>::OpBaseTimesVector<1, 3, 3>;
84 auto fe_lhs = boost::make_shared<DomainEle>(ep_ptr->mField);
85 auto fe_rhs = boost::make_shared<DomainEle>(ep_ptr->mField);
86
87 fe_lhs->getUserPolynomialBase() = boost::shared_ptr<BaseFunction>(
88 new CGGUserPolynomialBase(nullptr, true));
89 fe_rhs->getUserPolynomialBase() = boost::shared_ptr<BaseFunction>(
90 new CGGUserPolynomialBase(nullptr, true));
91 CHKERR
92 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
93 fe_lhs->getOpPtrVector(), {L2}, ep_ptr->materialH1Positions,
94 ep_ptr->frontAdjEdges);
95 CHKERR
96 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
97 fe_rhs->getOpPtrVector(), {L2}, ep_ptr->materialH1Positions,
98 ep_ptr->frontAdjEdges);
99
100 fe_lhs->getOpPtrVector().push_back(
101 new OpDomainMass(ep_ptr->spatialH1Disp, ep_ptr->spatialH1Disp));
102 auto w_ptr = boost::make_shared<MatrixDouble>();
103 fe_rhs->getOpPtrVector().push_back(
105 fe_rhs->getOpPtrVector().push_back(
106 new OpRhs(ep_ptr->spatialH1Disp, w_ptr));
107
109 ep_ptr->elementVolumeName, fe_lhs,
110 nullptr, nullptr);
112 ep_ptr->elementVolumeName, fe_rhs, nullptr,
113 nullptr);
114
115 // preProcRhs = boost::make_shared<FEMethod>();
116 // struct MinusOne : public ScalingMethod {
117 // double getScale(const double time) { return -time; }
118 // };
119 // preProcRhs->preProcessHook = EssentialPreProc<DisplacementCubitBcData>(
120 // ep_ptr->mField, preProcRhs, {boost::make_shared<MinusOne>()});
121
122 CHKERR KSPAppendOptionsPrefix(ksp, "prjspatial_");
123 CHKERR KSPSetFromOptions(ksp);
124 CHKERR KSPSetDM(ksp, ep_ptr->dmPrjSpatial);
125 CHKERR KSPSetUp(ksp);
127 };
128
129 CHK_THROW_MESSAGE(set_up(), "set up");
130
131 return ksp;
132 };
133
134 prjKsp = create_post_step_ksp();
137 prjDM = ep_ptr->dmPrjSpatial;
138
140};
141
144 prjKsp.reset();
145 prjD.reset();
146 prjF.reset();
147 prjDM.reset();
148 preProcRhs.reset();
150};
151
154 MOFEM_LOG("EP", Sev::inform) << "Pre step";
155
156 double time;
157 CHKERR TSGetTime(ts, &time);
158
160
161 auto debug_crack = [&]() {
163
164 PetscBool debug_crack_mesh = PETSC_FALSE;
165 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-debug_crack_mesh",
166 &debug_crack_mesh, PETSC_NULLPTR);
167 if (debug_crack_mesh) {
168
169 auto append_meshsets_from_block = [](MoFEM::Interface &m_field,
170 const std::string &block_name,
171 const int dim,
172 std::vector<EntityHandle> &r) {
174 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
175 auto bcs = mesh_mng->getCubitMeshsetPtr(
176
177 std::regex((boost::format("%s(.*)") % block_name).str())
178
179 );
180
181 for (auto bc : bcs) {
182 Range ents;
183 CHKERR m_field.get_moab().get_entities_by_dimension(
184 bc->getMeshset(), dim, ents, true);
185 if (!ents.empty()) {
186 r.push_back(bc->getMeshset());
187 }
188 }
189
191 };
192
193 if (!epPtr->mField.get_comm_rank() &&
195 if (epPtr->maxMovedFaces) {
197 ->addEntitiesToMeshset(BLOCKSET, epPtr->addCrackMeshsetId,
199 }
200
201 auto meshset_ptr = get_temp_meshset_ptr(epPtr->mField.get_moab());
202 Range tets;
203 CHKERR epPtr->mField.get_moab().get_entities_by_dimension(
204 *meshset_ptr, 3, tets);
205 CHKERR epPtr->mField.get_moab().add_entities(*meshset_ptr, tets);
206
207 std::vector<EntityHandle> meshsets;
208 meshsets.push_back(*meshset_ptr);
209
210 CHKERR append_meshsets_from_block(epPtr->mField, "CRACK", 2,
211 meshsets);
212 CHKERR append_meshsets_from_block(epPtr->mField, "FRONT", 1,
213 meshsets);
214 CHKERR append_meshsets_from_block(epPtr->mField, "EDGE", 1,
215 meshsets);
216
217 int time_step = 0;
218 CHKERR TSGetStepNumber(ts, &time_step);
219 std::string file_name =
220 "crack_meshsets_" + std::to_string(time_step) + ".h5m";
221 CHKERR epPtr->mField.get_moab().write_file(file_name.c_str(), "MOAB",
222 nullptr, meshsets.data(),
223 static_cast<int>(meshsets.size()));
224 }
225 }
226
228 };
229
232 CHKERR debug_crack();
234 }
235 CHKERR epPtr->projectGeometry(0, time);
237 }
238
239 Vec T;
240 CHKERR TSGetSolution(ts, &T);
241
242 CHKERR VecCopy(T, epPtr->solTSStep);
243 CHKERR VecGhostUpdateBegin(epPtr->solTSStep, INSERT_VALUES, SCATTER_FORWARD);
244 CHKERR VecGhostUpdateEnd(epPtr->solTSStep, INSERT_VALUES, SCATTER_FORWARD);
245
247}
248
251
252 double time;
253 CHKERR TSGetTime(ts, &time);
254
255 MOFEM_LOG("EP", Sev::inform) << "Solve H1 post-step";
256 CHKERR VecZeroEntries(prjF);
257 CHKERR KSPSolve(prjKsp, prjF, prjD);
258 CHKERR VecGhostUpdateBegin(prjD, INSERT_VALUES, SCATTER_FORWARD);
259 CHKERR VecGhostUpdateEnd(prjD, INSERT_VALUES, SCATTER_FORWARD);
260 CHKERR DMoFEMMeshToLocalVector(prjDM, prjD, INSERT_VALUES, SCATTER_REVERSE);
261
262 // The projected H1 field now carries the accepted deformation. Reset the
263 // incremental stretch and rotation before crack calculations and TS
264 // monitors so that the accepted increment is not applied a second time.
265 Vec T;
266 CHKERR TSGetSolution(ts, &T);
267 CHKERR resetIncrementalKinematics(epPtr, T);
268
271 case GRIFFITH_FORCE:
273 MOFEM_LOG("EP", Sev::inform) << "Calculate Griffith force";
275 break;
276 default:
277 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
278 "Energy release selector not handled");
279 };
281 std::numeric_limits<double>::epsilon()) {
282 MOFEM_LOG("EP", Sev::inform) << "Calculate faces orientation";
283
286 }
288 }
289
290 // Clear history after rebasing incremental kinematics onto the H1 field.
291 // With no H1 configuration, retain it until the next pre-step copy.
293 CHKERR VecZeroEntries(epPtr->solTSStep);
294
295 PetscBool local_stop = PETSC_FALSE;
296 PetscBool global_stop = PETSC_FALSE;
300 const double area_increase =
302 const bool crack_arrest_stops =
305 if (area_increase > EshelbianCore::maxCrackExtension ||
307 crack_arrest_stops) {
308 MOFEM_LOG_C("EP", Sev::warning,
309 "Stopping crack growth. Area increase: %3.12e, "
310 "average Griffiths energy: %3.12e, critical Griffiths "
311 "energy: %3.12e",
312 area_increase, epPtr->avgGriffithsEnergy,
314 local_stop = PETSC_TRUE;
315 }
316 }
317 MPI_Bcast(&local_stop, 1, MPIU_BOOL, 0, PETSC_COMM_WORLD);
318 global_stop = local_stop;
319
320 if (global_stop) {
321 TSSetConvergedReason(ts, TS_CONVERGED_USER);
324 } else {
327 }
328 break;
329 default:
330 break;
331 }
332
334};
335} // namespace EshelbianPlasticity
Eshelbian plasticity interface.
#define MOFEM_LOG_C(channel, severity, format,...)
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, FIELD_DIM > OpDomainMass
@ ROW
#define MAX_DOFS_ON_ENTITY
Maximal number of DOFs on entity.
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ BLOCKSET
@ 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.
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMMoFEMKSPSetComputeRHS(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set KSP right hand side evaluation function
Definition DMMoFEM.cpp:627
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
PetscErrorCode DMMoFEMKSPSetComputeOperators(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
Set KSP operators and push mofem finite element methods.
Definition DMMoFEM.cpp:668
@ GAUSS
Gaussian quadrature integration.
@ PETSC
Standard PETSc assembly.
#define MOFEM_LOG(channel, severity)
Log.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto createKSP(MPI_Comm comm)
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
constexpr auto field_name
CGG User Polynomial Base.
boost::shared_ptr< Range > frontAdjEdges
MoFEM::Interface & mField
const std::string spatialL2Disp
static enum SolverType solverType
const std::string materialH1Positions
static bool noCrackExtension
static PetscBool crackingOn
static double griffithEnergy
Griffith energy.
const std::string elementVolumeName
static enum RotSelector gradApproximator
boost::shared_ptr< Range > maxMovedFaces
const std::string spatialH1Disp
static double maxCrackExtension
static double crackingStartTime
MoFEMErrorCode calculateCrackArea(boost::shared_ptr< double > &area_ptr)
MoFEMErrorCode calculateOrientation(const int tag, bool set_orientation)
MoFEMErrorCode setNewFrontCoordinates()
MoFEMErrorCode projectGeometry(const EntityHandle meshset=0, double time=0)
MoFEMErrorCode projectMaterialTags(const EntityHandle meshset=0)
const std::string rotAxis
SmartPetscObj< DM > dmPrjSpatial
Projection spatial displacement.
static int nbStepsNoCrackExtension
boost::shared_ptr< double > currentCrackAreaPtr
double avgGriffithsEnergy
MoFEMErrorCode addCrackSurfaces(const bool debug=false)
MoFEMErrorCode calculateFaceMaterialForce(const int tag, TS ts, SmartPetscObj< Vec > *adjoint_gradient_vector=nullptr)
static bool potentialCrackArrest
static int addCrackMeshsetId
static PetscBool propagateUnderCompression
static enum EnergyReleaseSelector energyReleaseSelector
SmartPetscObj< Vec > solTSStep
const std::string stretchTensor
static MoFEMErrorCode preStepFun(TS ts)
static boost::shared_ptr< FEMethod > preProcRhs
static MoFEMErrorCode postStepFun(TS ts)
static MoFEMErrorCode postStepInitialise(EshelbianCore *ep_ptr)
virtual moab::Interface & get_moab()=0
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Section manager is used to create indexes and sections.
Definition ISManager.hpp:23
Interface for managing meshsets containing materials and boundary conditions.
Specialization for MatrixDouble vector field values calculation.
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.