ASPECT
utilities.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2023 by the authors of the ASPECT code.
3 
4  This file is part of ASPECT.
5 
6  ASPECT is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2, or (at your option)
9  any later version.
10 
11  ASPECT is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with ASPECT; see the file LICENSE. If not see
18  <http://www.gnu.org/licenses/>.
19 */
20 
21 
22 #ifndef _aspect_utilities_h
23 #define _aspect_utilities_h
24 
25 #include <aspect/global.h>
26 
27 #include <array>
28 #include <random>
29 #include <deal.II/base/point.h>
30 #include <deal.II/base/conditional_ostream.h>
31 #include <deal.II/base/table_indices.h>
32 #include <deal.II/base/function_lib.h>
33 #include <deal.II/dofs/dof_handler.h>
34 #include <deal.II/fe/component_mask.h>
35 
37 #include <aspect/structured_data.h>
38 
39 
40 
41 namespace aspect
42 {
43  template <int dim> class SimulatorAccess;
44 
45  namespace GeometryModel
46  {
47  template <int dim> class Interface;
48  }
49 
54  namespace Utilities
55  {
56  using namespace dealii;
57  using namespace ::Utilities;
58 
59 
73  template <typename T>
74  std::vector<T>
75  possibly_extend_from_1_to_N (const std::vector<T> &values,
76  const unsigned int N,
77  const std::string &id_text);
78 
79  namespace MapParsing
80  {
85  struct Options
86  {
87  /* A list of valid key names that are allowed
88  * to appear in the map. If this list is empty
89  * it is assumed to be equal to the list of
90  * required keys. If this list is longer than
91  * list_of_required_keys, every key that is
92  * allowed but not required will be ignored when
93  * parsing the map.
94  */
95  std::vector<std::string> list_of_allowed_keys;
96 
97  /* A list of valid key names that are required
98  * to appear in the map. Only these keys will be
99  * parsed into the map structure and the order of
100  * these keys determines the order of entries
101  * in the output vector.
102  */
103  std::vector<std::string> list_of_required_keys;
104 
105  /*
106  * A name that identifies the type of input property (e.g. 'density', 'viscosity')
107  * that is being parsed by this function. This name is used in generating
108  * error messages if the map does not conform to the expected format.
109  */
110  std::string property_name;
111 
112  /*
113  * If true, allow multiple values
114  * for each key. If false only allow a single value per key. In either
115  * case each key is only allowed to appear once. Multiple values
116  * for a key are delimited by a "|" character, as in
117  * "key1: value1|value2|value3, key2: value1|value2".
118  */
120 
121  /*
122  * Whether to allow for some keys in list_of_required_keys to be
123  * not set to any values, i.e. they do not appear at all.
124  * This also allows a completely empty map.
125  */
127 
128  /*
129  * Whether to store the number of values
130  * per key in n_values_per_key while creating
131  * the map. This vector can be later accessed
132  * and used (for example) to check that subsequent calls to
133  * parse other input parameters have the same
134  * structure.
135  */
137 
138  /*
139  * Whether to check the number of values
140  * per key in the map against values stored
141  * in n_values_per_key. This allows to
142  * check that subsequent calls to
143  * parse other input parameters have the same
144  * structure.
145  */
147 
148  /*
149  * A vector of unsigned
150  * integers that is used by store_values_per_key and
151  * check_values_per_key to either store the current map
152  * structure or check the map structure against an existing
153  * map. This parameter is only used if either of these
154  * two parameters are set to true
155  */
156  std::vector<unsigned int> n_values_per_key;
157 
162  Options() = delete;
163 
174  Options(const std::vector<std::string> &list_of_required_keys,
175  const std::string &property_name)
176  :
177  list_of_allowed_keys(list_of_required_keys),
178  list_of_required_keys(list_of_required_keys),
179  property_name(property_name),
180  allow_multiple_values_per_key(false),
181  allow_missing_keys(false),
182  store_values_per_key(false),
183  check_values_per_key(false),
184  n_values_per_key()
185  {}
186  };
187 
213  std::vector<double>
214  parse_map_to_double_array(const std::string &input_string,
215  Options &options);
216  }
217 
291  std::vector<double>
292  parse_map_to_double_array (const std::string &key_value_map,
293  const std::vector<std::string> &list_of_keys,
294  const bool expects_background_field,
295  const std::string &property_name,
296  const bool allow_multiple_values_per_key = false,
297  const std::unique_ptr<std::vector<unsigned int>> &n_values_per_key = nullptr,
298  const bool allow_missing_keys = false);
299 
313  template <typename T>
314  Table<2,T>
315  parse_input_table (const std::string &input_string,
316  const unsigned int n_rows,
317  const unsigned int n_columns,
318  const std::string &property_name);
319 
332  template <int dim>
333  std::vector<std::string>
334  expand_dimensional_variable_names (const std::vector<std::string> &var_declarations);
335 
342  template <int dim>
343  IndexSet extract_locally_active_dofs_with_component(const DoFHandler<dim> &dof_handler,
344  const ComponentMask &component_mask);
345 
355  template <int dim>
356  std::vector<Point<dim>> get_unit_support_points(const SimulatorAccess<dim> &simulator_access);
357 
358 
359 
365  template <int dim>
366  bool
367  point_is_in_triangulation(const Mapping<dim> &mapping,
368  const parallel::distributed::Triangulation<dim> &triangulation,
369  const Point<dim> &point,
370  const MPI_Comm mpi_communicator);
371 
372 
373  namespace Coordinates
374  {
375 
381  template <int dim>
382  std::array<double,dim>
383  WGS84_coordinates(const ::Point<dim> &position);
384 
395  template <int dim>
396  std::array<double,dim>
397  cartesian_to_spherical_coordinates(const ::Point<dim> &position);
398 
404  template <int dim>
405  ::Point<dim>
406  spherical_to_cartesian_coordinates(const std::array<double,dim> &scoord);
407 
413  template <int dim>
414  Tensor<1,dim>
415  spherical_to_cartesian_vector(const Tensor<1,dim> &spherical_vector,
416  const ::Point<dim> &position);
417 
418 
424  template <int dim>
425  std::array<double,3>
426  cartesian_to_ellipsoidal_coordinates(const ::Point<3> &position,
427  const double semi_major_axis_a,
428  const double eccentricity);
429 
434  template <int dim>
435  ::Point<3>
436  ellipsoidal_to_cartesian_coordinates(const std::array<double,3> &phi_theta_d,
437  const double semi_major_axis_a,
438  const double eccentricity);
439 
440 
447  string_to_coordinate_system (const std::string &);
448  }
449 
450 
455  template <int dim>
456  bool
457  polygon_contains_point(const std::vector<Point<2>> &point_list,
458  const ::Point<2> &point);
459 
465  template <int dim>
466  double
467  signed_distance_to_polygon(const std::vector<Point<2>> &point_list,
468  const ::Point<2> &point);
469 
470 
477  double
478  distance_to_line(const std::array<::Point<2>,2> &point_list,
479  const ::Point<2> &point);
480 
488  template <int dim>
489  std::array<Tensor<1,dim>,dim-1>
490  orthogonal_vectors (const Tensor<1,dim> &v);
491 
496  Tensor<2,3>
497  rotation_matrix_from_axis (const Tensor<1,3> &rotation_axis,
498  const double rotation_angle);
499 
506  Tensor<2,3>
507  compute_rotation_matrix_for_slice (const Tensor<1,3> &point_one,
508  const Tensor<1,3> &point_two);
509 
546  std::pair<double,double> real_spherical_harmonic( unsigned int l, // degree
547  unsigned int m, // order
548  double theta, // colatitude (radians)
549  double phi ); // longitude (radians)
550 
554  struct ThousandSep : std::numpunct<char>
555  {
556  protected:
557  char do_thousands_sep() const override
558  {
559  return ',';
560  }
561 
562  std::string do_grouping() const override
563  {
564  return "\003"; // groups of 3 digits (this string is in octal format)
565  }
566 
567  };
568 
581  bool fexists(const std::string &filename);
582 
596  bool fexists(const std::string &filename,
597  const MPI_Comm comm);
598 
604  bool filename_is_url(const std::string &filename);
605 
625  std::string
626  read_and_distribute_file_content(const std::string &filename,
627  const MPI_Comm comm);
628 
641  void
642  collect_and_write_file_content(const std::string &filename,
643  const std::string &file_content,
644  const MPI_Comm comm);
645 
659  int
660  mkdirp(std::string pathname, const mode_t mode = 0755);
661 
672  void create_directory(const std::string &pathname,
673  const MPI_Comm comm,
674  bool silent);
675 
680  namespace tk
681  {
685  class spline
686  {
687  public:
697  void set_points(const std::vector<double> &x,
698  const std::vector<double> &y,
699  const bool cubic_spline = true,
700  const bool monotone_spline = false);
704  double operator() (double x) const;
705 
706  private:
710  std::vector<double> m_x;
711 
718  std::vector<double> m_a, m_b, m_c, m_y;
719  };
720  }
721 
729  inline
730  void
731  extract_composition_values_at_q_point (const std::vector<std::vector<double>> &composition_values,
732  const unsigned int q,
733  std::vector<double> &composition_values_at_q_point);
734 
739  std::string
740  expand_ASPECT_SOURCE_DIR (const std::string &location);
741 
746  std::string parenthesize_if_nonempty (const std::string &s);
747 
752  bool has_unique_entries (const std::vector<std::string> &strings);
753 
754 
755 
777  double weighted_p_norm_average (const std::vector<double> &weights,
778  const std::vector<double> &values,
779  const double p);
780 
781 
807  template <typename T>
808  T derivative_of_weighted_p_norm_average (const double averaged_parameter,
809  const std::vector<double> &weights,
810  const std::vector<double> &values,
811  const std::vector<T> &derivatives,
812  const double p);
831  template <int dim>
832  double compute_spd_factor(const double eta,
833  const SymmetricTensor<2,dim> &strain_rate,
834  const SymmetricTensor<2,dim> &dviscosities_dstrain_rate,
835  const double SPD_safety_factor);
836 
840  template <int dim>
841  Point<dim> convert_array_to_point(const std::array<double,dim> &array);
842 
846  template <int dim>
847  std::array<double,dim> convert_point_to_array(const Point<dim> &point);
848 
856  class Operator
857  {
858  public:
863  {
869  replace_if_valid
870  };
871 
876  Operator();
877 
881  Operator(const operation op);
882 
887  double operator() (const double x, const double y) const;
888 
893  bool operator== (const operation op) const;
894 
895  private:
900  };
901 
906  std::vector<Operator> create_model_operator_list(const std::vector<std::string> &operator_names);
907 
911  const std::string get_model_operator_options();
912 
918  template <int dim>
919  SymmetricTensor<2,dim> nth_basis_for_symmetric_tensors (const unsigned int k);
920 
924  template <int dim>
926  {
927  public:
931  NaturalCoordinate(Point<dim> &position,
932  const GeometryModel::Interface<dim> &geometry_model);
933 
938  NaturalCoordinate(const std::array<double, dim> &coord,
939  const Utilities::Coordinates::CoordinateSystem &coord_system);
940 
945  std::array<double,dim> &get_coordinates();
946 
951  const std::array<double,dim> &get_coordinates() const;
952 
957  std::array<double,dim-1> get_surface_coordinates() const;
958 
963  double get_depth_coordinate() const;
964 
965  private:
971 
975  std::array<double,dim> coordinates;
976  };
977 
978 
997  template <int dim, typename VectorType>
998  void
999  project_cellwise(const Mapping<dim> &mapping,
1000  const DoFHandler<dim> &dof_handler,
1001  const unsigned int component_index,
1002  const Quadrature<dim> &quadrature,
1003  const std::function<void(
1004  const typename DoFHandler<dim>::active_cell_iterator &,
1005  const std::vector<Point<dim>> &,
1006  std::vector<double> &)> &function,
1007  VectorType &vec_result);
1008 
1032  void throw_linear_solver_failure_exception(const std::string &solver_name,
1033  const std::string &function_name,
1034  const std::vector<SolverControl> &solver_controls,
1035  const std::exception &exc,
1036  const MPI_Comm mpi_communicator,
1037  const std::string &output_filename = "");
1038 
1046  template <int dim>
1048  {
1049  public:
1059  VectorFunctionFromVelocityFunctionObject (const unsigned int n_components,
1060  const std::function<Tensor<1,dim> (const Point<dim> &)> &function_object);
1061 
1069  double value (const Point<dim> &p,
1070  const unsigned int component = 0) const override;
1071 
1081  void vector_value (const Point<dim> &p,
1082  Vector<double> &values) const override;
1083 
1084  private:
1089  const std::function<Tensor<1,dim> (const Point<dim> &)> function_object;
1090  };
1091 
1098  template <typename T>
1099  inline
1100  std::vector<std::size_t>
1101  compute_sorting_permutation(const std::vector<T> &vector);
1102 
1110  template <typename T>
1111  inline
1112  std::vector<T>
1114  const std::vector<T> &vector,
1115  const std::vector<std::size_t> &permutation_vector);
1116 
1129  std::vector<Tensor<2,3>>
1130  rotation_matrices_random_draw_volume_weighting(const std::vector<double> volume_fractions,
1131  const std::vector<Tensor<2,3>> rotation_matrices,
1132  const unsigned int n_output_matrices,
1133  std::mt19937 &random_number_generator);
1134 
1138  double wrap_angle(const double angle);
1139 
1144  std::array<double,3> zxz_euler_angles_from_rotation_matrix(const Tensor<2,3> &rotation_matrix);
1145 
1150  Tensor<2,3> zxz_euler_angles_to_rotation_matrix(const double phi1,
1151  const double theta,
1152  const double phi2);
1153 
1154  }
1155 }
1156 
1157 
1158 // inline implementations:
1159 #ifndef DOXYGEN
1160 namespace aspect
1161 {
1162  namespace Utilities
1163  {
1164 
1165  template <typename T>
1166  inline
1167  std::vector<T>
1168  possibly_extend_from_1_to_N (const std::vector<T> &values,
1169  const unsigned int N,
1170  const std::string &id_text)
1171  {
1172  if (values.size() == 1)
1173  {
1174  return std::vector<T> (N, values[0]);
1175  }
1176  else if (values.size() == N)
1177  {
1178  return values;
1179  }
1180  else
1181  {
1182  // Non-specified behavior
1183  AssertThrow(false,
1184  ExcMessage("Length of " + id_text + " list must be " +
1185  "either one or " + Utilities::to_string(N) +
1186  ". Currently it is " + Utilities::to_string(values.size()) + "."));
1187  }
1188 
1189  // This should never happen, but return an empty vector so the compiler
1190  // will be happy
1191  return std::vector<T> ();
1192  }
1193 
1194  inline
1195  void
1196  extract_composition_values_at_q_point (const std::vector<std::vector<double>> &composition_values,
1197  const unsigned int q,
1198  std::vector<double> &composition_values_at_q_point)
1199  {
1200  Assert(q<composition_values.size(), ExcInternalError());
1201  Assert(composition_values_at_q_point.size() > 0,
1202  ExcInternalError());
1203 
1204  for (unsigned int k=0; k < composition_values_at_q_point.size(); ++k)
1205  {
1206  Assert(composition_values[k].size() == composition_values_at_q_point.size(),
1207  ExcInternalError());
1208  composition_values_at_q_point[k] = composition_values[k][q];
1209  }
1210  }
1211 
1212  template <typename T>
1213  inline
1214  std::vector<std::size_t>
1215  compute_sorting_permutation(const std::vector<T> &vector)
1216  {
1217  std::vector<std::size_t> p(vector.size());
1218  std::iota(p.begin(), p.end(), 0);
1219  std::sort(p.begin(), p.end(),
1220  [&](std::size_t i, std::size_t j)
1221  {
1222  return vector[i] < vector[j];
1223  });
1224  return p;
1225  }
1226 
1227  template <typename T>
1228  inline
1229  std::vector<T>
1231  const std::vector<T> &vector,
1232  const std::vector<std::size_t> &permutation_vector)
1233  {
1234  std::vector<T> sorted_vec(vector.size());
1235  std::transform(permutation_vector.begin(), permutation_vector.end(), sorted_vec.begin(),
1236  [&](std::size_t i)
1237  {
1238  return vector[i];
1239  });
1240  return sorted_vec;
1241  }
1242 
1246  namespace Tensors
1247  {
1248 
1252  SymmetricTensor<4,3>
1253  rotate_full_stiffness_tensor(const Tensor<2,3> &rotation_tensor, const SymmetricTensor<4,3> &input_tensor);
1254 
1259  SymmetricTensor<2,6>
1260  rotate_voigt_stiffness_matrix(const Tensor<2,3> &rotation_tensor, const SymmetricTensor<2,6> &input_tensor);
1261 
1266  SymmetricTensor<2,6>
1267  to_voigt_stiffness_matrix(const SymmetricTensor<4,3> &input_tensor);
1268 
1273  SymmetricTensor<4,3>
1274  to_full_stiffness_tensor(const SymmetricTensor<2,6> &input_tensor);
1275 
1280  Tensor<1,21>
1281  to_voigt_stiffness_vector(const SymmetricTensor<2,6> &input_tensor);
1282 
1287  SymmetricTensor<2,6>
1288  to_voigt_stiffness_matrix(const Tensor<1,21> &input_tensor);
1289 
1294  Tensor<1,21>
1295  to_voigt_stiffness_vector(const SymmetricTensor<4,3> &input);
1296 
1297 
1302  template <int dim>
1303  const Tensor<dim,dim> &levi_civita();
1304 
1305  // Declare the existence of a specialization:
1306  template <>
1307  const Tensor<3,3> &levi_civita<3>();
1308  }
1309 
1310  }
1311 }
1312 #endif
1313 
1314 #endif
T derivative_of_weighted_p_norm_average(const double averaged_parameter, const std::vector< double > &weights, const std::vector< double > &values, const std::vector< T > &derivatives, const double p)
std::string read_and_distribute_file_content(const std::string &filename, const MPI_Comm comm)
Point< dim > convert_array_to_point(const std::array< double, dim > &array)
std::vector< double > m_y
Definition: utilities.h:718
Tensor< 1, dim > spherical_to_cartesian_vector(const Tensor< 1, dim > &spherical_vector, const ::Point< dim > &position)
Tensor< 2, 3 > compute_rotation_matrix_for_slice(const Tensor< 1, 3 > &point_one, const Tensor< 1, 3 > &point_two)
std::vector< std::string > list_of_required_keys
Definition: utilities.h:103
double weighted_p_norm_average(const std::vector< double > &weights, const std::vector< double > &values, const double p)
double distance_to_line(const std::array<::Point< 2 >, 2 > &point_list, const ::Point< 2 > &point)
std::vector< std::string > expand_dimensional_variable_names(const std::vector< std::string > &var_declarations)
std::array< double, dim > coordinates
Definition: utilities.h:975
void collect_and_write_file_content(const std::string &filename, const std::string &file_content, const MPI_Comm comm)
double compute_spd_factor(const double eta, const SymmetricTensor< 2, dim > &strain_rate, const SymmetricTensor< 2, dim > &dviscosities_dstrain_rate, const double SPD_safety_factor)
Table< 2, T > parse_input_table(const std::string &input_string, const unsigned int n_rows, const unsigned int n_columns, const std::string &property_name)
std::pair< double, double > real_spherical_harmonic(unsigned int l, unsigned int m, double theta, double phi)
std::vector< double > m_x
Definition: utilities.h:710
std::string expand_ASPECT_SOURCE_DIR(const std::string &location)
Tensor< 2, 3 > zxz_euler_angles_to_rotation_matrix(const double phi1, const double theta, const double phi2)
std::array< Tensor< 1, dim >, dim-1 > orthogonal_vectors(const Tensor< 1, dim > &v)
std::string to_string(const Newton::Parameters::Stabilization preconditioner_stabilization)
std::array< double, dim > WGS84_coordinates(const ::Point< dim > &position)
::Point< 3 > ellipsoidal_to_cartesian_coordinates(const std::array< double, 3 > &phi_theta_d, const double semi_major_axis_a, const double eccentricity)
void project_cellwise(const Mapping< dim > &mapping, const DoFHandler< dim > &dof_handler, const unsigned int component_index, const Quadrature< dim > &quadrature, const std::function< void(const typename DoFHandler< dim >::active_cell_iterator &, const std::vector< Point< dim >> &, std::vector< double > &)> &function, VectorType &vec_result)
bool point_is_in_triangulation(const Mapping< dim > &mapping, const parallel::distributed::Triangulation< dim > &triangulation, const Point< dim > &point, const MPI_Comm mpi_communicator)
void throw_linear_solver_failure_exception(const std::string &solver_name, const std::string &function_name, const std::vector< SolverControl > &solver_controls, const std::exception &exc, const MPI_Comm mpi_communicator, const std::string &output_filename="")
bool polygon_contains_point(const std::vector< Point< 2 >> &point_list, const ::Point< 2 > &point)
int mkdirp(std::string pathname, const mode_t mode=0755)
Utilities::Coordinates::CoordinateSystem coordinate_system
Definition: utilities.h:970
::Point< dim > spherical_to_cartesian_coordinates(const std::array< double, dim > &scoord)
std::string do_grouping() const override
Definition: utilities.h:562
std::vector< T > possibly_extend_from_1_to_N(const std::vector< T > &values, const unsigned int N, const std::string &id_text)
std::array< double, 3 > cartesian_to_ellipsoidal_coordinates(const ::Point< 3 > &position, const double semi_major_axis_a, const double eccentricity)
Options(const std::vector< std::string > &list_of_required_keys, const std::string &property_name)
Definition: utilities.h:174
std::array< double, dim > convert_point_to_array(const Point< dim > &point)
std::vector< Point< dim > > get_unit_support_points(const SimulatorAccess< dim > &simulator_access)
std::vector< T > apply_permutation(const std::vector< T > &vector, const std::vector< std::size_t > &permutation_vector)
IndexSet extract_locally_active_dofs_with_component(const DoFHandler< dim > &dof_handler, const ComponentMask &component_mask)
std::vector< unsigned int > n_values_per_key
Definition: utilities.h:156
double wrap_angle(const double angle)
bool fexists(const std::string &filename, const MPI_Comm comm)
std::vector< Operator > create_model_operator_list(const std::vector< std::string > &operator_names)
double signed_distance_to_polygon(const std::vector< Point< 2 >> &point_list, const ::Point< 2 > &point)
std::vector< Tensor< 2, 3 > > rotation_matrices_random_draw_volume_weighting(const std::vector< double > volume_fractions, const std::vector< Tensor< 2, 3 >> rotation_matrices, const unsigned int n_output_matrices, std::mt19937 &random_number_generator)
void create_directory(const std::string &pathname, const MPI_Comm comm, bool silent)
std::vector< double > parse_map_to_double_array(const std::string &key_value_map, const std::vector< std::string > &list_of_keys, const bool expects_background_field, const std::string &property_name, const bool allow_multiple_values_per_key=false, const std::unique_ptr< std::vector< unsigned int >> &n_values_per_key=nullptr, const bool allow_missing_keys=false)
std::string parenthesize_if_nonempty(const std::string &s)
std::array< double, 3 > zxz_euler_angles_from_rotation_matrix(const Tensor< 2, 3 > &rotation_matrix)
void extract_composition_values_at_q_point(const std::vector< std::vector< double >> &composition_values, const unsigned int q, std::vector< double > &composition_values_at_q_point)
const std::string get_model_operator_options()
char do_thousands_sep() const override
Definition: utilities.h:557
std::vector< std::string > list_of_allowed_keys
Definition: utilities.h:95
bool filename_is_url(const std::string &filename)
SymmetricTensor< 2, dim > nth_basis_for_symmetric_tensors(const unsigned int k)
std::vector< std::size_t > compute_sorting_permutation(const std::vector< T > &vector)
CoordinateSystem string_to_coordinate_system(const std::string &)
Definition: compat.h:42
std::array< double, dim > cartesian_to_spherical_coordinates(const ::Point< dim > &position)
bool has_unique_entries(const std::vector< std::string > &strings)
Tensor< 2, 3 > rotation_matrix_from_axis(const Tensor< 1, 3 > &rotation_axis, const double rotation_angle)