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.
mpc_contact_criteria.h
Go to the documentation of this file.
1 // KRATOS ______ __ __ _____ __ __ __
2 // / ____/___ ____ / /_____ ______/ /_/ ___// /________ _______/ /___ ___________ _/ /
3 // / / / __ \/ __ \/ __/ __ `/ ___/ __/\__ \/ __/ ___/ / / / ___/ __/ / / / ___/ __ `/ /
4 // / /___/ /_/ / / / / /_/ /_/ / /__/ /_ ___/ / /_/ / / /_/ / /__/ /_/ /_/ / / / /_/ / /
5 // \____/\____/_/ /_/\__/\__,_/\___/\__//____/\__/_/ \__,_/\___/\__/\__,_/_/ \__,_/_/ MECHANICS
6 //
7 // License: BSD License
8 // license: ContactStructuralMechanicsApplication/license.txt
9 //
10 // Main authors: Vicente Mataix Ferrandiz
11 //
12 
13 #pragma once
14 
15 // System includes
16 
17 // External includes
18 
19 // Project includes
25 
26 namespace Kratos
27 {
30 
34 
38 
42 
46 
53 template<class TSparseSpace, class TDenseSpace>
55  : public ConvergenceCriteria< TSparseSpace, TDenseSpace >
56 {
57 public:
60 
63 
66 
69 
72 
75 
78 
80  using TablePrinterPointerType = TableStreamUtility::Pointer;
81 
83  using IndexType = std::size_t;
84 
85  // Geometry definition
87 
91 
95  explicit MPCContactCriteria()
96  : BaseType()
97  {
98  }
99 
104  explicit MPCContactCriteria(Kratos::Parameters ThisParameters)
105  : BaseType()
106  {
107  // Validate and assign defaults
108  ThisParameters = this->ValidateAndAssignParameters(ThisParameters, this->GetDefaultParameters());
109  this->AssignSettings(ThisParameters);
110  }
111 
114  : BaseType(rOther)
115  {
116  }
117 
119  ~MPCContactCriteria() override = default;
120 
124 
128 
133  typename BaseType::Pointer Create(Parameters ThisParameters) const override
134  {
135  return Kratos::make_shared<ClassType>(ThisParameters);
136  }
137 
148  ModelPart& rModelPart,
149  DofsArrayType& rDofSet,
150  const TSystemMatrixType& rA,
151  const TSystemVectorType& rDx,
152  const TSystemVectorType& rb
153  ) override
154  {
155  BaseType::PreCriteria(rModelPart, rDofSet, rA, rDx, rb);
156 
157  // Auxiliary zero array
158  const array_1d<double, 3> zero_array = ZeroVector(3);
159 
160  // We initailize the contact force
161  auto& r_nodes_array = rModelPart.GetSubModelPart("Contact").Nodes();
162 
163  // We save the current WEIGHTED_GAP in the buffer and reset the CONTACT_FORCE
164  block_for_each(r_nodes_array, [&](Node& rNode) {
165  rNode.SetValue(CONTACT_FORCE, zero_array);
166  rNode.FastGetSolutionStepValue(WEIGHTED_GAP, 1) = rNode.FastGetSolutionStepValue(WEIGHTED_GAP);
167  });
168 
169  // Compute weighted gap
170  ComputeWeightedGap(rModelPart);
171 
172  // Reset the NODAL_AREA
173  VariableUtils().SetNonHistoricalVariableToZero(NODAL_AREA, r_nodes_array);
174 
175  return true;
176  }
177 
188  ModelPart& rModelPart,
189  DofsArrayType& rDofSet,
190  const TSystemMatrixType& rA,
191  const TSystemVectorType& rDx,
192  const TSystemVectorType& rb
193  ) override
194  {
195  // We call the base class
196  BaseType::PostCriteria(rModelPart, rDofSet, rA, rDx, rb);
197 
198  // Getting process info
199  const ProcessInfo& r_process_info = rModelPart.GetProcessInfo();
200  if (r_process_info[NL_ITERATION_NUMBER] > 0) {
201  // Getting REACTION_CHECK_STIFFNESS_FACTOR
202  const double reaction_check_stiffness_factor = r_process_info.Has(REACTION_CHECK_STIFFNESS_FACTOR) ? r_process_info.GetValue(REACTION_CHECK_STIFFNESS_FACTOR) : 1.0e-12;
203 
204  // Compute weighted gap
205  ComputeWeightedGap(rModelPart);
206 
207  // Transfer reaction from master to slave
208  std::size_t sub_contact_counter = 0;
209  CounterContactModelParts(rModelPart, sub_contact_counter);
210 
211  // Mapping reaction
212  Parameters mapping_parameters = Parameters(R"({"distance_threshold" : 1.0e24, "update_interface" : false, "origin_variable" : "REACTION", "mapping_coefficient" : -1.0e0})" );
213  if (r_process_info.Has(DISTANCE_THRESHOLD)) {
214  mapping_parameters["distance_threshold"].SetDouble(r_process_info[DISTANCE_THRESHOLD]);
215  }
216  auto& r_contact_model_part = rModelPart.GetSubModelPart("Contact");
217  for (std::size_t i_contact = 0; i_contact < sub_contact_counter; ++i_contact) {
218  auto& r_sub = r_contact_model_part.GetSubModelPart("ContactSub" + std::to_string(i_contact));
219  auto& r_sub_master = r_sub.GetSubModelPart("MasterSubModelPart" + std::to_string(i_contact));
220  auto& r_sub_slave = r_sub.GetSubModelPart("SlaveSubModelPart" + std::to_string(i_contact));
221  SimpleMortarMapperProcessWrapper(r_sub_master, r_sub_slave, mapping_parameters).Execute();
222  }
223 
224  // TODO: Add frictional check
225 
226  // Getting process info
227  Properties::Pointer p_properties = rModelPart.Elements().begin()->pGetProperties();
228  for (auto& r_elements : rModelPart.Elements()) {
229  if (r_elements.pGetProperties()->Has(YOUNG_MODULUS)) {
230  p_properties = r_elements.pGetProperties();
231  }
232  }
233 
234  // Defining the convergence
235  IndexType is_active_set_converged = 0, is_slip_converged = 0;
236 
237  // Checking just after first iteration
238  // We get the YOUNG_MODULUS
239  const double young_modulus = p_properties->Has(YOUNG_MODULUS) ? p_properties->GetValue(YOUNG_MODULUS) : 0.0;
240  const double auxiliary_check = young_modulus > 0.0 ? -(reaction_check_stiffness_factor * young_modulus) : 0.0;
241 
242  // We check the active/inactive set during the first non-linear iteration or for the general semi-smooth case
243  auto& r_nodes_array = r_contact_model_part.Nodes();
244 
245  // If frictionaless or mesh tying
246  if (rModelPart.IsNot(SLIP)) {
247  is_active_set_converged = block_for_each<SumReduction<IndexType>>(r_nodes_array, [&](Node& rNode) {
248  if (rNode.Is(SLAVE)) {
249  // The contact force corresponds with the reaction in the normal direction
250  const array_1d<double, 3>& r_total_force = rNode.FastGetSolutionStepValue(REACTION);
251 
252  const double nodal_area = rNode.Has(NODAL_AREA) ? rNode.GetValue(NODAL_AREA) : 1.0;
253  const double gap = rNode.FastGetSolutionStepValue(WEIGHTED_GAP)/nodal_area;
254  const array_1d<double, 3>& r_normal = rNode.FastGetSolutionStepValue(NORMAL);
255  const double contact_force = inner_prod(r_total_force, r_normal);
256  const double contact_pressure = contact_force/rNode.GetValue(NODAL_MAUX);
257 
258  if (contact_pressure < auxiliary_check || gap < 0.0) { // NOTE: This could be conflictive (< or <=)
259  // We save the contact force
260  rNode.SetValue(CONTACT_FORCE, contact_force/rNode.GetValue(NODAL_PAUX) * r_normal);
261  rNode.SetValue(NORMAL_CONTACT_STRESS, contact_pressure);
262  if (rNode.IsNot(ACTIVE)) {
263  rNode.Set(ACTIVE, true);
264  return 1;
265  }
266  } else {
267  if (rNode.Is(ACTIVE)) {
268  rNode.Set(ACTIVE, false);
269  return 1;
270  }
271  }
272  }
273  return 0;
274  });
275  } else { // If frictional
277  std::tie(is_active_set_converged, is_slip_converged) = block_for_each<TwoReduction>(r_nodes_array, [&](Node& rNode) {
278  if (rNode.Is(SLAVE)) {
279  const double auxiliary_check = young_modulus > 0.0 ? -(reaction_check_stiffness_factor * young_modulus) : 0.0;
280  // The contact force corresponds with the reaction in the normal direction
281  const array_1d<double, 3>& r_total_force = rNode.FastGetSolutionStepValue(REACTION);
282 
283  const double nodal_area = rNode.Has(NODAL_AREA) ? rNode.GetValue(NODAL_AREA) : 1.0;
284  const double gap = rNode.FastGetSolutionStepValue(WEIGHTED_GAP)/nodal_area;
285  const array_1d<double, 3>& r_normal = rNode.FastGetSolutionStepValue(NORMAL);
286  const double contact_force = inner_prod(r_total_force, r_normal);
287  const double normal_contact_pressure = contact_force/rNode.GetValue(NODAL_MAUX);
288 
289  if (normal_contact_pressure < auxiliary_check || gap < 0.0) { // NOTE: This could be conflictive (< or <=)
290  // We save the contact force
291  rNode.SetValue(CONTACT_FORCE, r_total_force/rNode.GetValue(NODAL_PAUX));
292  rNode.SetValue(NORMAL_CONTACT_STRESS, normal_contact_pressure);
293  if (rNode.IsNot(ACTIVE)) {
294  rNode.Set(ACTIVE, true);
295  return std::make_tuple(1,0);
296  }
297 
298  // The friction coefficient
299  const double tangential_contact_pressure = norm_2(r_total_force - contact_force * r_normal)/rNode.GetValue(NODAL_MAUX);
300  const bool is_slip = rNode.Is(SLIP);
301  const double mu = rNode.GetValue(FRICTION_COEFFICIENT);
302 
303  if (tangential_contact_pressure <= - mu * contact_force) { // STICK CASE // TODO: Check the <=
304  rNode.SetValue(TANGENTIAL_CONTACT_STRESS, tangential_contact_pressure);
305  if (is_slip) {
306  rNode.Set(SLIP, false);
307  return std::make_tuple(0,1);
308  }
309  } else { // SLIP CASE
310  rNode.SetValue(TANGENTIAL_CONTACT_STRESS, - mu * contact_force);
311  if (!is_slip) {
312  rNode.Set(SLIP, true);
313  return std::make_tuple(0,1);
314  }
315  }
316  } else {
317  if (rNode.Is(ACTIVE)) {
318  rNode.Set(ACTIVE, false);
319  rNode.Reset(SLIP);
320  return std::make_tuple(1,0);
321  }
322  }
323  }
324  return std::make_tuple(0,0);
325  });
326  }
327 
328  // We set the constraints active and inactive in function of the active set
329  auto& r_conditions_array = rModelPart.GetSubModelPart("ComputingContact").Conditions();
330  block_for_each(r_conditions_array, [&](Condition& rCond) {
331  const auto& r_slave_geometry = rCond.GetGeometry().GetGeometryPart(CouplingGeometryType::Master);
332  std::size_t counter = 0;
333  for (auto& r_node : r_slave_geometry) {
334  if (r_node.IsNot(ACTIVE)) {
335  ++counter;
336  }
337  }
338 
339  // In case of traction we deactivate
340  if (counter == r_slave_geometry.size()) {
341  rCond.Set(ACTIVE, false);
342  // We deactivate the constraints on inactive conditions
343  if (rCond.Has(CONSTRAINT_POINTER)) {
344  auto p_const = rCond.GetValue(CONSTRAINT_POINTER);
345 
346  // In case of traction we deactivate
347  p_const->Set(ACTIVE, false);
348  } else {
349  KRATOS_ERROR << "Contact conditions must have defined CONSTRAINT_POINTER" << std::endl;
350  }
351  }
352  });
353 
354  // We save to the process info if the active set has converged
355  const bool active_set_converged = (is_active_set_converged == 0 ? true : false);
356  const bool slip_set_converged = (is_slip_converged == 0 ? true : false);
357 
358  if (rModelPart.GetCommunicator().MyPID() == 0 && this->GetEchoLevel() > 0) {
359  if (active_set_converged) {
360  KRATOS_INFO("MPCContactCriteria") << BOLDFONT("\tActive set") << " convergence is " << BOLDFONT(FGRN("achieved")) << std::endl;
361  } else {
362  KRATOS_INFO("MPCContactCriteria") << BOLDFONT("\tActive set") << " convergence is " << BOLDFONT(FRED("not achieved")) << std::endl;
363  }
364  if (slip_set_converged) {
365  KRATOS_INFO("MPCContactCriteria") << BOLDFONT("\tSlip set") << " convergence is " << BOLDFONT(FGRN("achieved")) << std::endl;
366  } else {
367  KRATOS_INFO("MPCContactCriteria") << BOLDFONT("\tSlip set") << " convergence is " << BOLDFONT(FRED("not achieved")) << std::endl;
368  }
369  }
370 
371  return (active_set_converged && slip_set_converged);
372  }
373 
374  return true;
375  }
376 
381  void Initialize(ModelPart& rModelPart) override
382  {
383  BaseType::Initialize(rModelPart);
384  }
385 
391  {
392  Parameters default_parameters = Parameters(R"(
393  {
394  "name" : "mpc_contact_criteria"
395  })" );
396 
397  // Getting base class default parameters
398  const Parameters base_default_parameters = BaseType::GetDefaultParameters();
399  default_parameters.RecursivelyAddMissingParameters(base_default_parameters);
400  return default_parameters;
401  }
402 
407  static std::string Name()
408  {
409  return "mpc_contact_criteria";
410  }
411 
415 
419 
423 
425  std::string Info() const override
426  {
427  return "MPCContactCriteria";
428  }
429 
431  void PrintInfo(std::ostream& rOStream) const override
432  {
433  rOStream << Info();
434  }
435 
437  void PrintData(std::ostream& rOStream) const override
438  {
439  rOStream << Info();
440  }
441 
443 protected:
446 
450 
454 
458 
463  void AssignSettings(const Parameters ThisParameters) override
464  {
465  BaseType::AssignSettings(ThisParameters);
466  }
467 
469 private:
472 
476 
480 
484 
489  void ComputeWeightedGap(ModelPart& rModelPart)
490  {
491  auto& r_nodes_array = rModelPart.GetSubModelPart("Contact").Nodes();
492  // Set to zero the weighted gap
493  if (rModelPart.Is(SLIP)) {
494  // Reset
495  VariableUtils().SetHistoricalVariableToZero(WEIGHTED_GAP, r_nodes_array);
496  VariableUtils().SetHistoricalVariableToZero(WEIGHTED_SLIP, r_nodes_array);
497  } else {
498  VariableUtils().SetHistoricalVariableToZero(WEIGHTED_GAP, r_nodes_array);
499  }
500 
501  // Compute the contribution
502  ContactUtilities::ComputeExplicitContributionConditions(rModelPart.GetSubModelPart("ComputingContact"));
503  }
504 
510  void CounterContactModelParts(
511  ModelPart& rModelPart,
512  std::size_t& rCounter
513  )
514  {
515  for (auto& r_name : rModelPart.GetSubModelPartNames()) {
516  if (r_name.find("ContactSub") != std::string::npos && r_name.find("ComputingContactSub") == std::string::npos) {
517  ++rCounter;
518  }
519  auto& r_sub = rModelPart.GetSubModelPart(r_name);
520  if (r_sub.IsSubModelPart()) {
521  CounterContactModelParts(r_sub, rCounter);
522  }
523  }
524  }
525 
527 }; // Class MPCContactCriteria
528 
531 
532 } // namespace Kratos
533 
std::string Info() const override
Turn back information as a string.
Definition: periodic_interface_process.hpp:93
Base class for all Conditions.
Definition: condition.h:59
This is the base class to define the different convergence criterion considered.
Definition: convergence_criteria.h:58
virtual bool PostCriteria(ModelPart &rModelPart, DofsArrayType &rDofSet, const TSystemMatrixType &rA, const TSystemVectorType &rDx, const TSystemVectorType &rb)
Criterias that need to be called after getting the solution.
Definition: convergence_criteria.h:261
virtual Parameters ValidateAndAssignParameters(Parameters ThisParameters, const Parameters DefaultParameters) const
This method validate and assign default parameters.
Definition: convergence_criteria.h:466
virtual bool PreCriteria(ModelPart &rModelPart, DofsArrayType &rDofSet, const TSystemMatrixType &rA, const TSystemVectorType &rDx, const TSystemVectorType &rb)
Criterias that need to be called before getting the solution.
Definition: convergence_criteria.h:241
TSparseSpace::MatrixType TSystemMatrixType
Matrix type definition.
Definition: convergence_criteria.h:72
ModelPart::DofsArrayType DofsArrayType
DoF array type definition.
Definition: convergence_criteria.h:81
TSparseSpace::VectorType TSystemVectorType
Vector type definition.
Definition: convergence_criteria.h:74
The CouplingGeometry connects two or more geometries of different types and entities.
Definition: coupling_geometry.h:41
static constexpr IndexType Master
Definition: coupling_geometry.h:72
bool Has(const Variable< TDataType > &rThisVariable) const
Checks if the data container has a value associated with a given variable.
Definition: data_value_container.h:382
TDataType & GetValue(const Variable< TDataType > &rThisVariable)
Gets the value associated with a given variable.
Definition: data_value_container.h:268
bool Is(Flags const &rOther) const
Definition: flags.h:274
bool IsNot(Flags const &rOther) const
Definition: flags.h:291
GeometryType & GetGeometry()
Returns the reference of the geometry.
Definition: geometrical_object.h:158
Custom convergence criteria for the contact problem.
Definition: mpc_contact_criteria.h:56
~MPCContactCriteria() override=default
Destructor.
std::string Info() const override
Turn back information as a string.
Definition: mpc_contact_criteria.h:425
std::size_t IndexType
The index type definition.
Definition: mpc_contact_criteria.h:83
void AssignSettings(const Parameters ThisParameters) override
This method assigns settings to member variables.
Definition: mpc_contact_criteria.h:463
MPCContactCriteria(MPCContactCriteria const &rOther)
Copy constructor.
Definition: mpc_contact_criteria.h:113
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: mpc_contact_criteria.h:431
void Initialize(ModelPart &rModelPart) override
This function initialize the convergence criteria.
Definition: mpc_contact_criteria.h:381
MPCContactCriteria()
Default constructor.
Definition: mpc_contact_criteria.h:95
KRATOS_CLASS_POINTER_DEFINITION(MPCContactCriteria)
Pointer definition of MPCContactCriteria.
bool PreCriteria(ModelPart &rModelPart, DofsArrayType &rDofSet, const TSystemMatrixType &rA, const TSystemVectorType &rDx, const TSystemVectorType &rb) override
Criterias that need to be called before getting the solution.
Definition: mpc_contact_criteria.h:147
bool PostCriteria(ModelPart &rModelPart, DofsArrayType &rDofSet, const TSystemMatrixType &rA, const TSystemVectorType &rDx, const TSystemVectorType &rb) override
Compute relative and absolute error.
Definition: mpc_contact_criteria.h:187
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: mpc_contact_criteria.h:437
static std::string Name()
Returns the name of the class as used in the settings (snake_case format)
Definition: mpc_contact_criteria.h:407
Parameters GetDefaultParameters() const override
This method provides the defaults parameters to avoid conflicts between the different constructors.
Definition: mpc_contact_criteria.h:390
MPCContactCriteria(Kratos::Parameters ThisParameters)
Default constructor. (with parameters)
Definition: mpc_contact_criteria.h:104
TableStreamUtility::Pointer TablePrinterPointerType
The table stream definition TODO: Replace by logger.
Definition: mpc_contact_criteria.h:80
BaseType::Pointer Create(Parameters ThisParameters) const override
Create method.
Definition: mpc_contact_criteria.h:133
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ProcessInfo & GetProcessInfo()
Definition: model_part.h:1746
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
ModelPart & GetSubModelPart(std::string const &SubModelPartName)
Definition: model_part.cpp:2029
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
This class defines the node.
Definition: node.h:65
TVariableType::Type & FastGetSolutionStepValue(const TVariableType &rThisVariable)
Definition: node.h:435
void SetValue(const TVariableType &rThisVariable, typename TVariableType::Type const &rValue)
Definition: node.h:493
This class provides to Kratos a data structure for I/O based on the standard of JSON.
Definition: kratos_parameters.h:59
void SetDouble(const double Value)
This method sets the double contained in the current Parameter.
Definition: kratos_parameters.cpp:787
void RecursivelyAddMissingParameters(const Parameters &rDefaultParameters)
This function is designed to verify that the parameters under testing contain at least all parameters...
Definition: kratos_parameters.cpp:1457
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
ProcessInfo holds the current value of different solution parameters.
Definition: process_info.h:59
This class wraps automatically the different types mof mappers.
Definition: simple_mortar_mapper_wrapper_process.h:54
void Execute() override
Execute method is used to execute the Process algorithms.
Definition: simple_mortar_mapper_wrapper_process.h:224
utility function to do a sum reduction
Definition: reduction_utilities.h:68
This class implements a set of auxiliar, already parallelized, methods to perform some common tasks r...
Definition: variable_utils.h:63
void SetHistoricalVariableToZero(const Variable< TType > &rVariable, NodesContainerType &rNodes)
Sets the nodal value of any variable to zero.
Definition: variable_utils.h:757
void SetNonHistoricalVariableToZero(const Variable< TType > &rVariable, TContainerType &rContainer)
Sets the nodal value of any variable to zero.
Definition: variable_utils.h:724
#define FGRN(x)
Definition: color_utilities.h:27
#define FRED(x)
Definition: color_utilities.h:26
#define BOLDFONT(x)
Definition: color_utilities.h:34
#define KRATOS_INFO(label)
Definition: logger.h:250
Kratos::ModelPart ModelPart
Definition: kratos_wrapper.h:31
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
void block_for_each(TIterator itBegin, TIterator itEnd, TFunction &&rFunction)
Execute a functor on all items of a range in parallel.
Definition: parallel_utilities.h:299
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
int counter
Definition: script_THERMAL_CORRECT.py:218
Definition: reduction_utilities.h:310