OGS
PhaseFieldProcess.cpp
Go to the documentation of this file.
1 
11 #include "PhaseFieldProcess.h"
12 
13 #include <cassert>
14 
16 #include "PhaseFieldFEM.h"
17 #include "ProcessLib/Process.h"
19 
20 namespace ProcessLib
21 {
22 namespace PhaseField
23 {
24 template <int DisplacementDim>
26  std::string name,
27  MeshLib::Mesh& mesh,
28  std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
29  std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
30  unsigned const integration_order,
31  std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>&&
32  process_variables,
34  SecondaryVariableCollection&& secondary_variables,
35  bool const use_monolithic_scheme)
36  : Process(std::move(name), mesh, std::move(jacobian_assembler), parameters,
37  integration_order, std::move(process_variables),
38  std::move(secondary_variables), use_monolithic_scheme),
39  _process_data(std::move(process_data))
40 {
41  if (use_monolithic_scheme)
42  {
43  OGS_FATAL(
44  "Monolithic scheme is not implemented for the PhaseField process.");
45  }
46 
47  _nodal_forces = MeshLib::getOrCreateMeshProperty<double>(
48  mesh, "NodalForces", MeshLib::MeshItemType::Node, DisplacementDim);
49 }
50 
51 template <int DisplacementDim>
53 {
54  return false;
55 }
56 
57 template <int DisplacementDim>
60  const int process_id) const
61 {
62  // For the M process (deformation) in the staggered scheme.
63  if (process_id == 0)
64  {
65  auto const& l = *_local_to_global_index_map;
66  return {l.dofSizeWithoutGhosts(), l.dofSizeWithoutGhosts(),
67  &l.getGhostIndices(), &this->_sparsity_pattern};
68  }
69 
70  // For staggered scheme and phase field process.
71  auto const& l = *_local_to_global_index_map_single_component;
72  return {l.dofSizeWithoutGhosts(), l.dofSizeWithoutGhosts(),
73  &l.getGhostIndices(), &_sparsity_pattern_with_single_component};
74 }
75 
76 template <int DisplacementDim>
79 {
80  // For the M process (deformation) in the staggered scheme.
81  if (process_id == 0)
82  {
83  return *_local_to_global_index_map;
84  }
85 
86  // For the equation of phasefield
87  return *_local_to_global_index_map_single_component;
88 }
89 
90 template <int DisplacementDim>
92 {
93  // For displacement equation.
94  const int mechanics_process_id = 0;
95  constructDofTableOfSpecifiedProcessStaggeredScheme(mechanics_process_id);
96 
97  // TODO move the two data members somewhere else.
98  // for extrapolation of secondary variables of stress or strain
99  std::vector<MeshLib::MeshSubset> all_mesh_subsets_single_component{
100  *_mesh_subset_all_nodes};
101  _local_to_global_index_map_single_component =
102  std::make_unique<NumLib::LocalToGlobalIndexMap>(
103  std::move(all_mesh_subsets_single_component),
104  // by location order is needed for output
106 
107  assert(_local_to_global_index_map_single_component);
108 
109  // For phase field equation.
110  _sparsity_pattern_with_single_component = NumLib::computeSparsityPattern(
111  *_local_to_global_index_map_single_component, _mesh);
112 }
113 
114 template <int DisplacementDim>
116  NumLib::LocalToGlobalIndexMap const& dof_table,
117  MeshLib::Mesh const& mesh,
118  unsigned const integration_order)
119 {
121  DisplacementDim, PhaseFieldLocalAssembler>(
122  mesh.getElements(), dof_table, _local_assemblers,
123  mesh.isAxiallySymmetric(), integration_order, _process_data);
124 
125  _secondary_variables.addSecondaryVariable(
126  "sigma",
128  DisplacementDim>::RowsAtCompileTime,
129  getExtrapolator(), _local_assemblers,
130  &LocalAssemblerInterface::getIntPtSigma));
131 
132  _secondary_variables.addSecondaryVariable(
133  "epsilon",
135  DisplacementDim>::RowsAtCompileTime,
136  getExtrapolator(), _local_assemblers,
137  &LocalAssemblerInterface::getIntPtEpsilon));
138 
139  // Initialize local assemblers after all variables have been set.
141  &LocalAssemblerInterface::initialize, _local_assemblers,
142  *_local_to_global_index_map);
143 }
144 
145 template <int DisplacementDim>
147 {
148  // Staggered scheme:
149  // for the equations of deformation.
150  const int mechanical_process_id = 0;
151  initializeProcessBoundaryConditionsAndSourceTerms(
152  *_local_to_global_index_map, mechanical_process_id);
153  // for the phase field
154  const int phasefield_process_id = 1;
155  initializeProcessBoundaryConditionsAndSourceTerms(
156  *_local_to_global_index_map_single_component, phasefield_process_id);
157 }
158 
159 template <int DisplacementDim>
161  const double t, double const dt, std::vector<GlobalVector*> const& x,
162  std::vector<GlobalVector*> const& xdot, int const process_id,
164 {
165  DBUG("Assemble PhaseFieldProcess.");
166 
167  std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>>
168  dof_tables;
169 
170  // For the staggered scheme
171  if (process_id == 1)
172  {
173  DBUG(
174  "Assemble the equations of phase field in "
175  "PhaseFieldProcess for the staggered scheme.");
176  }
177  else
178  {
179  DBUG(
180  "Assemble the equations of deformation in "
181  "PhaseFieldProcess for the staggered scheme.");
182  }
183  dof_tables.emplace_back(*_local_to_global_index_map_single_component);
184  dof_tables.emplace_back(*_local_to_global_index_map);
185 
186  ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
187 
188  // Call global assembler for each local assembly item.
190  _global_assembler, &VectorMatrixAssembler::assemble, _local_assemblers,
191  pv.getActiveElementIDs(), dof_tables, t, dt, x, xdot, process_id, M, K,
192  b);
193 }
194 
195 template <int DisplacementDim>
197  const double t, double const dt, std::vector<GlobalVector*> const& x,
198  std::vector<GlobalVector*> const& xdot, const double dxdot_dx,
199  const double dx_dx, int const process_id, GlobalMatrix& M, GlobalMatrix& K,
200  GlobalVector& b, GlobalMatrix& Jac)
201 {
202  std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>>
203  dof_tables;
204 
205  // For the staggered scheme
206  if (process_id == 1)
207  {
208  DBUG(
209  "Assemble the Jacobian equations of phase field in "
210  "PhaseFieldProcess for the staggered scheme.");
211  }
212  else
213  {
214  DBUG(
215  "Assemble the Jacobian equations of deformation in "
216  "PhaseFieldProcess for the staggered scheme.");
217  }
218  dof_tables.emplace_back(*_local_to_global_index_map);
219  dof_tables.emplace_back(*_local_to_global_index_map_single_component);
220 
221  ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
222 
223  // Call global assembler for each local assembly item.
226  _local_assemblers, pv.getActiveElementIDs(), dof_tables, t, dt, x, xdot,
227  dxdot_dx, dx_dx, process_id, M, K, b, Jac);
228 
229  if (process_id == 0)
230  {
231  b.copyValues(*_nodal_forces);
232  std::transform(_nodal_forces->begin(), _nodal_forces->end(),
233  _nodal_forces->begin(), [](double val) { return -val; });
234  }
235 }
236 
237 template <int DisplacementDim>
239  std::vector<GlobalVector*> const& x, double const t, double const dt,
240  const int process_id)
241 {
242  DBUG("PreTimestep PhaseFieldProcess {:d}.", process_id);
243 
244  _process_data.injected_volume = t;
245 
246  _x_previous_timestep =
248 
249  ProcessLib::ProcessVariable const& pv = getProcessVariables(process_id)[0];
250 
252  &LocalAssemblerInterface::preTimestep, _local_assemblers,
253  pv.getActiveElementIDs(), getDOFTable(process_id), *x[process_id], t,
254  dt);
255 }
256 
257 template <int DisplacementDim>
259  std::vector<GlobalVector*> const& x, const double t,
260  const double /*delta_t*/, int const process_id)
261 {
262  if (isPhaseFieldProcess(process_id))
263  {
264  DBUG("PostTimestep PhaseFieldProcess.");
265 
266  _process_data.elastic_energy = 0.0;
267  _process_data.surface_energy = 0.0;
268  _process_data.pressure_work = 0.0;
269 
270  std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>>
271  dof_tables;
272 
273  dof_tables.emplace_back(*_local_to_global_index_map);
274  dof_tables.emplace_back(*_local_to_global_index_map_single_component);
275 
276  ProcessLib::ProcessVariable const& pv =
277  getProcessVariables(process_id)[0];
278 
280  &LocalAssemblerInterface::computeEnergy, _local_assemblers,
281  pv.getActiveElementIDs(), dof_tables, *x[process_id], t,
282  _process_data.elastic_energy, _process_data.surface_energy,
283  _process_data.pressure_work, _coupled_solutions);
284 
285  INFO("Elastic energy: {:g} Surface energy: {:g} Pressure work: {:g} ",
286  _process_data.elastic_energy, _process_data.surface_energy,
287  _process_data.pressure_work);
288  }
289 }
290 
291 template <int DisplacementDim>
293  GlobalVector const& x, GlobalVector const& /*xdot*/, const double t,
294  double const /*dt*/, const int process_id)
295 {
296  _process_data.crack_volume = 0.0;
297 
298  if (!isPhaseFieldProcess(process_id))
299  {
300  std::vector<std::reference_wrapper<NumLib::LocalToGlobalIndexMap>>
301  dof_tables;
302 
303  dof_tables.emplace_back(*_local_to_global_index_map);
304  dof_tables.emplace_back(*_local_to_global_index_map_single_component);
305 
306  DBUG("PostNonLinearSolver crack volume computation.");
307 
308  ProcessLib::ProcessVariable const& pv =
309  getProcessVariables(process_id)[0];
311  &LocalAssemblerInterface::computeCrackIntegral, _local_assemblers,
312  pv.getActiveElementIDs(), dof_tables, x, t,
313  _process_data.crack_volume, _coupled_solutions);
314 
315  INFO("Integral of crack: {:g}", _process_data.crack_volume);
316 
317  if (_process_data.hydro_crack)
318  {
319  _process_data.pressure_old = _process_data.pressure;
320  _process_data.pressure =
321  _process_data.injected_volume / _process_data.crack_volume;
322  _process_data.pressure_error =
323  std::abs(_process_data.pressure_old - _process_data.pressure) /
324  _process_data.pressure;
325  INFO("Internal pressure: {:g} and Pressure error: {:.4e}",
326  _process_data.pressure, _process_data.pressure_error);
327  auto& u = *_coupled_solutions->coupled_xs[0];
328  MathLib::LinAlg::scale(const_cast<GlobalVector&>(u),
329  _process_data.pressure);
330  }
331  }
332  else
333  {
334  if (_process_data.hydro_crack)
335  {
336  auto& u = *_coupled_solutions->coupled_xs[0];
337  MathLib::LinAlg::scale(const_cast<GlobalVector&>(u),
338  1 / _process_data.pressure);
339  }
340  }
341 }
342 
343 template <int DisplacementDim>
345  GlobalVector& lower, GlobalVector& upper, int const /*process_id*/)
346 {
347  lower.setZero();
348  MathLib::LinAlg::setLocalAccessibleVector(*_x_previous_timestep);
349  MathLib::LinAlg::copy(*_x_previous_timestep, upper);
350 
351  GlobalIndexType const x_begin = _x_previous_timestep->getRangeBegin();
352  GlobalIndexType const x_end = _x_previous_timestep->getRangeEnd();
353 
354  for (GlobalIndexType i = x_begin; i < x_end; i++)
355  {
356  if ((*_x_previous_timestep)[i] > _process_data.irreversible_threshold)
357  {
358  upper.set(i, 1.0);
359  }
360  }
361 }
362 
363 template <int DisplacementDim>
365  int const process_id) const
366 {
367  return process_id == 1;
368 }
369 
370 template class PhaseFieldProcess<2>;
371 template class PhaseFieldProcess<3>;
372 
373 } // namespace PhaseField
374 } // namespace ProcessLib
#define OGS_FATAL(...)
Definition: Error.h:26
GlobalMatrix::IndexType GlobalIndexType
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void DBUG(char const *fmt, Args const &... args)
Definition: Logging.h:27
Global vector based on Eigen vector.
Definition: EigenVector.h:26
void copyValues(std::vector< double > &u) const
Copy vector values.
Definition: EigenVector.h:94
void set(IndexType rowId, double v)
set entry
Definition: EigenVector.h:77
bool isAxiallySymmetric() const
Definition: Mesh.h:126
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition: Mesh.h:98
virtual void preTimestep(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table, GlobalVector const &x, double const t, double const delta_t)
virtual void initialize(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
bool isPhaseFieldProcess(int const process_id) const
NumLib::LocalToGlobalIndexMap const & getDOFTable(const int process_id) const override
void updateConstraints(GlobalVector &lower, GlobalVector &upper, int const process_id) override
MathLib::MatrixSpecifications getMatrixSpecifications(const int process_id) const override
MeshLib::PropertyVector< double > * _nodal_forces
void postTimestepConcreteProcess(std::vector< GlobalVector * > const &x, const double t, const double delta_t, int const process_id) override
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
void preTimestepConcreteProcess(std::vector< GlobalVector * > const &x, double const t, double const dt, const int process_id) override
void initializeConcreteProcess(NumLib::LocalToGlobalIndexMap const &dof_table, MeshLib::Mesh const &mesh, unsigned const integration_order) override
Process specific initialization called by initialize().
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
void postNonLinearSolverConcreteProcess(GlobalVector const &x, GlobalVector const &xdot, const double t, double const dt, int const process_id) override
PhaseFieldProcess(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, PhaseFieldProcessData< DisplacementDim > &&process_data, SecondaryVariableCollection &&secondary_variables, bool const use_monolithic_scheme)
std::vector< std::size_t > const & getActiveElementIDs() const
Handles configuration of several secondary variables from the project file.
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)
void assemble(std::size_t const mesh_item_id, LocalAssemblerInterface &local_assembler, std::vector< std::reference_wrapper< NumLib::LocalToGlobalIndexMap >> const &dof_tables, double const t, double const dt, std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &xdot, int const process_id, GlobalMatrix &M, GlobalMatrix &K, GlobalVector &b)
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Definition: KelvinVector.h:48
void scale(PETScVector &x, double const a)
Definition: LinAlg.cpp:44
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37
void setLocalAccessibleVector(PETScVector const &x)
Definition: LinAlg.cpp:27
@ BY_LOCATION
Ordering data by spatial location.
GlobalSparsityPattern computeSparsityPattern(LocalToGlobalIndexMap const &dof_table, MeshLib::Mesh const &mesh)
Computes a sparsity pattern for the given inputs.
void createLocalAssemblers(std::vector< MeshLib::Element * > const &mesh_elements, NumLib::LocalToGlobalIndexMap const &dof_table, std::vector< std::unique_ptr< LocalAssemblerInterface >> &local_assemblers, ExtraCtorArgs &&... extra_ctor_args)
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)