PRISMS-PF Manual
Loading...
Searching...
No Matches
utilities.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: © 2025 PRISMS Center at the University of Michigan
2// SPDX-License-Identifier: GNU Lesser General Public Version 2.1
3
4#pragma once
5
6#include <deal.II/base/config.h>
7#include <deal.II/base/exceptions.h>
8#include <deal.II/base/mpi.h>
9#include <deal.II/base/point.h>
10#include <deal.II/base/tensor.h>
11#include <deal.II/base/vectorization.h>
12#include <deal.II/matrix_free/evaluation_flags.h>
13
14#include <boost/range/algorithm.hpp>
15#include <boost/range/algorithm_ext.hpp>
16
18
19#include <prismspf/config.h>
20
21#include <string>
22#include <string_view>
23#include <unordered_map>
24
26
27class MPI_InitFinalize : public dealii::Utilities::MPI::MPI_InitFinalize
28{
29public:
30#ifdef DEBUG
31 MPI_InitFinalize(int &argc,
32 char **&argv,
33 [[maybe_unused]] const unsigned int max_num_threads =
34 dealii::numbers::invalid_unsigned_int)
35 : dealii::Utilities::MPI::MPI_InitFinalize(argc, argv, 1)
36 {}
37#else
39 int &argc,
40 char **&argv,
41 const unsigned int max_num_threads = dealii::numbers::invalid_unsigned_int)
42 : dealii::Utilities::MPI::MPI_InitFinalize(argc, argv, max_num_threads)
43 {}
44#endif
45};
46
50template <typename Type>
51Type
52string_to_type(const std::string &string,
53 const std::unordered_map<std::string, Type> &table)
54{
55 auto iterator = table.find(string);
56 AssertThrow(iterator != table.end(),
57 dealii::ExcMessage("Unknown table entry: " + string));
58 return iterator->second;
59}
60
78template <typename Type, typename OtherType>
79std::pair<OtherType, Type>
81 const std::string &string,
82 const std::unordered_map<std::string, Type> &table,
83 const std::unordered_map<std::string, OtherType> &other_table,
84 const std::pair<char, char> &delimiters = {'(', ')'})
85{
86 // Check to see if the string has any delimiters
87 const auto opening_delimiter_position = string.find(delimiters.first);
88 const auto closing_delimiter_position = string.find(delimiters.second);
89
90 bool has_opening_delimiter = opening_delimiter_position != std::string_view::npos;
91 bool has_closing_delimiter = closing_delimiter_position != std::string_view::npos;
92
93 // Some checks for malformed input
94 AssertThrow(closing_delimiter_position >= opening_delimiter_position,
95 dealii::ExcMessage(
96 "Opening delimiter must precede the closing delimiter. You had " +
97 string));
98 AssertThrow(has_closing_delimiter == has_opening_delimiter,
99 dealii::ExcMessage("You must either have a delimiter pair or not. You seem "
100 "to only have one delimiter. You had " +
101 string));
102
103 // Case 2 - no delimiters
104 if (!has_closing_delimiter && !has_opening_delimiter)
105 {
106 const auto second_type = string_to_type("", table);
107 const auto first_type = string_to_type(string, other_table);
108 return {first_type, second_type};
109 }
110
111 // More checks for malformed input
112 AssertThrow(closing_delimiter_position == string.size() - 1,
113 dealii::ExcMessage(
114 "Closing delimiter must be at the end of the string. You had " + string));
115
116 // Case 1 - delimiters
117 std::string_view input_view {string};
118 std::string_view outer_string = input_view.substr(0, opening_delimiter_position);
119 std::string_view inner_string =
120 input_view.substr(opening_delimiter_position + 1,
121 closing_delimiter_position - opening_delimiter_position - 1);
122
123 AssertThrow(!outer_string.empty() && !inner_string.empty(),
124 dealii::ExcMessage(
125 "Inner and outer map entries must not be empty. You had " + string));
126 // NOTE: This will allocate the string views to strings on the heap. Hopefully this
127 // isn't so bad in performance, but I didn't wanna support heterogeneous lookup tables.
128 // I can't imagine this becoming a performance problem right now since we only deal with
129 // strings in the initialization of simulations; however, if it does, it shouldn't be
130 // two hard to support heterogeneous lookup or a table that uses std::string_view.
131 const auto second_type = string_to_type(std::string(outer_string), table);
132 const auto first_type = string_to_type(std::string(inner_string), other_table);
133 return {first_type, second_type};
134}
135
140template <typename Number>
141inline DEAL_II_ALWAYS_INLINE Number
142pmod(const Number &value, const Number &modulus)
143{
144 return std::fmod(std::fmod(value, modulus) + modulus, modulus);
145}
146
150template <unsigned int dim>
151constexpr unsigned int voigt_tensor_size = (2 * dim) - 1 + (dim / 3);
152
157template <unsigned int dim, typename T>
158inline DEAL_II_ALWAYS_INLINE void
159compute_stress(const dealii::Tensor<2, voigt_tensor_size<dim>, T> &elasticity_tensor,
160 const dealii::Tensor<1, voigt_tensor_size<dim>, T> &strain,
161 dealii::Tensor<1, voigt_tensor_size<dim>, T> &stress)
162{
163 stress = elasticity_tensor * strain;
164}
165
170template <unsigned int dim, typename T>
171inline DEAL_II_ALWAYS_INLINE void
172compute_stress(const dealii::Tensor<2, voigt_tensor_size<dim>, T> &elasticity_tensor,
173 const dealii::Tensor<2, dim, T> &strain,
174 dealii::Tensor<2, dim, T> &stress)
175{
176 dealii::Tensor<1, voigt_tensor_size<dim>, T> sigma;
177 dealii::Tensor<1, voigt_tensor_size<dim>, T> epsilon;
178
179 if constexpr (dim == 3)
180 {
181 const int xx_dir = 0;
182 const int yy_dir = 1;
183 const int zz_dir = 2;
184 const int yz_dir = 3;
185 const int xz_dir = 4;
186 const int xy_dir = 5;
187
188 epsilon[xx_dir] = strain[xx_dir][xx_dir];
189 epsilon[yy_dir] = strain[yy_dir][yy_dir];
190 epsilon[zz_dir] = strain[zz_dir][zz_dir];
191 // In Voigt notation: epsilonngineering shear strain=zz_dir*strain
192 epsilon[yz_dir] = strain[yy_dir][zz_dir] + strain[zz_dir][yy_dir];
193 epsilon[xz_dir] = strain[xx_dir][zz_dir] + strain[zz_dir][xx_dir];
194 epsilon[xy_dir] = strain[xx_dir][yy_dir] + strain[yy_dir][xx_dir];
195
196 // Multiply elasticity_tensor and epsilon to get sigma
197 sigma = elasticity_tensor * epsilon;
198
199 stress[xx_dir][xx_dir] = sigma[xx_dir];
200 stress[yy_dir][yy_dir] = sigma[yy_dir];
201 stress[zz_dir][zz_dir] = sigma[zz_dir];
202
203 stress[yy_dir][zz_dir] = sigma[yz_dir];
204 stress[zz_dir][yy_dir] = sigma[yz_dir];
205
206 stress[xx_dir][zz_dir] = sigma[xz_dir];
207 stress[zz_dir][xx_dir] = sigma[xz_dir];
208
209 stress[xx_dir][yy_dir] = sigma[xy_dir];
210 stress[yy_dir][xx_dir] = sigma[xy_dir];
211 }
212 else if constexpr (dim == 2)
213 {
214 const int xx_dir = 0;
215 const int yy_dir = 1;
216 const int xy_dir = 2;
217
218 epsilon[xx_dir] = strain[xx_dir][xx_dir];
219 epsilon[yy_dir] = strain[yy_dir][yy_dir];
220 // In Voigt notation: epsilonngineering shear strain=xy_dir*strain
221 epsilon[xy_dir] = strain[xx_dir][yy_dir] + strain[yy_dir][xx_dir];
222
223 // Multiply elasticity_tensor and epsilon to get sigma
224 sigma = elasticity_tensor * epsilon;
225
226 stress[xx_dir][xx_dir] = sigma[xx_dir];
227 stress[yy_dir][yy_dir] = sigma[yy_dir];
228 stress[xx_dir][yy_dir] = sigma[xy_dir];
229 stress[yy_dir][xx_dir] = sigma[xy_dir];
230 }
231 else
232 {
233 const int xx_dir = 0;
234
235 stress[xx_dir][xx_dir] = elasticity_tensor[xx_dir][xx_dir] * strain[xx_dir][xx_dir];
236 }
237}
238
242inline std::string
243strip_whitespace(const std::string &_text)
244{
245 std::string text = _text;
246 boost::range::remove_erase_if(text, ::isspace);
247 return text;
248}
249
253inline const char *
254bool_to_string(bool boolean)
255{
256 return boolean ? "true" : "false";
257}
258
262inline std::string
263eval_flags_to_string(dealii::EvaluationFlags::EvaluationFlags flag)
264{
265 std::string result;
266
267 if ((flag & dealii::EvaluationFlags::EvaluationFlags::values) != 0U)
268 {
269 result += "values";
270 }
271 if ((flag & dealii::EvaluationFlags::EvaluationFlags::gradients) != 0U)
272 {
273 if (!result.empty())
274 {
275 result += " | ";
276 }
277 result += "gradients";
278 }
279 if ((flag & dealii::EvaluationFlags::EvaluationFlags::hessians) != 0U)
280 {
281 if (!result.empty())
282 {
283 result += " | ";
284 }
285 result += "hessians";
286 }
287
288 if (result.empty())
289 {
290 return "nothing";
291 }
292
293 return result;
294}
295
296template <unsigned int dim, typename number>
297inline DEAL_II_ALWAYS_INLINE std::vector<number>
298dealii_point_to_vector(const dealii::Point<dim, number> &point)
299{
300 static_assert(dim < 4, "We only allow 3 space dimensions");
301
302 std::vector<number> vec(3, 0.0);
303
304 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-constant-array-index)
305
306 for (unsigned int i = 0; i < dim; ++i)
307 {
308 vec[i] = point[i];
309 }
310
311 // NOLINTEND(cppcoreguidelines-pro-bounds-constant-array-index)
312
313 return vec;
314}
315
316PRISMS_PF_END_NAMESPACE
317
MPI_InitFinalize(int &argc, char **&argv, const unsigned int max_num_threads=dealii::numbers::invalid_unsigned_int)
Definition utilities.h:38
Definition conditional_ostreams.cc:20
inline ::dealii::VectorizedArray< Number, width > fmod(const ::dealii::VectorizedArray< Number, width > &numer, const Number denom)
Definition vectorized_operations.h:54
Type
Factory function to create appropriate reader based on input file type not a member of ReadFieldBase ...
Definition read_field_factory.h:30
std::string strip_whitespace(const std::string &_text)
Remove whitespace from strings.
Definition utilities.h:243
std::pair< OtherType, Type > string_to_type_pair_with_delimiters(const std::string &string, const std::unordered_map< std::string, Type > &table, const std::unordered_map< std::string, OtherType > &other_table, const std::pair< char, char > &delimiters={'(', ')'})
Helper function that converts a string to some type pair, given two mappings and a set of delimiters.
Definition utilities.h:80
Type string_to_type(const std::string &string, const std::unordered_map< std::string, Type > &table)
Helper function that converts a string to some type, given a mapping.
Definition utilities.h:52
std::string eval_flags_to_string(dealii::EvaluationFlags::EvaluationFlags flag)
Convert evaluation flags to string.
Definition utilities.h:263
DEAL_II_ALWAYS_INLINE void compute_stress(const dealii::Tensor< 2, voigt_tensor_size< dim >, T > &elasticity_tensor, const dealii::Tensor< 1, voigt_tensor_size< dim >, T > &strain, dealii::Tensor< 1, voigt_tensor_size< dim >, T > &stress)
Compute the stress with a given displacement and elasticity tensor. This assumes that the provided pa...
Definition utilities.h:159
constexpr unsigned int voigt_tensor_size
Voigt notation index range.
Definition utilities.h:151
DEAL_II_ALWAYS_INLINE std::vector< number > dealii_point_to_vector(const dealii::Point< dim, number > &point)
Definition utilities.h:298
DEAL_II_ALWAYS_INLINE Number pmod(const Number &value, const Number &modulus)
Positive moldulo (remainder) returns the normal remainder. (c++ fmod is defined abnormally for negati...
Definition utilities.h:142
const char * bool_to_string(bool boolean)
Convert bool to string.
Definition utilities.h:254