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