KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
geo_mechanics_newton_raphson_erosion_process_strategy.hpp
Go to the documentation of this file.
1 // KRATOS___
2 // // ) )
3 // // ___ ___
4 // // ____ //___) ) // ) )
5 // // / / // // / /
6 // ((____/ / ((____ ((___/ / MECHANICS
7 //
8 // License: geo_mechanics_application/license.txt
9 //
10 // Main authors: Jonathan Nuttall,
11 // Aron Noordam
12 //
13 
14 #pragma once
15 
16 // Project includes
17 #include "includes/define.h"
19 #include "includes/model_part.h"
20 
21 // Application includes
22 #include "boost/range/adaptor/filtered.hpp"
26 
27 #include <chrono>
28 #include <ctime>
29 #include <iostream>
30 #include <tuple>
31 
32 namespace Kratos
33 {
34 
35 template <class TSparseSpace, class TDenseSpace, class TLinearSolver>
37  : public GeoMechanicsNewtonRaphsonStrategy<TSparseSpace, TDenseSpace, TLinearSolver>
38 {
39 public:
41 
50  typename boost::range_detail::filtered_range<std::function<bool(Element*)>, std::vector<Element*>>;
52  using NodeType = Node;
54 
56  typename TSchemeType::Pointer pScheme,
57  typename TLinearSolver::Pointer pNewLinearSolver,
58  typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria,
59  typename TBuilderAndSolverType::Pointer pNewBuilderAndSolver,
60  Parameters& rParameters,
61  int MaxIterations = 30,
62  bool CalculateReactions = false,
63  bool ReformDofSetAtEachStep = false,
64  bool MoveMeshFlag = false)
65  : GeoMechanicsNewtonRaphsonStrategy<TSparseSpace, TDenseSpace, TLinearSolver>(
66  model_part,
67  pScheme,
68  pNewLinearSolver,
69  pNewConvergenceCriteria,
70  pNewBuilderAndSolver,
71  rParameters,
72  MaxIterations,
73  CalculateReactions,
74  ReformDofSetAtEachStep,
76  {
77  rank = model_part.GetCommunicator().MyPID();
78  mPipingIterations = rParameters["max_piping_iterations"].GetInt();
79  }
80 
81  void FinalizeSolutionStep() override
82  {
83  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
84  << "Max Piping Iterations: " << mPipingIterations << std::endl;
85 
86  bool grow = true;
87 
88  // get piping elements
89  std::vector<Element*> PipeElements = GetPipingElements();
90  unsigned int n_el = PipeElements.size(); // number of piping elements
91 
92  // get initially open pipe elements
93  unsigned int openPipeElements = this->InitialiseNumActivePipeElements(PipeElements);
94 
95  if (PipeElements.empty()) {
96  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
97  << "No Pipe Elements -> Finalizing Solution " << std::endl;
99  return;
100  }
101  // calculate max pipe height and pipe increment
102  double amax = CalculateMaxPipeHeight(PipeElements);
103 
104  // continue this loop, while the pipe is growing in length
105  while (grow && (openPipeElements < n_el)) {
106  // todo: JDN (20220817) : grow not used.
107  // bool Equilibrium = false;
108 
109  // get tip element and activate
110  Element* tip_element = PipeElements.at(openPipeElements);
111  openPipeElements += 1;
112  tip_element->SetValue(PIPE_ACTIVE, true);
113 
114  // Get all open pipe elements
115  std::function<bool(Element*)> filter = [](Element* i) {
116  return i->Has(PIPE_ACTIVE) && i->GetValue(PIPE_ACTIVE);
117  };
118  filtered_elements OpenPipeElements = PipeElements | boost::adaptors::filtered(filter);
119  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
120  << "Number of Open Pipe Elements: " << boost::size(OpenPipeElements) << std::endl;
121 
122  // non-lin picard iteration, for deepening the pipe
123  // Todo JDN (20220817):: Deal with Equilibrium redundancy
124  // Equilibrium = check_pipe_equilibrium(OpenPipeElements, amax, mPipingIterations);
125  check_pipe_equilibrium(OpenPipeElements, amax, mPipingIterations);
126 
127  // check if pipe should grow in length
128  std::tie(grow, openPipeElements) =
129  check_status_tip_element(openPipeElements, n_el, amax, PipeElements);
130 
131  // if n open elements is lower than total pipe elements, save pipe height current
132  // growing iteration or reset to previous iteration in case the pipe should not grow.
133  if (openPipeElements < n_el) {
134  save_or_reset_pipe_heights(OpenPipeElements, grow);
135  }
136  // recalculate groundwater flow
137  bool converged = Recalculate();
138 
139  // error check
140  KRATOS_ERROR_IF_NOT(converged) << "Groundwater flow calculation failed to converge." << std::endl;
141  }
142 
144  }
145 
150  int Check() override
151  {
152  KRATOS_TRY
153 
154  BaseType::Check();
156  this->GetScheme()->Check(BaseType::GetModelPart());
157  return 0;
158 
159  KRATOS_CATCH("")
160  }
161 
162  //-----------------------------Get Piping Elements--------------------------------------
163 
164  std::vector<Element*> GetPipingElements()
165  {
166  ModelPart& CurrentModelPart = this->GetModelPart();
167  std::vector<Element*> PipeElements;
168  double PipeElementStartX;
169 
170  for (Element& element : CurrentModelPart.Elements()) {
171  if (element.GetProperties().Has(PIPE_START_ELEMENT)) {
172  PipeElements.push_back(&element);
173 
174  long unsigned int startElement = element.GetProperties()[PIPE_START_ELEMENT];
175 
176  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
177  << element.Id() << " " << startElement << std::endl;
178 
179  if (element.Id() == startElement) {
180  PipeElementStartX = element.GetGeometry().GetPoint(0)[0];
181  }
182  }
183  }
184 
185  if (PipeElements.empty()) {
186  return PipeElements;
187  }
188 
189  // Get Maximum X Value in Pipe
190  auto rightPipe = std::max_element(PipeElements.begin(), PipeElements.end(),
191  [](const Element* a, const Element* b) {
192  return a->GetGeometry().GetPoint(0)[0] < b->GetGeometry().GetPoint(0)[0];
193  });
194 
195  // Get Minimum X Value in Pipe
196  auto leftPipe = std::min_element(PipeElements.begin(), PipeElements.end(),
197  [](const Element* a, const Element* b) {
198  return a->GetGeometry().GetPoint(0)[0] < b->GetGeometry().GetPoint(0)[0];
199  });
200 
201  double minX = leftPipe[0]->GetGeometry().GetPoint(0)[0];
202  double maxX = rightPipe[0]->GetGeometry().GetPoint(0)[0];
203 
204  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
205  << minX << " " << maxX << " " << PipeElementStartX << std::endl;
206 
207  if ((minX != PipeElementStartX) && (maxX != PipeElementStartX)) {
208  KRATOS_ERROR << "Unable to determine pipe direction (multiple directions possible) - "
209  "Check PIPE_START_ELEMENT"
210  << std::endl;
211  }
212 
213  if (minX == PipeElementStartX) {
214  // Pipe Left -> Right
215  sort(PipeElements.begin(), PipeElements.end(), [](const Element* lhs, const Element* rhs) {
216  return lhs->GetGeometry().GetPoint(0)[0] < rhs->GetGeometry().GetPoint(0)[0];
217  });
218  } else {
219  // Pipe Right -> Left
220  sort(PipeElements.begin(), PipeElements.end(), [](const Element* lhs, const Element* rhs) {
221  return lhs->GetGeometry().GetPoint(0)[0] > rhs->GetGeometry().GetPoint(0)[0];
222  });
223  }
224 
225  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
226  << "Number of Pipe Elements: " << PipeElements.size() << std::endl;
227  for (const Element* pipeElement : PipeElements) {
228  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
229  << "PipeElementIDs (in order): " << pipeElement->Id() << std::endl;
230  }
231 
232  return PipeElements;
233  }
234 
235 private:
236  unsigned int mPipingIterations;
237  int rank;
238  double small_pipe_height = 1e-10;
239  double pipe_height_accuracy = small_pipe_height * 10;
240 
247  int InitialiseNumActivePipeElements(std::vector<Element*> PipeElements)
248  {
249  int nOpenElements = 0;
250 
251  for (Element* pipe_element : PipeElements) {
252  if (pipe_element->GetValue(PIPE_ACTIVE)) {
253  nOpenElements += 1;
254  }
255  }
256  return nOpenElements;
257  }
258 
265  double CalculateParticleDiameter(const PropertiesType& Prop)
266  {
267  double diameter;
268 
269  if (Prop[PIPE_MODIFIED_D]) diameter = 2.08e-4 * pow((Prop[PIPE_D_70] / 2.08e-4), 0.4);
270  else diameter = Prop[PIPE_D_70];
271  return diameter;
272  }
273 
279  double CalculateMaxPipeHeight(std::vector<Element*> pipe_elements)
280  {
281  double max_diameter = 0;
282  double height_factor = 100;
283 
284  // loop over all elements
285  for (Element* pipe_element : pipe_elements) {
286  // calculate pipe particle diameter of pipe element
287  PropertiesType prop = pipe_element->GetProperties();
288  double particle_diameter = this->CalculateParticleDiameter(prop);
289 
290  // get maximum pipe particle diameter of all pipe elements
291  if (particle_diameter > max_diameter) {
292  max_diameter = particle_diameter;
293  }
294  }
295 
296  // max pipe height is maximum pipe particle diameter * a constant
297  return max_diameter * height_factor;
298  }
299 
306  double CalculatePipeHeightIncrement(double max_pipe_height, const unsigned int n_steps)
307  {
308  return max_pipe_height / (n_steps - 1);
309  }
310 
311  bool Recalculate()
312  {
313  KRATOS_INFO_IF("ResidualBasedNewtonRaphsonStrategy", this->GetEchoLevel() > 0 && rank == 0)
314  << "Recalculating" << std::endl;
315  // KRATOS_INFO_IF("PipingLoop") << "Recalculating" << std::endl;
316  // ModelPart& CurrentModelPart = this->GetModelPart();
317  // this->Clear();
318 
319  // Reset displacements to the initial (Assumes Water Pressure is the convergence criteria)
320  /* block_for_each(CurrentModelPart.Nodes(), [&](Node& rNode) {
321  auto dold = rNode.GetSolutionStepValue(WATER_PRESSURE, 1);
322  rNode.GetSolutionStepValue(WATER_PRESSURE, 0) = dold;
323  });*/
324 
328  }
329 
330  bool check_pipe_equilibrium(filtered_elements open_pipe_elements, double amax, unsigned int mPipingIterations)
331  {
332  bool equilibrium = false;
333  bool converged = true;
334  unsigned int PipeIter = 0;
335  // todo: JDN (20220817) : grow not used.
336  // bool grow = true;
337 
338  // calculate max pipe height and pipe increment
339  double da = CalculatePipeHeightIncrement(amax, mPipingIterations);
340 
341  while (PipeIter < mPipingIterations && !equilibrium && converged) {
342  // set equilibrium on true
343  equilibrium = true;
344 
345  // perform a flow calculation and stop growing if the calculation doesn't converge
346  converged = Recalculate();
347 
348  // todo: JDN (20220817) : grow not used.
349  // if (!converged)
350  //{
351  // grow = false;
352  //}
353 
354  if (converged) {
355  // Update depth of open piping Elements
356  equilibrium = true;
357  for (auto OpenPipeElement : open_pipe_elements) {
358  auto pElement = static_cast<SteadyStatePwPipingElement<2, 4>*>(OpenPipeElement);
359 
360  // get open pipe element geometry and properties
361  auto& Geom = OpenPipeElement->GetGeometry();
362  auto& prop = OpenPipeElement->GetProperties();
363 
364  // calculate equilibrium pipe height and get current pipe height
365  double eq_height = pElement->CalculateEquilibriumPipeHeight(
366  prop, Geom, OpenPipeElement->GetValue(PIPE_ELEMENT_LENGTH));
367  double current_height = OpenPipeElement->GetValue(PIPE_HEIGHT);
368 
369  // set erosion on true if current pipe height is greater than the equilibrium height
370  if (current_height > eq_height) {
371  OpenPipeElement->SetValue(PIPE_EROSION, true);
372  }
373 
374  // check this if statement, I don't understand the check for pipe erosion
375  if (((!OpenPipeElement->GetValue(PIPE_EROSION) || (current_height > eq_height)) &&
376  current_height < amax)) {
377  OpenPipeElement->SetValue(PIPE_HEIGHT, OpenPipeElement->GetValue(PIPE_HEIGHT) + da);
378  equilibrium = false;
379  }
380 
381  // check if equilibrium height and current pipe heights are diverging, stop
382  // picard iterations if this is the case and set pipe height on zero
383  if (!OpenPipeElement->GetValue(PIPE_EROSION) && (PipeIter > 1) &&
384  ((eq_height - current_height) > OpenPipeElement->GetValue(DIFF_PIPE_HEIGHT))) {
385  equilibrium = true;
386  OpenPipeElement->SetValue(PIPE_HEIGHT, small_pipe_height);
387  }
388 
389  // calculate difference between equilibrium height and current pipe height
390  OpenPipeElement->SetValue(DIFF_PIPE_HEIGHT, eq_height - current_height);
391  }
392  // increment piping iteration number
393  PipeIter += 1;
394  }
395  }
396  return equilibrium;
397  }
398 
407  std::tuple<bool, int> check_status_tip_element(unsigned int n_open_elements,
408  unsigned int n_elements,
409  double max_pipe_height,
410  std::vector<Element*> PipeElements)
411  {
412  bool grow = true;
413  // check status of tip element, stop growing if pipe_height is zero or greater than maximum
414  // pipe height or if all elements are open
415  if (n_open_elements < n_elements) {
416  Element* tip_element = PipeElements.at(n_open_elements - 1);
417  double pipe_height = tip_element->GetValue(PIPE_HEIGHT);
418 
419  if ((pipe_height > max_pipe_height + std::numeric_limits<double>::epsilon()) ||
420  (pipe_height < pipe_height_accuracy)) {
421  // stable element found; pipe length does not increase during current time step
422  grow = false;
423  tip_element->SetValue(PIPE_EROSION, false);
424  tip_element->SetValue(PIPE_ACTIVE, false);
425  n_open_elements -= 1;
426 
427  KRATOS_INFO_IF("PipingLoop", this->GetEchoLevel() > 0 && rank == 0)
428  << "Number of Open Pipe Elements: " << n_open_elements << std::endl;
429  }
430  } else {
431  grow = false;
432  }
433  return std::make_tuple(grow, n_open_elements);
434  }
435 
442  void save_or_reset_pipe_heights(filtered_elements open_pipe_elements, bool grow)
443  {
444  for (Element* OpenPipeElement : open_pipe_elements) {
445  if (grow) {
446  OpenPipeElement->SetValue(PREV_PIPE_HEIGHT, OpenPipeElement->GetValue(PIPE_HEIGHT));
447  } else {
448  OpenPipeElement->SetValue(PIPE_HEIGHT, OpenPipeElement->GetValue(PREV_PIPE_HEIGHT));
449  }
450  }
451  }
452 
453  //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
454 
455 }; // Class GeoMechanicsNewtonRaphsonStrategy
456 
457 } // namespace Kratos
Current class provides an implementation for the base builder and solving operations.
Definition: builder_and_solver.h:64
This is the base class to define the different convergence criterion considered.
Definition: convergence_criteria.h:58
Base class for all Elements.
Definition: element.h:60
Definition: geo_mechanics_newton_raphson_erosion_process_strategy.hpp:38
typename boost::range_detail::filtered_range< std::function< bool(Element *)>, std::vector< Element * > > filtered_elements
Definition: geo_mechanics_newton_raphson_erosion_process_strategy.hpp:50
void FinalizeSolutionStep() override
Performs all the required operations that should be done (for each step) after solving the solution s...
Definition: geo_mechanics_newton_raphson_erosion_process_strategy.hpp:81
std::vector< Element * > GetPipingElements()
Definition: geo_mechanics_newton_raphson_erosion_process_strategy.hpp:164
KRATOS_CLASS_POINTER_DEFINITION(GeoMechanicsNewtonRaphsonErosionProcessStrategy)
Properties PropertiesType
Definition: geo_mechanics_newton_raphson_erosion_process_strategy.hpp:51
int Check() override
Function to perform expensive checks.
Definition: geo_mechanics_newton_raphson_erosion_process_strategy.hpp:150
GeoMechanicsNewtonRaphsonErosionProcessStrategy(ModelPart &model_part, typename TSchemeType::Pointer pScheme, typename TLinearSolver::Pointer pNewLinearSolver, typename TConvergenceCriteriaType::Pointer pNewConvergenceCriteria, typename TBuilderAndSolverType::Pointer pNewBuilderAndSolver, Parameters &rParameters, int MaxIterations=30, bool CalculateReactions=false, bool ReformDofSetAtEachStep=false, bool MoveMeshFlag=false)
Definition: geo_mechanics_newton_raphson_erosion_process_strategy.hpp:55
Definition: geo_mechanics_newton_raphson_strategy.hpp:31
void SetValue(const TVariableType &rThisVariable, typename TVariableType::Type const &rValue)
Definition: geometrical_object.h:238
Geometry base class.
Definition: geometry.h:71
Implicit solving strategy base class This is the base class from which we will derive all the implici...
Definition: implicit_solving_strategy.h:61
BaseType::TSystemVectorType TSystemVectorType
Definition: implicit_solving_strategy.h:72
Scheme< TSparseSpace, TDenseSpace > TSchemeType
Definition: implicit_solving_strategy.h:82
BaseType::DofsArrayType DofsArrayType
Definition: implicit_solving_strategy.h:90
BuilderAndSolver< TSparseSpace, TDenseSpace, TLinearSolver > TBuilderAndSolverType
Definition: implicit_solving_strategy.h:84
BaseType::TSystemMatrixType TSystemMatrixType
Definition: implicit_solving_strategy.h:70
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
This class defines the node.
Definition: node.h:65
This class provides to Kratos a data structure for I/O based on the standard of JSON.
Definition: kratos_parameters.h:59
int GetInt() const
This method returns the integer contained in the current Parameter.
Definition: kratos_parameters.cpp:666
A sorted associative container similar to an STL set, but uses a vector to store pointers to its data...
Definition: pointer_vector_set.h:72
Properties encapsulates data shared by different Elements or Conditions. It can store any type of dat...
Definition: properties.h:69
TBuilderAndSolverType::Pointer GetBuilderAndSolver()
Get method for the builder and solver.
Definition: residualbased_newton_raphson_strategy.h:493
TSchemeType::Pointer GetScheme()
Get method for the time scheme.
Definition: residualbased_newton_raphson_strategy.h:475
bool SolveSolutionStep() override
Solves the current step. This function returns true if a solution has been found, false otherwise.
Definition: residualbased_newton_raphson_strategy.h:884
void Predict() override
Operation to predict the solution ... if it is not called a trivial predictor is used in which the va...
Definition: residualbased_newton_raphson_strategy.h:625
void InitializeSolutionStep() override
Performs all the required operations that should be done (for each step) before solving the solution ...
Definition: residualbased_newton_raphson_strategy.h:781
void FinalizeSolutionStep() override
Performs all the required operations that should be done (for each step) after solving the solution s...
Definition: residualbased_newton_raphson_strategy.h:848
This class provides the implementation of the basic tasks that are needed by the solution strategy.
Definition: scheme.h:56
Solving strategy base class This is the base class from which we will derive all the strategies (impl...
Definition: solving_strategy.h:64
ModelPart & GetModelPart()
Operations to get the pointer to the model.
Definition: solving_strategy.h:350
int GetEchoLevel()
This returns the level of echo for the solving strategy.
Definition: solving_strategy.h:271
virtual int Check()
Function to perform expensive checks.
Definition: solving_strategy.h:377
bool MoveMeshFlag()
This function returns the flag that says if the mesh is moved.
Definition: solving_strategy.h:290
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF_NOT(conditional)
Definition: exception.h:163
#define KRATOS_INFO_IF(label, conditional)
Definition: logger.h:251
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
REACTION_CHECK_STIFFNESS_FACTOR INNER_LOOP_ITERATION DISTANCE_THRESHOLD ACTIVE_CHECK_FACTOR AUXILIAR_COORDINATES NORMAL_GAP WEIGHTED_GAP WEIGHTED_SCALAR_RESIDUAL bool
Definition: contact_structural_mechanics_application_variables.h:93
int n_steps
Definition: bombardelli_test.py:27
model_part
Definition: face_heat.py:14
rhs
Definition: generate_frictional_mortar_condition.py:297
lhs
Definition: generate_frictional_mortar_condition.py:297
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
prop
Definition: read_stl.py:10
height_factor
Definition: sp_statistics.py:22
integer i
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31
Definition: mesh_converter.cpp:33