v0.16.0
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()) {
194 if (epPtr->maxMovedFaces) {
196 ->addEntitiesToMeshset(BLOCKSET, epPtr->addCrackMeshsetId,
198 }
199
200 auto meshset_ptr = get_temp_meshset_ptr(epPtr->mField.get_moab());
201 Range tets;
202 CHKERR epPtr->mField.get_moab().get_entities_by_dimension(
203 *meshset_ptr, 3, tets);
204 CHKERR epPtr->mField.get_moab().add_entities(*meshset_ptr, tets);
205
206 std::vector<EntityHandle> meshsets;
207 meshsets.push_back(*meshset_ptr);
208
209 CHKERR append_meshsets_from_block(epPtr->mField, "CRACK", 2,
210 meshsets);
211 CHKERR append_meshsets_from_block(epPtr->mField, "FRONT", 1,
212 meshsets);
213 CHKERR append_meshsets_from_block(epPtr->mField, "EDGE", 1,
214 meshsets);
215
216 int time_step = 0;
217 CHKERR TSGetStepNumber(ts, &time_step);
218 std::string file_name =
219 "crack_meshsets_" + std::to_string(time_step) + ".h5m";
220 CHKERR epPtr->mField.get_moab().write_file(file_name.c_str(), "MOAB",
221 nullptr, meshsets.data(),
222 static_cast<int>(meshsets.size()));
223 }
224 }
225
227 };
228
231 CHKERR debug_crack();
233 }
234 CHKERR epPtr->projectGeometry(0, time);
236 }
237
238 Vec T;
239 CHKERR TSGetSolution(ts, &T);
240
241 CHKERR VecCopy(T, epPtr->solTSStep);
242 CHKERR VecGhostUpdateBegin(epPtr->solTSStep, INSERT_VALUES, SCATTER_FORWARD);
243 CHKERR VecGhostUpdateEnd(epPtr->solTSStep, INSERT_VALUES, SCATTER_FORWARD);
244
246}
247
250
251 double time;
252 CHKERR TSGetTime(ts, &time);
253
254 MOFEM_LOG("EP", Sev::inform) << "Solve H1 post-step";
255 CHKERR VecZeroEntries(prjF);
256 CHKERR KSPSolve(prjKsp, prjF, prjD);
257 CHKERR VecGhostUpdateBegin(prjD, INSERT_VALUES, SCATTER_FORWARD);
258 CHKERR VecGhostUpdateEnd(prjD, INSERT_VALUES, SCATTER_FORWARD);
259 CHKERR DMoFEMMeshToLocalVector(prjDM, prjD, INSERT_VALUES, SCATTER_REVERSE);
260
261 // The projected H1 field now carries the accepted deformation. Reset the
262 // incremental stretch and rotation before crack calculations and TS
263 // monitors so that the accepted increment is not applied a second time.
264 Vec T;
265 CHKERR TSGetSolution(ts, &T);
266 CHKERR resetIncrementalKinematics(epPtr, T);
267
270 case GRIFFITH_FORCE:
272 MOFEM_LOG("EP", Sev::inform) << "Calculate Griffith force";
274 break;
275 default:
276 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
277 "Energy release selector not handled");
278 };
280 std::numeric_limits<double>::epsilon()) {
281 MOFEM_LOG("EP", Sev::inform) << "Calculate faces orientation";
283 }
285 }
286
287 CHKERR VecZeroEntries(epPtr->solTSStep);
288
289 PetscBool local_stop = PETSC_FALSE;
290 PetscBool global_stop = PETSC_FALSE;
294 const double area_increase =
296 if (area_increase > EshelbianCore::maxCrackExtension ||
298 MOFEM_LOG_C("EP", Sev::warning,
299 "Stopping crack growth. Area increase: %3.12e, "
300 "average Griffiths energy: %3.12e, critical Griffiths "
301 "energy: %3.12e",
302 area_increase, epPtr->avgGriffithsEnergy,
304 local_stop = PETSC_TRUE;
305 }
306 }
307
308 MPI_Bcast(&local_stop, 1, MPIU_BOOL, 0, PETSC_COMM_WORLD);
309 global_stop = local_stop;
310
311 if (global_stop) {
312 TSSetConvergedReason(ts, TS_CONVERGED_USER);
313 }
314 break;
315 default:
316 break;
317 }
318
320};
321} // 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 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.
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 int addCrackMeshsetId
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.