OGS
ThermoRichardsMechanicsProcess.cpp
Go to the documentation of this file.
1 
12 
13 #include <cassert>
14 
15 #include "BaseLib/Error.h"
16 #include "CreateLocalAssemblers.h"
17 #include "MeshLib/Elements/Utils.h"
20 #include "ProcessLib/Process.h"
22 
23 namespace ProcessLib
24 {
25 namespace ThermoRichardsMechanics
26 {
27 template <int DisplacementDim>
29  std::string name,
30  MeshLib::Mesh& mesh,
31  std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
32  std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
33  unsigned const integration_order,
34  std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&&
35  process_variables,
37  SecondaryVariableCollection&& secondary_variables,
38  bool const use_monolithic_scheme)
39  : Process(std::move(name), mesh, std::move(jacobian_assembler), parameters,
40  integration_order, std::move(process_variables),
41  std::move(secondary_variables), use_monolithic_scheme),
42  process_data_(std::move(process_data))
43 {
44  nodal_forces_ = MeshLib::getOrCreateMeshProperty<double>(
45  mesh, "NodalForces", MeshLib::MeshItemType::Node, DisplacementDim);
46 
47  hydraulic_flow_ = MeshLib::getOrCreateMeshProperty<double>(
48  mesh, "HydraulicFlow", MeshLib::MeshItemType::Node, 1);
49 
50  heat_flux_ = MeshLib::getOrCreateMeshProperty<double>(
51  mesh, "HeatFlux", MeshLib::MeshItemType::Node, 1);
52 
53  // TODO (naumov) remove ip suffix. Probably needs modification of the mesh
54  // properties, s.t. there is no "overlapping" with cell/point data.
55  // See getOrCreateMeshProperty.
56  _integration_point_writer.emplace_back(
57  std::make_unique<IntegrationPointWriter>(
58  "sigma_ip",
59  static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/,
60  integration_order, local_assemblers_, &LocalAssemblerIF::getSigma));
61 
62  _integration_point_writer.emplace_back(
63  std::make_unique<IntegrationPointWriter>(
64  "saturation_ip", 1 /*n components*/, integration_order,
66 
67  _integration_point_writer.emplace_back(
68  std::make_unique<IntegrationPointWriter>(
69  "porosity_ip", 1 /*n components*/, integration_order,
71 
72  _integration_point_writer.emplace_back(
73  std::make_unique<IntegrationPointWriter>(
74  "transport_porosity_ip", 1 /*n components*/, integration_order,
76 
77  _integration_point_writer.emplace_back(
78  std::make_unique<IntegrationPointWriter>(
79  "swelling_stress_ip",
80  static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/,
81  integration_order, local_assemblers_,
83 
84  _integration_point_writer.emplace_back(
85  std::make_unique<IntegrationPointWriter>(
86  "epsilon_ip",
87  static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/,
88  integration_order, local_assemblers_,
90 }
91 
92 template <int DisplacementDim>
94 {
95  return false;
96 }
97 
98 template <int DisplacementDim>
101  const int /*process_id*/) const
102 {
103  auto const& l = *_local_to_global_index_map;
104  return {l.dofSizeWithoutGhosts(), l.dofSizeWithoutGhosts(),
105  &l.getGhostIndices(), &this->_sparsity_pattern};
106 }
107 
108 template <int DisplacementDim>
110 {
111  // Create single component dof in every of the mesh's nodes.
112  _mesh_subset_all_nodes =
113  std::make_unique<MeshLib::MeshSubset>(_mesh, _mesh.getNodes());
114  // Create single component dof in the mesh's base nodes.
115  base_nodes_ = MeshLib::getBaseNodes(_mesh.getElements());
116  mesh_subset_base_nodes_ =
117  std::make_unique<MeshLib::MeshSubset>(_mesh, base_nodes_);
118 
119  // TODO move the two data members somewhere else.
120  // for extrapolation of secondary variables of stress or strain
121  std::vector<MeshLib::MeshSubset> all__meshsubsets_single_component{
122  *_mesh_subset_all_nodes};
123  local_to_global_index_map_single_component_ =
124  std::make_unique<NumLib::LocalToGlobalIndexMap>(
125  std::move(all__meshsubsets_single_component),
126  // by location order is needed for output
128 
129  // For temperature, which is the first variable.
130  std::vector<MeshLib::MeshSubset> all__meshsubsets{*mesh_subset_base_nodes_};
131 
132  // For pressure, which is the second variable
133  all__meshsubsets.push_back(*mesh_subset_base_nodes_);
134 
135  // For displacement.
136  const int monolithic_process_id = 0;
137  std::generate_n(std::back_inserter(all__meshsubsets),
138  getProcessVariables(monolithic_process_id)[2]
139  .get()
140  .getNumberOfGlobalComponents(),
141  [&]() { return *_mesh_subset_all_nodes; });
142 
143  std::vector<int> const vec_n_components{1, 1, DisplacementDim};
144  _local_to_global_index_map =
145  std::make_unique<NumLib::LocalToGlobalIndexMap>(
146  std::move(all__meshsubsets), vec_n_components,
148  assert(_local_to_global_index_map);
149 }
150 
151 template <int DisplacementDim>
153  NumLib::LocalToGlobalIndexMap const& dof_table,
154  MeshLib::Mesh const& mesh,
155  unsigned const integration_order)
156 {
157  using nlohmann::json;
158 
159  const int mechanical_process_id = 0;
160  const int deformation_variable_id = 2;
161  createLocalAssemblers<DisplacementDim,
163  mesh.getDimension(), mesh.getElements(), dof_table,
164  // use displacement process variable to set shape function order
165  getProcessVariables(mechanical_process_id)[deformation_variable_id]
166  .get()
167  .getShapeFunctionOrder(),
168  local_assemblers_, mesh.isAxiallySymmetric(), integration_order,
169  process_data_);
170 
171  auto add_secondary_variable = [&](std::string const& name,
172  int const num_components,
173  auto get_ip_values_function)
174  {
175  _secondary_variables.addSecondaryVariable(
176  name,
177  makeExtrapolator(num_components, getExtrapolator(),
178  local_assemblers_,
179  std::move(get_ip_values_function)));
180  };
181 
182  add_secondary_variable("sigma",
184  DisplacementDim>::RowsAtCompileTime,
185  &LocalAssemblerIF::getIntPtSigma);
186 
187  add_secondary_variable("swelling_stress",
189  DisplacementDim>::RowsAtCompileTime,
190  &LocalAssemblerIF::getIntPtSwellingStress);
191 
192  add_secondary_variable("epsilon",
194  DisplacementDim>::RowsAtCompileTime,
195  &LocalAssemblerIF::getIntPtEpsilon);
196 
197  add_secondary_variable("velocity", DisplacementDim,
198  &LocalAssemblerIF::getIntPtDarcyVelocity);
199 
200  add_secondary_variable("saturation", 1,
201  &LocalAssemblerIF::getIntPtSaturation);
202 
203  add_secondary_variable("porosity", 1, &LocalAssemblerIF::getIntPtPorosity);
204 
205  add_secondary_variable("transport_porosity", 1,
206  &LocalAssemblerIF::getIntPtTransportPorosity);
207 
208  add_secondary_variable("dry_density_solid", 1,
209  &LocalAssemblerIF::getIntPtDryDensitySolid);
210 
211  //
212  // enable output of internal variables defined by material models
213  //
215  LocalAssemblerIF>(process_data_.solid_materials,
216  add_secondary_variable);
217 
218  process_data_.element_saturation = MeshLib::getOrCreateMeshProperty<double>(
219  const_cast<MeshLib::Mesh&>(mesh), "saturation_avg",
221 
222  process_data_.element_porosity = MeshLib::getOrCreateMeshProperty<double>(
223  const_cast<MeshLib::Mesh&>(mesh), "porosity_avg",
225 
226  process_data_.element_stresses = MeshLib::getOrCreateMeshProperty<double>(
227  const_cast<MeshLib::Mesh&>(mesh), "stress_avg",
230  DisplacementDim>::RowsAtCompileTime);
231 
232  process_data_.pressure_interpolated =
233  MeshLib::getOrCreateMeshProperty<double>(
234  const_cast<MeshLib::Mesh&>(mesh), "pressure_interpolated",
236  process_data_.temperature_interpolated =
237  MeshLib::getOrCreateMeshProperty<double>(
238  const_cast<MeshLib::Mesh&>(mesh), "temperature_interpolated",
240 
241  // Set initial conditions for integration point data.
242  for (auto const& ip_writer : _integration_point_writer)
243  {
244  // Find the mesh property with integration point writer's name.
245  auto const& name = ip_writer->name();
246  if (!mesh.getProperties().existsPropertyVector<double>(name))
247  {
248  continue;
249  }
250  auto const& _meshproperty =
251  *mesh.getProperties().template getPropertyVector<double>(name);
252 
253  // The mesh property must be defined on integration points.
254  if (_meshproperty.getMeshItemType() !=
256  {
257  continue;
258  }
259 
260  auto const ip_meta_data = getIntegrationPointMetaData(mesh, name);
261 
262  // Check the number of components.
263  if (ip_meta_data.n_components !=
264  _meshproperty.getNumberOfGlobalComponents())
265  {
266  OGS_FATAL(
267  "Different number of components in meta data ({:d}) than in "
268  "the integration point field data for '{:s}': {:d}.",
269  ip_meta_data.n_components, name,
270  _meshproperty.getNumberOfGlobalComponents());
271  }
272 
273  // Now we have a properly named vtk's field data array and the
274  // corresponding meta data.
275  std::size_t position = 0;
276  for (auto& local_asm : local_assemblers_)
277  {
278  std::size_t const integration_points_read =
279  local_asm->setIPDataInitialConditions(
280  name, &_meshproperty[position],
281  ip_meta_data.integration_order);
282  if (integration_points_read == 0)
283  {
284  OGS_FATAL(
285  "No integration points read in the integration point "
286  "initial conditions set function.");
287  }
288  position += integration_points_read * ip_meta_data.n_components;
289  }
290  }
291 
292  // Initialize local assemblers after all variables have been set.
293  GlobalExecutor::executeMemberOnDereferenced(&LocalAssemblerIF::initialize,
294  local_assemblers_,
295  *_local_to_global_index_map);
296 }
297 
298 template <int DisplacementDim>
300  DisplacementDim>::initializeBoundaryConditions()
301 {
302  const int process_id = 0;
303  initializeProcessBoundaryConditionsAndSourceTerms(
304  *_local_to_global_index_map, process_id);
305 }
306 
307 template <int DisplacementDim>
309  setInitialConditionsConcreteProcess(std::vector<GlobalVector*>& x,
310  double const t,
311  int const process_id)
312 {
313  DBUG("SetInitialConditions ThermoRichardsMechanicsProcess.");
314 
316  &LocalAssemblerIF::setInitialConditions, local_assemblers_,
317  *_local_to_global_index_map, *x[process_id], t, _use_monolithic_scheme,
318  process_id);
319 }
320 
321 template <int DisplacementDim>
323  const double /*t*/, double const /*dt*/,
324  std::vector<GlobalVector*> const& /*x*/,
325  std::vector<GlobalVector*> const& /*xdot*/, int const /*process_id*/,
326  GlobalMatrix& /*M*/, GlobalMatrix& /*K*/, GlobalVector& /*b*/)
327 {
328  OGS_FATAL(
329  "The Picard method or the Newton-Raphson method with numerical "
330  "Jacobian is not implemented for ThermoRichardsMechanics with the full "
331  "monolithic coupling scheme");
332 }
333 
334 template <int DisplacementDim>
337  const double t, double const dt, std::vector<GlobalVector*> const& x,
338  std::vector<GlobalVector*> const& xdot, const double dxdot_dx,
339  const double dx_dx, int const process_id, GlobalMatrix& M,
341 {
342  std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>>
343  dof_tables;
344 
345  DBUG(
346  "Assemble the Jacobian of ThermoRichardsMechanics for the monolithic "
347  "scheme.");
348  dof_tables.emplace_back(*_local_to_global_index_map);
349 
350  ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
351 
354  local_assemblers_, pv.getActiveElementIDs(), dof_tables, t, dt, x, xdot,
355  dxdot_dx, dx_dx, process_id, M, K, b, Jac);
356 
357  auto copyRhs = [&](int const variable_id, auto& output_vector)
358  {
359  transformVariableFromGlobalVector(b, variable_id, dof_tables[0],
360  output_vector, std::negate<double>());
361  };
362 
363  copyRhs(0, *heat_flux_);
364  copyRhs(1, *hydraulic_flow_);
365  copyRhs(2, *nodal_forces_);
366 }
367 
368 template <int DisplacementDim>
370  postTimestepConcreteProcess(std::vector<GlobalVector*> const& x,
371  double const t, double const dt,
372  const int process_id)
373 {
374  DBUG("PostTimestep ThermoRichardsMechanicsProcess.");
375 
376  auto const dof_tables = getDOFTables(x.size());
377 
378  ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
380  &LocalAssemblerIF::postTimestep, local_assemblers_,
381  pv.getActiveElementIDs(), dof_tables, x, t, dt);
382 }
383 
384 template <int DisplacementDim>
386  computeSecondaryVariableConcrete(const double t, const double dt,
387  std::vector<GlobalVector*> const& x,
388  GlobalVector const& x_dot,
389  int const process_id)
390 {
391  DBUG("Compute the secondary variables for ThermoRichardsMechanicsProcess.");
392 
393  auto const dof_tables = getDOFTables(x.size());
394 
395  ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
396 
398  &LocalAssemblerIF::computeSecondaryVariable, local_assemblers_,
399  pv.getActiveElementIDs(), dof_tables, t, dt, x, x_dot, process_id);
400 }
401 
402 template <int DisplacementDim>
403 std::tuple<NumLib::LocalToGlobalIndexMap*, bool> ThermoRichardsMechanicsProcess<
404  DisplacementDim>::getDOFTableForExtrapolatorData() const
405 {
406  const bool manage_storage = false;
407  return std::make_tuple(local_to_global_index_map_single_component_.get(),
408  manage_storage);
409 }
410 
411 template <int DisplacementDim>
414  const int /*process_id*/) const
415 {
416  return *_local_to_global_index_map;
417 }
418 
419 template <int DisplacementDim>
420 std::vector<NumLib::LocalToGlobalIndexMap const*>
422  int const number_of_processes) const
423 {
424  std::vector<NumLib::LocalToGlobalIndexMap const*> dof_tables;
425  dof_tables.reserve(number_of_processes);
426  std::generate_n(std::back_inserter(dof_tables), number_of_processes,
427  [&]() { return &getDOFTable(dof_tables.size()); });
428  return dof_tables;
429 }
430 
431 template class ThermoRichardsMechanicsProcess<2>;
432 template class ThermoRichardsMechanicsProcess<3>;
433 
434 } // namespace ThermoRichardsMechanics
435 } // namespace ProcessLib
#define OGS_FATAL(...)
Definition: Error.h:26
void DBUG(char const *fmt, Args const &... args)
Definition: Logging.h:27
Global vector based on Eigen vector.
Definition: EigenVector.h:26
bool isAxiallySymmetric() const
Definition: Mesh.h:126
unsigned getDimension() const
Returns the dimension of the mesh (determined by the maximum dimension over all elements).
Definition: Mesh.h:71
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition: Mesh.h:98
Properties & getProperties()
Definition: Mesh.h:123
bool existsPropertyVector(std::string const &name) const
std::vector< std::size_t > const & getActiveElementIDs() const
std::vector< std::unique_ptr< IntegrationPointWriter > > _integration_point_writer
Definition: Process.h:350
Handles configuration of several secondary variables from the project file.
Global assembler for the monolithic scheme of the non-isothermal Richards flow coupled with mechanics...
void computeSecondaryVariableConcrete(double const t, double const dt, std::vector< GlobalVector * > const &x, GlobalVector const &x_dot, int const process_id) override
void assembleWithJacobianConcreteProcess(const double t, double const dt, std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &xdot, const double dxdot_dx, const double dx_dx, int const process_id, GlobalMatrix &M, GlobalMatrix &K, GlobalVector &b, GlobalMatrix &Jac) override
ThermoRichardsMechanicsProcess(std::string name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< std::unique_ptr< ParameterLib::ParameterBase >> const &parameters, unsigned const integration_order, std::vector< std::vector< std::reference_wrapper< ProcessVariable >>> &&process_variables, ThermoRichardsMechanicsProcessData< DisplacementDim > &&process_data, SecondaryVariableCollection &&secondary_variables, bool const use_monolithic_scheme)
void assembleConcreteProcess(const double t, double const dt, std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &xdot, int const process_id, GlobalMatrix &M, GlobalMatrix &K, GlobalVector &b) override
MathLib::MatrixSpecifications getMatrixSpecifications(const int process_id) const override
void initializeConcreteProcess(NumLib::LocalToGlobalIndexMap const &dof_table, MeshLib::Mesh const &mesh, unsigned const integration_order) override
Process specific initialization called by initialize().
std::vector< NumLib::LocalToGlobalIndexMap const * > getDOFTables(const int number_of_processes) const
void postTimestepConcreteProcess(std::vector< GlobalVector * > const &x, double const t, double const dt, const int process_id) override
void setInitialConditionsConcreteProcess(std::vector< GlobalVector * > &x, double const t, int const process_id) override
NumLib::LocalToGlobalIndexMap const & getDOFTable(const int process_id) const override
void assembleWithJacobian(std::size_t const mesh_item_id, LocalAssemblerInterface &local_assembler, std::vector< std::reference_wrapper< NumLib::LocalToGlobalIndexMap >> const &dof_tables, const double t, double const dt, std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &xdot, const double dxdot_dx, const double dx_dx, int const process_id, GlobalMatrix &M, GlobalMatrix &K, GlobalVector &b, GlobalMatrix &Jac)
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Definition: KelvinVector.h:48
std::vector< Node * > getBaseNodes(std::vector< Element * > const &elements)
Definition: Utils.h:26
@ BY_LOCATION
Ordering data by spatial location.
void transformVariableFromGlobalVector(GlobalVector const &input_vector, int const variable_id, NumLib::LocalToGlobalIndexMap const &local_to_global_index_map, MeshLib::PropertyVector< double > &output_vector, Functor mapFunction)
Definition: DOFTableUtil.h:59
void solidMaterialInternalToSecondaryVariables(std::map< int, std::unique_ptr< MaterialLib::Solids::MechanicsBase< DisplacementDim >>> const &solid_materials, AddSecondaryVariableCallback const &add_secondary_variable)
void createLocalAssemblers(const unsigned, std::vector< MeshLib::Element * > const &mesh_elements, NumLib::LocalToGlobalIndexMap const &dof_table, const unsigned shapefunction_order, std::vector< std::unique_ptr< LocalAssemblerInterface >> &local_assemblers, ExtraCtorArgs &&... extra_ctor_args)
IntegrationPointMetaData getIntegrationPointMetaData(MeshLib::Mesh const &mesh, std::string const &name)
std::pair< std::vector< GlobalVector * >, std::vector< GlobalVector * > > setInitialConditions(double const t0, std::vector< std::unique_ptr< ProcessData >> const &per_process_data)
Definition: TimeLoop.cpp:216
SecondaryVariableFunctions makeExtrapolator(const unsigned num_components, NumLib::Extrapolator &extrapolator, LocalAssemblerCollection const &local_assemblers, typename NumLib::ExtrapolatableLocalAssemblerCollection< LocalAssemblerCollection >::IntegrationPointValuesMethod integration_point_values_method)
static void executeSelectedMemberOnDereferenced(Method method, Container const &container, std::vector< std::size_t > const &active_container_ids, Args &&... args)
static void executeSelectedMemberDereferenced(Object &object, Method method, Container const &container, std::vector< std::size_t > const &active_container_ids, Args &&... args)
static void executeMemberOnDereferenced(Method method, Container const &container, Args &&... args)
virtual std::vector< double > getTransportPorosity() const =0
virtual std::vector< double > getPorosity() const =0
virtual std::vector< double > getEpsilon() const =0
virtual std::vector< double > getSaturation() const =0
virtual std::vector< double > getSigma() const =0
virtual std::vector< double > getSwellingStress() const =0