OGS
SolidMaterialInternalToSecondaryVariables.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 <map>
7#include <memory>
8
13
15{
16
17template <typename SolidMaterial>
18std::map<std::string,
19 std::vector<std::pair<int, typename SolidMaterial::InternalVariable>>>
21 std::map<int, std::shared_ptr<SolidMaterial>> const& solid_materials)
22{
23 assert(!solid_materials.empty());
24
25 // For each name of an internal variable collect all solid material/
26 // internal variable pairs.
27 std::map<
28 std::string,
29 std::vector<std::pair<int, typename SolidMaterial::InternalVariable>>>
30 internal_variables_by_name;
31 for (auto const& [material_id, solid_material] : solid_materials)
32 {
33 auto const& internal_variables = solid_material->getInternalVariables();
34 for (auto const& iv : internal_variables)
35 {
36 internal_variables_by_name[iv.name].push_back({material_id, iv});
37 }
38 }
39
40 // Check for each internal variable name, that the number of components is
41 // equal for all materials.
42 for (auto const& [name, mat_iv_collection] : internal_variables_by_name)
43 {
44 if (mat_iv_collection.empty())
45 {
46 continue;
47 }
48 auto const num_components =
49 mat_iv_collection.front().second.num_components;
50
51 if (!std::all_of(
52 begin(mat_iv_collection), end(mat_iv_collection),
53 [num_components](auto const& mat_iv)
54 { return mat_iv.second.num_components == num_components; }))
55 {
57 "Not for all material ids the secondary variable '{:s}' has "
58 "{:d} components.",
59 name, num_components);
60 }
61 }
62
63 return internal_variables_by_name;
64}
65
66template <typename InternalVariable>
68{
69 template <typename LocalAssemblerInterface>
70 InternalVariable const* findInternalVariable(
71 LocalAssemblerInterface const& loc_asm) const
72 {
73 int const material_id =
74 material_id_independent ? 0 : loc_asm.getMaterialID();
75
76 auto const mat_iv_it = std::find_if(
78 [material_id](auto const& x) { return x.first == material_id; });
79 if (mat_iv_it == end(mat_iv_collection))
80 {
81 // If local assembler does not provide correct solid material
82 // model return empty vector, which will be ignored by the
83 // extrapolation algorithm.
84 return nullptr;
85 }
86
87 assert(num_components == mat_iv_it->second.num_components);
88
89 return &mat_iv_it->second;
90 }
91
92 std::vector<std::pair<int, InternalVariable>> mat_iv_collection;
95};
96
97template <typename Pair>
98InternalVariablesCollection(std::vector<Pair>&&, int, bool)
100
101template <typename SolidMaterial>
103 std::map<int, std::shared_ptr<SolidMaterial>> const& solid_materials,
104 auto const& function)
105{
106 auto internal_variables_by_name = collectInternalVariables(solid_materials);
107
108 // Multiple material ids could be present but only one material for the
109 // whole domain. In this case the choice of callbacks is independent of
110 // local assembler's material id, and the material id is 0.
111 // \see selectSolidConstitutiveRelation() for material id logic.
112 bool const material_id_independent = solid_materials.size() == 1;
113
114 // Create *single* callback passing all solid materials to it. Choose
115 // correct solid material based on the local assembler's solid material in
116 // the callback.
117 for (auto&& [name, mat_iv_collection] : internal_variables_by_name)
118 {
119 auto const num_components =
120 mat_iv_collection.front().second.num_components;
121
122 function(name,
123 InternalVariablesCollection{std::move(mat_iv_collection),
124 num_components,
125 material_id_independent});
126 }
127}
128
129template <typename InternalVariable>
131{
132public:
135 internal_variables_collection)
137 std::move(internal_variables_collection))
138 {
139 }
140
141 template <typename LocalAssemblerInterface>
142 std::vector<double> const& operator()(
143 LocalAssemblerInterface const& loc_asm,
144 const double /*t*/,
145 std::vector<GlobalVector*> const& /*x*/,
146 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
147 std::vector<double>& cache) const
148 {
149 cache.clear();
150
151 auto const* const iv =
152 internal_variables_collection_.findInternalVariable(loc_asm);
153
154 if (iv == nullptr)
155 {
156 // If the material model for the present material group does not
157 // have the requested internal variable, return an empty vector,
158 // which will be ignored by the extrapolation algorithm.
159 return cache;
160 }
161
162 auto const& fct = iv->getter;
163
164 const unsigned num_int_pts = loc_asm.getNumberOfIntegrationPoints();
165 assert(num_int_pts > 0);
166
167 auto cache_mat = MathLib::createZeroedMatrix<Eigen::Matrix<
168 double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(
169 cache, internal_variables_collection_.num_components, num_int_pts);
170
171 // TODO avoid the heap allocation (one per finite element)
172 std::vector<double> cache_column(num_int_pts);
173
174 for (unsigned i = 0; i < num_int_pts; ++i)
175 {
176 auto const& state = loc_asm.getMaterialStateVariablesAt(i);
177
178 auto const& int_pt_values = fct(state, cache_column);
179 assert(int_pt_values.size() ==
180 static_cast<std::size_t>(
181 internal_variables_collection_.num_components));
182 auto const int_pt_values_vec = MathLib::toVector(int_pt_values);
183
184 cache_mat.col(i).noalias() = int_pt_values_vec;
185 }
186
187 return cache;
188 }
189
190private:
193};
194
195template <typename LocalAssemblerInterface, typename SolidMaterial,
196 typename AddSecondaryVariableCallback>
198 std::map<int, std::shared_ptr<SolidMaterial>> const& solid_materials,
199 AddSecondaryVariableCallback const& add_secondary_variable)
200{
201 auto register_secondary_variable =
202 [&add_secondary_variable](
203 std::string const& name,
205 typename SolidMaterial::InternalVariable>&&
206 internal_variables_collection)
207 {
208 DBUG("Registering internal variable {:s}.", name);
209
210 add_secondary_variable(name,
211 internal_variables_collection.num_components,
213 std::move(internal_variables_collection)});
214 };
215
217 register_secondary_variable);
218}
219
220template <typename InternalVariable>
222{
223public:
226 internal_variables_collection)
227 : internal_variables_collection_(internal_variables_collection)
228 {
229 }
230
231 template <typename LocalAssemblerInterface>
232 std::vector<double> operator()(LocalAssemblerInterface const& loc_asm) const
233 {
234 auto const iv =
235 internal_variables_collection_.findInternalVariable(loc_asm);
236 if (iv == nullptr)
237 {
238 // If the material model for the present material group does not
239 // have the requested internal variable, return an empty vector,
240 // which will be ignored by the integration point writer.
241 return {};
242 }
243
244 auto const& fct = iv->reference;
245
246 return loc_asm.getMaterialStateVariableInternalState(
247 fct, internal_variables_collection_.num_components);
248 };
249
250private:
253};
254
255template <typename LocalAssemblerInterface, typename SolidMaterial>
257 std::map<int, std::shared_ptr<SolidMaterial>> const& solid_materials,
258 std::vector<std::unique_ptr<LocalAssemblerInterface>> const&
259 local_assemblers,
260 std::vector<std::unique_ptr<MeshLib::IntegrationPointWriter>>&
261 integration_point_writer,
262 int const integration_order)
263{
264 auto add_integration_point_writer =
265 [&local_assemblers, &integration_point_writer, integration_order](
266 std::string const& name,
268 typename SolidMaterial::InternalVariable>&&
269 internal_variables_collection)
270 {
271 DBUG("Creating integration point writer for internal variable {:s}.",
272 name);
273
274 integration_point_writer.emplace_back(
275 std::make_unique<MeshLib::IntegrationPointWriter>(
276 "material_state_variable_" + name + "_ip",
277 internal_variables_collection.num_components, integration_order,
278 local_assemblers,
280 std::move(internal_variables_collection)}));
281 };
282
284 add_integration_point_writer);
285}
286} // namespace ProcessLib::Deformation
#define OGS_FATAL(...)
Definition Error.h:19
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
CollectIntegrationPointDataForExtrapolation(InternalVariablesCollection< InternalVariable > &&internal_variables_collection)
std::vector< double > const & operator()(LocalAssemblerInterface const &loc_asm, const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const
CollectIntegrationPointDataForIpWriter(InternalVariablesCollection< InternalVariable > &&internal_variables_collection)
std::vector< double > operator()(LocalAssemblerInterface const &loc_asm) const
Eigen::Map< const Vector > toVector(std::vector< double > const &data, Eigen::VectorXd::Index size)
Creates an Eigen mapped vector from the given data vector.
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
std::map< std::string, std::vector< std::pair< int, typename SolidMaterial::InternalVariable > > > collectInternalVariables(std::map< int, std::shared_ptr< SolidMaterial > > const &solid_materials)
void solidMaterialInternalVariablesToIntegrationPointWriter(std::map< int, std::shared_ptr< SolidMaterial > > const &solid_materials, std::vector< std::unique_ptr< LocalAssemblerInterface > > const &local_assemblers, std::vector< std::unique_ptr< MeshLib::IntegrationPointWriter > > &integration_point_writer, int const integration_order)
void solidMaterialInternalToSecondaryVariables(std::map< int, std::shared_ptr< SolidMaterial > > const &solid_materials, AddSecondaryVariableCallback const &add_secondary_variable)
InternalVariablesCollection(std::vector< Pair > &&, int, bool) -> InternalVariablesCollection< typename Pair::second_type >
void forEachSolidMaterialInternalVariable(std::map< int, std::shared_ptr< SolidMaterial > > const &solid_materials, auto const &function)
InternalVariable const * findInternalVariable(LocalAssemblerInterface const &loc_asm) const
std::vector< std::pair< int, InternalVariable > > mat_iv_collection