OGS
MaterialForces.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 <cassert>
7#include <tuple>
8#include <vector>
9
17
18namespace ProcessLib
19{
20namespace SmallDeformation
21{
23{
24 virtual std::vector<double> const& getMaterialForces(
25 std::vector<double> const& local_x,
26 std::vector<double>& nodal_values) = 0;
27
28 virtual ~MaterialForcesInterface() = default;
29};
30
31template <int DisplacementDim, typename ShapeFunction,
32 typename ShapeMatricesType, typename NodalForceVectorType,
33 typename NodalDisplacementVectorType, typename GradientVectorType,
34 typename GradientMatrixType, typename IPData, typename StressData,
35 typename OutputData, typename IntegrationMethod>
36std::vector<double> const& getMaterialForces(
37 std::vector<double> const& local_x, std::vector<double>& nodal_values,
38 IntegrationMethod const& integration_method, IPData const& ip_data,
39 StressData const& stress_data, OutputData const& output_data,
40 MeshLib::Element const& element, bool const is_axially_symmetric)
41{
42 unsigned const n_integration_points =
43 integration_method.getNumberOfPoints();
44
45 nodal_values.clear();
47 nodal_values, ShapeFunction::NPOINTS * DisplacementDim);
48
49 for (unsigned ip = 0; ip < n_integration_points; ip++)
50 {
51 auto const& sigma =
53 DisplacementDim>>(stress_data[ip])
54 .sigma;
55 auto const& N = ip_data[ip].N_u;
56 auto const& dNdx = ip_data[ip].dNdx_u;
57
58 auto const& psi = std::get<FreeEnergyDensityData>(output_data[ip])
59 .free_energy_density;
60
61 auto const x_coord =
63 element, ip_data[ip].N_u);
64
65 // For the 2D case the 33-component is needed (and the four entries
66 // of the non-symmetric matrix); In 3d there are nine entries.
67 GradientMatrixType G(
68 DisplacementDim * DisplacementDim + (DisplacementDim == 2 ? 1 : 0),
69 ShapeFunction::NPOINTS * DisplacementDim);
71 dNdx, G, is_axially_symmetric, N, x_coord);
72
73 GradientVectorType const grad_u =
74 G * Eigen::Map<NodalForceVectorType const>(
75 local_x.data(), ShapeFunction::NPOINTS * DisplacementDim);
76
77 GradientVectorType eshelby_stress;
78 eshelby_stress.setZero(DisplacementDim * DisplacementDim +
79 (DisplacementDim == 2 ? 1 : 0));
80
81 if (DisplacementDim == 3)
82 {
83 eshelby_stress[0] = eshelby_stress[DisplacementDim + 1] =
84 eshelby_stress[8] = psi;
85
86 eshelby_stress[0] -= sigma[0] * grad_u[0] +
87 sigma[3] / std::sqrt(2) * grad_u[3] +
88 sigma[5] / std::sqrt(2) * grad_u[6];
89
90 eshelby_stress[1] -= sigma[3] / std::sqrt(2) * grad_u[0] +
91 sigma[1] * grad_u[3] +
92 sigma[4] / std::sqrt(2) * grad_u[6];
93
94 eshelby_stress[2] -= sigma[5] / std::sqrt(2) * grad_u[0] +
95 sigma[4] / std::sqrt(2) * grad_u[3] +
96 sigma[2] * grad_u[6];
97
98 eshelby_stress[3] -= sigma[0] * grad_u[1] +
99 sigma[3] / std::sqrt(2) * grad_u[4] +
100 sigma[5] / std::sqrt(2) * grad_u[7];
101
102 eshelby_stress[4] -= sigma[3] / std::sqrt(2) * grad_u[1] +
103 sigma[1] * grad_u[4] +
104 sigma[4] / std::sqrt(2) * grad_u[7];
105
106 eshelby_stress[5] -= sigma[5] / std::sqrt(2) * grad_u[1] +
107 sigma[4] / std::sqrt(2) * grad_u[4] +
108 sigma[2] * grad_u[7];
109
110 eshelby_stress[6] -= sigma[0] * grad_u[2] +
111 sigma[3] / std::sqrt(2) * grad_u[5] +
112 sigma[5] / std::sqrt(2) * grad_u[8];
113
114 eshelby_stress[7] -= sigma[3] / std::sqrt(2) * grad_u[2] +
115 sigma[1] * grad_u[5] +
116 sigma[4] / std::sqrt(2) * grad_u[8];
117
118 eshelby_stress[8] -= sigma[5] / std::sqrt(2) * grad_u[2] +
119 sigma[4] / std::sqrt(2) * grad_u[5] +
120 sigma[2] * grad_u[8];
121 }
122 else if (DisplacementDim == 2)
123 {
124 eshelby_stress[0] = eshelby_stress[DisplacementDim + 1] =
125 eshelby_stress[4] = psi;
126
127 eshelby_stress[0] -=
128 sigma[0] * grad_u[0] + sigma[3] / std::sqrt(2) * grad_u[2];
129
130 eshelby_stress[1] -=
131 sigma[3] / std::sqrt(2) * grad_u[0] + sigma[1] * grad_u[2];
132
133 eshelby_stress[2] -=
134 sigma[0] * grad_u[1] + sigma[3] / std::sqrt(2) * grad_u[3];
135
136 eshelby_stress[3] -=
137 sigma[3] / std::sqrt(2) * grad_u[1] + sigma[1] * grad_u[3];
138
139 // for axial-symmetric case the following is not zero in general
140 eshelby_stress[4] -= sigma[2] * grad_u[4];
141 }
142 else
143 {
144 OGS_FATAL(
145 "Material forces not implemented for displacement "
146 "dimension "
147 "other than 2 and 3.");
148 }
149
150 auto const& w = ip_data[ip].integration_weight;
151 local_b += G.transpose() * eshelby_stress * w;
152 }
153
154 return nodal_values;
155}
156
157template <typename LocalAssemblerInterface>
159 std::unique_ptr<GlobalVector>& material_forces,
160 std::vector<std::unique_ptr<LocalAssemblerInterface>> const&
161 local_assemblers,
162 NumLib::LocalToGlobalIndexMap const& local_to_global_index_map,
163 GlobalVector const& x)
164{
165 DBUG("Compute material forces for small deformation process.");
166
167 // Prepare local storage and fetch values.
169
170 if (!material_forces)
171 {
172 material_forces =
174 }
175
176 MathLib::LinAlg::set(*material_forces, 0);
177
179 [](const std::size_t mesh_item_id,
180 LocalAssemblerInterface& local_assembler,
181 const NumLib::LocalToGlobalIndexMap& dof_table,
182 GlobalVector const& x,
183 GlobalVector& node_values)
184 {
185 auto const indices = NumLib::getIndices(mesh_item_id, dof_table);
186 std::vector<double> local_data;
187 auto const local_x = x.get(indices);
188
189 local_assembler.getMaterialForces(local_x, local_data);
190
191 assert(local_data.size() == indices.size());
192 node_values.add(indices, local_data);
193 },
194 local_assemblers, local_to_global_index_map, x, *material_forces);
195 MathLib::LinAlg::finalizeAssembly(*material_forces);
196}
197
198} // namespace SmallDeformation
199} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
MathLib::EigenVector GlobalVector
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
void add(IndexType rowId, double v)
add entry
Definition EigenVector.h:70
double get(IndexType rowId) const
get entry
Definition EigenVector.h:52
void finalizeAssembly(PETScMatrix &A)
Definition LinAlg.cpp:191
void setLocalAccessibleVector(PETScVector const &x)
Definition LinAlg.cpp:20
void set(PETScVector &x, PetscScalar const a)
Definition LinAlg.cpp:25
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
double interpolateXCoordinate(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
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
void writeMaterialForces(std::unique_ptr< GlobalVector > &material_forces, std::vector< std::unique_ptr< LocalAssemblerInterface > > const &local_assemblers, NumLib::LocalToGlobalIndexMap const &local_to_global_index_map, GlobalVector const &x)
std::vector< double > const & getMaterialForces(std::vector< double > const &local_x, std::vector< double > &nodal_values, IntegrationMethod const &integration_method, IPData const &ip_data, StressData const &stress_data, OutputData const &output_data, MeshLib::Element const &element, bool const is_axially_symmetric)
static void executeDereferenced(F const &f, C const &c, Args_ &&... args)
virtual std::vector< double > const & getMaterialForces(std::vector< double > const &local_x, std::vector< double > &nodal_values)=0