OGS
MFrontGeneric.h
Go to the documentation of this file.
1
9
10#pragma once
11
12// clang-format off
13// The exception include is needed as in MGIS-rliv-2.2 branch it is missing.
14// TODO(naumov): remove after TFEL-5 update.
15#include <exception>
16#include <MGIS/Behaviour/Behaviour.hxx>
17// clang-format on
18
19#include <MGIS/Behaviour/BehaviourData.hxx>
20#include <MGIS/Behaviour/Integrate.hxx>
21#include <boost/mp11.hpp>
22
26#include "NumLib/Exceptions.h"
30#include "Variable.h"
31
33{
34namespace MPL = MaterialPropertyLib;
35
41template <typename Derived>
42constexpr auto eigenSwap45View(Eigen::MatrixBase<Derived> const& matrix)
43{
44 using Matrix =
45 Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime,
46 Derived::ColsAtCompileTime>;
47
48 return Matrix::NullaryExpr(
49 matrix.rows(), matrix.cols(),
50 [&m = matrix.derived()](Eigen::Index const row, Eigen::Index const col)
51 {
52 constexpr std::ptrdiff_t result[6] = {0, 1, 2, 3, 5, 4};
53 return m(result[row], result[col]);
54 });
55}
56
64template <int DisplacementDim, typename Derived>
65constexpr auto ogsTensorToMFrontTensor(Eigen::MatrixBase<Derived> const& matrix)
66{
67 using Matrix =
68 Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime,
69 Derived::ColsAtCompileTime>;
70
71 if constexpr (DisplacementDim == 2)
72 {
73 return Matrix::NullaryExpr(
74 matrix.rows(), matrix.cols(),
75 [&m = matrix.derived()](Eigen::Index const row,
76 Eigen::Index const col)
77 {
78 constexpr std::ptrdiff_t result[5] = {0, 3, 4, 1, 2};
79 return m(result[row], result[col]);
80 });
81 }
82 if constexpr (DisplacementDim == 3)
83 {
84 return Matrix::NullaryExpr(
85 matrix.rows(), matrix.cols(),
86 [&m = matrix.derived()](Eigen::Index const row,
87 Eigen::Index const col)
88 {
89 constexpr std::ptrdiff_t result[9] = {0, 4, 8, 1, 3,
90 2, 6, 5, 7};
91 return m(result[row], result[col]);
92 });
93 }
94}
95
96const char* varTypeToString(int v);
97
98int getEquivalentPlasticStrainOffset(mgis::behaviour::Behaviour const& b);
99
105template <int DisplacementDim>
106OGSMFrontTangentOperatorData tangentOperatorDataMFrontToOGS(
107 std::vector<double> const& mfront_data,
108 std::optional<
110 mgis::behaviour::Behaviour const& behaviour);
111
112extern template OGSMFrontTangentOperatorData tangentOperatorDataMFrontToOGS<2>(
113 std::vector<double> const& mfront_data,
114 std::optional<MathLib::KelvinVector::KelvinMatrixType<2>> const& Q,
115 mgis::behaviour::Behaviour const& behaviour);
116extern template OGSMFrontTangentOperatorData tangentOperatorDataMFrontToOGS<3>(
117 std::vector<double> const& mfront_data,
118 std::optional<MathLib::KelvinVector::KelvinMatrixType<3>> const& Q,
119 mgis::behaviour::Behaviour const& behaviour);
120
121// TODO template parameter only because of base class.
122template <int DisplacementDim>
125{
127 int const equivalent_plastic_strain_offset,
128 mgis::behaviour::Behaviour const& b)
129 : equivalent_plastic_strain_offset_(equivalent_plastic_strain_offset),
131 {
132 }
133
138
139 void pushBackState() override { mgis::behaviour::update(_behaviour_data); }
140
142 mgis::behaviour::BehaviourData _behaviour_data;
143
144 double getEquivalentPlasticStrain() const override
145 {
147 {
148 return _behaviour_data.s1
149 .internal_state_variables[static_cast<mgis::size_type>(
151 }
152
153 return 0.0;
154 }
155};
156
157namespace detail
158{
160template <int DisplacementDim, mgis::behaviour::Variable::Type MFrontType>
162
163template <int DisplacementDim>
168
169template <int DisplacementDim>
174
175template <int DisplacementDim>
180
181template <int DisplacementDim, mgis::behaviour::Variable::Type MFrontType>
183
186template <int DisplacementDim>
188{
190 std::optional<
192 double* target;
193
194 template <typename Grad>
195 void operator()(Grad)
196 {
197 auto constexpr num_comp = Grad::template size<DisplacementDim>();
198
199 if constexpr (Grad::type == mgis::behaviour::Variable::Type::SCALAR)
200 {
201 *target = variable_array.*Grad::mpl_var;
202 }
203 else if constexpr (Grad::type ==
204 mgis::behaviour::Variable::Type::STENSOR)
205 {
207 auto const& grad_ogs =
208 std::get<MPLType>(variable_array.*Grad::mpl_var);
209
210 auto const grad_mfront =
211 Q ? eigenSwap45View(Q->transpose() * grad_ogs).eval()
212 : eigenSwap45View(grad_ogs).eval();
213 std::copy_n(grad_mfront.data(), num_comp, target);
214 }
215 else if constexpr (Grad::type ==
216 mgis::behaviour::Variable::Type::TENSOR)
217 {
219 auto const& grad_ogs =
220 std::get<MPLType>(variable_array.*Grad::mpl_var);
221
222 if (Q.has_value())
223 {
224 OGS_FATAL("Rotations of tensors are not implemented.");
225 }
226
227 Eigen::Map<Eigen::Vector<double, num_comp>>{target} =
229 }
230 else
231 {
232 OGS_FATAL("Unsupported gradient type {}.",
233 varTypeToString(Grad::type));
234 }
235
236 target += num_comp;
237 }
238};
239} // namespace detail
240
243template <int DisplacementDim,
244 typename Gradients,
245 typename TDynForces,
246 typename ExtStateVars>
248{
249 static_assert(boost::mp11::mp_is_set<Gradients>::value);
250 static_assert(boost::mp11::mp_is_set<TDynForces>::value);
251 static_assert(boost::mp11::mp_is_set<ExtStateVars>::value);
252
254 boost::mp11::mp_append<Gradients, ExtStateVars>;
255
256 static_assert(boost::mp11::mp_is_set<GradientsAndExtStateVars>::value);
257
258public:
265
267 mgis::behaviour::Behaviour&& behaviour,
268 std::vector<ParameterLib::Parameter<double> const*>&&
269 material_properties,
270 std::map<std::string, ParameterLib::Parameter<double> const*>&&
271 state_variables_initial_properties,
272 std::optional<ParameterLib::CoordinateSystem> const&
273 local_coordinate_system)
274 : _behaviour(std::move(behaviour)),
277 _material_properties(std::move(material_properties)),
279 std::move(state_variables_initial_properties)),
280 _local_coordinate_system(local_coordinate_system
281 ? &local_coordinate_system.value()
282 : nullptr)
283 {
284 {
285 auto check_gradient = [&grads = _behaviour.gradients,
286 hyp = _behaviour.hypothesis,
287 i = 0]<typename Grad>(Grad) mutable
288 {
289 // TODO allow reordering of gradients and thermodynamic forces?
290 if (grads[i].name != Grad::name)
291 {
292 OGS_FATAL(
293 "OGS expects the {}th gradient to be {} but MFront "
294 "provides {}.",
295 i, Grad::name, grads[i].name);
296 }
297
298 if (grads[i].type != Grad::type)
299 {
300 OGS_FATAL(
301 "The behaviour's {}th driver ({}) must be of type {}.",
302 i, grads[i].name, varTypeToString(Grad::type));
303 }
304
305 if (mgis::behaviour::getVariableSize(grads[i], hyp) !=
306 Grad::template size<DisplacementDim>())
307 {
308 OGS_FATAL(
309 "The behaviour's {}th driver's ({}) size in OGS is {} "
310 "but {} in MFront.",
311 i, grads[i].name,
312 Grad::template size<DisplacementDim>(),
313 mgis::behaviour::getVariableSize(grads[i], hyp));
314 }
315
316 i++;
317 };
318
319 if (_behaviour.gradients.size() !=
320 boost::mp11::mp_size<Gradients>::value)
321 OGS_FATAL(
322 "The behaviour must have exactly {} gradients as input.",
323 boost::mp11::mp_size<Gradients>::value);
324
325 boost::mp11::mp_for_each<Gradients>(check_gradient);
326 }
327
328 {
329 auto check_tdyn_force = [&tdfs = _behaviour.thermodynamic_forces,
330 hyp = _behaviour.hypothesis,
331 i = 0]<typename TDF>(TDF) mutable
332 {
333 if (tdfs[i].name != TDF::name)
334 {
335 OGS_FATAL(
336 "OGS expects the {}th thermodynamic force to be {} but "
337 "MFront provides {}.",
338 i, TDF::name, tdfs[i].name);
339 }
340
341 if (tdfs[i].type != TDF::type)
342 {
343 OGS_FATAL(
344 "The behaviour's {}th thermodynamic force ({}) must be "
345 "of type {}.",
346 i, tdfs[i].name, varTypeToString(TDF::type));
347 }
348
349 if (mgis::behaviour::getVariableSize(tdfs[i], hyp) !=
350 TDF::template size<DisplacementDim>())
351 {
352 OGS_FATAL(
353 "The behaviour's {}th thermodynamic force ({}) must "
354 "have size {} instead of {}.",
355 i, tdfs[i].name, TDF::template size<DisplacementDim>(),
356 mgis::behaviour::getVariableSize(tdfs[i], hyp));
357 }
358
359 i++;
360 };
361
362 if (_behaviour.thermodynamic_forces.size() !=
363 boost::mp11::mp_size<TDynForces>::value)
364 OGS_FATAL(
365 "The behaviour must compute exactly {} thermodynamic "
366 "forces.",
367 boost::mp11::mp_size<TDynForces>::value);
368
369 boost::mp11::mp_for_each<TDynForces>(check_tdyn_force);
370 }
371
372 auto const hypothesis = _behaviour.hypothesis;
373
374 static_assert(
375 std::is_same_v<ExtStateVars, boost::mp11::mp_list<Temperature>>,
376 "Temperature is the only allowed external state variable.");
377
378 if (!_behaviour.esvs.empty())
379 {
380 if (_behaviour.esvs[0].name != "Temperature")
381 {
382 OGS_FATAL(
383 "Only temperature is supported as external state "
384 "variable.");
385 }
386
387 if (mgis::behaviour::getVariableSize(_behaviour.esvs[0],
388 hypothesis) != 1)
389 OGS_FATAL(
390 "Temperature must be a scalar instead of having {:d} "
391 "components.",
392 mgis::behaviour::getVariableSize(
393 _behaviour.thermodynamic_forces[0], hypothesis));
394 }
395
396 if (_behaviour.mps.size() != _material_properties.size())
397 {
398 ERR("There are {:d} material properties in the loaded behaviour:",
399 _behaviour.mps.size());
400 for (auto const& mp : _behaviour.mps)
401 {
402 ERR("\t{:s}", mp.name);
403 }
404 OGS_FATAL("But the number of passed material properties is {:d}.",
405 _material_properties.size());
406 }
407 }
408
409 std::unique_ptr<
410 typename MechanicsBase<DisplacementDim>::MaterialStateVariables>
412 {
413 return std::make_unique<MaterialStateVariablesMFront<DisplacementDim>>(
415 }
416
418 double const t,
421 material_state_variables) const
422 {
424 &material_state_variables));
425
426 auto& state =
428 material_state_variables);
429
430 auto const& ivs = getInternalVariables();
431
432 for (auto& [name, parameter] : _state_variables_initial_properties)
433 {
434 // find corresponding internal variable
435 auto const& iv = BaseLib::findElementOrError(
436 ivs,
437 [name = name](InternalVariable const& iv)
438 { return iv.name == name; },
439 [name = name]()
440 { OGS_FATAL("Internal variable `{:s}' not found.", name); });
441
442 // evaluate parameter
443 std::vector<double> values = (*parameter)(t, x);
444
445 // copy parameter data into iv
446 auto const values_span = iv.reference(state);
447 assert(values.size() == values_span.size());
448 std::copy_n(begin(values), values_span.size(), values_span.begin());
449 }
450
451 auto const& s1 = state._behaviour_data.s1.internal_state_variables;
452 auto& s0 = state._behaviour_data.s0.internal_state_variables;
453 std::copy(begin(s1), end(s1), begin(s0));
454 }
455
456 std::optional<std::tuple<OGSMFrontThermodynamicForcesData,
457 std::unique_ptr<typename MechanicsBase<
458 DisplacementDim>::MaterialStateVariables>,
461 MaterialPropertyLib::VariableArray const& variable_array_prev,
462 MaterialPropertyLib::VariableArray const& variable_array,
463 double const t,
465 double const dt,
467 material_state_variables) const
468 {
469 using namespace MathLib::KelvinVector;
470
471 assert(
473 &material_state_variables));
474 // New state, copy of current one, packed in unique_ptr for return.
475 auto state = std::make_unique<
478 material_state_variables));
479 auto& behaviour_data = state->_behaviour_data;
480
481 behaviour_data.dt = dt;
482 behaviour_data.rdt = 1.0;
483 behaviour_data.K[0] =
484 4.0; // if K[0] is greater than 3.5, the consistent
485 // tangent operator must be computed.
486 if (behaviour_data.s0.b.btype ==
487 mgis::behaviour::Behaviour::STANDARDFINITESTRAINBEHAVIOUR)
488 {
489 behaviour_data.K[1] = 1.0; // The second Piola-Kirchoff stress is
490 // used for the stress measure
491 behaviour_data.K[2] =
492 1.0; // The derivative of the second
493 // Piola-Kirchoff stress with respect to
494 // the Green-Lagrange strain is returned.
495 }
496
497 // evaluate parameters at (t, x)
498 {
499 {
500 auto out = behaviour_data.s0.material_properties.begin();
501 for (auto* param : _material_properties)
502 {
503 auto const& vals = (*param)(t - dt, x);
504 out = std::copy(vals.begin(), vals.end(), out);
505 }
506 assert(out == behaviour_data.s0.material_properties.end());
507 }
508
509 {
510 auto out = behaviour_data.s1.material_properties.begin();
511 for (auto* param : _material_properties)
512 {
513 auto const& vals = (*param)(t, x);
514 out = std::copy(vals.begin(), vals.end(), out);
515 }
516 assert(out == behaviour_data.s1.material_properties.end());
517 }
518 }
519
520 // TODO unify with gradient handling? Make gradient and external state
521 // var input both optional?
522 if (!behaviour_data.s0.external_state_variables.empty())
523 {
524 // assuming that there is only temperature
525 // NOTE the temperature can be NaN, e.g., if OGS's process does not
526 // have a temperature defined
527 behaviour_data.s0.external_state_variables[0] =
528 variable_array_prev.temperature;
529 }
530
531 if (!behaviour_data.s1.external_state_variables.empty())
532 {
533 // assuming that there is only temperature
534 // NOTE the temperature can be NaN, e.g., if OGS's process does not
535 // have a temperature defined
536 behaviour_data.s1.external_state_variables[0] =
537 variable_array.temperature;
538 }
539
540 // rotation tensor
541 std::optional<KelvinMatrixType<DisplacementDim>> Q;
543 {
545 _local_coordinate_system->transformation<DisplacementDim>(x));
546 }
547
548 boost::mp11::mp_for_each<Gradients>(
550 variable_array_prev, Q, behaviour_data.s0.gradients.data()});
551 boost::mp11::mp_for_each<Gradients>(
553 variable_array, Q, behaviour_data.s1.gradients.data()});
554
555 // previous and current state of thermodynamic forces are both set from
556 // variable_array_prev. TODO optimization potential compute Q * grad_ogs
557 // only once for both cases.
558 boost::mp11::mp_for_each<TDynForces>(
560 variable_array_prev, Q,
561 behaviour_data.s0.thermodynamic_forces.data()});
562 boost::mp11::mp_for_each<TDynForces>(
564 variable_array_prev, Q,
565 behaviour_data.s1.thermodynamic_forces.data()});
566
567 auto v = mgis::behaviour::make_view(behaviour_data);
568 auto const status = mgis::behaviour::integrate(v, _behaviour);
569 if (status != 1)
570 {
572 "MFront: integration failed with status " +
573 std::to_string(status) + ".");
574 }
575
576 OGSMFrontThermodynamicForcesData tdyn_forces_data;
577 tdyn_forces_data.data.resize( // TODO data stored on heap but size is
578 // compile-time constant
579 behaviour_data.s1.thermodynamic_forces.size());
580
581 boost::mp11::mp_for_each<TDynForces>(
582 [&out_data = tdyn_forces_data,
583 &in_data = behaviour_data.s1.thermodynamic_forces,
584 &Q]<typename TDF>(TDF tdf)
585 {
586 OGSMFrontThermodynamicForcesView<DisplacementDim, TDynForces>
587 view;
588
589 if constexpr (TDF::type ==
590 mgis::behaviour::Variable::Type::STENSOR)
591 {
592 if (Q)
593 {
594 view.block(tdf, out_data) =
595 *Q * eigenSwap45View(view.block(tdf, in_data));
596 }
597 else
598 {
599 view.block(tdf, out_data) =
600 eigenSwap45View(view.block(tdf, in_data));
601 }
602 }
603 else if constexpr (TDF::type ==
604 mgis::behaviour::Variable::Type::SCALAR)
605 {
606 view.block(tdf, out_data) = view.block(tdf, in_data);
607 }
608 else
609 {
610 OGS_FATAL("Not yet implemented.");
611 }
612 });
613
614 return std::make_optional(
615 std::make_tuple<OGSMFrontThermodynamicForcesData,
616 std::unique_ptr<typename MechanicsBase<
617 DisplacementDim>::MaterialStateVariables>,
619 std::move(tdyn_forces_data),
620 std::move(state),
622 behaviour_data.K, Q, _behaviour)));
623 }
624
625 std::vector<InternalVariable> getInternalVariables() const
626 {
627 std::vector<InternalVariable> internal_variables;
628
629 for (auto const& iv : _behaviour.isvs)
630 {
631 auto const name = iv.name;
632 auto const offset = mgis::behaviour::getVariableOffset(
633 _behaviour.isvs, name, _behaviour.hypothesis);
634 auto const size =
635 mgis::behaviour::getVariableSize(iv, _behaviour.hypothesis);
636
637 // TODO (naumov): For orthotropic materials the internal variables
638 // should be rotated to the global coordinate system before output.
639 // MFront stores the variables in local coordinate system.
640 // The `size` variable could be used to find out the type of
641 // variable.
642 InternalVariable new_variable{
643 name, static_cast<int>(size),
644 [offset, size](
645 typename MechanicsBase<
646 DisplacementDim>::MaterialStateVariables const& state,
647 std::vector<double>& cache) -> std::vector<double> const&
648 {
649 assert(dynamic_cast<MaterialStateVariablesMFront<
650 DisplacementDim> const*>(&state) != nullptr);
651 auto const& internal_state_variables =
653 DisplacementDim> const&>(state)
654 ._behaviour_data.s1.internal_state_variables;
655
656 cache.resize(size);
657 std::copy_n(internal_state_variables.data() + offset,
658 size,
659 begin(cache));
660 return cache;
661 },
662 [offset, size](typename MechanicsBase<
663 DisplacementDim>::MaterialStateVariables& state)
664 -> std::span<double>
665 {
666 assert(dynamic_cast<MaterialStateVariablesMFront<
667 DisplacementDim> const*>(&state) != nullptr);
668 auto& internal_state_variables =
669 static_cast<
671 state)
672 ._behaviour_data.s1.internal_state_variables;
673
674 return {internal_state_variables.data() + offset, size};
675 }};
676 internal_variables.push_back(new_variable);
677 }
678
679 return internal_variables;
680 }
681
682 template <typename ForcesGradsCombinations =
683 typename ForcesGradsCombinations<Gradients, TDynForces,
684 ExtStateVars>::type>
687 {
688 return OGSMFrontTangentOperatorBlocksView<DisplacementDim,
690 _behaviour.to_blocks};
691 }
692
698
699 double getBulkModulus(double const /*t*/,
701 KelvinMatrix const* const C) const
702 {
703 if (C == nullptr)
704 {
705 OGS_FATAL(
706 "MFront::getBulkModulus() requires the tangent stiffness C "
707 "input "
708 "argument to be valid.");
709 }
712 DisplacementDim)>::identity2;
713 return 1. / 9. * identity2.transpose() * *C * identity2;
714 }
715
717 double const /*t*/,
719 double const /*dt*/,
720 KelvinVector const& /*eps*/,
721 KelvinVector const& /*sigma*/,
723 /*material_state_variables*/) const
724 {
725 // TODO implement
726 return std::numeric_limits<double>::quiet_NaN();
727 }
728
729private:
730 mgis::behaviour::Behaviour _behaviour;
732 std::vector<ParameterLib::Parameter<double> const*> _material_properties;
733 std::map<std::string, ParameterLib::Parameter<double> const*>
736};
737} // namespace MaterialLib::Solids::MFront
#define OGS_FATAL(...)
Definition Error.h:26
std::optional< std::tuple< OGSMFrontThermodynamicForcesData, std::unique_ptr< typename MechanicsBase< DisplacementDim >::MaterialStateVariables >, OGSMFrontTangentOperatorData > > integrateStress(MaterialPropertyLib::VariableArray const &variable_array_prev, MaterialPropertyLib::VariableArray const &variable_array, double const t, ParameterLib::SpatialPosition const &x, double const dt, typename MechanicsBase< DisplacementDim >::MaterialStateVariables const &material_state_variables) const
OGSMFrontTangentOperatorBlocksView< DisplacementDim, ForcesGradsCombinations > createTangentOperatorBlocksView() const
std::unique_ptr< typename MechanicsBase< DisplacementDim >::MaterialStateVariables > createMaterialStateVariables() const
double computeFreeEnergyDensity(double const, ParameterLib::SpatialPosition const &, double const, KelvinVector const &, KelvinVector const &, typename MechanicsBase< DisplacementDim >::MaterialStateVariables const &) const
OGSMFrontThermodynamicForcesView< DisplacementDim, TDynForces > createThermodynamicForcesView() const
void initializeInternalStateVariables(double const t, ParameterLib::SpatialPosition const &x, typename MechanicsBase< DisplacementDim >::MaterialStateVariables &material_state_variables) const
MFrontGeneric(mgis::behaviour::Behaviour &&behaviour, std::vector< ParameterLib::Parameter< double > const * > &&material_properties, std::map< std::string, ParameterLib::Parameter< double > const * > &&state_variables_initial_properties, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system)
double getBulkModulus(double const, ParameterLib::SpatialPosition const &, KelvinMatrix const *const C) const
ranges::range_reference_t< Range > findElementOrError(Range &range, std::predicate< ranges::range_reference_t< Range > > auto &&predicate, std::invocable auto error_callback)
Definition Algorithm.h:81
typename MapToMPLType< DisplacementDim, MFrontType >::type MapToMPLType_t
OGSMFrontTangentOperatorData tangentOperatorDataMFrontToOGS(std::vector< double > const &mfront_data, std::optional< MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > const &Q, mgis::behaviour::Behaviour const &behaviour)
constexpr auto ogsTensorToMFrontTensor(Eigen::MatrixBase< Derived > const &matrix)
constexpr auto eigenSwap45View(Eigen::MatrixBase< Derived > const &matrix)
const char * varTypeToString(int v)
int getEquivalentPlasticStrainOffset(mgis::behaviour::Behaviour const &b)
Eigen::Matrix< double, tensorSize(Dim), 1 > Tensor
Definition Tensor.h:52
Eigen::Matrix< double, symmetric_tensor_size< GlobalDim >, 1 > SymmetricTensor
KelvinMatrixType< DisplacementDim > fourthOrderRotationMatrix(Eigen::Matrix< double, DisplacementDim, DisplacementDim, Eigen::ColMajor, DisplacementDim, DisplacementDim > const &transformation)
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
const Eigen::Matrix< double, KelvinVectorSize, 1 > Invariants< KelvinVectorSize >::identity2
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), kelvin_vector_dimensions(DisplacementDim), Eigen::RowMajor > KelvinMatrixType
static const double v
static const double t
MaterialStateVariablesMFront(int const equivalent_plastic_strain_offset, mgis::behaviour::Behaviour const &b)
MaterialStateVariablesMFront(MaterialStateVariablesMFront< DisplacementDim > &&)=delete
MaterialStateVariablesMFront(MaterialStateVariablesMFront< DisplacementDim > const &)=default
Used for disambiguation with MFront's thermodynamic forces data.
Used for disambiguation with MFront's tangent operator blocks data.
A struct mapping a MGIS variable type to its corresponding OGS type.
std::optional< MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > const & Q
MaterialPropertyLib::VariableArray const & variable_array
Helper type for providing access to internal variables.
A local coordinate system used for tensor transformations.