OGS
NonLinearFbar.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <boost/algorithm/string/predicate.hpp>
7#include <cmath>
8#include <string_view>
9#include <tuple>
10
11#include "GMatrix.h"
18
19namespace ProcessLib
20{
21namespace NonLinearFbar
22{
29
31 std::string_view const bar_det_f_type_name);
32
33template <int DisplacementDim, int NPOINTS, typename VectorTypeForFbar,
34 typename GradientVectorType, typename DNDX_Type>
35VectorTypeForFbar computeQVector(DNDX_Type const& dNdx,
36 GradientVectorType const& F,
37 bool const /*is_axially_symmetric*/)
38{
39 // Note: MathLib::VectorizedTensor::toTensor returns a (3 x 3) matrix by
40 // Eigen::Matrix3D. The size of the return matrix is wrong, which
41 // should be (DisplacementDim x DisplacementDim).
42 // Besides, Eigen::Matrix member inverse does not work with the mapped
43 // matrix, e.g. that by using topLeftCorner. Therefore a hard copy is
44 // needed for the following inverse, i.e. declaring F0inv as type
45 // Eigen::MatrixXd instead of type auto.
46 //
47 Eigen::MatrixXd const F_matrix =
49 .template topLeftCorner<DisplacementDim, DisplacementDim>();
50 auto const Finv = F_matrix.inverse();
51
52 VectorTypeForFbar FInvN =
53 VectorTypeForFbar::Zero(DisplacementDim * NPOINTS);
54 for (int i = 0; i < NPOINTS; ++i)
55 {
56 auto const dNidx = dNdx.col(i);
57 for (int k = 0; k < DisplacementDim; k++)
58 {
59 FInvN[k * NPOINTS + i] = Finv.col(k).dot(dNidx);
60 }
61 }
62
63 return FInvN;
64}
65
66template <int DisplacementDim, typename GradientVectorType,
67 typename VectorTypeForFbar, typename NodalVectorType,
68 typename ShapeFunction, typename ShapeMatricesType, typename IpData>
69std::tuple<double, VectorTypeForFbar> computeFBarInitialVariablesAverage(
70 std::vector<IpData, Eigen::aligned_allocator<IpData>> const& ip_data,
71 bool const compute_detF0_only, Eigen::VectorXd const& u,
72 NumLib::GenericIntegrationMethod const& integration_method,
73 MeshLib::Element const& element, bool const is_axially_symmetric)
74{
75 unsigned const n_integration_points =
76 integration_method.getNumberOfPoints();
77 // Compute the element volume
78 double volume = 0.0;
79 for (unsigned ip = 0; ip < n_integration_points; ip++)
80 {
81 auto const& w = ip_data[ip].integration_weight;
82 volume += w;
83 }
84
85 VectorTypeForFbar averaged_grad_N =
86 VectorTypeForFbar::Zero(DisplacementDim * ShapeFunction::NPOINTS);
87 NodalVectorType averaged_N_div_r;
88 if (is_axially_symmetric)
89 {
90 averaged_N_div_r = NodalVectorType::Zero(ShapeFunction::NPOINTS);
91 }
92
93 GradientVectorType F0 =
95
96 for (unsigned i = 0; i < ShapeFunction::NPOINTS; i++)
97 {
98 Eigen::Vector3d const bar_gradN =
100 ShapeMatricesType, IpData>(
101 i, element, integration_method, ip_data, is_axially_symmetric) /
102 volume;
103 averaged_grad_N.template segment<DisplacementDim>(i * DisplacementDim) =
104 bar_gradN.template segment<DisplacementDim>(0);
105
106 for (int k = 0; k < DisplacementDim; k++)
107 {
108 F0.template segment<DisplacementDim>(k * DisplacementDim) +=
109 u[k * ShapeFunction::NPOINTS + i] *
110 bar_gradN.template segment<DisplacementDim>(0);
111 }
112 if (is_axially_symmetric)
113 {
114 averaged_N_div_r[i] = bar_gradN[2];
115 F0[4] += bar_gradN[2] * u[i];
116 }
117 }
118
119 if (compute_detF0_only)
120 {
122 }
123
124 VectorTypeForFbar F0InvN =
125 VectorTypeForFbar::Zero(DisplacementDim * ShapeFunction::NPOINTS);
126
127 Eigen::MatrixXd const F_matrix =
129 .template topLeftCorner<DisplacementDim, DisplacementDim>();
130 auto const Finv = F_matrix.inverse();
131
132 for (unsigned i = 0; i < ShapeFunction::NPOINTS; ++i)
133 {
134 auto const dNidx = averaged_grad_N.template segment<DisplacementDim>(
135 i * DisplacementDim);
136 for (int k = 0; k < DisplacementDim; k++)
137 {
138 F0InvN[k * ShapeFunction::NPOINTS + i] = Finv.col(k).dot(dNidx);
139 }
140 // TODO: if(is_axially_symmetric)
141 }
142
143 return {MathLib::VectorizedTensor::determinant(F0), F0InvN};
144}
145
146template <int DisplacementDim, typename GradientVectorType,
147 typename GradientMatrixType, typename VectorTypeForFbar,
148 typename ShapeFunction, typename ShapeMatricesType>
149std::tuple<double, VectorTypeForFbar> computeFBarInitialVariablesElementCenter(
150 bool const compute_detF0_only, Eigen::VectorXd const& u,
151 MeshLib::Element const& element, bool const is_axially_symmetric)
152{
153 auto const shape_matrices_at_element_center =
155 ShapeFunction, ShapeMatricesType, DisplacementDim>(
156 element, is_axially_symmetric);
157
158 auto const N_0 = shape_matrices_at_element_center.N;
159 auto const dNdx_0 = shape_matrices_at_element_center.dNdx;
160
161 // For the 2D case the 33-component is needed (and the four entries
162 // of the non-symmetric matrix); In 3d there are nine entries.
163 GradientMatrixType G0(
164 DisplacementDim * DisplacementDim + (DisplacementDim == 2 ? 1 : 0),
165 ShapeFunction::NPOINTS * DisplacementDim);
166
167 auto const x_coord =
169 element, N_0);
171 dNdx_0, G0, is_axially_symmetric, N_0, x_coord);
172
173 GradientVectorType const grad_u = G0 * u;
174 GradientVectorType const F0 =
176
177 if (compute_detF0_only)
178 {
180 }
181
182 VectorTypeForFbar F0InvN =
183 computeQVector<DisplacementDim, ShapeFunction::NPOINTS,
184 VectorTypeForFbar, GradientVectorType,
185 typename ShapeMatricesType::GlobalDimNodalMatrixType>(
186 dNdx_0, F0, is_axially_symmetric);
187
188 return {MathLib::VectorizedTensor::determinant(F0), F0InvN};
189}
190
191template <int DisplacementDim>
193 bool const is_axially_symmetric)
194{
195 if (DisplacementDim == 3 || is_axially_symmetric)
196 {
199 DisplacementDim)>::identity2;
200 }
201
202 auto identity2 = MathLib::KelvinVector::Invariants<
204 DisplacementDim)>::identity2;
205
206 identity2[2] = 0.0;
207
208 return identity2;
209}
210
211template <int DisplacementDim>
213 double const alpha_p2,
215 bool const is_axially_symmetric)
216{
217 return (2.0 * eps_bar +
218 identityForF<DisplacementDim>(is_axially_symmetric)) /
219 alpha_p2;
220}
221
222} // namespace NonLinearFbar
223} // namespace ProcessLib
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
double determinant(Eigen::MatrixBase< Derived > const &tensor)
Computes determinant of a vectorized tensor.
Eigen::Matrix3d toTensor(Type< DisplacementDim > const &tensor)
Converts a vectorized tensor to a 3x3 matrix.
double interpolateXCoordinate(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
Eigen::Vector3d averageGradShapeFunction(int const local_node_id, MeshLib::Element const &element, NumLib::GenericIntegrationMethod const &integration_method, std::vector< IpData, Eigen::aligned_allocator< IpData > > const &ip_data, const bool is_axially_symmetric)
ShapeMatricesType::ShapeMatrices initShapeMatricesAtElementCenter(MeshLib::Element const &e, bool const is_axially_symmetric)
void computeGMatrix(DNDX_Type const &dNdx, GMatrixType &g_matrix, const bool is_axially_symmetric, N_Type const &N, const double radius)
Fills a G-matrix based on given shape function dN/dx values.
Definition GMatrix.h:18
MathLib::KelvinVector::KelvinVectorType< DisplacementDim > identityForF(bool const is_axially_symmetric)
std::tuple< double, VectorTypeForFbar > computeFBarInitialVariablesElementCenter(bool const compute_detF0_only, Eigen::VectorXd const &u, MeshLib::Element const &element, bool const is_axially_symmetric)
VectorTypeForFbar computeQVector(DNDX_Type const &dNdx, GradientVectorType const &F, bool const)
BarDetFType convertStringToDetFBarType(std::string_view const bar_det_f_type_name)
std::tuple< double, VectorTypeForFbar > computeFBarInitialVariablesAverage(std::vector< IpData, Eigen::aligned_allocator< IpData > > const &ip_data, bool const compute_detF0_only, Eigen::VectorXd const &u, NumLib::GenericIntegrationMethod const &integration_method, MeshLib::Element const &element, bool const is_axially_symmetric)
MathLib::KelvinVector::KelvinVectorType< DisplacementDim > compute2EPlusI(double const alpha_p2, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps_bar, bool const is_axially_symmetric)