v0.16.3
Loading...
Searching...
No Matches
neohookean_auxiliary_log_stress_atom.cpp
Go to the documentation of this file.
1/**
2 * @file neohookean_auxiliary_log_stress_atom.cpp
3 * @brief Verify the five-coordinate Neo-Hookean material map.
4 */
5
6#include <MoFEM.hpp>
7using namespace MoFEM;
10
11namespace {
12
13MoFEMErrorCode checkNear(const double actual, const double expected,
14 const double tolerance, const char *label) {
16 if (!std::isfinite(actual) ||
17 std::abs(actual - expected) >
18 tolerance * std::max(1., std::abs(expected)))
19 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
20 "%s: expected %.16e, obtained %.16e", label, expected, actual);
22}
23
24MoFEMErrorCode checkCoordinates(const Material::Coordinates &actual,
25 const Material::Coordinates &expected,
26 const double tolerance, const char *label) {
28 FTensor::Index<'A', 5> A;
29 double scale = 1.;
30 for (int aa = 0; aa != 5; ++aa)
31 scale = std::max(scale, std::abs(expected(aa)));
33 t_error(A) = (actual(A) - expected(A)) / scale;
34 CHKERR checkNear(std::sqrt(t_error(A) * t_error(A)), 0., tolerance, label);
36}
37
38MoFEMErrorCode checkPositiveSymmetric(const Material::Tangent &t_matrix,
39 const double tolerance,
40 const char *label) {
42 FTensor::Index<'A', 5> A;
43 FTensor::Index<'B', 5> B;
44 Material::Tangent t_error;
45 t_error(A, B) = t_matrix(A, B) - t_matrix(B, A);
46 CHKERR checkNear(std::sqrt(t_error(A, B) * t_error(A, B)), 0.,
47 tolerance *
48 std::max(1., std::sqrt(t_matrix(A, B) * t_matrix(A, B))),
49 label);
50 Material::Tangent t_eigen_vectors;
51 t_eigen_vectors(A, B) = t_matrix(A, B);
52 Material::Coordinates t_eigen_values;
53 CHKERR computeEigenValuesSymmetric(t_eigen_vectors, t_eigen_values);
54 for (int aa = 0; aa != 5; ++aa)
55 if (!std::isfinite(t_eigen_values(aa)) || t_eigen_values(aa) <= 0.)
56 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
57 "%s: eigenvalue %d is %.16e", label, aa, t_eigen_values(aa));
59}
60
61MoFEMErrorCode checkReference(const Material::Parameters &parameters,
62 const double tolerance) {
64 FTensor::Index<'A', 5> A;
65 FTensor::Index<'B', 5> B;
66 FTensor::Index<'i', 3> i;
67 FTensor::Index<'j', 3> j;
69 t_zero(A) = 0.;
70 Material::Coordinates t_stress;
71 Material::Tangent t_hessian;
72 double energy;
73 CHKERR Material::evaluateDeviator(parameters, t_zero, energy, &t_stress,
74 &t_hessian);
75 CHKERR checkNear(energy, 0., tolerance, "reference deviatoric energy");
76 CHKERR checkCoordinates(t_stress, t_zero, tolerance, "reference stress");
78 CHKERR Material::evaluateInverse(parameters, t_zero, inverse);
79 CHKERR checkCoordinates(inverse.tMaterialDeviator, t_zero, tolerance,
80 "reference inverse");
81 CHKERR checkNear(inverse.conjugateEnergy, 0., tolerance,
82 "reference conjugate energy");
83 constexpr auto t_delta = FTensor::Kronecker_Delta<int>();
84 Material::Tangent t_error;
85 t_error(A, B) = t_hessian(A, B) - 4. * parameters.c10 * t_delta(A, B);
86 CHKERR checkNear(std::sqrt(t_error(A, B) * t_error(A, B)), 0., tolerance,
87 "reference Hessian");
88 t_error(A, B) =
89 inverse.tCompliance(A, B) - t_delta(A, B) / (4. * parameters.c10);
90 CHKERR checkNear(std::sqrt(t_error(A, B) * t_error(A, B)), 0., tolerance,
91 "reference compliance");
92
94 CHKERR Material::evaluateVolume(parameters, 0., volume);
95 CHKERR checkNear(volume.jacobian, 1., tolerance, "reference Jacobian");
96 CHKERR checkNear(volume.energy, 0., tolerance, "reference volume energy");
97 CHKERR checkNear(volume.firstDerivative, 0., tolerance,
98 "reference volume derivative");
99 CHKERR checkNear(volume.secondDerivative, parameters.bulkModulus, tolerance,
100 "reference volume Hessian");
101 CHKERR Material::evaluateVolume(parameters, std::log(0.25), volume);
102 CHKERR checkNear(volume.secondDerivative, -parameters.bulkModulus / 8.,
103 tolerance, "unprojected compressed volume Hessian");
104
105 // A very small K keeps the response finite even near the largest finite J.
107 {parameters.c10, std::numeric_limits<double>::denorm_min()}, 709.7,
108 volume);
109 CHKERR checkNear(volume.energy / volume.firstDerivative, 0.5, tolerance,
110 "large finite volume energy");
111 CHKERR checkNear(volume.secondDerivative / volume.firstDerivative, 2.,
112 tolerance, "large finite volume Hessian");
113
114 for (int aa = 0; aa != 5; ++aa) {
115 Material::Coordinates t_coordinate;
116 t_coordinate(A) = 0.;
117 t_coordinate(aa) = 1.;
118 auto t_basis = Material::getTensor(t_coordinate);
119 CHKERR checkNear(t_basis(i, i), 0., tolerance, "basis trace");
120 CHKERR checkNear(t_basis(i, j) * t_basis(i, j), 1., tolerance,
121 "basis Frobenius norm");
122 CHKERR checkCoordinates(Material::getCoordinates(t_basis), t_coordinate,
123 tolerance, "basis coordinate round trip");
124 for (int bb = 0; bb != aa; ++bb) {
125 t_coordinate(A) = 0.;
126 t_coordinate(bb) = 1.;
127 const auto t_other_basis = Material::getTensor(t_coordinate);
128 CHKERR checkNear(t_basis(i, j) * t_other_basis(i, j), 0., tolerance,
129 "orthogonal tensor coordinates");
130 }
131 }
132 const FTensor::Tensor2<double, 3, 3> t_full(2., 3., 1., -1., -1., 4., 5., 0.,
133 2.);
134 const auto t_projected =
135 MoFEM::Tensor2SymmetricDeviatorBasis::getCoordinates(t_full);
136 const double sqrt_two = std::sqrt(2.);
137 const Material::Coordinates t_expected(3. / sqrt_two, -3. / std::sqrt(6.),
138 sqrt_two, 3. * sqrt_two,
139 2. * sqrt_two);
140 CHKERR checkCoordinates(t_projected, t_expected, tolerance,
141 "full tensor symmetric deviatoric projection");
142 CHKERR checkNear(t_projected(A) * t_projected(A), 34., tolerance,
143 "full tensor projected Frobenius norm");
145}
146
147MoFEMErrorCode checkMaterialState(const Material::Parameters &parameters,
148 const Material::Coordinates &t_deviator,
149 const double fd_step,
150 const double tolerance) {
152 FTensor::Index<'A', 5> A;
153 FTensor::Index<'B', 5> B;
154 FTensor::Index<'C', 5> C;
155 FTensor::Index<'i', 3> i;
156 FTensor::Index<'j', 3> j;
157 FTensor::Index<'k', 3> k;
158 Material::Coordinates t_stress;
159 Material::Tangent t_hessian;
160 double energy;
161 CHKERR Material::evaluateDeviator(parameters, t_deviator, energy, &t_stress,
162 &t_hessian);
164 CHKERR Material::evaluateInverse(parameters, t_stress, inverse);
165 CHKERR checkCoordinates(inverse.tMaterialDeviator, t_deviator, tolerance,
166 "inverse round trip");
167 CHKERR checkNear(inverse.deviatoricEnergy, energy, tolerance,
168 "inverse material energy");
169 CHKERR checkNear(energy + inverse.conjugateEnergy,
170 t_stress(A) * t_deviator(A), tolerance, "Fenchel identity");
171 double gap;
172 CHKERR Material::evaluateFenchelGap(parameters, t_deviator, t_stress, inverse,
173 gap);
174 CHKERR checkNear(gap, 0., tolerance, "zero gap at the material copy");
175 CHKERR checkPositiveSymmetric(t_hessian, tolerance, "deviatoric Hessian");
176 CHKERR checkPositiveSymmetric(inverse.tCompliance, tolerance, "compliance");
177
178 constexpr auto t_delta = FTensor::Kronecker_Delta<int>();
179 Material::Tangent t_inverse_error;
180 t_inverse_error(A, B) =
181 t_hessian(A, C) * inverse.tCompliance(C, B) - t_delta(A, B);
182 CHKERR checkNear(std::sqrt(t_inverse_error(A, B) * t_inverse_error(A, B)), 0.,
183 tolerance, "Hessian-compliance product");
184
185 Material::Coordinates t_direction(0.31, -0.27, 0.41, 0.19, -0.37);
186 const double direction_norm = std::sqrt(t_direction(B) * t_direction(B));
187 t_direction(A) = t_direction(A) / direction_norm;
188 const auto t_d = Material::getTensor(t_deviator);
189 const auto t_v = Material::getTensor(t_direction);
191 t_commutator(i, j) = t_d(i, k) * t_v(k, j) - t_v(i, k) * t_d(k, j);
192 if (std::sqrt(t_deviator(A) * t_deviator(A)) > 0.01 &&
193 std::sqrt(t_commutator(i, j) * t_commutator(i, j)) < 1.e-3)
194 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
195 "Material derivative test direction must be noncoaxial");
196
197 Material::Coordinates t_plus, t_minus, t_stress_plus, t_stress_minus;
198 t_plus(A) = t_deviator(A) + fd_step * t_direction(A);
199 t_minus(A) = t_deviator(A) - fd_step * t_direction(A);
200 double energy_plus, energy_minus;
201 CHKERR Material::evaluateDeviator(parameters, t_plus, energy_plus,
202 &t_stress_plus);
203 CHKERR Material::evaluateDeviator(parameters, t_minus, energy_minus,
204 &t_stress_minus);
205 CHKERR checkNear((energy_plus - energy_minus) / (2. * fd_step),
206 t_stress(A) * t_direction(A), tolerance,
207 "energy directional derivative");
208 Material::Coordinates t_fd, t_exact;
209 t_fd(A) = (t_stress_plus(A) - t_stress_minus(A)) / (2. * fd_step);
210 t_exact(A) = t_hessian(A, B) * t_direction(B);
211 CHKERR checkCoordinates(t_fd, t_exact, tolerance,
212 "forward stress directional derivative");
213
214 t_plus(A) = t_stress(A) + fd_step * t_direction(A);
215 t_minus(A) = t_stress(A) - fd_step * t_direction(A);
216 Material::InverseState inverse_plus, inverse_minus;
217 CHKERR Material::evaluateInverse(parameters, t_plus, inverse_plus);
218 CHKERR Material::evaluateInverse(parameters, t_minus, inverse_minus);
219 t_fd(A) =
220 (inverse_plus.tMaterialDeviator(A) - inverse_minus.tMaterialDeviator(A)) /
221 (2. * fd_step);
222 t_exact(A) = inverse.tCompliance(A, B) * t_direction(B);
223 CHKERR checkCoordinates(t_fd, t_exact, tolerance,
224 "inverse noncoaxial directional derivative");
225 CHKERR checkNear(
226 (inverse_plus.conjugateEnergy - inverse_minus.conjugateEnergy) /
227 (2. * fd_step),
228 t_deviator(A) * t_direction(A), tolerance,
229 "conjugate energy directional derivative");
230 t_plus(A) = t_deviator(A) + 0.2 * t_direction(A);
231 CHKERR Material::evaluateFenchelGap(parameters, t_plus, t_stress, inverse,
232 gap);
233 if (gap <= 0.)
234 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
235 "Distinct material copies must have a positive Fenchel gap");
237}
238
239MoFEMErrorCode checkSpectralStates(const Material::Parameters &parameters,
240 const double fd_step,
241 const double tolerance) {
243 FTensor::Index<'i', 3> i;
244 FTensor::Index<'j', 3> j;
245 FTensor::Index<'k', 3> k;
246 FTensor::Tensor2<double, 3, 3> t_rotation(0.36, -0.8, 0.48, 0.48, 0.6, 0.64,
247 -0.8, 0., 0.6);
248 for (const auto &diagonal : {std::array<double, 3>{0., 0., 0.},
249 {0.12, 0.12, -0.24},
250 {0.12, 0.120000001, -0.240000001},
251 {0.3, -0.12, -0.18}}) {
252 Material::SymmetricTensor t_diagonal;
253 t_diagonal(i, j) = 0.;
254 for (int aa = 0; aa != 3; ++aa)
255 t_diagonal(aa, aa) = diagonal[aa];
256 auto t_coordinates = Material::getCoordinates(t_diagonal);
257 CHKERR checkMaterialState(parameters, t_coordinates, fd_step, tolerance);
258 FTensor::Tensor2<double, 3, 3> t_rotated_left;
259 t_rotated_left(i, j) = t_rotation(i, k) * t_diagonal(k, j);
261 t_rotated(i, j) = (t_rotated_left(i, k) * t_rotation(j, k) ||
262 t_rotated_left(j, k) * t_rotation(i, k)) /
263 2.;
264 auto t_rotated_coordinates = Material::getCoordinates(t_rotated);
265 CHKERR checkMaterialState(parameters, t_rotated_coordinates, fd_step,
266 tolerance);
267
268 Material::Coordinates t_stress, t_rotated_stress;
269 double energy, rotated_energy;
270 CHKERR Material::evaluateDeviator(parameters, t_coordinates, energy,
271 &t_stress);
272 CHKERR Material::evaluateDeviator(parameters, t_rotated_coordinates,
273 rotated_energy, &t_rotated_stress);
274 CHKERR checkNear(rotated_energy, energy, tolerance,
275 "rotation-invariant energy");
276 auto t_s = Material::getTensor(t_stress);
277 t_rotated_left(i, j) = t_rotation(i, k) * t_s(k, j);
278 t_rotated(i, j) = (t_rotated_left(i, k) * t_rotation(j, k) ||
279 t_rotated_left(j, k) * t_rotation(i, k)) /
280 2.;
281 CHKERR checkCoordinates(t_rotated_stress,
282 Material::getCoordinates(t_rotated), tolerance,
283 "rotated material stress");
284 }
286}
287
288MoFEMErrorCode checkForwardReferences(const Material::Parameters &parameters,
289 const double fd_step,
290 const double tolerance) {
292 FTensor::Index<'i', 3> i;
293 FTensor::Index<'j', 3> j;
294 struct Reference {
295 std::array<double, 3> diagonal;
296 double energy;
297 std::array<double, 3> piola;
298 };
299 const std::array<Reference, 3> references{
300 {{{0.1, 0.1, 0.1},
301 0.520205037263637,
302 {3.63220735658965, 3.63220735658965, 3.63220735658965}},
303 {{0.3, -0.12, 0.02},
304 0.538123520405792,
305 {3.03780092210880, 1.14937771717195, 1.74058832297094}},
306 {{-0.3, 0.12, -0.02},
307 0.441373550717383,
308 {-3.68584071124042, 0.0674874416521112, -1.15285500880558}}}};
309 for (const auto &reference : references) {
311 t_h(i, j) = 0.;
312 for (int aa = 0; aa != 3; ++aa)
313 t_h(aa, aa) = reference.diagonal[aa];
314 const double theta = t_h(i, i);
315 auto t_deviator = Material::getCoordinates(t_h);
316 auto t_reconstructed = Material::getTensor(t_deviator, theta);
318 t_error(i, j) = t_reconstructed(i, j) - t_h(i, j);
319 CHKERR checkNear(std::sqrt(t_error(i, j) * t_error(i, j)), 0., tolerance,
320 "reconstructed logarithmic stretch");
321 Material::Coordinates t_stress;
322 double energy;
323 CHKERR Material::evaluateDeviator(parameters, t_deviator, energy,
324 &t_stress);
325 Material::VolumeState volume, volume_plus, volume_minus;
326 CHKERR Material::evaluateVolume(parameters, theta, volume);
327 CHKERR Material::evaluateVolume(parameters, theta + fd_step, volume_plus);
328 CHKERR Material::evaluateVolume(parameters, theta - fd_step, volume_minus);
329 CHKERR checkNear(energy + volume.energy, reference.energy, tolerance,
330 "independent forward energy");
331 const auto t_s = Material::getTensor(t_stress);
332 for (int aa = 0; aa != 3; ++aa)
333 CHKERR checkNear((t_s(aa, aa) + volume.firstDerivative) /
334 std::exp(reference.diagonal[aa]),
335 reference.piola[aa], tolerance,
336 "independent principal Piola stress");
337 CHKERR checkNear(
338 (volume_plus.energy - volume_minus.energy) / (2. * fd_step),
339 volume.firstDerivative, tolerance, "volumetric energy derivative");
340 CHKERR checkNear(
341 (volume_plus.firstDerivative - volume_minus.firstDerivative) /
342 (2. * fd_step),
343 volume.secondDerivative, tolerance, "volumetric tangent");
344 }
346}
347
348MoFEMErrorCode checkLargeStress(const Material::Parameters &parameters,
349 const double tolerance) {
351 FTensor::Index<'A', 5> A;
352 const Material::Coordinates t_direction(1., -0.5, 0.25, -0.75, 0.4);
353 for (const double scale : {1.e4, 1.e8, 1.e100, 1.e200}) {
354 Material::Coordinates t_stress;
355 t_stress(A) = scale * t_direction(A);
357 CHKERR Material::evaluateInverse(parameters, t_stress, inverse);
358 double energy;
359 Material::Coordinates t_recovered;
361 energy, &t_recovered);
362 CHKERR checkCoordinates(t_recovered, t_stress, tolerance,
363 "large finite stress round trip");
364 CHKERR checkNear(inverse.inverseResidual, 0., tolerance,
365 "large finite stress inverse residual");
366 CHKERR checkNear(energy + inverse.conjugateEnergy,
367 t_stress(A) * inverse.tMaterialDeviator(A), tolerance,
368 "large stress Fenchel identity");
369 }
371}
372
373MoFEMErrorCode checkSmallDeviator(const Material::Parameters &parameters,
374 const double tolerance) {
376 FTensor::Index<'A', 5> A;
377 const Material::Coordinates t_deviator(0.6e-10, -0.3e-10, 0.2e-10, -0.4e-10,
378 0.5e-10);
379 Material::Coordinates t_stress, t_error;
380 double energy;
381 CHKERR Material::evaluateDeviator(parameters, t_deviator, energy, &t_stress);
382 const double norm_squared = t_deviator(A) * t_deviator(A);
383 const double mu = 2. * parameters.c10;
384 CHKERR checkNear(energy / (mu * norm_squared), 1., tolerance,
385 "small-deviator relative energy");
386 t_error(A) = t_stress(A) / (2. * mu) - t_deviator(A);
387 CHKERR checkNear(std::sqrt((t_error(A) * t_error(A)) / norm_squared), 0.,
388 tolerance, "small-deviator relative stress");
390}
391
392MoFEMErrorCode checkEnergyScaling(const double tolerance) {
394 const Material::Parameters parameters{5.e307, 1.};
395 const Material::SymmetricTensor t_d(0.65, 0., 0., -0.325, 0., -0.325);
396 double energy;
398 energy);
399 CHKERR checkNear(energy / 8.56694110570638e307, 1., tolerance,
400 "finite energy despite large exponential term");
401 const Material::Coordinates t_small(1.e-200, 0., 0., 0., 0.);
402 CHKERR Material::evaluateDeviator(parameters, t_small, energy);
403 CHKERR checkNear(energy / 1.e-92, 1., tolerance,
404 "finite energy despite tiny squared strain");
405 const Material::SymmetricTensor t_distorted(0.55, 0., 0., -0.275, 0., -0.275);
406 Material::Coordinates t_stress;
408 parameters, Material::getCoordinates(t_distorted), energy, &t_stress);
409 CHKERR checkNear(t_stress(0) / 1.7163010440184161e308, 1., tolerance,
410 "finite projected principal stress");
411 CHKERR checkNear(t_stress(1) / 9.909068697744685e307, 1., tolerance,
412 "finite projected second stress coordinate");
414}
415
416MoFEMErrorCode checkConditioning(const Material::Parameters &parameters,
417 const double tolerance) {
419 FTensor::Index<'A', 5> A;
420 FTensor::Index<'B', 5> B;
421 FTensor::Index<'i', 3> i;
422 FTensor::Index<'j', 3> j;
423 double previous_condition = 0.;
424 for (const double amplitude : {0., 1., 2.}) {
425 Material::SymmetricTensor t_diagonal;
426 t_diagonal(i, j) = 0.;
427 t_diagonal(0, 0) = -amplitude;
428 t_diagonal(1, 1) = -amplitude;
429 t_diagonal(2, 2) = 2. * amplitude;
430 const auto t_deviator = Material::getCoordinates(t_diagonal);
431 Material::Coordinates t_stress;
432 double energy;
433 CHKERR Material::evaluateDeviator(parameters, t_deviator, energy,
434 &t_stress);
436 CHKERR Material::evaluateInverse(parameters, t_stress, inverse);
437 CHKERR checkCoordinates(inverse.tMaterialDeviator, t_deviator, tolerance,
438 "conditioned inverse round trip");
439 CHKERR checkNear(inverse.tCompliance(2, 2),
440 std::exp(2. * amplitude) / (4. * parameters.c10),
441 tolerance, "repeated-plane shear compliance");
442 Material::Tangent t_eigen_vectors;
443 t_eigen_vectors(A, B) = inverse.tCompliance(A, B);
444 Material::Coordinates t_eigen_values;
445 CHKERR computeEigenValuesSymmetric(t_eigen_vectors, t_eigen_values);
446 const double condition = t_eigen_values(4) / t_eigen_values(0);
447 if (!std::isfinite(condition) || condition <= previous_condition)
448 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
449 "Expected increasing compliance condition, got %.16e", condition);
450 CHKERR PetscPrintf(PETSC_COMM_WORLD,
451 "Auxiliary inverse a=%.1f: compliance condition %.8e\n",
452 amplitude, condition);
453 previous_condition = condition;
454 }
456}
457
458MoFEMErrorCode checkInvalidInputs(const Material::Parameters &parameters) {
460 const double infinity = std::numeric_limits<double>::infinity();
461 const double nan = std::numeric_limits<double>::quiet_NaN();
462 for (const auto bad : {Material::Parameters{0., parameters.bulkModulus},
463 {-1., parameters.bulkModulus},
464 {parameters.c10, 0.},
465 {parameters.c10, -1.},
466 {nan, parameters.bulkModulus},
467 {parameters.c10, infinity}}) {
468 CHKERR PetscPushErrorHandler(PetscReturnErrorHandler, nullptr);
469 const auto error = Material::validateParameters(bad);
470 CHKERR PetscPopErrorHandler();
471 if (!error)
472 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
473 "Invalid material parameters were accepted");
474 }
475 Material::Coordinates t_invalid(nan, 0., 0., 0., 0.);
478 double energy;
479 CHKERR PetscPushErrorHandler(PetscReturnErrorHandler, nullptr);
480 const auto inverse_error =
481 Material::evaluateInverse(parameters, t_invalid, inverse);
482 const auto forward_error =
483 Material::evaluateDeviator(parameters, t_invalid, energy);
484 const auto volume_error =
485 Material::evaluateVolume(parameters, infinity, volume);
486 CHKERR PetscPopErrorHandler();
487 if (!inverse_error || !forward_error || !volume_error)
488 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
489 "Non-finite material input was accepted");
491}
492
493} // namespace
494
495static char help[] =
496 "Neo-Hookean auxiliary logarithmic stress material atom.\n"
497 "Use -json_config neohookean_auxiliary_log_stress_atom.json.\n";
498
499int main(int argc, char *argv[]) {
500 MoFEM::Core::Initialize(&argc, &argv, nullptr, help);
501 try {
502 moab::Core moab;
503 MoFEM::Core core(moab);
504 MoFEM::Interface &m_field = core;
505 auto *json_config = m_field.getInterface<JsonConfigManager>();
506 auto *meshsets_manager = m_field.getInterface<MeshsetsManager>();
507 // Only material parameters are needed; this atom has no element geometry.
508 CHKERR meshsets_manager->addMeshset(BLOCKSET, 1001, "MAT_NEOHOOKEAN");
509 CHKERR meshsets_manager->setMeshsetFromFile();
510 const auto block =
511 json_config->getParamsFromBlockset("MAT_NEOHOOKEAN", 1001);
512 if (block.size() != 2 || !block.count("c10") || !block.count("k"))
513 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
514 "Atom requires MAT_NEOHOOKEAN JSON block 1001 with c10,k");
515 const Material::Parameters parameters{block.at("c10"), block.at("k")};
517 CHKERR checkNear(parameters.c10, 1.7, 1.e-14, "reference C10");
518 CHKERR checkNear(parameters.bulkModulus, 8.5, 1.e-14, "reference K");
519 PetscReal fd_step = 0., tolerance = 0.;
520 CHKERR PetscOptionsGetReal(nullptr, nullptr, "-auxiliary_atom_fd_step",
521 &fd_step, nullptr);
522 CHKERR PetscOptionsGetReal(nullptr, nullptr, "-auxiliary_atom_tolerance",
523 &tolerance, nullptr);
524 if (!std::isfinite(fd_step) || fd_step <= 0. || !std::isfinite(tolerance) ||
525 tolerance <= 0.)
526 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
527 "Atom requires positive finite JSON finite-difference settings");
528 CHKERR checkReference(parameters, tolerance);
529 CHKERR checkReference({parameters.c10, 0.1}, tolerance);
530 CHKERR checkSpectralStates(parameters, fd_step, tolerance);
531 CHKERR checkForwardReferences(parameters, fd_step, tolerance);
532 CHKERR checkLargeStress(parameters, tolerance);
533 CHKERR checkSmallDeviator(parameters, tolerance);
534 CHKERR checkEnergyScaling(tolerance);
535 CHKERR checkConditioning(parameters, tolerance);
536 CHKERR checkInvalidInputs(parameters);
537 CHKERR PetscPrintf(
538 PETSC_COMM_WORLD,
539 "Neo-Hookean auxiliary logarithmic stress atom passed\n");
540 }
543 return 0;
544}
Neo-Hookean material law in orthonormal logarithmic coordinates.
int main()
Kronecker Delta class.
#define CATCH_ERRORS
Catch errors.
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ BLOCKSET
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
PetscErrorCode PetscOptionsGetReal(PetscOptions *, const char pre[], const char name[], PetscReal *dval, PetscBool *set)
MoFEMErrorCode computeEigenValuesSymmetric(const MatrixDouble &mat, VectorDouble &eig, MatrixDouble &eigen_vec)
compute eigenvalues of a symmetric matrix using lapack dsyev
constexpr AssemblyType A
double inverseResidual
Sum of principal logarithms before projection.
static MoFEMErrorCode evaluateInverse(const Parameters &parameters, const Coordinates &t_stress, InverseState &state)
Recover Dm(Td), its compliance and conjugate energy; no state is cached.
static MoFEMErrorCode validateParameters(const Parameters &parameters)
Check finite, strictly positive C10, K and representable mu = 2*C10.
static SymmetricTensor getTensor(const Coordinates &t_coordinates, double theta=0.)
Reconstruct H = D + theta*I/3 from the fixed five-coordinate basis.
static MoFEMErrorCode evaluateDeviator(const Parameters &parameters, const Coordinates &t_deviator, double &energy, Coordinates *stress_ptr=nullptr, Tangent *hessian_ptr=nullptr)
Evaluate f(D), optionally its five-component gradient and Hessian.
static MoFEMErrorCode evaluateFenchelGap(const Parameters &parameters, const Coordinates &t_deviator, const Coordinates &t_stress, const InverseState &inverse, double &gap, double *energy_ptr=nullptr)
static Coordinates getCoordinates(const SymmetricTensor &t_tensor)
Project a symmetric tensor onto the fixed trace-free basis.
static MoFEMErrorCode evaluateVolume(const Parameters &parameters, double theta, VolumeState &state)
Evaluate g(J) = K*(J-1)^2/2 and its logarithmic-volume derivatives.
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
std::map< std::string, double > getParamsFromBlockset(const std::string &type_name, int meshset_id) const
Interface for managing meshsets containing materials and boundary conditions.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
double scale
Definition plastic.cpp:123