From fb19014ddffb552fce58b9794c46190861725dcc Mon Sep 17 00:00:00 2001
From: Dmitri Naumov <github@naumov.de>
Date: Mon, 27 Feb 2023 17:36:43 +0100
Subject: [PATCH] [PL/LD] LargeDeformation using MFront

Implementation of a finite strain mechanics process based solely on the
MFront material models.
---
 Applications/ApplicationsLib/ProjectData.cpp  |  32 ++
 .../LARGE_DEFORMATION/c_LARGE_DEFORMATION.md  |   1 +
 .../LARGE_DEFORMATION/constitutive_relation   |   1 +
 .../process_variables/i_process_variables.md  |   0
 .../process_variables/t_process_variable.md   |   1 +
 .../LARGE_DEFORMATION/t_initial_stress.md     |   1 +
 .../t_reference_temperature.md                |   1 +
 .../t_specific_body_force.md                  |   1 +
 ProcessLib/Deformation/GMatrixPolicy.h        |  13 +-
 ProcessLib/Deformation/NonLinearBMatrix.h     | 120 +++++
 ProcessLib/LargeDeformation/CMakeLists.txt    |  16 +
 .../ConstitutiveRelations/Base.h              | 159 +++++++
 .../ConstitutiveRelations/ConstitutiveData.h  |  84 ++++
 .../ConstitutiveModels.h                      |  38 ++
 .../ConstitutiveSetting.cpp                   |  62 +++
 .../ConstitutiveSetting.h                     |  42 ++
 .../CreateConstitutiveSetting.cpp             |  54 +++
 .../CreateConstitutiveSetting.h               |  31 ++
 .../ConstitutiveRelations/Gravity.cpp         |  23 +
 .../ConstitutiveRelations/Gravity.h           |  40 ++
 .../ConstitutiveRelations/Invoke.h            |  54 +++
 .../ConstitutiveRelations/MaterialState.h     |  32 ++
 .../ConstitutiveRelations/SolidDensity.cpp    |  26 ++
 .../ConstitutiveRelations/SolidDensity.h      |  24 +
 .../ConstitutiveRelations/SolidMechanics.cpp  |  85 ++++
 .../ConstitutiveRelations/SolidMechanics.h    |  85 ++++
 .../ConstitutiveRelations/StressData.h        |  32 ++
 .../CreateLargeDeformationProcess.cpp         | 162 +++++++
 .../CreateLargeDeformationProcess.h           |  85 ++++
 .../LargeDeformation/CreateLocalAssemblers.h  |  91 ++++
 .../LargeDeformation/IntegrationPointData.h   |  26 ++
 .../LargeDeformation/LargeDeformationFEM.h    | 415 ++++++++++++++++++
 .../LargeDeformationProcess.cpp               | 217 +++++++++
 .../LargeDeformationProcess.h                 |  89 ++++
 .../LargeDeformationProcessData.h             |  62 +++
 .../LocalAssemblerInterface.h                 | 176 ++++++++
 scripts/cmake/ProcessesSetup.cmake            |   4 +
 37 files changed, 2379 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/c_LARGE_DEFORMATION.md
 create mode 120000 Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/constitutive_relation
 create mode 100644 Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/process_variables/i_process_variables.md
 create mode 100644 Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/process_variables/t_process_variable.md
 create mode 100644 Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_initial_stress.md
 create mode 100644 Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_reference_temperature.md
 create mode 100644 Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_specific_body_force.md
 create mode 100644 ProcessLib/Deformation/NonLinearBMatrix.h
 create mode 100644 ProcessLib/LargeDeformation/CMakeLists.txt
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/Base.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveData.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveModels.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.cpp
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.cpp
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.cpp
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/Invoke.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/MaterialState.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.cpp
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.cpp
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.h
 create mode 100644 ProcessLib/LargeDeformation/ConstitutiveRelations/StressData.h
 create mode 100644 ProcessLib/LargeDeformation/CreateLargeDeformationProcess.cpp
 create mode 100644 ProcessLib/LargeDeformation/CreateLargeDeformationProcess.h
 create mode 100644 ProcessLib/LargeDeformation/CreateLocalAssemblers.h
 create mode 100644 ProcessLib/LargeDeformation/IntegrationPointData.h
 create mode 100644 ProcessLib/LargeDeformation/LargeDeformationFEM.h
 create mode 100644 ProcessLib/LargeDeformation/LargeDeformationProcess.cpp
 create mode 100644 ProcessLib/LargeDeformation/LargeDeformationProcess.h
 create mode 100644 ProcessLib/LargeDeformation/LargeDeformationProcessData.h
 create mode 100644 ProcessLib/LargeDeformation/LocalAssemblerInterface.h

diff --git a/Applications/ApplicationsLib/ProjectData.cpp b/Applications/ApplicationsLib/ProjectData.cpp
index cf9658d5d8c..d1bbb257401 100644
--- a/Applications/ApplicationsLib/ProjectData.cpp
+++ b/Applications/ApplicationsLib/ProjectData.cpp
@@ -85,6 +85,9 @@
 #ifdef OGS_BUILD_PROCESS_HYDROMECHANICS
 #include "ProcessLib/HydroMechanics/CreateHydroMechanicsProcess.h"
 #endif
+#ifdef OGS_BUILD_PROCESS_LARGEDEFORMATION
+#include "ProcessLib/LargeDeformation/CreateLargeDeformationProcess.h"
+#endif
 #ifdef OGS_BUILD_PROCESS_LIE
 #include "ProcessLib/LIE/HydroMechanics/CreateHydroMechanicsProcess.h"
 #include "ProcessLib/LIE/SmallDeformation/CreateSmallDeformationProcess.h"
@@ -874,6 +877,35 @@ void ProjectData::parseProcesses(
         }
         else
 #endif
+#ifdef OGS_BUILD_PROCESS_LARGEDEFORMATION
+            if (type == "LARGE_DEFORMATION")
+        {
+            switch (_mesh_vec[0]->getDimension())
+            {
+                case 2:
+                    process = ProcessLib::LargeDeformation::
+                        createLargeDeformationProcess<2>(
+                            name, *_mesh_vec[0], std::move(jacobian_assembler),
+                            _process_variables, _parameters,
+                            _local_coordinate_system, integration_order,
+                            process_config, _media);
+                    break;
+                case 3:
+                    process = ProcessLib::LargeDeformation::
+                        createLargeDeformationProcess<3>(
+                            name, *_mesh_vec[0], std::move(jacobian_assembler),
+                            _process_variables, _parameters,
+                            _local_coordinate_system, integration_order,
+                            process_config, _media);
+                    break;
+                default:
+                    OGS_FATAL(
+                        "LARGE_DEFORMATION process does not support given "
+                        "dimension");
+            }
+        }
+        else
+#endif
 #ifdef OGS_BUILD_PROCESS_LIE
             if (type == "HYDRO_MECHANICS_WITH_LIE")
         {
diff --git a/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/c_LARGE_DEFORMATION.md b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/c_LARGE_DEFORMATION.md
new file mode 100644
index 00000000000..5349d2c6274
--- /dev/null
+++ b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/c_LARGE_DEFORMATION.md
@@ -0,0 +1 @@
+Finite strain deformation process.
diff --git a/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/constitutive_relation b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/constitutive_relation
new file mode 120000
index 00000000000..cfcb5e03bbe
--- /dev/null
+++ b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/constitutive_relation
@@ -0,0 +1 @@
+../../../../material/solid/constitutive_relation
\ No newline at end of file
diff --git a/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/process_variables/i_process_variables.md b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/process_variables/i_process_variables.md
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/process_variables/t_process_variable.md b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/process_variables/t_process_variable.md
new file mode 100644
index 00000000000..d55b23cfca7
--- /dev/null
+++ b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/process_variables/t_process_variable.md
@@ -0,0 +1 @@
+The displacement vector field.
diff --git a/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_initial_stress.md b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_initial_stress.md
new file mode 100644
index 00000000000..9832658f886
--- /dev/null
+++ b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_initial_stress.md
@@ -0,0 +1 @@
+\copydoc ProcessLib::SmallDeformation::SmallDeformationProcessData::initial_stress
diff --git a/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_reference_temperature.md b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_reference_temperature.md
new file mode 100644
index 00000000000..ce255b04b79
--- /dev/null
+++ b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_reference_temperature.md
@@ -0,0 +1 @@
+Reference temperature, an optional input.
diff --git a/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_specific_body_force.md b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_specific_body_force.md
new file mode 100644
index 00000000000..a481e852d81
--- /dev/null
+++ b/Documentation/ProjectFile/prj/processes/process/LARGE_DEFORMATION/t_specific_body_force.md
@@ -0,0 +1 @@
+\copydoc ProcessLib::SmallDeformation::SmallDeformationProcessData::specific_body_force
diff --git a/ProcessLib/Deformation/GMatrixPolicy.h b/ProcessLib/Deformation/GMatrixPolicy.h
index 363222a461b..2665fd33521 100644
--- a/ProcessLib/Deformation/GMatrixPolicy.h
+++ b/ProcessLib/Deformation/GMatrixPolicy.h
@@ -20,11 +20,11 @@ template <typename ShapeFunction, int DisplacementDim>
 class GMatrixPolicyType
 {
 private:
-    /// Reusing the ShapeMatrixPolicy vector type.
+    /// Fixed size vector type independent of the ShapeMatrixPolicy needed for
+    /// storage of gradient vector in the MPL VariableArray.
     template <int N>
-    using VectorType =
-        typename ShapeMatrixPolicyType<ShapeFunction,
-                                       DisplacementDim>::template VectorType<N>;
+    using VectorTypeFixedSize = typename EigenFixedShapeMatrixPolicy<
+        ShapeFunction, DisplacementDim>::template VectorType<N>;
 
     /// Reusing the ShapeMatrixPolicy matrix type.
     template <int N, int M>
@@ -40,7 +40,8 @@ public:
     using GradientMatrixType = MatrixType<DisplacementDim * DisplacementDim +
                                               (DisplacementDim == 2 ? 1 : 0),
                                           _number_of_dof>;
-    using GradientVectorType = VectorType<DisplacementDim * DisplacementDim +
-                                          (DisplacementDim == 2 ? 1 : 0)>;
+    using GradientVectorType =
+        VectorTypeFixedSize<DisplacementDim * DisplacementDim +
+                            (DisplacementDim == 2 ? 1 : 0)>;
 };
 }  // namespace ProcessLib
diff --git a/ProcessLib/Deformation/NonLinearBMatrix.h b/ProcessLib/Deformation/NonLinearBMatrix.h
new file mode 100644
index 00000000000..4b191a41849
--- /dev/null
+++ b/ProcessLib/Deformation/NonLinearBMatrix.h
@@ -0,0 +1,120 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <cmath>
+
+#include "ProcessLib/Deformation/BMatrixPolicy.h"
+
+namespace ProcessLib
+{
+namespace NonLinearBMatrix
+{
+/// Fills a non linear B-matrix based on given shape function dN/dx values and
+/// displacement gradient.
+template <int DisplacementDim,
+          int NPOINTS,
+          typename BMatrixType,
+          typename GradientVectorType,
+          typename N_Type,
+          typename DNDX_Type>
+BMatrixType computeBMatrix(DNDX_Type const& dNdx,
+                           N_Type const& N,
+                           GradientVectorType const& grad_u,
+                           const double radius,
+                           const bool is_axially_symmetric)
+{
+    static_assert(0 < DisplacementDim && DisplacementDim <= 3,
+                  "NonLinearBMatrix::computeBMatrix: DisplacementDim must be "
+                  "in range [1,3].");
+
+    BMatrixType B = BMatrixType::Zero(
+        MathLib::KelvinVector::kelvin_vector_dimensions(DisplacementDim),
+        NPOINTS * DisplacementDim);
+
+    switch (DisplacementDim)
+    {
+        case 3:
+            for (int i = 0; i < NPOINTS; ++i)
+            {
+                B(0, i) = dNdx(0, i) * grad_u[0];
+                B(1, i) = dNdx(1, i) * grad_u[1];
+                B(2, i) = dNdx(2, i) * grad_u[2];
+
+                B(0, NPOINTS + i) = dNdx(0, i) * grad_u[3];
+                B(1, NPOINTS + i) = dNdx(1, i) * grad_u[4];
+                B(2, NPOINTS + i) = dNdx(2, i) * grad_u[5];
+
+                B(0, 2 * NPOINTS + i) = dNdx(0, i) * grad_u[6];
+                B(1, 2 * NPOINTS + i) = dNdx(1, i) * grad_u[7];
+                B(2, 2 * NPOINTS + i) = dNdx(2, i) * grad_u[8];
+
+                B(3, i) = (dNdx(1, i) * grad_u[0] + dNdx(0, i) * grad_u[1]) /
+                          std::sqrt(2);
+                B(4, i) = (dNdx(2, i) * grad_u[1] + dNdx(1, i) * grad_u[2]) /
+                          std::sqrt(2);
+                B(5, i) = (dNdx(2, i) * grad_u[0] + dNdx(0, i) * grad_u[2]) /
+                          std::sqrt(2);
+
+                B(3, NPOINTS + i) =
+                    (dNdx(1, i) * grad_u[3] + dNdx(0, i) * grad_u[4]) /
+                    std::sqrt(2);
+                B(4, NPOINTS + i) =
+                    (dNdx(2, i) * grad_u[4] + dNdx(1, i) * grad_u[5]) /
+                    std::sqrt(2);
+                B(5, NPOINTS + i) =
+                    (dNdx(2, i) * grad_u[3] + dNdx(0, i) * grad_u[5]) /
+                    std::sqrt(2);
+
+                B(3, 2 * NPOINTS + i) =
+                    (dNdx(1, i) * grad_u[6] + dNdx(0, i) * grad_u[7]) /
+                    std::sqrt(2);
+                B(4, 2 * NPOINTS + i) =
+                    (dNdx(2, i) * grad_u[7] + dNdx(1, i) * grad_u[8]) /
+                    std::sqrt(2);
+                B(5, 2 * NPOINTS + i) =
+                    (dNdx(2, i) * grad_u[6] + dNdx(0, i) * grad_u[8]) /
+                    std::sqrt(2);
+            }
+            break;
+        case 2:
+            for (int i = 0; i < NPOINTS; ++i)
+            {
+                B(0, i) = dNdx(0, i) * grad_u[0];
+                B(1, i) = dNdx(1, i) * grad_u[1];
+                // B(2, i) = 0;
+
+                B(0, NPOINTS + i) = dNdx(0, i) * grad_u[2];
+                B(1, NPOINTS + i) = dNdx(1, i) * grad_u[3];
+                // B(2, NPOINTS + i) = 0;
+
+                B(3, i) = (dNdx(1, i) * grad_u[0] + dNdx(0, i) * grad_u[1]) /
+                          std::sqrt(2);
+                B(3, NPOINTS + i) =
+                    (dNdx(1, i) * grad_u[2] + dNdx(0, i) * grad_u[3]) /
+                    std::sqrt(2);
+            }
+            if (is_axially_symmetric)
+            {
+                for (int i = 0; i < NPOINTS; ++i)
+                {
+                    B(2, i) = grad_u[4] * N[i] / radius;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+
+    return B;
+}
+}  // namespace NonLinearBMatrix
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/CMakeLists.txt b/ProcessLib/LargeDeformation/CMakeLists.txt
new file mode 100644
index 00000000000..f8a62ae04ab
--- /dev/null
+++ b/ProcessLib/LargeDeformation/CMakeLists.txt
@@ -0,0 +1,16 @@
+get_source_files(SOURCES)
+append_source_files(SOURCES ConstitutiveRelations)
+
+if (NOT OGS_USE_MFRONT)
+    message(FATAL_ERROR
+"LargeDeformations process without MFront library is not available. Use enable \
+MFront in the CMake settings via OGS_USE_MFRONT variable.")
+endif()
+
+ogs_add_library(LargeDeformation ${SOURCES})
+target_link_libraries(LargeDeformation PUBLIC ProcessLib PRIVATE ParameterLib)
+
+target_precompile_headers(LargeDeformation PRIVATE [["BaseLib/Error.h"]]
+    [["BaseLib/ConfigTree.h"]] [["BaseLib/Logging.h"]]
+    [["ProcessLib/Process.h"]] [["MaterialLib/MPL/Medium.h"]]
+    [["MaterialLib/MPL/Property.h"]] <Eigen/Core>)
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/Base.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/Base.h
new file mode 100644
index 00000000000..04493186ac8
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/Base.h
@@ -0,0 +1,159 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "BaseLib/StrongType.h"
+#include "MaterialLib/MPL/Medium.h"
+#include "MaterialLib/MPL/Utils/Tensor.h"
+#include "MathLib/KelvinVector.h"
+#include "ParameterLib/SpatialPosition.h"
+#include "ProcessLib/Reflection/ReflectionData.h"
+
+namespace ProcessLib::LargeDeformation
+{
+template <int DisplacementDim>
+using KelvinVector = MathLib::KelvinVector::KelvinVectorType<DisplacementDim>;
+
+template <int DisplacementDim>
+using KelvinMatrix = MathLib::KelvinVector::KelvinMatrixType<DisplacementDim>;
+
+template <int DisplacementDim>
+using GlobalDimVector = Eigen::Vector<double, DisplacementDim>;
+
+template <int DisplacementDim>
+using GlobalDimMatrix =
+    Eigen::Matrix<double, DisplacementDim, DisplacementDim, Eigen::RowMajor>;
+
+/// Convenience alias for not a number.
+static constexpr double nan = std::numeric_limits<double>::quiet_NaN();
+
+/// Used to set a Kelvin vector to all not-a-number.
+template <int DisplacementDim>
+constexpr KelvinVector<DisplacementDim> KVnan()
+{
+    return KelvinVector<DisplacementDim>::Constant(nan);
+}
+
+/// Used to set a Kelvin matrix to all not-a-number.
+template <int DisplacementDim>
+constexpr KelvinMatrix<DisplacementDim> KMnan()
+{
+    return KelvinMatrix<DisplacementDim>::Constant(nan);
+}
+
+/// Used to set a D dimensional vector to all not-a-number.
+template <int D>
+constexpr GlobalDimVector<D> DVnan()
+{
+    return GlobalDimVector<D>::Constant(nan);
+}
+
+/// Used to set a D x D matrix to all not-a-number.
+template <int D>
+constexpr GlobalDimMatrix<D> DMnan()
+{
+    return GlobalDimMatrix<D>::Constant(nan);
+}
+
+/// Used to set a Kelvin vector to all zero.
+template <int DisplacementDim>
+constexpr KelvinVector<DisplacementDim> KVzero()
+{
+    return KelvinVector<DisplacementDim>::Zero();
+}
+
+/// Used to set a Kelvin matrix to all zero.
+template <int DisplacementDim>
+constexpr KelvinMatrix<DisplacementDim> KMzero()
+{
+    return KelvinMatrix<DisplacementDim>::Zero();
+}
+
+/// Represents a previous state of type T.
+template <typename T>
+struct PrevState
+{
+    PrevState() = default;
+    explicit PrevState(T const& t) : t{t} {}
+    explicit PrevState(T&& t) : t{std::move(t)} {}
+
+    PrevState<T>& operator=(T const& u)
+    {
+        t = u;
+        return *this;
+    }
+
+    PrevState<T>& operator=(T&& u)
+    {
+        t = std::move(u);
+        return *this;
+    }
+
+    T& operator*() { return t; }
+    T const& operator*() const { return t; }
+
+    T* operator->() { return &t; }
+    T const* operator->() const { return &t; }
+
+private:
+    T t;
+};
+
+struct SpaceTimeData
+{
+    ParameterLib::SpatialPosition x;
+    double t;
+    double dt;
+};
+
+struct MediaData
+{
+    explicit MediaData(MaterialPropertyLib::Medium const& medium)
+        : medium{medium}, solid{medium.phase("Solid")}
+    {
+    }
+
+    MaterialPropertyLib::Medium const& medium;
+    MaterialPropertyLib::Phase const& solid;
+};
+
+using Temperature = BaseLib::StrongType<double, struct TemperatureTag>;
+
+template <int DisplacementDim>
+struct DeformationGradientData
+{
+    // TODO Move initialization to the local assembler.
+    MaterialPropertyLib::Tensor<DisplacementDim> deformation_gradient =
+        MaterialPropertyLib::Tensor<DisplacementDim>::Zero();
+
+    static auto reflect()
+    {
+        using Self = DeformationGradientData<DisplacementDim>;
+
+        return ProcessLib::Reflection::reflectWithName(
+            "deformation_gradient", &Self::deformation_gradient);
+    }
+};
+
+template <int DisplacementDim>
+struct StrainData
+{
+    // TODO Move initialization to the local assembler.
+    KelvinVector<DisplacementDim> eps = KVnan<DisplacementDim>();
+
+    static auto reflect()
+    {
+        using Self = StrainData<DisplacementDim>;
+
+        return ProcessLib::Reflection::reflectWithName("epsilon", &Self::eps);
+    }
+};
+
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveData.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveData.h
new file mode 100644
index 00000000000..e1a21bf1b4c
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveData.h
@@ -0,0 +1,84 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "Gravity.h"
+#include "ProcessLib/Reflection/ReflectionData.h"
+#include "SolidDensity.h"
+#include "SolidMechanics.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+/// Data whose state must be tracked by the process.
+template <int DisplacementDim>
+struct StatefulData
+{
+    StressData<DisplacementDim> stress_data;
+
+    static auto reflect()
+    {
+        using Self = StatefulData<DisplacementDim>;
+
+        return Reflection::reflectWithoutName(&Self::stress_data);
+    }
+};
+
+/// Data whose state must be tracked by the process.
+template <int DisplacementDim>
+struct StatefulDataPrev
+{
+    PrevState<StressData<DisplacementDim>> stress_data;
+
+    StatefulDataPrev<DisplacementDim>& operator=(
+        StatefulData<DisplacementDim> const& state)
+    {
+        stress_data = state.stress_data;
+
+        return *this;
+    }
+};
+
+/// Data that is needed for output purposes, but not directly for the assembly.
+template <int DisplacementDim>
+struct OutputData
+{
+    StrainData<DisplacementDim> eps_data;
+
+    static auto reflect()
+    {
+        using Self = OutputData<DisplacementDim>;
+
+        return Reflection::reflectWithoutName(&Self::eps_data);
+    }
+};
+
+/// Data that is needed for the equation system assembly.
+template <int DisplacementDim>
+struct ConstitutiveData
+{
+    SolidMechanicsDataStateless<DisplacementDim> s_mech_data;
+    VolumetricBodyForce<DisplacementDim> volumetric_body_force;
+};
+
+/// Data that stores intermediate values, which are not needed outside the
+/// constitutive setting.
+template <int DisplacementDim>
+struct ConstitutiveTempData
+{
+    PrevState<StrainData<DisplacementDim>> eps_data_prev;
+    DeformationGradientData<DisplacementDim> deformation_gradient_data;
+    PrevState<DeformationGradientData<DisplacementDim>>
+        deformation_gradient_data_prev;
+    SolidDensity rho_SR;
+};
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveModels.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveModels.h
new file mode 100644
index 00000000000..688a591c480
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveModels.h
@@ -0,0 +1,38 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "Gravity.h"
+#include "SolidDensity.h"
+#include "SolidMechanics.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+/// Constitutive models used for assembly.
+template <int DisplacementDim>
+struct ConstitutiveModels
+{
+    template <typename TRMProcessData>
+    explicit ConstitutiveModels(
+        TRMProcessData const& process_data,
+        SolidConstitutiveRelation<DisplacementDim> const& solid_material)
+        : s_mech_model(solid_material),
+          gravity_model(process_data.specific_body_force)
+    {
+    }
+
+    SolidMechanicsModel<DisplacementDim> s_mech_model;
+    SolidDensityModel rho_S_model;
+    GravityModel<DisplacementDim> gravity_model;
+};
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.cpp b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.cpp
new file mode 100644
index 00000000000..87b7cde859c
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.cpp
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "ConstitutiveSetting.h"
+
+#include "Invoke.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+template <int DisplacementDim>
+void ConstitutiveSetting<DisplacementDim>::eval(
+    ConstitutiveModels<DisplacementDim>& models, double const t,
+    double const dt, ParameterLib::SpatialPosition const& x_position,
+    MaterialPropertyLib::Medium const& medium, double const T_ref,
+    GradientVectorType const& deformation_gradient,
+    GradientVectorType const& deformation_gradient_prev,
+    StatefulData<DisplacementDim>& state,
+    StatefulDataPrev<DisplacementDim> const& prev_state,
+    MaterialStateData<DisplacementDim>& mat_state,
+    ConstitutiveTempData<DisplacementDim>& tmp,
+    ConstitutiveData<DisplacementDim>& cd) const
+{
+    namespace MPL = MaterialPropertyLib;
+
+    auto& deformation_gradient_data = tmp.deformation_gradient_data;
+    deformation_gradient_data.deformation_gradient = deformation_gradient;
+    auto& deformation_gradient_data_prev = tmp.deformation_gradient_data_prev;
+    deformation_gradient_data_prev->deformation_gradient =
+        deformation_gradient_prev;
+    auto& rho_SR = tmp.rho_SR;
+
+    auto& s_mech_data = cd.s_mech_data;
+    auto& volumetric_body_force = cd.volumetric_body_force;
+
+    Temperature const T{T_ref};
+    SpaceTimeData const x_t{x_position, t, dt};
+    MediaData const media_data{medium};
+
+    assertEvalArgsUnique(models.s_mech_model);
+    models.s_mech_model.eval(
+        x_t, T, deformation_gradient_data, deformation_gradient_data_prev,
+        mat_state, prev_state.stress_data, state.stress_data, s_mech_data);
+
+    assertEvalArgsUnique(models.rho_S_model);
+    models.rho_S_model.eval(x_t, media_data, T, rho_SR);
+
+    assertEvalArgsUnique(models.gravity_model);
+    models.gravity_model.eval(rho_SR, volumetric_body_force);
+}
+
+template struct ConstitutiveSetting<2>;
+template struct ConstitutiveSetting<3>;
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.h
new file mode 100644
index 00000000000..63862f0167f
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/ConstitutiveSetting.h
@@ -0,0 +1,42 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "ConstitutiveData.h"
+#include "ConstitutiveModels.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+template <int DisplacementDim>
+struct ConstitutiveSetting
+{
+    using GradientVectorType = Eigen::Matrix<
+        double,
+        DisplacementDim * DisplacementDim + (DisplacementDim == 2 ? 1 : 0), 1>;
+
+    /// Evaluate the constitutive setting.
+    void eval(ConstitutiveModels<DisplacementDim>& models, double const t,
+              double const dt, ParameterLib::SpatialPosition const& x_position,
+              MaterialPropertyLib::Medium const& medium, double const T_ref,
+              GradientVectorType const& deformation_gradient,
+              GradientVectorType const& deformation_gradient_prev,
+              StatefulData<DisplacementDim>& state,
+              StatefulDataPrev<DisplacementDim> const& prev_state,
+              MaterialStateData<DisplacementDim>& mat_state,
+              ConstitutiveTempData<DisplacementDim>& tmp,
+              ConstitutiveData<DisplacementDim>& cd) const;
+};
+
+extern template struct ConstitutiveSetting<2>;
+extern template struct ConstitutiveSetting<3>;
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.cpp b/ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.cpp
new file mode 100644
index 00000000000..0ec6c150565
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.cpp
@@ -0,0 +1,54 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "CreateConstitutiveSetting.h"
+
+#include "MaterialLib/SolidModels/CreateConstitutiveRelationsGeneric.h"
+#include "MaterialLib/SolidModels/MFront/CreateMFrontGeneric.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+template <int DisplacementDim>
+std::unique_ptr<SolidConstitutiveRelation<DisplacementDim>> createMFrontGeneric(
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    BaseLib::ConfigTree const& config)
+{
+    namespace MSM = MaterialLib::Solids::MFront;
+    using namespace boost::mp11;
+
+    bool const library_path_is_relative_to_prj_file = true;
+
+    return MSM::createMFrontGeneric<
+        DisplacementDim, mp_list<MSM::DeformationGradient>,
+        mp_list<MSM::SecondPiolaKirchhoffStress>, mp_list<MSM::Temperature>>(
+        parameters, local_coordinate_system, config,
+        library_path_is_relative_to_prj_file);
+}
+
+template <int DisplacementDim>
+std::map<int, std::unique_ptr<SolidConstitutiveRelation<DisplacementDim>>>
+CreateConstitutiveSetting<DisplacementDim>::createSolidConstitutiveRelations(
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    BaseLib::ConfigTree const& config)
+{
+    return MaterialLib::Solids::createConstitutiveRelationsGeneric(
+        parameters, local_coordinate_system, config,
+        createMFrontGeneric<DisplacementDim>);
+}
+
+template struct CreateConstitutiveSetting<2>;
+template struct CreateConstitutiveSetting<3>;
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.h
new file mode 100644
index 00000000000..300f1303d5a
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/CreateConstitutiveSetting.h
@@ -0,0 +1,31 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "SolidMechanics.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+template <int DisplacementDim>
+struct CreateConstitutiveSetting
+{
+    static std::map<int,
+                    std::unique_ptr<SolidConstitutiveRelation<DisplacementDim>>>
+    createSolidConstitutiveRelations(
+        std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const&
+            parameters,
+        std::optional<ParameterLib::CoordinateSystem> const&
+            local_coordinate_system,
+        BaseLib::ConfigTree const& config);
+};
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.cpp b/ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.cpp
new file mode 100644
index 00000000000..e12252c257d
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.cpp
@@ -0,0 +1,23 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "Gravity.h"
+
+namespace ProcessLib::LargeDeformation
+{
+template <int DisplacementDim>
+void GravityModel<DisplacementDim>::eval(
+    SolidDensity const& rho_SR, VolumetricBodyForce<DisplacementDim>& out) const
+{
+    *out = *rho_SR * specific_body_force_;
+}
+
+template struct GravityModel<2>;
+template struct GravityModel<3>;
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.h
new file mode 100644
index 00000000000..223e31ff79b
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/Gravity.h
@@ -0,0 +1,40 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "BaseLib/StrongType.h"
+#include "SolidDensity.h"
+
+namespace ProcessLib::LargeDeformation
+{
+template <int DisplacementDim>
+using VolumetricBodyForce =
+    BaseLib::StrongType<GlobalDimVector<DisplacementDim>, struct GravityTag>;
+
+template <int DisplacementDim>
+struct GravityModel
+{
+    explicit GravityModel(
+        Eigen::Vector<double, DisplacementDim> const& specific_body_force)
+        : specific_body_force_(specific_body_force)
+    {
+    }
+
+    void eval(SolidDensity const& rho_SR,
+              VolumetricBodyForce<DisplacementDim>& out) const;
+
+private:
+    // TODO (naumov) Do we need to store this for each integration point?
+    Eigen::Vector<double, DisplacementDim> const specific_body_force_;
+};
+
+extern template struct GravityModel<2>;
+extern template struct GravityModel<3>;
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/Invoke.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/Invoke.h
new file mode 100644
index 00000000000..5fd51486065
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/Invoke.h
@@ -0,0 +1,54 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include <boost/mp11.hpp>
+
+namespace ProcessLib::LargeDeformation
+{
+namespace detail
+{
+template <typename Result, typename Class, typename... Args>
+constexpr bool areEvalArgumentTypesUnique(Result (Class::*)(Args...))
+{
+    using namespace boost::mp11;
+    return mp_is_set<
+        mp_transform<std::remove_cvref_t, mp_list<Args...>>>::value;
+}
+
+template <typename Result, typename Class, typename... Args>
+constexpr bool areEvalArgumentTypesUnique(Result (Class::*)(Args...) const)
+{
+    using namespace boost::mp11;
+    return mp_is_set<
+        mp_transform<std::remove_cvref_t, mp_list<Args...>>>::value;
+}
+}  // namespace detail
+
+/// Checks whether the argument types of the eval() method of the given type T
+/// are unique.
+///
+/// Argument types differing only in constness, reference or volatility are
+/// considered equal.
+template <typename T>
+constexpr bool areEvalArgumentTypesUnique()
+{
+    return detail::areEvalArgumentTypesUnique(&T::eval);
+}
+
+/// Statically asserts that the argument types of the passed Model's eval()
+/// method are unique.
+template <typename Model>
+constexpr void assertEvalArgsUnique(Model const&)
+{
+    static_assert(areEvalArgumentTypesUnique<std::remove_cvref_t<Model>>());
+}
+
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/MaterialState.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/MaterialState.h
new file mode 100644
index 00000000000..771a7e56313
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/MaterialState.h
@@ -0,0 +1,32 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "MaterialLib/SolidModels/MechanicsBase.h"
+
+namespace ProcessLib::LargeDeformation
+{
+template <int DisplacementDim>
+class MaterialStateData
+{
+    using MSV = typename MaterialLib::Solids::MechanicsBase<
+        DisplacementDim>::MaterialStateVariables;
+
+public:
+    explicit MaterialStateData(std::unique_ptr<MSV>&& material_state_variables)
+        : material_state_variables(std::move(material_state_variables))
+    {
+    }
+
+    void pushBackState() { material_state_variables->pushBackState(); }
+
+    std::unique_ptr<MSV> material_state_variables;
+};
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.cpp b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.cpp
new file mode 100644
index 00000000000..71716ad4828
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.cpp
@@ -0,0 +1,26 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "SolidDensity.h"
+
+namespace ProcessLib::LargeDeformation
+{
+void SolidDensityModel::eval(SpaceTimeData const& x_t,
+                             MediaData const& media_data,
+                             Temperature const& temperature,
+                             SolidDensity& out) const
+{
+    namespace MPL = MaterialPropertyLib;
+    MPL::VariableArray variables;
+    variables.temperature = *temperature;
+
+    *out = media_data.solid.property(MPL::PropertyType::density)
+               .template value<double>(variables, x_t.x, x_t.t, x_t.dt);
+}
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.h
new file mode 100644
index 00000000000..b98043d0986
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidDensity.h
@@ -0,0 +1,24 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "Base.h"
+#include "BaseLib/StrongType.h"
+
+namespace ProcessLib::LargeDeformation
+{
+using SolidDensity = BaseLib::StrongType<double, struct SolidDensityTag>;
+
+struct SolidDensityModel
+{
+    void eval(SpaceTimeData const& x_t, MediaData const& media_data,
+              Temperature const& temperature, SolidDensity& out) const;
+};
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.cpp b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.cpp
new file mode 100644
index 00000000000..87b7cd5b90c
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.cpp
@@ -0,0 +1,85 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "SolidMechanics.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+template <int DisplacementDim>
+void SolidMechanicsModel<DisplacementDim>::eval(
+    SpaceTimeData const& x_t,
+    Temperature const& temperature,
+    DeformationGradientData<DisplacementDim> const& deformation_gradient_data,
+    PrevState<DeformationGradientData<DisplacementDim>> const&
+        deformation_gradient_data_prev,
+    MaterialStateData<DisplacementDim>& mat_state,
+    PrevState<StressData<DisplacementDim>> const& stress_data_prev,
+    StressData<DisplacementDim>& stress_data,
+    SolidMechanicsDataStateless<DisplacementDim>& current_stateless) const
+{
+    namespace MPL = MaterialPropertyLib;
+
+    // current state
+    MPL::VariableArray variables;
+    {
+        // thermodynamic forces
+        variables.stress = stress_data.sigma;
+
+        // gradient
+        variables.deformation_gradient =
+            deformation_gradient_data.deformation_gradient;
+
+        // external state variables
+        variables.temperature = *temperature;
+    }
+
+    // previous state
+    MPL::VariableArray variables_prev;
+    {
+        // thermodynamic forces
+        variables_prev.stress = stress_data_prev->sigma;
+
+        // gradient
+        variables_prev.deformation_gradient =
+            deformation_gradient_data_prev->deformation_gradient;
+
+        // external state variables
+        variables_prev.temperature = *temperature;
+    }
+
+    auto solution = solid_material_.integrateStress(
+        variables_prev, variables, x_t.t, x_t.x, x_t.dt,
+        *mat_state.material_state_variables);
+
+    if (!solution)
+    {
+        OGS_FATAL("Computation of local constitutive relation failed.");
+    }
+
+    auto& tdyn_forces_data = std::get<0>(*solution);
+
+    auto const view = solid_material_.createThermodynamicForcesView();
+
+    stress_data.sigma =
+        view.block(MSM::second_piola_kirchhoff_stress, tdyn_forces_data);
+    mat_state.material_state_variables = std::move(std::get<1>(*solution));
+
+    auto const& tangent_operator_data = std::get<2>(*solution);
+
+    current_stateless.stiffness_tensor = tangent_operator_blocks_view_.block(
+        MSM::second_piola_kirchhoff_stress, MSM::green_lagrange_strain,
+        tangent_operator_data);
+}
+
+template struct SolidMechanicsModel<2>;
+template struct SolidMechanicsModel<3>;
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.h
new file mode 100644
index 00000000000..1240a6687c7
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/SolidMechanics.h
@@ -0,0 +1,85 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "MaterialLib/SolidModels/MFront/MFrontGeneric.h"
+#include "MaterialLib/SolidModels/MFront/Variable.h"
+#include "MaterialState.h"
+#include "StressData.h"
+
+namespace ProcessLib::LargeDeformation
+{
+namespace ConstitutiveRelations
+{
+template <int DisplacementDim>
+struct SolidMechanicsDataStateless
+{
+    KelvinMatrix<DisplacementDim> stiffness_tensor = KMnan<DisplacementDim>();
+    KelvinVector<DisplacementDim> J_uT_BT_K_N = KVnan<DisplacementDim>();
+    KelvinVector<DisplacementDim> J_up_BT_K_N = KVnan<DisplacementDim>();
+};
+
+namespace MSM = MaterialLib::Solids::MFront;
+
+template <int DisplacementDim>
+using SolidConstitutiveRelation =
+    MSM::MFrontGeneric<DisplacementDim,
+                       boost::mp11::mp_list<MSM::DeformationGradient>,
+                       boost::mp11::mp_list<MSM::SecondPiolaKirchhoffStress>,
+                       boost::mp11::mp_list<MSM::Temperature>>;
+
+template <int DisplacementDim>
+struct SolidMechanicsModel
+{
+    explicit SolidMechanicsModel(
+        SolidConstitutiveRelation<DisplacementDim> const& solid_material)
+        : solid_material_(solid_material),
+          tangent_operator_blocks_view_{
+              solid_material.template createTangentOperatorBlocksView<
+                  typename MSM::ForcesGradsCombinations<
+                      boost::mp11::mp_list<MSM::GreenLagrangeStrain>,
+                      boost::mp11::mp_list<MSM::SecondPiolaKirchhoffStress>,
+                      boost::mp11::mp_list<MSM::Temperature>>::type>()}
+    {
+    }
+
+    void eval(
+        SpaceTimeData const& x_t,
+        Temperature const& temperature,
+        DeformationGradientData<DisplacementDim> const&
+            deformation_gradient_data,
+        PrevState<DeformationGradientData<DisplacementDim>> const&
+            deformation_gradient_data_prev,
+        MaterialStateData<DisplacementDim>& mat_state,
+        PrevState<StressData<DisplacementDim>> const& stress_data_prev,
+        StressData<DisplacementDim>& stress_data,
+        SolidMechanicsDataStateless<DisplacementDim>& current_stateless) const;
+
+    auto getInternalVariables() const
+    {
+        return solid_material_.getInternalVariables();
+    }
+
+private:
+    SolidConstitutiveRelation<DisplacementDim> const& solid_material_;
+
+    MSM::OGSMFrontTangentOperatorBlocksView<
+        DisplacementDim,
+        MSM::ForcesGradsCombinations<
+            boost::mp11::mp_list<MSM::GreenLagrangeStrain>,
+            boost::mp11::mp_list<MSM::SecondPiolaKirchhoffStress>,
+            boost::mp11::mp_list<MSM::Temperature>>::type>
+        tangent_operator_blocks_view_;
+};
+
+extern template struct SolidMechanicsModel<2>;
+extern template struct SolidMechanicsModel<3>;
+}  // namespace ConstitutiveRelations
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/ConstitutiveRelations/StressData.h b/ProcessLib/LargeDeformation/ConstitutiveRelations/StressData.h
new file mode 100644
index 00000000000..4007fd92350
--- /dev/null
+++ b/ProcessLib/LargeDeformation/ConstitutiveRelations/StressData.h
@@ -0,0 +1,32 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include "Base.h"
+
+namespace ProcessLib::LargeDeformation
+{
+
+template <int DisplacementDim>
+struct StressData
+{
+    // Stress is stateful for some constitutive settings and therefore must be
+    // initialized to something valid, e.g., zero.
+    // TODO find a better solution for that.
+    KelvinVector<DisplacementDim> sigma = KVzero<DisplacementDim>();
+
+    static auto reflect()
+    {
+        using Self = StressData<DisplacementDim>;
+
+        return ProcessLib::Reflection::reflectWithName("sigma", &Self::sigma);
+    }
+};
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/CreateLargeDeformationProcess.cpp b/ProcessLib/LargeDeformation/CreateLargeDeformationProcess.cpp
new file mode 100644
index 00000000000..6ef1479129c
--- /dev/null
+++ b/ProcessLib/LargeDeformation/CreateLargeDeformationProcess.cpp
@@ -0,0 +1,162 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "CreateLargeDeformationProcess.h"
+
+#include <cassert>
+
+#include "ConstitutiveRelations/CreateConstitutiveSetting.h"
+#include "LargeDeformationProcess.h"
+#include "LargeDeformationProcessData.h"
+#include "MaterialLib/MPL/CreateMaterialSpatialDistributionMap.h"
+#include "ParameterLib/Utils.h"
+#include "ProcessLib/Output/CreateSecondaryVariables.h"
+#include "ProcessLib/Utils/ProcessUtils.h"
+
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+template <int DisplacementDim>
+std::unique_ptr<Process> createLargeDeformationProcess(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media)
+{
+    //! \ogs_file_param{prj__processes__process__type}
+    config.checkConfigParameter("type", "LARGE_DEFORMATION");
+    DBUG("Create LargeDeformationProcess.");
+
+    /// \section processvariablesld Process Variables
+
+    //! \ogs_file_param{prj__processes__process__LARGE_DEFORMATION__process_variables}
+    auto const pv_config = config.getConfigSubtree("process_variables");
+
+    /// Primary process variables as they appear in the global component vector:
+    auto per_process_variables = findProcessVariables(
+        variables, pv_config,
+        {//! \ogs_file_param_special{prj__processes__process__LARGE_DEFORMATION__process_variables__process_variable}
+         "process_variable"});
+
+    DBUG("Associate displacement with process variable '{:s}'.",
+         per_process_variables.back().get().getName());
+
+    if (per_process_variables.back().get().getNumberOfGlobalComponents() !=
+        DisplacementDim)
+    {
+        OGS_FATAL(
+            "Number of components of the process variable '{:s}' is different "
+            "from the displacement dimension: got {:d}, expected {:d}",
+            per_process_variables.back().get().getName(),
+            per_process_variables.back().get().getNumberOfGlobalComponents(),
+            DisplacementDim);
+    }
+    std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>
+        process_variables;
+    process_variables.push_back(std::move(per_process_variables));
+
+    /// \section parametersld Process Parameters
+    auto solid_constitutive_relations =
+        ConstitutiveRelations::CreateConstitutiveSetting<DisplacementDim>::
+            createSolidConstitutiveRelations(parameters,
+                                             local_coordinate_system, config);
+
+    // Specific body force
+    Eigen::Matrix<double, DisplacementDim, 1> specific_body_force;
+    {
+        std::vector<double> const b =
+            //! \ogs_file_param{prj__processes__process__LARGE_DEFORMATION__specific_body_force}
+            config.getConfigParameter<std::vector<double>>(
+                "specific_body_force");
+        if (b.size() != DisplacementDim)
+        {
+            OGS_FATAL(
+                "The size of the specific body force vector does not match the "
+                "displacement dimension. Vector size is {:d}, displacement "
+                "dimension is {:d}",
+                b.size(), DisplacementDim);
+        }
+
+        std::copy_n(b.data(), b.size(), specific_body_force.data());
+    }
+
+    auto media_map =
+        MaterialPropertyLib::createMaterialSpatialDistributionMap(media, mesh);
+
+    // Reference temperature
+    auto const reference_temperature = ParameterLib::findOptionalTagParameter<
+        double>(
+        //! \ogs_file_param_special{prj__processes__process__LARGE_DEFORMATION__reference_temperature}
+        config, "reference_temperature", parameters, 1, &mesh);
+    if (reference_temperature)
+    {
+        DBUG("Use '{:s}' as reference temperature parameter.",
+             (*reference_temperature).name);
+    }
+
+    // Initial stress conditions
+    auto const initial_stress = ParameterLib::findOptionalTagParameter<double>(
+        //! \ogs_file_param_special{prj__processes__process__LARGE_DEFORMATION__initial_stress}
+        config, "initial_stress", parameters,
+        // Symmetric tensor size, 4 or 6, not a Kelvin vector.
+        MathLib::KelvinVector::kelvin_vector_dimensions(DisplacementDim),
+        &mesh);
+
+    LargeDeformationProcessData<DisplacementDim> process_data{
+        materialIDs(mesh),
+        std::move(media_map),
+        std::move(solid_constitutive_relations),
+        initial_stress,
+        specific_body_force,
+        reference_temperature};
+
+    SecondaryVariableCollection secondary_variables;
+
+    ProcessLib::createSecondaryVariables(config, secondary_variables);
+
+    return std::make_unique<LargeDeformationProcess<DisplacementDim>>(
+        std::move(name), mesh, std::move(jacobian_assembler), parameters,
+        integration_order, std::move(process_variables),
+        std::move(process_data), std::move(secondary_variables));
+}
+
+template std::unique_ptr<Process> createLargeDeformationProcess<2>(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+template std::unique_ptr<Process> createLargeDeformationProcess<3>(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+}  // namespace LargeDeformation
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/CreateLargeDeformationProcess.h b/ProcessLib/LargeDeformation/CreateLargeDeformationProcess.h
new file mode 100644
index 00000000000..a911b6147a3
--- /dev/null
+++ b/ProcessLib/LargeDeformation/CreateLargeDeformationProcess.h
@@ -0,0 +1,85 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace BaseLib
+{
+class ConfigTree;
+}
+namespace MaterialPropertyLib
+{
+class Medium;
+}
+namespace MeshLib
+{
+class Mesh;
+}
+namespace ParameterLib
+{
+struct CoordinateSystem;
+struct ParameterBase;
+}  // namespace ParameterLib
+namespace ProcessLib
+{
+class AbstractJacobianAssembler;
+class Process;
+class ProcessVariable;
+}  // namespace ProcessLib
+
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+template <int DisplacementDim>
+std::unique_ptr<Process> createLargeDeformationProcess(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+extern template std::unique_ptr<Process> createLargeDeformationProcess<2>(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+extern template std::unique_ptr<Process> createLargeDeformationProcess<3>(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<ProcessVariable> const& variables,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    std::optional<ParameterLib::CoordinateSystem> const&
+        local_coordinate_system,
+    unsigned const integration_order,
+    BaseLib::ConfigTree const& config,
+    std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
+
+}  // namespace LargeDeformation
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/CreateLocalAssemblers.h b/ProcessLib/LargeDeformation/CreateLocalAssemblers.h
new file mode 100644
index 00000000000..25df30ec75c
--- /dev/null
+++ b/ProcessLib/LargeDeformation/CreateLocalAssemblers.h
@@ -0,0 +1,91 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "BaseLib/Logging.h"
+#include "NumLib/DOF/LocalToGlobalIndexMap.h"
+#include "ProcessLib/Utils/LocalAssemblerFactoryForDimGreaterEqualN.h"
+
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+namespace detail
+{
+template <int GlobalDim,
+          template <typename /* shp fct */, int /* global dim */>
+          class LocalAssemblerImplementation,
+          typename LocalAssemblerInterface,
+          IntegrationMethodProviderOrIntegrationOrder ProviderOrOrder,
+          typename... ExtraCtorArgs>
+void createLocalAssemblers(
+    NumLib::LocalToGlobalIndexMap const& dof_table,
+    std::vector<MeshLib::Element*> const& mesh_elements,
+    std::vector<std::unique_ptr<LocalAssemblerInterface>>& local_assemblers,
+    ProviderOrOrder const& provider_or_order,
+    ExtraCtorArgs&&... extra_ctor_args)
+{
+    DBUG("Create local assemblers.");
+
+    auto const& integration_method_provider =
+        getIntegrationMethodProvider(provider_or_order);
+
+    using IntMethProv =
+        std::remove_cvref_t<decltype(integration_method_provider)>;
+    using LocAsmFactory = ProcessLib::LocalAssemblerFactorySD<
+        LocalAssemblerInterface, LocalAssemblerImplementation, IntMethProv,
+        GlobalDim, ExtraCtorArgs...>;
+
+    LocAsmFactory factory(dof_table, integration_method_provider);
+    local_assemblers.resize(mesh_elements.size());
+
+    DBUG("Calling local assembler builder for all mesh elements.");
+    GlobalExecutor::transformDereferenced(
+        factory, mesh_elements, local_assemblers,
+        std::forward<ExtraCtorArgs>(extra_ctor_args)...);
+}
+
+}  // namespace detail
+
+/*! Creates local assemblers for each element of the given \c mesh.
+ *
+ * \tparam LocalAssemblerImplementation the individual local assembler type
+ * \tparam LocalAssemblerInterface the general local assembler interface
+ * \tparam ExtraCtorArgs types of additional constructor arguments.
+ *         Those arguments will be passed to the constructor of
+ *         \c LocalAssemblerImplementation.
+ *
+ * The first two template parameters cannot be deduced from the arguments.
+ * Therefore they always have to be provided manually.
+ */
+template <int GlobalDim,
+          template <typename /* shp fct */, int /* global dim */>
+          class LocalAssemblerImplementation,
+          typename LocalAssemblerInterface,
+          IntegrationMethodProviderOrIntegrationOrder ProviderOrOrder,
+          typename... ExtraCtorArgs>
+void createLocalAssemblers(
+    std::vector<MeshLib::Element*> const& mesh_elements,
+    NumLib::LocalToGlobalIndexMap const& dof_table,
+    std::vector<std::unique_ptr<LocalAssemblerInterface>>& local_assemblers,
+    ProviderOrOrder const& provider_or_order,
+    ExtraCtorArgs&&... extra_ctor_args)
+{
+    DBUG("Create local assemblers.");
+
+    detail::createLocalAssemblers<GlobalDim, LocalAssemblerImplementation>(
+        dof_table, mesh_elements, local_assemblers, provider_or_order,
+        std::forward<ExtraCtorArgs>(extra_ctor_args)...);
+}
+}  // namespace LargeDeformation
+
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/IntegrationPointData.h b/ProcessLib/LargeDeformation/IntegrationPointData.h
new file mode 100644
index 00000000000..ec0f0de8406
--- /dev/null
+++ b/ProcessLib/LargeDeformation/IntegrationPointData.h
@@ -0,0 +1,26 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+namespace ProcessLib::LargeDeformation
+{
+
+template <typename BMatricesType, typename ShapeMatricesType,
+          int DisplacementDim>
+struct IntegrationPointData final
+{
+    double integration_weight;
+    typename ShapeMatricesType::NodalRowVectorType N;
+    typename ShapeMatricesType::GlobalDimNodalMatrixType dNdx;
+
+    EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
+};
+
+}  // namespace ProcessLib::LargeDeformation
diff --git a/ProcessLib/LargeDeformation/LargeDeformationFEM.h b/ProcessLib/LargeDeformation/LargeDeformationFEM.h
new file mode 100644
index 00000000000..34b68953855
--- /dev/null
+++ b/ProcessLib/LargeDeformation/LargeDeformationFEM.h
@@ -0,0 +1,415 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include "IntegrationPointData.h"
+#include "LocalAssemblerInterface.h"
+#include "MaterialLib/PhysicalConstant.h"
+#include "MathLib/EigenBlockMatrixView.h"
+#include "MathLib/LinAlg/Eigen/EigenMapTools.h"
+#include "NumLib/DOF/LocalDOF.h"
+#include "NumLib/Extrapolation/ExtrapolatableElement.h"
+#include "NumLib/Fem/FiniteElement/TemplateIsoparametric.h"
+#include "NumLib/Fem/InitShapeMatrices.h"
+#include "NumLib/Fem/ShapeMatrixPolicy.h"
+#include "ParameterLib/Parameter.h"
+#include "ProcessLib/Deformation/BMatrixPolicy.h"
+#include "ProcessLib/Deformation/GMatrix.h"
+#include "ProcessLib/Deformation/GMatrixPolicy.h"
+#include "ProcessLib/Deformation/LinearBMatrix.h"
+#include "ProcessLib/Deformation/NonLinearBMatrix.h"
+#include "ProcessLib/LocalAssemblerInterface.h"
+#include "ProcessLib/LocalAssemblerTraits.h"
+
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+namespace MPL = MaterialPropertyLib;
+
+/// Used for the extrapolation of the integration point values. It is ordered
+/// (and stored) by integration points.
+template <typename ShapeMatrixType>
+struct SecondaryData
+{
+    std::vector<ShapeMatrixType, Eigen::aligned_allocator<ShapeMatrixType>> N;
+};
+
+template <typename ShapeFunction, int DisplacementDim>
+class LargeDeformationLocalAssembler
+    : public LargeDeformationLocalAssemblerInterface<DisplacementDim>
+{
+public:
+    using ShapeMatricesType =
+        ShapeMatrixPolicyType<ShapeFunction, DisplacementDim>;
+    using NodalMatrixType = typename ShapeMatricesType::NodalMatrixType;
+    using NodalVectorType = typename ShapeMatricesType::NodalVectorType;
+    using ShapeMatrices = typename ShapeMatricesType::ShapeMatrices;
+    using BMatricesType = BMatrixPolicyType<ShapeFunction, DisplacementDim>;
+
+    using BMatrixType = typename BMatricesType::BMatrixType;
+    using StiffnessMatrixType = typename BMatricesType::StiffnessMatrixType;
+    using NodalForceVectorType = typename BMatricesType::NodalForceVectorType;
+    using NodalDisplacementVectorType =
+        typename BMatricesType::NodalForceVectorType;
+
+    using GMatricesType = GMatrixPolicyType<ShapeFunction, DisplacementDim>;
+    using GradientVectorType = typename GMatricesType::GradientVectorType;
+    using GradientMatrixType = typename GMatricesType::GradientMatrixType;
+    using IpData =
+        IntegrationPointData<BMatricesType, ShapeMatricesType, DisplacementDim>;
+
+    static constexpr auto& N_u_op = MathLib::eigenBlockMatrixView<
+        DisplacementDim, typename ShapeMatricesType::NodalRowVectorType>;
+    static constexpr auto& sigma_geom_op = MathLib::eigenBlockMatrixView<
+        DisplacementDim,
+        Eigen::Matrix<double, DisplacementDim, DisplacementDim>>;
+
+    LargeDeformationLocalAssembler(LargeDeformationLocalAssembler const&) =
+        delete;
+    LargeDeformationLocalAssembler(LargeDeformationLocalAssembler&&) = delete;
+
+    LargeDeformationLocalAssembler(
+        MeshLib::Element const& e,
+        std::size_t const /*local_matrix_size*/,
+        NumLib::GenericIntegrationMethod const& integration_method,
+        bool const is_axially_symmetric,
+        LargeDeformationProcessData<DisplacementDim>& process_data)
+        : LargeDeformationLocalAssemblerInterface<DisplacementDim>(
+              e, integration_method, is_axially_symmetric, process_data)
+    {
+        unsigned const n_integration_points =
+            this->integration_method_.getNumberOfPoints();
+
+        _ip_data.resize(n_integration_points);
+        _secondary_data.N.resize(n_integration_points);
+
+        auto const shape_matrices =
+            NumLib::initShapeMatrices<ShapeFunction, ShapeMatricesType,
+                                      DisplacementDim>(
+                e, is_axially_symmetric, this->integration_method_);
+
+        for (unsigned ip = 0; ip < n_integration_points; ip++)
+        {
+            auto& ip_data = _ip_data[ip];
+            auto const& sm = shape_matrices[ip];
+            _ip_data[ip].integration_weight =
+                this->integration_method_.getWeightedPoint(ip).getWeight() *
+                sm.integralMeasure * sm.detJ;
+
+            ip_data.N = sm.N;
+            ip_data.dNdx = sm.dNdx;
+
+            _secondary_data.N[ip] = shape_matrices[ip].N;
+        }
+    }
+
+    void initializeConcrete() override
+    {
+        unsigned const n_integration_points =
+            this->integration_method_.getNumberOfPoints();
+        for (unsigned ip = 0; ip < n_integration_points; ip++)
+        {
+            auto const& ip_data = _ip_data[ip];
+
+            ParameterLib::SpatialPosition const x_position{
+                std::nullopt, this->element_.getID(), ip,
+                MathLib::Point3d(
+                    NumLib::interpolateCoordinates<ShapeFunction,
+                                                   ShapeMatricesType>(
+                        this->element_, ip_data.N))};
+
+            /// Set initial stress from parameter.
+            if (this->process_data_.initial_stress != nullptr)
+            {
+                this->current_states_[ip].stress_data.sigma.noalias() =
+                    MathLib::KelvinVector::symmetricTensorToKelvinVector<
+                        DisplacementDim>((*this->process_data_.initial_stress)(
+                        std::numeric_limits<
+                            double>::quiet_NaN() /* time independent */,
+                        x_position));
+            }
+
+            double const t = 0;  // TODO (naumov) pass t from top
+            auto& material_state = this->material_states_[ip];
+            this->solid_material_.initializeInternalStateVariables(
+                t, x_position, *material_state.material_state_variables);
+
+            material_state.pushBackState();
+            this->prev_states_[ip] = this->current_states_[ip];
+        }
+    }
+
+    typename ConstitutiveRelations::ConstitutiveData<DisplacementDim>
+    updateConstitutiveRelations(
+        Eigen::Ref<Eigen::VectorXd const> const& u,
+        Eigen::Ref<Eigen::VectorXd const> const& u_prev,
+        ParameterLib::SpatialPosition const& x_position, double const t,
+        double const dt,
+        IntegrationPointData<BMatricesType, ShapeMatricesType, DisplacementDim>&
+            ip_data,
+        typename ConstitutiveRelations::ConstitutiveSetting<DisplacementDim>&
+            CS,
+        MaterialPropertyLib::Medium const& medium,
+        typename ConstitutiveRelations::StatefulData<DisplacementDim>&
+            current_state,
+        typename ConstitutiveRelations::StatefulDataPrev<DisplacementDim> const&
+            prev_state,
+        MaterialStateData<DisplacementDim>& material_state,
+        typename ConstitutiveRelations::OutputData<DisplacementDim>&
+            output_data) const
+    {
+        auto const& N = ip_data.N;
+        auto const& dNdx = ip_data.dNdx;
+        auto const x_coord =
+            NumLib::interpolateXCoordinate<ShapeFunction, ShapeMatricesType>(
+                this->element_, N);
+
+        // For the 2D case the 33-component is needed (and the four entries
+        // of the non-symmetric matrix); In 3d there are nine entries.
+        GradientMatrixType G(
+            DisplacementDim * DisplacementDim + (DisplacementDim == 2 ? 1 : 0),
+            ShapeFunction::NPOINTS * DisplacementDim);
+        Deformation::computeGMatrix<DisplacementDim, ShapeFunction::NPOINTS>(
+            dNdx, G, this->is_axially_symmetric_, N, x_coord);
+
+        GradientVectorType const grad_u = G * u;
+        GradientVectorType gradient_vector_identity =
+            GradientVectorType::Zero();
+        if constexpr (DisplacementDim == 2)
+        {
+            gradient_vector_identity[0] = 1;
+            gradient_vector_identity[3] = 1;
+            gradient_vector_identity[4] = 1;
+        }
+        if constexpr (DisplacementDim == 3)
+        {
+            gradient_vector_identity[0] = 1;
+            gradient_vector_identity[4] = 1;
+            gradient_vector_identity[8] = 1;
+        }
+
+        auto const B_0 =
+            LinearBMatrix::computeBMatrix<DisplacementDim,
+                                          ShapeFunction::NPOINTS,
+                                          typename BMatricesType::BMatrixType>(
+                dNdx, N, x_coord, this->is_axially_symmetric_);
+
+        auto const B_N = NonLinearBMatrix::computeBMatrix<
+            DisplacementDim, ShapeFunction::NPOINTS,
+            typename BMatricesType::BMatrixType>(dNdx, N, grad_u, x_coord,
+                                                 this->is_axially_symmetric_);
+
+        auto const B = B_0 + 0.5 * B_N;  // For Green-Lagrange strain.
+
+        double const T_ref =
+            this->process_data_.reference_temperature
+                ? (*this->process_data_.reference_temperature)(t, x_position)[0]
+                : std::numeric_limits<double>::quiet_NaN();
+
+        typename ConstitutiveRelations::ConstitutiveModels<DisplacementDim>
+            models(this->process_data_, this->solid_material_);
+        typename ConstitutiveRelations::ConstitutiveTempData<DisplacementDim>
+            tmp;
+        typename ConstitutiveRelations::ConstitutiveData<DisplacementDim> CD;
+
+        output_data.eps_data.eps = B * u;
+
+        CS.eval(models, t, dt, x_position,              //
+                medium,                                 //
+                T_ref,                                  //
+                grad_u + gradient_vector_identity,      //
+                G * u_prev + gradient_vector_identity,  //
+                current_state, prev_state, material_state, tmp, CD);
+
+        return CD;
+    }
+
+    void assemble(double const /*t*/, double const /*dt*/,
+                  std::vector<double> const& /*local_x*/,
+                  std::vector<double> const& /*local_x_prev*/,
+                  std::vector<double>& /*local_M_data*/,
+                  std::vector<double>& /*local_K_data*/,
+                  std::vector<double>& /*local_b_data*/) override
+    {
+        OGS_FATAL(
+            "LargeDeformationLocalAssembler: assembly without jacobian is not "
+            "implemented.");
+    }
+
+    void assembleWithJacobian(double const t, double const dt,
+                              std::vector<double> const& local_x,
+                              std::vector<double> const& local_x_prev,
+                              std::vector<double>& /*local_M_data*/,
+                              std::vector<double>& /*local_K_data*/,
+                              std::vector<double>& local_b_data,
+                              std::vector<double>& local_Jac_data) override
+    {
+        auto const local_matrix_size = local_x.size();
+
+        auto local_Jac = MathLib::createZeroedMatrix<StiffnessMatrixType>(
+            local_Jac_data, local_matrix_size, local_matrix_size);
+
+        auto local_b = MathLib::createZeroedVector<NodalDisplacementVectorType>(
+            local_b_data, local_matrix_size);
+
+        auto [u] = localDOF(local_x);
+        auto [u_prev] = localDOF(local_x_prev);
+
+        unsigned const n_integration_points =
+            this->integration_method_.getNumberOfPoints();
+
+        ParameterLib::SpatialPosition x_position;
+        x_position.setElementID(this->element_.getID());
+
+        typename ConstitutiveRelations::ConstitutiveSetting<DisplacementDim>
+            constitutive_setting;
+        auto const& medium =
+            *this->process_data_.media_map.getMedium(this->element_.getID());
+
+        for (unsigned ip = 0; ip < n_integration_points; ip++)
+        {
+            x_position.setIntegrationPoint(ip);
+            auto const& w = _ip_data[ip].integration_weight;
+            auto const& N = _ip_data[ip].N;
+            auto const& dNdx = _ip_data[ip].dNdx;
+
+            auto const x_coord =
+                NumLib::interpolateXCoordinate<ShapeFunction,
+                                               ShapeMatricesType>(
+                    this->element_, N);
+
+            // For the 2D case the 33-component is needed (and the four entries
+            // of the non-symmetric matrix); In 3d there are nine entries.
+            GradientMatrixType G(DisplacementDim * DisplacementDim +
+                                     (DisplacementDim == 2 ? 1 : 0),
+                                 ShapeFunction::NPOINTS * DisplacementDim);
+            Deformation::computeGMatrix<DisplacementDim,
+                                        ShapeFunction::NPOINTS>(
+                dNdx, G, this->is_axially_symmetric_, N, x_coord);
+
+            GradientVectorType const grad_u = G * u;
+
+            auto const B_0 = LinearBMatrix::computeBMatrix<
+                DisplacementDim, ShapeFunction::NPOINTS,
+                typename BMatricesType::BMatrixType>(
+                dNdx, N, x_coord, this->is_axially_symmetric_);
+
+            auto const B_N = NonLinearBMatrix::computeBMatrix<
+                DisplacementDim, ShapeFunction::NPOINTS,
+                typename BMatricesType::BMatrixType>(
+                dNdx, N, grad_u, x_coord, this->is_axially_symmetric_);
+
+            auto const B = B_0 + B_N;
+
+            auto const CD = updateConstitutiveRelations(
+                u, u_prev, x_position, t, dt, _ip_data[ip],
+                constitutive_setting, medium, this->current_states_[ip],
+                this->prev_states_[ip], this->material_states_[ip],
+                this->output_data_[ip]);
+
+            auto const& sigma = this->current_states_[ip].stress_data.sigma;
+            auto const& b = *CD.volumetric_body_force;
+            auto const& C = CD.s_mech_data.stiffness_tensor;
+
+            local_b.noalias() -=
+                (B.transpose() * sigma - N_u_op(N).transpose() * b) * w;
+
+            auto const sigma_tensor =
+                MathLib::KelvinVector::kelvinVectorToTensor(sigma);
+            if constexpr (DisplacementDim == 2)
+            {
+                using SigmaGeom =
+                    typename ShapeMatricesType::template MatrixType<5, 5>;
+                SigmaGeom sigma_geom = SigmaGeom::Zero(5, 5);
+                sigma_geom.template block<4, 4>(0, 0) = sigma_geom_op(
+                    sigma_tensor.template block<2, 2>(0, 0).eval());
+                sigma_geom(4, 4) = sigma_tensor(2, 2);
+
+                local_Jac.noalias() += G.transpose() * sigma_geom * G * w;
+            }
+            if constexpr (DisplacementDim == 3)
+            {
+                local_Jac.noalias() +=
+                    G.transpose() * sigma_geom_op(sigma_tensor) * G * w;
+            }
+            local_Jac.noalias() += B.transpose() * C * B * w;
+        }
+    }
+
+    void postTimestepConcrete(Eigen::VectorXd const& local_x,
+                              Eigen::VectorXd const& local_x_prev,
+                              double const t, double const dt,
+                              bool const /*use_monolithic_scheme*/,
+                              int const /*process_id*/) override
+    {
+        unsigned const n_integration_points =
+            this->integration_method_.getNumberOfPoints();
+
+        ParameterLib::SpatialPosition x_position;
+        x_position.setElementID(this->element_.getID());
+
+        typename ConstitutiveRelations::ConstitutiveSetting<DisplacementDim>
+            constitutive_setting;
+
+        auto& medium =
+            *this->process_data_.media_map.getMedium(this->element_.getID());
+
+        for (unsigned ip = 0; ip < n_integration_points; ip++)
+        {
+            x_position.setIntegrationPoint(ip);
+
+            updateConstitutiveRelations(
+                local_x, local_x_prev, x_position, t, dt, _ip_data[ip],
+                constitutive_setting, medium, this->current_states_[ip],
+                this->prev_states_[ip], this->material_states_[ip],
+                this->output_data_[ip]);
+
+            this->material_states_[ip].pushBackState();
+        }
+
+        for (unsigned ip = 0; ip < n_integration_points; ip++)
+        {
+            this->prev_states_[ip] = this->current_states_[ip];
+        }
+    }
+
+    Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
+        const unsigned integration_point) const override
+    {
+        auto const& N = _secondary_data.N[integration_point];
+
+        // assumes N is stored contiguously in memory
+        return Eigen::Map<const Eigen::RowVectorXd>(N.data(), N.size());
+    }
+
+private:
+    static constexpr auto localDOF(std::vector<double> const& x)
+    {
+        return NumLib::localDOF<
+            NumLib::Vectorial<ShapeFunction, DisplacementDim>>(x);
+    }
+
+private:
+    std::vector<IpData, Eigen::aligned_allocator<IpData>> _ip_data;
+
+    SecondaryData<typename ShapeMatrices::ShapeType> _secondary_data;
+
+    static const int displacement_size =
+        ShapeFunction::NPOINTS * DisplacementDim;
+};
+
+}  // namespace LargeDeformation
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/LargeDeformationProcess.cpp b/ProcessLib/LargeDeformation/LargeDeformationProcess.cpp
new file mode 100644
index 00000000000..02733399248
--- /dev/null
+++ b/ProcessLib/LargeDeformation/LargeDeformationProcess.cpp
@@ -0,0 +1,217 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "LargeDeformationProcess.h"
+
+#include <cassert>
+
+#include "CreateLocalAssemblers.h"
+#include "LargeDeformationFEM.h"
+#include "MeshLib/Utils/IntegrationPointWriter.h"
+#include "MeshLib/Utils/getOrCreateMeshProperty.h"
+#include "NumLib/DOF/DOFTableUtil.h"
+#include "ProcessLib/Deformation/SolidMaterialInternalToSecondaryVariables.h"
+#include "ProcessLib/Process.h"
+#include "ProcessLib/Reflection/ReflectionForExtrapolation.h"
+#include "ProcessLib/Reflection/ReflectionForIPWriters.h"
+#include "ProcessLib/Utils/SetIPDataInitialConditions.h"
+
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+template <int DisplacementDim>
+LargeDeformationProcess<DisplacementDim>::LargeDeformationProcess(
+    std::string name,
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
+    unsigned const integration_order,
+    std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&&
+        process_variables,
+    LargeDeformationProcessData<DisplacementDim>&& process_data,
+    SecondaryVariableCollection&& secondary_variables)
+    : Process(std::move(name), mesh, std::move(jacobian_assembler), parameters,
+              integration_order, std::move(process_variables),
+              std::move(secondary_variables)),
+      _process_data(std::move(process_data))
+{
+    _nodal_forces = MeshLib::getOrCreateMeshProperty<double>(
+        mesh, "NodalForces", MeshLib::MeshItemType::Node, DisplacementDim);
+
+    _process_data.principal_stress_vector[0] =
+        MeshLib::getOrCreateMeshProperty<double>(
+            const_cast<MeshLib::Mesh&>(mesh), "principal_stress_vector_1",
+            MeshLib::MeshItemType::Cell, 3);
+
+    _process_data.principal_stress_vector[1] =
+        MeshLib::getOrCreateMeshProperty<double>(
+            const_cast<MeshLib::Mesh&>(mesh), "principal_stress_vector_2",
+            MeshLib::MeshItemType::Cell, 3);
+
+    _process_data.principal_stress_vector[2] =
+        MeshLib::getOrCreateMeshProperty<double>(
+            const_cast<MeshLib::Mesh&>(mesh), "principal_stress_vector_3",
+            MeshLib::MeshItemType::Cell, 3);
+
+    _process_data.principal_stress_values =
+        MeshLib::getOrCreateMeshProperty<double>(
+            const_cast<MeshLib::Mesh&>(mesh), "principal_stress_values",
+            MeshLib::MeshItemType::Cell, 3);
+
+    ProcessLib::Reflection::addReflectedIntegrationPointWriters<
+        DisplacementDim>(LargeDeformationLocalAssemblerInterface<
+                             DisplacementDim>::getReflectionDataForOutput(),
+                         _integration_point_writer, integration_order,
+                         _local_assemblers);
+}
+
+template <int DisplacementDim>
+bool LargeDeformationProcess<DisplacementDim>::isLinear() const
+{
+    return false;
+}
+
+template <int DisplacementDim>
+void LargeDeformationProcess<DisplacementDim>::initializeConcreteProcess(
+    NumLib::LocalToGlobalIndexMap const& dof_table,
+    MeshLib::Mesh const& mesh,
+    unsigned const integration_order)
+{
+    ProcessLib::LargeDeformation::createLocalAssemblers<
+        DisplacementDim, LargeDeformationLocalAssembler>(
+        mesh.getElements(), dof_table, _local_assemblers,
+        NumLib::IntegrationOrder{integration_order}, mesh.isAxiallySymmetric(),
+        _process_data);
+
+    auto add_secondary_variable = [&](std::string const& name,
+                                      int const num_components,
+                                      auto get_ip_values_function)
+    {
+        _secondary_variables.addSecondaryVariable(
+            name,
+            makeExtrapolator(num_components, getExtrapolator(),
+                             _local_assemblers,
+                             std::move(get_ip_values_function)));
+    };
+
+    ProcessLib::Reflection::addReflectedSecondaryVariables<DisplacementDim>(
+        LargeDeformationLocalAssemblerInterface<
+            DisplacementDim>::getReflectionDataForOutput(),
+        _secondary_variables, getExtrapolator(), _local_assemblers);
+
+    //
+    // enable output of internal variables defined by material models
+    //
+    ProcessLib::Deformation::solidMaterialInternalToSecondaryVariables<
+        LocalAssemblerInterface>(_process_data.solid_materials,
+                                 add_secondary_variable);
+
+    ProcessLib::Deformation::
+        solidMaterialInternalVariablesToIntegrationPointWriter(
+            _process_data.solid_materials, _local_assemblers,
+            _integration_point_writer, integration_order);
+
+    bool const remove_name_suffix = true;
+    setIPDataInitialConditions(_integration_point_writer, mesh.getProperties(),
+                               _local_assemblers, remove_name_suffix);
+
+    // Initialize local assemblers after all variables have been set.
+    GlobalExecutor::executeMemberOnDereferenced(
+        &LocalAssemblerInterface::initialize, _local_assemblers,
+        *_local_to_global_index_map);
+}
+
+template <int DisplacementDim>
+void LargeDeformationProcess<DisplacementDim>::assembleConcreteProcess(
+    double const t, double const dt, std::vector<GlobalVector*> const& x,
+    std::vector<GlobalVector*> const& x_prev, int const process_id,
+    GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b)
+{
+    DBUG("Assemble LargeDeformationProcess.");
+
+    ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
+
+    std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>>
+        dof_table = {std::ref(*_local_to_global_index_map)};
+    // Call global assembler for each local assembly item.
+    GlobalExecutor::executeSelectedMemberDereferenced(
+        _global_assembler, &VectorMatrixAssembler::assemble, _local_assemblers,
+        pv.getActiveElementIDs(), dof_table, t, dt, x, x_prev, process_id, M, K,
+        b);
+
+    _global_output(t, process_id, M, K, b);
+}
+
+template <int DisplacementDim>
+void LargeDeformationProcess<DisplacementDim>::
+    assembleWithJacobianConcreteProcess(
+        double const t, double const dt, std::vector<GlobalVector*> const& x,
+        std::vector<GlobalVector*> const& x_prev, int const process_id,
+        GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b, GlobalMatrix& Jac)
+{
+    DBUG("AssembleWithJacobian LargeDeformationProcess.");
+
+    ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
+
+    std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>>
+        dof_table = {std::ref(*_local_to_global_index_map)};
+    // Call global assembler for each local assembly item.
+    GlobalExecutor::executeSelectedMemberDereferenced(
+        _global_assembler, &VectorMatrixAssembler::assembleWithJacobian,
+        _local_assemblers, pv.getActiveElementIDs(), dof_table, t, dt, x,
+        x_prev, process_id, M, K, b, Jac);
+
+    transformVariableFromGlobalVector(b, 0, *_local_to_global_index_map,
+                                      *_nodal_forces, std::negate<double>());
+
+    _global_output(t, process_id, M, K, b, &Jac);
+}
+
+template <int DisplacementDim>
+void LargeDeformationProcess<DisplacementDim>::postTimestepConcreteProcess(
+    std::vector<GlobalVector*> const& x,
+    std::vector<GlobalVector*> const& x_prev, double const t, double const dt,
+    int const process_id)
+{
+    DBUG("PostTimestep LargeDeformationProcess.");
+    std::vector<NumLib::LocalToGlobalIndexMap const*> dof_tables;
+    dof_tables.reserve(x.size());
+    std::generate_n(std::back_inserter(dof_tables), x.size(),
+                    [&]() { return _local_to_global_index_map.get(); });
+
+    ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
+    GlobalExecutor::executeSelectedMemberOnDereferenced(
+        &LocalAssemblerInterface::postTimestep, _local_assemblers,
+        pv.getActiveElementIDs(), dof_tables, x, x_prev, t, dt,
+        _use_monolithic_scheme, process_id);
+}
+
+template <int DisplacementDim>
+void LargeDeformationProcess<DisplacementDim>::computeSecondaryVariableConcrete(
+    double const t, double const dt, std::vector<GlobalVector*> const& x,
+    GlobalVector const& x_prev, int const process_id)
+{
+    DBUG("Compute the secondary variables for LargeDeformationProcess.");
+    std::vector<NumLib::LocalToGlobalIndexMap const*> dof_tables;
+    dof_tables.reserve(x.size());
+    std::generate_n(std::back_inserter(dof_tables), x.size(),
+                    [&]() { return _local_to_global_index_map.get(); });
+
+    ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
+    GlobalExecutor::executeSelectedMemberOnDereferenced(
+        &LocalAssemblerInterface::computeSecondaryVariable, _local_assemblers,
+        pv.getActiveElementIDs(), dof_tables, t, dt, x, x_prev, process_id);
+}
+template class LargeDeformationProcess<2>;
+template class LargeDeformationProcess<3>;
+
+}  // namespace LargeDeformation
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/LargeDeformationProcess.h b/ProcessLib/LargeDeformation/LargeDeformationProcess.h
new file mode 100644
index 00000000000..3568e2fcc0f
--- /dev/null
+++ b/ProcessLib/LargeDeformation/LargeDeformationProcess.h
@@ -0,0 +1,89 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include "LargeDeformationProcessData.h"
+#include "LocalAssemblerInterface.h"
+#include "ProcessLib/Process.h"
+
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+template <int DisplacementDim>
+class LargeDeformationProcess final : public Process
+{
+public:
+    LargeDeformationProcess(
+        std::string name,
+        MeshLib::Mesh& mesh,
+        std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&&
+            jacobian_assembler,
+        std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const&
+            parameters,
+        unsigned const integration_order,
+        std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&&
+            process_variables,
+        LargeDeformationProcessData<DisplacementDim>&& process_data,
+        SecondaryVariableCollection&& secondary_variables);
+
+    //! \name ODESystem interface
+    //! @{
+    bool isLinear() const override;
+    //! @}
+
+private:
+    using LocalAssemblerInterface =
+        LargeDeformationLocalAssemblerInterface<DisplacementDim>;
+
+    void initializeConcreteProcess(
+        NumLib::LocalToGlobalIndexMap const& dof_table,
+        MeshLib::Mesh const& mesh,
+        unsigned const integration_order) override;
+
+    void assembleConcreteProcess(double const t, double const dt,
+                                 std::vector<GlobalVector*> const& x,
+                                 std::vector<GlobalVector*> const& x_prev,
+                                 int const process_id, GlobalMatrix& M,
+                                 GlobalMatrix& K, GlobalVector& b) override;
+
+    void assembleWithJacobianConcreteProcess(
+        const double t, double const dt, std::vector<GlobalVector*> const& x,
+        std::vector<GlobalVector*> const& x_prev, int const process_id,
+        GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b,
+        GlobalMatrix& Jac) override;
+
+    void postTimestepConcreteProcess(std::vector<GlobalVector*> const& x,
+                                     std::vector<GlobalVector*> const& x_prev,
+                                     double const t, double const dt,
+                                     int const process_id) override;
+
+    void computeSecondaryVariableConcrete(double const t, double const dt,
+                                          std::vector<GlobalVector*> const& x,
+                                          GlobalVector const& x_prev,
+                                          int const process_id) override;
+
+private:
+    LargeDeformationProcessData<DisplacementDim> _process_data;
+
+    std::vector<std::unique_ptr<LocalAssemblerInterface>> _local_assemblers;
+
+    MeshLib::PropertyVector<double>* _nodal_forces = nullptr;
+    MeshLib::PropertyVector<double>* _material_forces = nullptr;
+
+    Assembly::GlobalMatrixOutput _global_output;
+};
+
+extern template class LargeDeformationProcess<2>;
+extern template class LargeDeformationProcess<3>;
+
+}  // namespace LargeDeformation
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/LargeDeformationProcessData.h b/ProcessLib/LargeDeformation/LargeDeformationProcessData.h
new file mode 100644
index 00000000000..45075f87305
--- /dev/null
+++ b/ProcessLib/LargeDeformation/LargeDeformationProcessData.h
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <Eigen/Core>
+#include <memory>
+#include <utility>
+
+#include "ConstitutiveRelations/SolidMechanics.h"
+#include "MaterialLib/MPL/MaterialSpatialDistributionMap.h"
+#include "ParameterLib/Parameter.h"
+
+namespace MaterialLib
+{
+namespace Solids
+{
+template <int DisplacementDim>
+struct MechanicsBase;
+}
+}  // namespace MaterialLib
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+template <int DisplacementDim>
+struct LargeDeformationProcessData
+{
+    MeshLib::PropertyVector<int> const* const material_ids = nullptr;
+
+    MaterialPropertyLib::MaterialSpatialDistributionMap media_map;
+
+    std::map<int,
+             std::unique_ptr<ConstitutiveRelations::SolidConstitutiveRelation<
+                 DisplacementDim>>>
+        solid_materials;
+
+    /// Optional, initial stress field. A symmetric tensor, short vector
+    /// representation of length 4 or 6, ParameterLib::Parameter<double>.
+    ParameterLib::Parameter<double> const* const initial_stress;
+
+    /// Specific body forces applied to the solid.
+    /// It is usually used to apply gravitational forces.
+    /// A vector of displacement dimension's length.
+    Eigen::Matrix<double, DisplacementDim, 1> const specific_body_force;
+
+    ParameterLib::Parameter<double> const* const reference_temperature;
+
+    std::array<MeshLib::PropertyVector<double>*, 3> principal_stress_vector = {
+        nullptr, nullptr, nullptr};
+    MeshLib::PropertyVector<double>* principal_stress_values = nullptr;
+};
+
+}  // namespace LargeDeformation
+}  // namespace ProcessLib
diff --git a/ProcessLib/LargeDeformation/LocalAssemblerInterface.h b/ProcessLib/LargeDeformation/LocalAssemblerInterface.h
new file mode 100644
index 00000000000..b8943377678
--- /dev/null
+++ b/ProcessLib/LargeDeformation/LocalAssemblerInterface.h
@@ -0,0 +1,176 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "ConstitutiveRelations/ConstitutiveData.h"
+#include "ConstitutiveRelations/ConstitutiveSetting.h"
+#include "ConstitutiveRelations/MaterialState.h"
+#include "LargeDeformationProcessData.h"
+#include "MaterialLib/SolidModels/MechanicsBase.h"
+#include "MaterialLib/SolidModels/SelectSolidConstitutiveRelation.h"
+#include "NumLib/Extrapolation/ExtrapolatableElement.h"
+#include "NumLib/Fem/Integration/GenericIntegrationMethod.h"
+#include "ProcessLib/LocalAssemblerInterface.h"
+#include "ProcessLib/Reflection/ReflectionSetIPData.h"
+#include "ProcessLib/Utils/SetOrGetIntegrationPointData.h"
+
+namespace ProcessLib
+{
+namespace LargeDeformation
+{
+template <int DisplacementDim>
+struct LargeDeformationLocalAssemblerInterface
+    : public ProcessLib::LocalAssemblerInterface,
+      public NumLib::ExtrapolatableElement
+{
+    LargeDeformationLocalAssemblerInterface(
+        MeshLib::Element const& e,
+        NumLib::GenericIntegrationMethod const& integration_method,
+        bool const is_axially_symmetric,
+        LargeDeformationProcessData<DisplacementDim>& process_data)
+        : process_data_(process_data),
+          integration_method_(integration_method),
+          element_(e),
+          is_axially_symmetric_(is_axially_symmetric),
+          solid_material_(MaterialLib::Solids::selectSolidConstitutiveRelation(
+              process_data_.solid_materials, process_data_.material_ids,
+              element_.getID()))
+    {
+        unsigned const n_integration_points =
+            integration_method_.getNumberOfPoints();
+
+        material_states_.reserve(n_integration_points);
+        for (unsigned ip = 0; ip < n_integration_points; ++ip)
+        {
+            material_states_.emplace_back(
+                solid_material_.createMaterialStateVariables());
+        }
+
+        current_states_.resize(n_integration_points);
+        prev_states_.resize(n_integration_points);
+        output_data_.resize(n_integration_points);
+    }
+    /// Returns number of read integration points.
+    std::size_t setIPDataInitialConditions(std::string const& name,
+                                           double const* values,
+                                           int const integration_order)
+    {
+        if (integration_order !=
+            static_cast<int>(integration_method_.getIntegrationOrder()))
+        {
+            OGS_FATAL(
+                "Setting integration point initial conditions; The integration "
+                "order of the local assembler for element {:d} is different "
+                "from the integration order in the initial condition.",
+                element_.getID());
+        }
+
+        if (name.starts_with("material_state_variable_"))
+        {
+            std::string const variable_name = name.substr(24, name.size() - 24);
+            DBUG("Setting material state variable '{:s}'", variable_name);
+
+            auto const& internal_variables =
+                solid_material_.getInternalVariables();
+            if (auto const iv = std::find_if(
+                    begin(internal_variables), end(internal_variables),
+                    [&variable_name](auto const& iv)
+                    { return iv.name == variable_name; });
+                iv != end(internal_variables))
+            {
+                return ProcessLib::
+                    setIntegrationPointDataMaterialStateVariables(
+                        values, material_states_,
+                        &MaterialStateData<
+                            DisplacementDim>::material_state_variables,
+                        iv->reference);
+            }
+
+            WARN(
+                "Could not find variable {:s} in solid material model's "
+                "internal variables.",
+                variable_name);
+            return 0;
+        }
+
+        // TODO this logic could be pulled out of the local assembler into the
+        // process. That might lead to a slightly better performance due to less
+        // string comparisons.
+        return ProcessLib::Reflection::reflectSetIPData<DisplacementDim>(
+            name, values, current_states_);
+    }
+
+    // TODO move to NumLib::ExtrapolatableElement
+    unsigned getNumberOfIntegrationPoints() const
+    {
+        return integration_method_.getNumberOfPoints();
+    }
+
+    int getMaterialID() const
+    {
+        return process_data_.material_ids == nullptr
+                   ? 0
+                   : (*process_data_.material_ids)[element_.getID()];
+    }
+
+    std::vector<double> getMaterialStateVariableInternalState(
+        std::function<std::span<double>(
+            typename MaterialLib::Solids::MechanicsBase<DisplacementDim>::
+                MaterialStateVariables&)> const& get_values_span,
+        int const& n_components) const
+    {
+        return ProcessLib::getIntegrationPointDataMaterialStateVariables(
+            material_states_,
+            &MaterialStateData<DisplacementDim>::material_state_variables,
+            get_values_span, n_components);
+    }
+
+    typename MaterialLib::Solids::MechanicsBase<
+        DisplacementDim>::MaterialStateVariables const&
+    getMaterialStateVariablesAt(unsigned integration_point) const
+    {
+        return *material_states_[integration_point].material_state_variables;
+    }
+
+    static auto getReflectionDataForOutput()
+    {
+        using Self = LargeDeformationLocalAssemblerInterface<DisplacementDim>;
+
+        return ProcessLib::Reflection::reflectWithoutName(
+            &Self::current_states_, &Self::output_data_);
+    }
+
+protected:
+    LargeDeformationProcessData<DisplacementDim>& process_data_;
+
+    // Material state is special, because it contains both the current and the
+    // old state.
+    std::vector<MaterialStateData<DisplacementDim>> material_states_;
+    std::vector<typename ConstitutiveRelations::StatefulData<DisplacementDim>>
+        current_states_;  // TODO maybe do not store but rather re-evaluate for
+                          // state update
+    std::vector<
+        typename ConstitutiveRelations::StatefulDataPrev<DisplacementDim>>
+        prev_states_;
+    std::vector<typename ConstitutiveRelations::OutputData<DisplacementDim>>
+        output_data_;
+
+    NumLib::GenericIntegrationMethod const& integration_method_;
+    MeshLib::Element const& element_;
+    bool const is_axially_symmetric_;
+    typename ConstitutiveRelations::SolidConstitutiveRelation<
+        DisplacementDim> const& solid_material_;
+};
+
+}  // namespace LargeDeformation
+}  // namespace ProcessLib
diff --git a/scripts/cmake/ProcessesSetup.cmake b/scripts/cmake/ProcessesSetup.cmake
index 119f8e47c78..b80a7a86f64 100644
--- a/scripts/cmake/ProcessesSetup.cmake
+++ b/scripts/cmake/ProcessesSetup.cmake
@@ -26,6 +26,10 @@ set(_processes_list
     TwoPhaseFlowWithPP
     TwoPhaseFlowWithPrho
 )
+if(OGS_USE_MFRONT)
+    set(_processes_list ${_processes_list} LargeDeformation)
+endif()
+
 if(OGS_USE_PETSC)
     set(_processes_list ${_processes_list} PhaseField)
 endif()
-- 
GitLab