OGS
CreatePhaseFieldProcess.cpp
Go to the documentation of this file.
1 
12 
13 #include <cassert>
14 
17 #include "ParameterLib/Utils.h"
18 #include "PhaseFieldProcess.h"
19 #include "PhaseFieldProcessData.h"
22 
23 namespace ProcessLib
24 {
25 namespace PhaseField
26 {
27 template <int DisplacementDim>
28 std::unique_ptr<Process> createPhaseFieldProcess(
29  std::string name,
30  MeshLib::Mesh& mesh,
31  std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
32  std::vector<ProcessVariable> const& variables,
33  std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
34  std::optional<ParameterLib::CoordinateSystem> const&
35  local_coordinate_system,
36  unsigned const integration_order,
37  BaseLib::ConfigTree const& config)
38 {
40  config.checkConfigParameter("type", "PHASE_FIELD");
41  DBUG("Create PhaseFieldProcess.");
42 
43  auto const coupling_scheme =
45  config.getConfigParameterOptional<std::string>("coupling_scheme");
46  const bool use_monolithic_scheme =
47  !(coupling_scheme && (*coupling_scheme == "staggered"));
48 
50 
52  auto const pv_config = config.getConfigSubtree("process_variables");
53 
54  ProcessVariable* variable_ph;
55  ProcessVariable* variable_u;
56  std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>
57  process_variables;
58  if (use_monolithic_scheme) // monolithic scheme.
59  {
60  OGS_FATAL("Monolithic implementation is not available.");
61  }
62  else // staggered scheme.
63  {
64  using namespace std::string_literals;
65  for (
68  auto const& variable_name :
69  {
70  "displacement"s,
72  "phasefield"s})
73  {
74  auto per_process_variables =
75  findProcessVariables(variables, pv_config, {variable_name});
76  process_variables.push_back(std::move(per_process_variables));
77  }
78  variable_u = &process_variables[0][0].get();
79  variable_ph = &process_variables[1][0].get();
80  }
81 
82  DBUG("Associate displacement with process variable '{:s}'.",
83  variable_u->getName());
84 
85  if (variable_u->getNumberOfGlobalComponents() != DisplacementDim)
86  {
87  OGS_FATAL(
88  "Number of components of the process variable '{:s}' is different "
89  "from the displacement dimension: got {:d}, expected {:d}",
90  variable_u->getName(),
91  variable_u->getNumberOfGlobalComponents(),
92  DisplacementDim);
93  }
94 
95  DBUG("Associate phase field with process variable '{:s}'.",
96  variable_ph->getName());
97  if (variable_ph->getNumberOfGlobalComponents() != 1)
98  {
99  OGS_FATAL(
100  "Phasefield process variable '{:s}' is not a scalar variable but "
101  "has {:d} components.",
102  variable_ph->getName(),
103  variable_ph->getNumberOfGlobalComponents());
104  }
106  auto solid_constitutive_relations =
107  MaterialLib::Solids::createConstitutiveRelations<DisplacementDim>(
108  parameters, local_coordinate_system, config);
109 
110  auto const phasefield_parameters_config =
112  config.getConfigSubtree("phasefield_parameters");
113 
114  // Residual stiffness
115  auto const& residual_stiffness = ParameterLib::findParameter<double>(
116  phasefield_parameters_config,
118  "residual_stiffness", parameters, 1);
119  DBUG("Use '{:s}' as residual stiffness.", residual_stiffness.name);
120 
121  // Crack resistance
122  auto const& crack_resistance = ParameterLib::findParameter<double>(
123  phasefield_parameters_config,
125  "crack_resistance", parameters, 1);
126  DBUG("Use '{:s}' as crack resistance.", crack_resistance.name);
127 
128  // Crack length scale
129  auto const& crack_length_scale = ParameterLib::findParameter<double>(
130  phasefield_parameters_config,
132  "crack_length_scale", parameters, 1);
133  DBUG("Use '{:s}' as crack length scale.", crack_length_scale.name);
134 
135  // Characteristic_length
136  auto const characteristic_length =
138  config.getConfigParameter<double>("characteristic_length", 1.0);
139 
140  // Solid density
141  auto const& solid_density = ParameterLib::findParameter<double>(
142  config,
144  "solid_density", parameters, 1);
145  DBUG("Use '{:s}' as solid density parameter.", solid_density.name);
146 
147  // Specific body force
148  Eigen::Matrix<double, DisplacementDim, 1> specific_body_force;
149  {
150  std::vector<double> const b =
152  config.getConfigParameter<std::vector<double>>(
153  "specific_body_force");
154  if (b.size() != DisplacementDim)
155  {
156  OGS_FATAL(
157  "The size of the specific body force vector does not match the "
158  "displacement dimension. Vector size is {:d}, displacement "
159  "dimension is {:d}",
160  b.size(), DisplacementDim);
161  }
162 
163  std::copy_n(b.data(), b.size(), specific_body_force.data());
164  }
165 
166  auto const crack_scheme =
168  config.getConfigParameterOptional<std::string>("hydro_crack_scheme");
169  if (crack_scheme &&
170  ((*crack_scheme != "propagating") && (*crack_scheme != "static")))
171  {
172  OGS_FATAL(
173  "crack_scheme must be 'propagating' or 'static' but '{:s}' "
174  "was given",
175  crack_scheme->c_str());
176  }
177 
178  const bool hydro_crack = (crack_scheme && (*crack_scheme == "propagating"));
179  const bool crack_pressure = crack_scheme.has_value();
180 
181  auto const irreversible_threshold =
183  config.getConfigParameter<double>("irreversible_threshold", 0.05);
184 
185  auto const phasefield_model = [&]
186  {
187  auto const phasefield_model_string =
189  config.getConfigParameter<std::string>("phasefield_model");
190 
191  if (phasefield_model_string == "AT1")
192  {
193  return PhaseFieldModel::AT1;
194  }
195  if (phasefield_model_string == "AT2")
196  {
197  return PhaseFieldModel::AT2;
198  }
199  if (phasefield_model_string == "COHESIVE")
200  {
202  }
203  OGS_FATAL(
204  "phasefield_model must be 'AT1', 'AT2' or 'COHESIVE' but '{:s}' "
205  "was given",
206  phasefield_model_string.c_str());
207  }();
208 
209  auto const softening_curve = [&]
210  {
211  auto const softening_curve_string =
213  config.getConfigParameterOptional<std::string>("softening_curve");
214  if (softening_curve_string)
215  {
216  if (*softening_curve_string == "Linear")
217  {
218  return SofteningCurve::Linear;
219  }
220  if (*softening_curve_string == "Exponential")
221  {
223  }
224  OGS_FATAL(
225  "softening_curve must be 'Linear' or 'Exponential' but '{:s}' "
226  "was given",
227  softening_curve_string->c_str());
228  }
229  return SofteningCurve::Linear; // default
230  }();
231 
232  auto const energy_split_model = [&]
233  {
234  auto const energy_split_model_string =
236  config.getConfigParameter<std::string>("energy_split_model");
237 
238  if (energy_split_model_string == "Isotropic")
239  {
241  }
242  if (energy_split_model_string == "VolumetricDeviatoric")
243  {
245  }
246  if (energy_split_model_string == "EffectiveStress")
247  {
249  }
250  if (energy_split_model_string == "OrthoVolDev")
251  {
253  }
254  if (energy_split_model_string == "OrthoMasonry")
255  {
257  }
258  OGS_FATAL(
259  "energy_split_model must be 'Isotropic' or 'VolumetricDeviatoric' "
260  "but '{:s}' was given",
261  energy_split_model_string);
262  }();
263 
264  std::unique_ptr<DegradationDerivative> degradation_derivative;
265  if (phasefield_model == PhaseFieldModel::COHESIVE)
266  {
267  degradation_derivative =
268  std::make_unique<COHESIVE_DegradationDerivative>(
269  characteristic_length, softening_curve);
270  }
271  else
272  {
273  degradation_derivative = std::make_unique<AT_DegradationDerivative>();
274  }
275 
277  materialIDs(mesh),
278  std::move(solid_constitutive_relations),
279  residual_stiffness,
280  crack_resistance,
281  crack_length_scale,
282  solid_density,
283  specific_body_force,
284  hydro_crack,
285  crack_pressure,
286  irreversible_threshold,
287  phasefield_model,
288  energy_split_model,
289  softening_curve,
290  characteristic_length,
291  std::move(degradation_derivative)};
292 
293  SecondaryVariableCollection secondary_variables;
294 
295  ProcessLib::createSecondaryVariables(config, secondary_variables);
296 
297  return std::make_unique<PhaseFieldProcess<DisplacementDim>>(
298  std::move(name), mesh, std::move(jacobian_assembler), parameters,
299  integration_order, std::move(process_variables),
300  std::move(process_data), std::move(secondary_variables),
301  use_monolithic_scheme);
302 }
303 
304 template std::unique_ptr<Process> createPhaseFieldProcess<2>(
305  std::string name,
306  MeshLib::Mesh& mesh,
307  std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
308  std::vector<ProcessVariable> const& variables,
309  std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
310  std::optional<ParameterLib::CoordinateSystem> const&
311  local_coordinate_system,
312  unsigned const integration_order,
313  BaseLib::ConfigTree const& config);
314 
315 template std::unique_ptr<Process> createPhaseFieldProcess<3>(
316  std::string name,
317  MeshLib::Mesh& mesh,
318  std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
319  std::vector<ProcessVariable> const& variables,
320  std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
321  std::optional<ParameterLib::CoordinateSystem> const&
322  local_coordinate_system,
323  unsigned const integration_order,
324  BaseLib::ConfigTree const& config);
325 
326 } // namespace PhaseField
327 } // namespace ProcessLib
#define OGS_FATAL(...)
Definition: Error.h:26
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition: Logging.h:29
void checkConfigParameter(std::string const &param, T const &value) const
std::optional< T > getConfigParameterOptional(std::string const &param) const
T getConfigParameter(std::string const &param) const
ConfigTree getConfigSubtree(std::string const &root) const
Definition: ConfigTree.cpp:150
std::string const & getName() const
int getNumberOfGlobalComponents() const
Returns the number of components of the process variable.
Handles configuration of several secondary variables from the project file.
static const double s
PropertyVector< int > const * materialIDs(Mesh const &mesh)
Definition: Mesh.cpp:269
template std::unique_ptr< Process > createPhaseFieldProcess< 2 >(std::string name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< ProcessVariable > const &variables, std::vector< std::unique_ptr< ParameterLib::ParameterBase >> const &parameters, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system, unsigned const integration_order, BaseLib::ConfigTree const &config)
std::unique_ptr< Process > createPhaseFieldProcess(std::string name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< ProcessVariable > const &variables, std::vector< std::unique_ptr< ParameterLib::ParameterBase >> const &parameters, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system, unsigned const integration_order, BaseLib::ConfigTree const &config)
template std::unique_ptr< Process > createPhaseFieldProcess< 3 >(std::string name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< ProcessVariable > const &variables, std::vector< std::unique_ptr< ParameterLib::ParameterBase >> const &parameters, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system, unsigned const integration_order, BaseLib::ConfigTree const &config)
std::vector< std::reference_wrapper< ProcessVariable > > findProcessVariables(std::vector< ProcessVariable > const &variables, BaseLib::ConfigTree const &pv_config, std::initializer_list< std::string > tags)
void createSecondaryVariables(BaseLib::ConfigTree const &config, SecondaryVariableCollection &secondary_variables)