72 {
73
74
76
77
78 moab::Core mb_instance;
79 moab::Interface &moab = mb_instance;
80
81 try {
82
85
86 PetscBool ale = PETSC_FALSE;
88 PetscBool test_jacobian = PETSC_FALSE;
90 PETSC_NULLPTR);
91
93
95
101
102 if (ale == PETSC_TRUE) {
105 }
107
108
109 DM dm;
111
112
113 {
116
117 }
118
119
120 if (ale == PETSC_TRUE) {
123
124 }
125
126 boost::shared_ptr<ForcesAndSourcesCore> fe_lhs_ptr(
128 boost::shared_ptr<ForcesAndSourcesCore> fe_rhs_ptr(
132 };
133 fe_lhs_ptr->getRuleHook =
VolRule();
134 fe_rhs_ptr->getRuleHook =
VolRule();
135
137 nullptr, nullptr);
139 nullptr, nullptr);
140
142 boost::shared_ptr<map<int, BlockData>> block_sets_ptr =
143 boost::make_shared<map<int, BlockData>>();
144 (*block_sets_ptr)[0].
iD = 0;
145 (*block_sets_ptr)[0].E = 1;
146 (*block_sets_ptr)[0].PoissonRatio = 0.25;
149
150
151 const double rho_n = 2.0;
152 const double rho_0 = 0.5;
153
154 auto my_operators = [&](boost::shared_ptr<ForcesAndSourcesCore> &fe_lhs_ptr,
155 boost::shared_ptr<ForcesAndSourcesCore> &fe_rhs_ptr,
156 boost::shared_ptr<map<int, BlockData>>
157 &block_sets_ptr,
158 const std::string x_field,
159 const std::string X_field, const bool ale,
160 const bool field_disp) {
162
163 boost::shared_ptr<HookeElement::DataAtIntegrationPts> data_at_pts(
164 new HookeElement::DataAtIntegrationPts());
165 boost::shared_ptr<MatrixDouble> mat_coords_ptr =
166 boost::make_shared<MatrixDouble>();
167 boost::shared_ptr<VectorDouble> rho_at_gauss_pts_ptr =
168 boost::make_shared<VectorDouble>();
169 boost::shared_ptr<MatrixDouble> rho_grad_at_gauss_pts_ptr =
170 boost::make_shared<MatrixDouble>();
171
172 if (fe_lhs_ptr) {
173 if (ale == PETSC_FALSE) {
174 fe_lhs_ptr->getOpPtrVector().push_back(
177 x_field, mat_coords_ptr, rho_at_gauss_pts_ptr,
178 rho_grad_at_gauss_pts_ptr));
179 fe_lhs_ptr->getOpPtrVector().push_back(
180 new HookeElement::OpCalculateStiffnessScaledByDensityField(
181 x_field, x_field, block_sets_ptr, data_at_pts,
182 rho_at_gauss_pts_ptr, rho_n, rho_0));
183 fe_lhs_ptr->getOpPtrVector().push_back(
184 new HookeElement::OpLhs_dx_dx<1>(x_field, x_field, data_at_pts));
185 } else {
186 fe_lhs_ptr->getOpPtrVector().push_back(
188 data_at_pts->HMat));
189 fe_lhs_ptr->getOpPtrVector().push_back(
192 X_field, mat_coords_ptr, rho_at_gauss_pts_ptr,
193 rho_grad_at_gauss_pts_ptr));
194 fe_lhs_ptr->getOpPtrVector().push_back(
195 new HookeElement::OpCalculateStiffnessScaledByDensityField(
196 x_field, x_field, block_sets_ptr, data_at_pts,
197 rho_at_gauss_pts_ptr, rho_n, rho_0));
198 fe_lhs_ptr->getOpPtrVector().push_back(
200 data_at_pts->hMat));
201 fe_lhs_ptr->getOpPtrVector().push_back(
202 new HookeElement::OpCalculateStrainAle(x_field, x_field,
203 data_at_pts));
204 fe_lhs_ptr->getOpPtrVector().push_back(
205 new HookeElement::OpCalculateStress<1>(x_field, x_field,
206 data_at_pts));
207 fe_lhs_ptr->getOpPtrVector().push_back(
208 new HookeElement::OpAleLhs_dx_dx<1>(x_field, x_field,
209 data_at_pts));
210 fe_lhs_ptr->getOpPtrVector().push_back(
211 new HookeElement::OpAleLhs_dx_dX<1>(x_field, X_field,
212 data_at_pts));
213 fe_lhs_ptr->getOpPtrVector().push_back(
214 new HookeElement::OpCalculateEnergy(X_field, X_field,
215 data_at_pts));
216 fe_lhs_ptr->getOpPtrVector().push_back(
217 new HookeElement::OpCalculateEshelbyStress(X_field, X_field,
218 data_at_pts));
219 fe_lhs_ptr->getOpPtrVector().push_back(
220 new HookeElement::OpAleLhs_dX_dX<1>(X_field, X_field,
221 data_at_pts));
222 fe_lhs_ptr->getOpPtrVector().push_back(
223 new HookeElement::OpAleLhsPre_dX_dx<1>(X_field, x_field,
224 data_at_pts));
225 fe_lhs_ptr->getOpPtrVector().push_back(
226 new HookeElement::OpAleLhs_dX_dx(X_field, x_field, data_at_pts));
227 fe_lhs_ptr->getOpPtrVector().push_back(
228 new HookeElement::OpAleLhsWithDensity_dx_dX(
229 x_field, X_field, data_at_pts, rho_at_gauss_pts_ptr,
230 rho_grad_at_gauss_pts_ptr, rho_n, rho_0));
231 fe_lhs_ptr->getOpPtrVector().push_back(
232 new HookeElement::OpAleLhsWithDensity_dX_dX(
233 X_field, X_field, data_at_pts, rho_at_gauss_pts_ptr,
234 rho_grad_at_gauss_pts_ptr, rho_n, rho_0));
235 }
236 }
237
238 if (fe_rhs_ptr) {
239
240 if (ale == PETSC_FALSE) {
241 fe_rhs_ptr->getOpPtrVector().push_back(
243 data_at_pts->hMat));
244 fe_rhs_ptr->getOpPtrVector().push_back(
247 x_field, mat_coords_ptr, rho_at_gauss_pts_ptr,
248 rho_grad_at_gauss_pts_ptr));
249 fe_rhs_ptr->getOpPtrVector().push_back(
250 new HookeElement::OpCalculateStiffnessScaledByDensityField(
251 x_field, x_field, block_sets_ptr, data_at_pts,
252 rho_at_gauss_pts_ptr, rho_n, rho_0));
253 if (field_disp) {
254 fe_rhs_ptr->getOpPtrVector().push_back(
255 new HookeElement::OpCalculateStrain<1>(x_field, x_field,
256 data_at_pts));
257 } else {
258 fe_rhs_ptr->getOpPtrVector().push_back(
259 new HookeElement::OpCalculateStrain<0>(x_field, x_field,
260 data_at_pts));
261 }
262 fe_rhs_ptr->getOpPtrVector().push_back(
263 new HookeElement::OpCalculateStress<1>(x_field, x_field,
264 data_at_pts));
265 fe_rhs_ptr->getOpPtrVector().push_back(
266 new HookeElement::OpRhs_dx(x_field, x_field, data_at_pts));
267 } else {
268 fe_rhs_ptr->getOpPtrVector().push_back(
270 data_at_pts->HMat));
271 fe_rhs_ptr->getOpPtrVector().push_back(
274 X_field, mat_coords_ptr, rho_at_gauss_pts_ptr,
275 rho_grad_at_gauss_pts_ptr));
276 fe_rhs_ptr->getOpPtrVector().push_back(
277 new HookeElement::OpCalculateStiffnessScaledByDensityField(
278 x_field, x_field, block_sets_ptr, data_at_pts,
279 rho_at_gauss_pts_ptr, rho_n, rho_0));
280 fe_rhs_ptr->getOpPtrVector().push_back(
282 data_at_pts->hMat));
283 fe_rhs_ptr->getOpPtrVector().push_back(
284 new HookeElement::OpCalculateStrainAle(x_field, x_field,
285 data_at_pts));
286 fe_rhs_ptr->getOpPtrVector().push_back(
287 new HookeElement::OpCalculateStress<1>(x_field, x_field,
288 data_at_pts));
289 fe_rhs_ptr->getOpPtrVector().push_back(
290 new HookeElement::OpAleRhs_dx(x_field, x_field, data_at_pts));
291 fe_rhs_ptr->getOpPtrVector().push_back(
292 new HookeElement::OpCalculateEnergy(X_field, X_field,
293 data_at_pts));
294 fe_rhs_ptr->getOpPtrVector().push_back(
295 new HookeElement::OpCalculateEshelbyStress(X_field, X_field,
296 data_at_pts));
297 fe_rhs_ptr->getOpPtrVector().push_back(
298 new HookeElement::OpAleRhs_dX(X_field, X_field, data_at_pts));
299 }
300 }
302 };
303 CHKERR my_operators(fe_lhs_ptr, fe_rhs_ptr, block_sets_ptr,
"x",
"X", ale,
304 false);
306 CHKERR DMCreateGlobalVector(dm, &x);
307 CHKERR VecDuplicate(x, &f);
309
310
311
312
313
314
315
316
318 CHKERR DMCreateMatrix(dm, &A);
319 CHKERR MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &fdA);
320
321 if (test_jacobian == PETSC_TRUE) {
322 char testing_options[] =
323 "-snes_test_jacobian -snes_test_jacobian_display "
324 "-snes_no_convergence_test -snes_atol 0 -snes_rtol 0 -snes_max_it 1 "
325 "-pc_type none";
326 CHKERR PetscOptionsInsertString(NULL, testing_options);
327 } else {
328 char testing_options[] = "-snes_no_convergence_test -snes_atol 0 "
329 "-snes_rtol 0 -snes_max_it 1 -pc_type none";
330 CHKERR PetscOptionsInsertString(NULL, testing_options);
331 }
332
333 SNES snes;
334 CHKERR SNESCreate(PETSC_COMM_WORLD, &snes);
339 CHKERR SNESSetFromOptions(snes);
340
341 CHKERR SNESSolve(snes, NULL, x);
342
343 if (test_jacobian == PETSC_FALSE) {
344 double nrm_A0;
345 CHKERR MatNorm(A, NORM_INFINITY, &nrm_A0);
346
347 char testing_options_fd[] = "-snes_fd";
348 CHKERR PetscOptionsInsertString(NULL, testing_options_fd);
349
352 CHKERR SNESSetFromOptions(snes);
353
354 CHKERR SNESSolve(snes, NULL, x);
355 CHKERR MatAXPY(A, -1, fdA, SUBSET_NONZERO_PATTERN);
356
357 double nrm_A;
358 CHKERR MatNorm(A, NORM_INFINITY, &nrm_A);
359 PetscPrintf(PETSC_COMM_WORLD, "Matrix norms %3.4e %3.4e\n", nrm_A,
360 nrm_A / nrm_A0);
361 nrm_A /= nrm_A0;
362
363 const double tol = 1e-5;
366 "Difference between hand-calculated tangent matrix and finite "
367 "difference matrix is too big");
368 }
369 }
370
375 CHKERR SNESDestroy(&snes);
376
377
379 }
381
382
384
385 return 0;
386}
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ MOFEM_ATOM_TEST_INVALID
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PetscErrorCode DMMoFEMSNESSetFunction(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set SNES residual evaluation function
PetscErrorCode DMMoFEMSNESSetJacobian(DM dm, const char fe_name[], MoFEM::FEMethod *method, MoFEM::BasicMethod *pre_only, MoFEM::BasicMethod *post_only)
set SNES Jacobian evaluation function
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
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
PetscErrorCode DMMoFEMGetSnesCtx(DM dm, MoFEM::SnesCtx **snes_ctx)
get MoFEM::SnesCtx data structure
virtual MoFEMErrorCode get_finite_element_entities_by_dimension(const std::string name, int dim, Range &ents) const =0
get entities in the finite element by dimension
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.
const FTensor::Tensor2< T, Dim, Dim > Vec
PetscErrorCode SnesMat(SNES snes, Vec x, Mat A, Mat B, void *ctx)
This is MoFEM implementation for the left hand side (tangent matrix) evaluation in SNES solver.
PetscErrorCode SnesRhs(SNES snes, Vec x, Vec f, void *ctx)
This is MoFEM implementation for the right hand side (residual vector) evaluation in SNES solver.
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Deprecated interface functions.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for MatrixDouble vector field values calculation.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
MoFEMErrorCode addDomainField(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_ZERO, int verb=-1)
Add field on domain.
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
MoFEMErrorCode getOptions()
get options
MoFEMErrorCode getDM(DM *dm)
Get DM.
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
const std::string getDomainFEName() const
Get the Domain FE Name.
Interface for nonlinear (SNES) solver.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Volume finite element base.
data for calculation heat conductivity and heat capacity elements
Set integration rule to volume elements.
int operator()(int, int, int) const