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.
partitioned_fsi_utilities.hpp
Go to the documentation of this file.
1 // | / |
2 // ' / __| _` | __| _ \ __|
3 // . \ | ( | | ( |\__ `
4 // _|\_\_| \__,_|\__|\___/ ____/
5 // Multi-Physics
6 //
7 // License: BSD License
8 // Kratos default license: kratos/license.txt
9 //
10 // Main authors: Ruben Zorrilla
11 //
12 
13 #if !defined( KRATOS_PARTITIONED_FSI_UTILITIES )
14 #define KRATOS_PARTITIONED_FSI_UTILITIES
15 
16 
17 /* System includes */
18 #include <set>
19 #include <typeinfo>
20 
21 /* External includes */
22 
23 /* Project includes */
24 #include "includes/define.h"
25 #include "includes/variables.h"
27 #include "includes/fsi_variables.h"
28 #include "containers/array_1d.h"
29 #include "includes/model_part.h"
30 #include "includes/communicator.h"
33 #include "utilities/math_utils.h"
35 #include "utilities/openmp_utils.h"
37 
38 
39 namespace Kratos
40 {
41 
65 template<class TSpace, class TValueType, unsigned int TDim>
67 {
68 
69 public:
70 
75  typedef typename TSpace::VectorType VectorType;
76  typedef typename TSpace::MatrixType MatrixType;
77 
78  typedef typename TSpace::VectorPointerType VectorPointerType;
79  typedef typename TSpace::MatrixPointerType MatrixPointerType;
80 
81  //~ /** Counted pointer of ClassName */
92 
96 
99  virtual ~PartitionedFSIUtilities() = default;
100 
113  const ModelPart &rOriginInterfaceModelPart,
114  ModelPart &rDestinationInterfaceModelPart)
115  {
116  // Check the origin interface model part
117  const auto& r_communicator = rOriginInterfaceModelPart.GetCommunicator();
118  KRATOS_ERROR_IF(r_communicator.GlobalNumberOfNodes() == 0) << "Origin model part has no nodes." << std::endl;
119  KRATOS_ERROR_IF(r_communicator.GlobalNumberOfConditions() == 0) << "Origin model part has no conditions." << std::endl;
120 
121  // Check the destination interface model part
122  KRATOS_ERROR_IF(rDestinationInterfaceModelPart.IsSubModelPart()) << "Destination model part must be a root model part." << std::endl;
123  KRATOS_ERROR_IF(rDestinationInterfaceModelPart.NumberOfNodes() != 0) << "Destination interface model part should be empty. Current number of nodes: " << rDestinationInterfaceModelPart.NumberOfNodes() << std::endl;
124  KRATOS_ERROR_IF(rDestinationInterfaceModelPart.NumberOfElements() != 0) << "Destination interface model part should be empty. Current number of elements: " << rDestinationInterfaceModelPart.NumberOfElements() << std::endl;
125  KRATOS_ERROR_IF(rDestinationInterfaceModelPart.NumberOfConditions() != 0) << "Destination interface model part should be empty. Current number of conditions: " << rDestinationInterfaceModelPart.NumberOfConditions() << std::endl;
126 
127  // Emulate the origin interface nodes in the coupling skin
128  // Note that if the origin model part is MPI parallel we copy the PARTITION_INDEX to the coupling skin mesh
129  if (rOriginInterfaceModelPart.IsDistributed()) {
130  for (const auto &r_node : rOriginInterfaceModelPart.Nodes()) {
131  auto p_new_node = rDestinationInterfaceModelPart.CreateNewNode(r_node.Id(), r_node);
132  p_new_node->FastGetSolutionStepValue(PARTITION_INDEX) = r_node.FastGetSolutionStepValue(PARTITION_INDEX);
133  }
134  } else {
135  for (const auto &r_node : rOriginInterfaceModelPart.Nodes()) {
136  rDestinationInterfaceModelPart.CreateNewNode(r_node.Id(), r_node);
137  }
138  }
139 
140  // Create the new element based skin
141  for (const auto &r_cond: rOriginInterfaceModelPart.Conditions()) {
142  // Set the element nodes vector
143  std::vector<ModelPart::IndexType> nodes_vect;
144  for (const auto &r_node : r_cond.GetGeometry()) {
145  nodes_vect.push_back(r_node.Id());
146  }
147 
148  // Create the new condition element
149  rDestinationInterfaceModelPart.CreateNewCondition(this->GetSkinConditionName(), r_cond.Id(), nodes_vect, r_cond.pGetProperties());
150  }
151  }
152 
158  int GetInterfaceResidualSize(ModelPart& rInterfaceModelPart)
159  {
160  // Check the block size. 1 for double coupling variables an TDim for array type coupling variables
161  double A; // Fake double to check the type from
162  unsigned int block_size = typeid(TValueType).hash_code() == typeid(A).hash_code() ? 1 : TDim;
163  int local_number_of_nodes = (rInterfaceModelPart.GetCommunicator().LocalMesh().NumberOfNodes()) * block_size;
164  return rInterfaceModelPart.GetCommunicator().GetDataCommunicator().SumAll(local_number_of_nodes);
165  }
166 
172  double GetInterfaceArea(ModelPart& rInterfaceModelPart)
173  {
174  double interface_area = 0.0;
175 
176  auto& rLocalMesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
177  ModelPart::ConditionIterator local_mesh_conditions_begin = rLocalMesh.ConditionsBegin();
178  #pragma omp parallel for firstprivate(local_mesh_conditions_begin) reduction(+:interface_area)
179  for(int k=0; k < static_cast<int>(rLocalMesh.NumberOfConditions()); ++k) {
180  const ModelPart::ConditionIterator it_cond = local_mesh_conditions_begin+k;
181  const Condition::GeometryType& rGeom = it_cond->GetGeometry();
182  interface_area += rGeom.Length();
183  }
184 
185  return rInterfaceModelPart.GetCommunicator().GetDataCommunicator().SumAll(interface_area);
186  }
187 
194  virtual VectorPointerType SetUpInterfaceVector(ModelPart& rInterfaceModelPart)
195  {
197  const unsigned int residual_size = this->GetInterfaceResidualSize(rInterfaceModelPart);
198  if (TSpace::Size(*p_int_vector) != residual_size){
199  TSpace::Resize(p_int_vector, residual_size);
200  }
201  TSpace::SetToZero(*p_int_vector);
202  return p_int_vector;
203  }
204 
212  const ModelPart& rInterfaceModelPart,
213  const Variable<TValueType> &rOriginVariable,
214  VectorType &rInterfaceVector)
215  {
216  auto &r_local_mesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
217  auto nodes_begin = r_local_mesh.NodesBegin();
218  #pragma omp parallel for firstprivate(nodes_begin)
219  for (int i_node = 0; i_node < static_cast<int>(r_local_mesh.NumberOfNodes()); ++i_node) {
220  auto it_node = nodes_begin + i_node;
221  const auto &r_value = it_node->FastGetSolutionStepValue(rOriginVariable);
222  this->AuxSetLocalValue(rInterfaceVector, r_value, i_node);
223  }
224  }
225 
241  ModelPart &rInterfaceModelPart,
242  const Variable<TValueType> &rOriginalVariable,
243  const Variable<TValueType> &rModifiedVariable,
244  const Variable<TValueType> &rResidualVariable,
245  VectorType &rInterfaceResidual,
246  const std::string ResidualType = "nodal",
247  const Variable<double> &rResidualNormVariable = FSI_INTERFACE_RESIDUAL_NORM)
248  {
249  TSpace::SetToZero(rInterfaceResidual);
250 
251  // Call compute the provided variables residual
252  if (ResidualType == "nodal") {
253  // Compute node-by-node residual
254  this->ComputeNodeByNodeResidual(rInterfaceModelPart, rOriginalVariable, rModifiedVariable, rResidualVariable);
255  } else if (ResidualType == "consistent") {
256  // Compute consitent residual
257  this->ComputeConsistentResidual(rInterfaceModelPart, rOriginalVariable, rModifiedVariable, rResidualVariable);
258  } else {
259  KRATOS_ERROR << "Provided interface residual type " << ResidualType << " is not available. Available options are \"nodal\" and \"consistent\"" << std::endl;
260  }
261 
262  // Assemble the final consistent residual values
263  auto& rLocalMesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
264  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
265  #pragma omp parallel for firstprivate(local_mesh_nodes_begin)
266  for(int k = 0; k < static_cast<int>(rLocalMesh.NumberOfNodes()); ++k) {
267  const ModelPart::NodeIterator it_node = local_mesh_nodes_begin+k;
268  const auto &r_res_value = it_node->FastGetSolutionStepValue(rResidualVariable);
269  this->AuxSetLocalValue(rInterfaceResidual, r_res_value, k);
270  }
271 
272  // Store the L2 norm of the error in the fluid process info
273  rInterfaceModelPart.GetProcessInfo().GetValue(rResidualNormVariable) = TSpace::TwoNorm(rInterfaceResidual);
274  }
275 
288  ModelPart &rInterfaceModelPart,
289  const Variable<TValueType> &rOriginalVariable,
290  const Variable<TValueType> &rModifiedVariable,
291  const Variable<TValueType> &rResidualVariable,
292  const std::string ResidualType = "nodal")
293  {
294  // Set an auxiliar interface vector
295  VectorPointerType p_interface_residual = this->SetUpInterfaceVector(rInterfaceModelPart);
296 
297  // Call compute the provided variables residual
298  if (ResidualType == "nodal") {
299  // Compute node-by-node residual
300  this->ComputeNodeByNodeResidual(rInterfaceModelPart, rOriginalVariable, rModifiedVariable, rResidualVariable);
301  } else if (ResidualType == "consistent") {
302  // Compute consitent residual
303  this->ComputeConsistentResidual(rInterfaceModelPart, rOriginalVariable, rModifiedVariable, rResidualVariable);
304  } else {
305  KRATOS_ERROR << "Provided interface residual type " << ResidualType << " is not available. Available options are \"nodal\" and \"consistent\"" << std::endl;
306  }
307 
308  // Assemble the final consistent residual values
309  auto &rLocalMesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
310  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
311  #pragma omp parallel for firstprivate(local_mesh_nodes_begin)
312  for(int k=0; k<static_cast<int>(rLocalMesh.NumberOfNodes()); ++k) {
313  const ModelPart::NodeIterator it_node = local_mesh_nodes_begin + k;
314  const auto &r_res_value = it_node->FastGetSolutionStepValue(rResidualVariable);
315  this->AuxSetLocalValue(*p_interface_residual, r_res_value, k);
316  }
317 
318  // Return the L2 norm of the error in the fluid process info
319  return TSpace::TwoNorm(*p_interface_residual);
320  }
321 
329  virtual void AuxSetLocalValue(
330  VectorType &rInterfaceResidual,
331  const double &rResidualValue,
332  const int AuxPosition)
333  {
334  this->SetLocalValue(rInterfaceResidual, AuxPosition, rResidualValue);
335  }
336 
346  virtual void AuxSetLocalValue(
347  VectorType &rInterfaceResidual,
348  const array_1d<double,3> &rResidualValue,
349  const int AuxPosition)
350  {
351  const unsigned int base_i = AuxPosition * TDim;
352  for (unsigned int jj = 0; jj < TDim; ++jj) {
353  this->SetLocalValue(rInterfaceResidual, base_i + jj, rResidualValue[jj]);
354  }
355  }
356 
363  virtual void UpdateInterfaceValues(
364  ModelPart &rInterfaceModelPart,
365  const Variable<TValueType> &rSolutionVariable,
366  const VectorType &rCorrectedGuess)
367  {
368  auto& rLocalMesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
369  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
370  #pragma omp parallel for firstprivate(local_mesh_nodes_begin)
371  for(int k = 0; k < static_cast<int>(rLocalMesh.NumberOfNodes()); ++k){
372  const ModelPart::NodeIterator it_node = local_mesh_nodes_begin + k;
373  TValueType &r_updated_value = it_node->FastGetSolutionStepValue(rSolutionVariable);
374  this->UpdateInterfaceLocalValue(rCorrectedGuess, r_updated_value, k);
375  }
376 
377  rInterfaceModelPart.GetCommunicator().SynchronizeVariable(rSolutionVariable);
378  }
379 
389  const VectorType &rCorrectedGuess,
390  double &rValueToUpdate,
391  const int AuxPosition)
392  {
393  rValueToUpdate = this->GetLocalValue(rCorrectedGuess, AuxPosition);
394  }
395 
405  const VectorType &rCorrectedGuess,
406  array_1d<double, 3> &rValueToUpdate,
407  const int AuxPosition)
408  {
409  const int base_i = AuxPosition * TDim;
410  for (unsigned int jj = 0; jj < TDim; ++jj){
411  rValueToUpdate[jj] = this->GetLocalValue(rCorrectedGuess, base_i + jj);
412  }
413  }
414 
419  virtual void ComputeAndPrintFluidInterfaceNorms(ModelPart& rInterfaceModelPart)
420  {
421  double p_norm = 0.0;
422  double vx_norm = 0.0;
423  double vy_norm = 0.0;
424  double vz_norm = 0.0;
425  double rx_norm = 0.0;
426  double ry_norm = 0.0;
427  double rz_norm = 0.0;
428  double ux_mesh_norm = 0.0;
429  double uy_mesh_norm = 0.0;
430  double uz_mesh_norm = 0.0;
431 
432  auto& rLocalMesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
433  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
434  #pragma omp parallel for firstprivate(local_mesh_nodes_begin) reduction(+ : p_norm, vx_norm, vy_norm, vz_norm, rx_norm, ry_norm, rz_norm, ux_mesh_norm, uy_mesh_norm, uz_mesh_norm)
435  for(int k=0; k<static_cast<int>(rLocalMesh.NumberOfNodes()); ++k)
436  {
437  const ModelPart::NodeIterator it_node = local_mesh_nodes_begin+k;
438 
439  p_norm += std::pow(it_node->FastGetSolutionStepValue(PRESSURE), 2);
440  vx_norm += std::pow(it_node->FastGetSolutionStepValue(VELOCITY_X), 2);
441  vy_norm += std::pow(it_node->FastGetSolutionStepValue(VELOCITY_Y), 2);
442  vz_norm += std::pow(it_node->FastGetSolutionStepValue(VELOCITY_Z), 2);
443  rx_norm += std::pow(it_node->FastGetSolutionStepValue(REACTION_X), 2);
444  ry_norm += std::pow(it_node->FastGetSolutionStepValue(REACTION_Y), 2);
445  rz_norm += std::pow(it_node->FastGetSolutionStepValue(REACTION_Z), 2);
446  ux_mesh_norm += std::pow(it_node->FastGetSolutionStepValue(MESH_DISPLACEMENT_X), 2);
447  uy_mesh_norm += std::pow(it_node->FastGetSolutionStepValue(MESH_DISPLACEMENT_Y), 2);
448  uz_mesh_norm += std::pow(it_node->FastGetSolutionStepValue(MESH_DISPLACEMENT_Z), 2);
449  }
450 
451  std::vector<double> local_data{p_norm, vx_norm, vy_norm, vz_norm, rx_norm, ry_norm, rz_norm, ux_mesh_norm, uy_mesh_norm, uz_mesh_norm};
452  std::vector<double> global_sum{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
453  rInterfaceModelPart.GetCommunicator().GetDataCommunicator().SumAll(local_data, global_sum);
454 
455  p_norm = global_sum[0];
456  vx_norm = global_sum[1];
457  vy_norm = global_sum[2];
458  vz_norm = global_sum[3];
459  rx_norm = global_sum[4];
460  ry_norm = global_sum[5];
461  rz_norm = global_sum[6];
462  ux_mesh_norm = global_sum[7];
463  uy_mesh_norm = global_sum[8];
464  uz_mesh_norm = global_sum[9];
465 
466  if (rInterfaceModelPart.GetCommunicator().MyPID() == 0)
467  {
468  std::cout << " " << std::endl;
469  std::cout << "|p_norm| = " << std::sqrt(p_norm) << std::endl;
470  std::cout << "|vx_norm| = " << std::sqrt(vx_norm) << std::endl;
471  std::cout << "|vy_norm| = " << std::sqrt(vy_norm) << std::endl;
472  std::cout << "|vz_norm| = " << std::sqrt(vz_norm) << std::endl;
473  std::cout << "|rx_norm| = " << std::sqrt(rx_norm) << std::endl;
474  std::cout << "|ry_norm| = " << std::sqrt(ry_norm) << std::endl;
475  std::cout << "|rz_norm| = " << std::sqrt(rz_norm) << std::endl;
476  std::cout << "|ux_mesh_norm| = " << std::sqrt(ux_mesh_norm) << std::endl;
477  std::cout << "|uy_mesh_norm| = " << std::sqrt(uy_mesh_norm) << std::endl;
478  std::cout << "|uz_mesh_norm| = " << std::sqrt(uz_mesh_norm) << std::endl;
479  std::cout << " " << std::endl;
480  }
481  }
482 
487  virtual void ComputeAndPrintStructureInterfaceNorms(ModelPart& rInterfaceModelPart)
488  {
489  double ux_norm = 0.0;
490  double uy_norm = 0.0;
491  double uz_norm = 0.0;
492 
493  auto& rLocalMesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
494  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
495  #pragma omp parallel for firstprivate(local_mesh_nodes_begin) reduction(+ : ux_norm, uy_norm, uz_norm)
496  for(int k=0; k<static_cast<int>(rLocalMesh.NumberOfNodes()); ++k)
497  {
498  const ModelPart::NodeIterator it_node = local_mesh_nodes_begin+k;
499  const array_1d<double, 3>& disp = it_node->FastGetSolutionStepValue(DISPLACEMENT);
500 
501  ux_norm += std::pow(disp[0], 2);
502  uy_norm += std::pow(disp[1], 2);
503  uz_norm += std::pow(disp[2], 2);
504  }
505 
506  std::vector<double> local_data{ux_norm, uy_norm, uz_norm};
507  std::vector<double> global_sum{0, 0, 0};
508  rInterfaceModelPart.GetCommunicator().GetDataCommunicator().SumAll(local_data, global_sum);
509 
510  ux_norm = global_sum[0];
511  uy_norm = global_sum[1];
512  uz_norm = global_sum[2];
513 
514  if (rInterfaceModelPart.GetCommunicator().MyPID() == 0)
515  {
516  std::cout << " " << std::endl;
517  std::cout << "|ux_norm| = " << std::sqrt(ux_norm) << std::endl;
518  std::cout << "|uy_norm| = " << std::sqrt(uy_norm) << std::endl;
519  std::cout << "|uz_norm| = " << std::sqrt(uz_norm) << std::endl;
520  std::cout << " " << std::endl;
521  }
522  }
523 
528  virtual void CheckCurrentCoordinatesFluid(ModelPart& rModelPart, const double tolerance)
529  {
530  auto& rLocalMesh = rModelPart.GetCommunicator().LocalMesh();
531  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
532  #pragma omp parallel for firstprivate(local_mesh_nodes_begin)
533  for(int k=0; k<static_cast<int>(rLocalMesh.NumberOfNodes()); ++k)
534  {
535  const ModelPart::NodeIterator it_node = local_mesh_nodes_begin+k;
536  const array_1d<double, 3>& disp = it_node->FastGetSolutionStepValue(MESH_DISPLACEMENT);
537 
538  if (std::fabs(it_node->X() - (it_node->X0() + disp[0])) > tolerance)
539  {
540  KRATOS_ERROR << "Node " << it_node->Id() << " X != X0 + deltaX";
541  }
542  if (std::fabs(it_node->Y() - (it_node->Y0() + disp[1])) > tolerance)
543  {
544  KRATOS_ERROR << "Node " << it_node->Id() << " Y != Y0 + deltaY";
545  }
546  if (std::fabs(it_node->Z() - (it_node->Z0() + disp[2])) > tolerance)
547  {
548  KRATOS_ERROR << "Node " << it_node->Id() << " Z != Z0 + deltaZ";
549  }
550  }
551  }
552 
557  virtual void CheckCurrentCoordinatesStructure(ModelPart& rModelPart, const double tolerance)
558  {
559  auto& rLocalMesh = rModelPart.GetCommunicator().LocalMesh();
560  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
561  #pragma omp parallel for firstprivate(local_mesh_nodes_begin)
562  for(int k=0; k<static_cast<int>(rLocalMesh.NumberOfNodes()); ++k)
563  {
564  const ModelPart::NodeIterator it_node = local_mesh_nodes_begin+k;
565  const array_1d<double, 3>& disp = it_node->FastGetSolutionStepValue(DISPLACEMENT);
566 
567  if (std::fabs(it_node->X() - (it_node->X0() + disp[0])) > tolerance)
568  {
569  KRATOS_ERROR << "Node " << it_node->Id() << " X != X0 + deltaX";
570  }
571  if (std::fabs(it_node->Y() - (it_node->Y0() + disp[1])) > tolerance)
572  {
573  KRATOS_ERROR << "Node " << it_node->Id() << " Y != Y0 + deltaY";
574  }
575  if (std::fabs(it_node->Z() - (it_node->Z0() + disp[2])) > tolerance)
576  {
577  KRATOS_ERROR << "Node " << it_node->Id() << " Z != Z0 + deltaZ";
578  }
579  }
580  }
581 
591  ModelPart &rFluidModelPart,
592  ModelPart &rStructureSkinModelPart)
593  {
594  // Create the bin-based point locator
595  BinBasedFastPointLocator<TDim> bin_based_locator(rFluidModelPart);
596 
597  // Update the search database
598  bin_based_locator.UpdateSearchDatabase();
599 
600  // For each structure skin node interpolate the pressure value from the fluid background mesh
601  Vector N;
602  Element::Pointer p_elem = nullptr;
603  #pragma omp parallel for firstprivate(N, p_elem)
604  for (int i_node = 0; i_node < static_cast<int>(rStructureSkinModelPart.NumberOfNodes()); ++i_node) {
605  auto it_node = rStructureSkinModelPart.NodesBegin() + i_node;
606  const bool found = bin_based_locator.FindPointOnMeshSimplified(it_node->Coordinates(), N, p_elem);
607  // If the structure skin is found, interpolate the POSITIVE_FACE_PRESSURE from the PRESSURE
608  if (found) {
609  const auto &r_geom = p_elem->GetGeometry();
610  double &r_pres = it_node->FastGetSolutionStepValue(POSITIVE_FACE_PRESSURE);
611  r_pres = 0.0;
612  for (unsigned int i_node = 0; i_node < r_geom.PointsNumber(); ++i_node) {
613  r_pres += N[i_node] * r_geom[i_node].FastGetSolutionStepValue(PRESSURE);
614  }
615  }
616  }
617  }
618 
620  ModelPart& rModelPart,
621  const Variable<double>& rPressureVariable,
622  const Variable<array_1d<double,3>>& rTractionVariable,
623  const bool SwapTractionSign)
624  {
625  // Update the nodal normals
626  NormalCalculationUtils().CalculateOnSimplex(rModelPart);
627 
628  // Set the nodal traction modulus calculation function
629  std::function<double(const double, const array_1d<double,3>)> traction_modulus_func;
630  if (SwapTractionSign) {
631  traction_modulus_func = [](const double PosPressure, const array_1d<double,3>& rNormal){return - PosPressure / norm_2(rNormal);};
632  } else {
633  traction_modulus_func = [](const double PosPressure, const array_1d<double,3>& rNormal){return PosPressure / norm_2(rNormal);};
634  }
635 
636  // Calculate the tractions from the pressure values
637  block_for_each(rModelPart.Nodes(), [&](Node& rNode){
638  const array_1d<double,3>& r_normal = rNode.FastGetSolutionStepValue(NORMAL);
639  const double p_pos = rNode.FastGetSolutionStepValue(rPressureVariable);
640  noalias(rNode.FastGetSolutionStepValue(rTractionVariable)) = traction_modulus_func(p_pos, r_normal) * r_normal;
641  });
642 
643  // Synchronize values among processes
644  rModelPart.GetCommunicator().SynchronizeVariable(rTractionVariable);
645  }
646 
648  ModelPart& rModelPart,
649  const Variable<double>& rPositivePressureVariable,
650  const Variable<double>& rNegativePressureVariable,
651  const Variable<array_1d<double,3>>& rTractionVariable,
652  const bool SwapTractionSign)
653  {
654  // Update the nodal normals
655  NormalCalculationUtils().CalculateOnSimplex(rModelPart);
656 
657  // Set the nodal traction modulus calculation function
658  std::function<double(const double, const double, const array_1d<double,3>)> traction_modulus_func;
659  if (SwapTractionSign) {
660  traction_modulus_func = [](const double PosPressure, const double NegPressure, const array_1d<double,3>& rNormal){return (NegPressure - PosPressure) / norm_2(rNormal);};
661  } else {
662  traction_modulus_func = [](const double PosPressure, const double NegPressure, const array_1d<double,3>& rNormal){return (PosPressure - NegPressure) / norm_2(rNormal);};
663  }
664 
665  // Calculate the tractions from the pressure values
666  block_for_each(rModelPart.Nodes(), [&](Node& rNode){
667  const array_1d<double,3>& r_normal = rNode.FastGetSolutionStepValue(NORMAL);
668  const double p_pos = rNode.FastGetSolutionStepValue(rPositivePressureVariable);
669  const double p_neg = rNode.FastGetSolutionStepValue(rNegativePressureVariable);
670  noalias(rNode.FastGetSolutionStepValue(rTractionVariable)) = traction_modulus_func(p_pos, p_neg, r_normal) * r_normal;
671  });
672 
673  // Synchronize values among processes
674  rModelPart.GetCommunicator().SynchronizeVariable(rTractionVariable);
675  }
676 
678 protected:
700  std::string GetSkinElementName()
701  {
702  std::string element_name;
703  if constexpr (TDim == 2) {
704  element_name = "Element2D2N";
705  } else {
706  element_name = "Element3D3N";
707  }
708 
709  return element_name;
710  }
711 
717  std::string GetSkinConditionName()
718  {
719  if constexpr (TDim == 2) {
720  return "LineCondition2D2N";
721  } else {
722  return "SurfaceCondition3D3N";
723  }
724  }
725 
736  ModelPart& rInterfaceModelPart,
737  const Variable<TValueType>& rOriginalVariable,
738  const Variable<TValueType>& rModifiedVariable,
739  const Variable<TValueType>& rErrorStorageVariable)
740  {
741  // Initialize the interface residual variable
742  VariableUtils().SetVariable<TValueType>(rErrorStorageVariable, rErrorStorageVariable.Zero(), rInterfaceModelPart.Nodes());
743 
744  #pragma omp parallel for
745  for(int i_cond = 0; i_cond < static_cast<int>(rInterfaceModelPart.NumberOfConditions()); ++i_cond) {
746 
747  auto it_cond = rInterfaceModelPart.ConditionsBegin() + i_cond;
748 
749  auto& rGeom = it_cond->GetGeometry();
750  const unsigned int n_nodes = rGeom.PointsNumber();
751 
752  // Initialize auxiliar array to save the condition nodes consistent residual
753  std::vector<TValueType> cons_res_vect(n_nodes);
754  for (unsigned int i = 0; i < n_nodes; ++i) {
755  cons_res_vect[i] = rErrorStorageVariable.Zero();
756  }
757 
758  // Compute the consistent residual
759  const auto &r_int_pts = rGeom.IntegrationPoints(GeometryData::IntegrationMethod::GI_GAUSS_2);
760  const auto N_container = rGeom.ShapeFunctionsValues(GeometryData::IntegrationMethod::GI_GAUSS_2);
761  Vector jac_gauss;
762  rGeom.DeterminantOfJacobian(jac_gauss, GeometryData::IntegrationMethod::GI_GAUSS_2);
763 
764  for (unsigned int i_gauss = 0; i_gauss < r_int_pts.size(); ++i_gauss) {
765  // Compute condition Gauss pt. data
766  const Vector N_gauss = row(N_container, i_gauss);
767  const double w_gauss = jac_gauss[i_gauss] * r_int_pts[i_gauss].Weight();
768 
769  // Add the current Gauss pt. residual contribution
770  for (unsigned int i_node = 0; i_node < n_nodes; ++i_node) {
771  for (unsigned int j_node = 0; j_node < n_nodes; ++j_node) {
772  const double aux_val = w_gauss * N_gauss[i_node] * N_gauss[j_node];
773  const TValueType value = rGeom[j_node].FastGetSolutionStepValue(rOriginalVariable);
774  const TValueType value_projected = rGeom[j_node].FastGetSolutionStepValue(rModifiedVariable);
775  cons_res_vect[i_node] += aux_val * (value - value_projected);
776  }
777  }
778  }
779 
780  // Save the computed consistent residual values
781  for (unsigned int i_node = 0; i_node < n_nodes; ++i_node) {
782  rGeom[i_node].SetLock(); // So it is safe to write in the condition node in OpenMP
783  rGeom[i_node].FastGetSolutionStepValue(rErrorStorageVariable) += cons_res_vect[i_node];
784  rGeom[i_node].UnSetLock(); // Free the condition node for other threads
785  }
786 
787  // Synchronize the computed error values
788  rInterfaceModelPart.GetCommunicator().AssembleCurrentData(rErrorStorageVariable);
789  }
790  }
791 
801  ModelPart& rInterfaceModelPart,
802  const Variable<TValueType>& rOriginalVariable,
803  const Variable<TValueType>& rModifiedVariable,
804  const Variable<TValueType>& rErrorStorageVariable)
805  {
806  auto& rLocalMesh = rInterfaceModelPart.GetCommunicator().LocalMesh();
807  ModelPart::NodeIterator local_mesh_nodes_begin = rLocalMesh.NodesBegin();
808  #pragma omp parallel for firstprivate(local_mesh_nodes_begin)
809  for(int k = 0; k < static_cast<int>(rLocalMesh.NumberOfNodes()); ++k) {
810  ModelPart::NodeIterator it_node = local_mesh_nodes_begin+k;
811  auto &r_error_storage = it_node->FastGetSolutionStepValue(rErrorStorageVariable);
812  const auto &value_origin = it_node->FastGetSolutionStepValue(rOriginalVariable);
813  const auto &value_modified = it_node->FastGetSolutionStepValue(rModifiedVariable);
814  r_error_storage = value_modified - value_origin;
815  }
816  }
817 
818  virtual void SetLocalValue(VectorType& rVector, int LocalRow, double Value) const
819  {
820  TSpace::SetValue(rVector,LocalRow,Value);
821  }
822 
823  virtual double GetLocalValue(const VectorType& rVector, int LocalRow) const
824  {
825  return TSpace::GetValue(rVector,LocalRow);
826  }
827 
842 private:
843 
880 }; /* Class PartitionedFSIUtilities */
881 
890 } /* namespace Kratos.*/
891 
892 #endif /* KRATOS_PARTITIONED_FSI_UTILITIES defined */
This class is designed to allow the fast location of MANY points on the top of a 3D mesh.
Definition: binbased_fast_point_locator.h:68
void UpdateSearchDatabase()
Function to construct or update the search database.
Definition: binbased_fast_point_locator.h:139
virtual bool SynchronizeVariable(Variable< int > const &rThisVariable)
Definition: communicator.cpp:357
virtual const DataCommunicator & GetDataCommunicator() const
Definition: communicator.cpp:340
virtual bool AssembleCurrentData(Variable< int > const &ThisVariable)
Definition: communicator.cpp:502
MeshType & LocalMesh()
Returns the reference to the mesh storing all local entities.
Definition: communicator.cpp:245
virtual int MyPID() const
Definition: communicator.cpp:91
TDataType & GetValue(const Variable< TDataType > &rThisVariable)
Gets the value associated with a given variable.
Definition: data_value_container.h:268
Geometry base class.
Definition: geometry.h:71
virtual double Length() const
Definition: geometry.h:1332
SizeType NumberOfNodes() const
Definition: mesh.h:259
ConditionIterator ConditionsBegin()
Definition: mesh.h:671
NodeIterator NodesBegin()
Definition: mesh.h:326
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
NodeType::Pointer CreateNewNode(int Id, double x, double y, double z, VariablesList::Pointer pNewVariablesList, IndexType ThisIndex=0)
Definition: model_part.cpp:270
ConditionIterator ConditionsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1361
bool IsSubModelPart() const
Definition: model_part.h:1893
Communicator & GetCommunicator()
Definition: model_part.h:1821
NodeIterator NodesBegin(IndexType ThisIndex=0)
Definition: model_part.h:487
ConditionsContainerType & Conditions(IndexType ThisIndex=0)
Definition: model_part.h:1381
SizeType NumberOfElements(IndexType ThisIndex=0) const
Definition: model_part.h:1027
ProcessInfo & GetProcessInfo()
Definition: model_part.h:1746
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
ConditionType::Pointer CreateNewCondition(std::string ConditionName, IndexType Id, std::vector< IndexType > ConditionNodeIds, PropertiesType::Pointer pProperties, IndexType ThisIndex=0)
Creates new condition with a node ids list.
bool IsDistributed() const
Definition: model_part.h:1898
SizeType NumberOfConditions(IndexType ThisIndex=0) const
Definition: model_part.h:1218
SizeType NumberOfNodes(IndexType ThisIndex=0) const
Definition: model_part.h:341
MeshType::ConditionIterator ConditionIterator
Definition: model_part.h:189
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
This class defines the node.
Definition: node.h:65
Definition: partitioned_fsi_utilities.hpp:67
virtual void AuxSetLocalValue(VectorType &rInterfaceResidual, const array_1d< double, 3 > &rResidualValue, const int AuxPosition)
Auxiliar call to SetLocalValue for array type This method serves as an auxiliar call to the SetLocalV...
Definition: partitioned_fsi_utilities.hpp:346
TSpace::VectorPointerType VectorPointerType
Definition: partitioned_fsi_utilities.hpp:78
double ComputeInterfaceResidualNorm(ModelPart &rInterfaceModelPart, const Variable< TValueType > &rOriginalVariable, const Variable< TValueType > &rModifiedVariable, const Variable< TValueType > &rResidualVariable, const std::string ResidualType="nodal")
Computes the interface residual norm This method computes the interface residual norm....
Definition: partitioned_fsi_utilities.hpp:287
virtual void CheckCurrentCoordinatesStructure(ModelPart &rModelPart, const double tolerance)
Definition: partitioned_fsi_utilities.hpp:557
void CalculateTractionFromPressureValues(ModelPart &rModelPart, const Variable< double > &rPositivePressureVariable, const Variable< double > &rNegativePressureVariable, const Variable< array_1d< double, 3 >> &rTractionVariable, const bool SwapTractionSign)
Definition: partitioned_fsi_utilities.hpp:647
void UpdateInterfaceLocalValue(const VectorType &rCorrectedGuess, double &rValueToUpdate, const int AuxPosition)
Corrected guess local double value update This auxiliar method helps to update the nodal database usi...
Definition: partitioned_fsi_utilities.hpp:388
TSpace::VectorType VectorType
Definition: partitioned_fsi_utilities.hpp:75
virtual VectorPointerType SetUpInterfaceVector(ModelPart &rInterfaceModelPart)
Definition: partitioned_fsi_utilities.hpp:194
void InitializeInterfaceVector(const ModelPart &rInterfaceModelPart, const Variable< TValueType > &rOriginVariable, VectorType &rInterfaceVector)
Definition: partitioned_fsi_utilities.hpp:211
PartitionedFSIUtilities(const PartitionedFSIUtilities &Other)=delete
double GetInterfaceArea(ModelPart &rInterfaceModelPart)
Definition: partitioned_fsi_utilities.hpp:172
virtual void UpdateInterfaceValues(ModelPart &rInterfaceModelPart, const Variable< TValueType > &rSolutionVariable, const VectorType &rCorrectedGuess)
Definition: partitioned_fsi_utilities.hpp:363
void EmbeddedPressureToPositiveFacePressureInterpolator(ModelPart &rFluidModelPart, ModelPart &rStructureSkinModelPart)
Pressure to positive face pressure interpolator This method interpolates the pressure in the embedded...
Definition: partitioned_fsi_utilities.hpp:590
KRATOS_CLASS_POINTER_DEFINITION(PartitionedFSIUtilities)
virtual void ComputeAndPrintFluidInterfaceNorms(ModelPart &rInterfaceModelPart)
Definition: partitioned_fsi_utilities.hpp:419
std::string GetSkinElementName()
Get the skin element name Auxiliary method that returns the auxiliary embedded skin element type name...
Definition: partitioned_fsi_utilities.hpp:700
virtual void ComputeAndPrintStructureInterfaceNorms(ModelPart &rInterfaceModelPart)
Definition: partitioned_fsi_utilities.hpp:487
std::string GetSkinConditionName()
Get the skin condition name Auxiliary method that returns the auxiliary embedded skin condition type ...
Definition: partitioned_fsi_utilities.hpp:717
void UpdateInterfaceLocalValue(const VectorType &rCorrectedGuess, array_1d< double, 3 > &rValueToUpdate, const int AuxPosition)
Corrected guess local array value update This auxiliar method helps to update the nodal database usin...
Definition: partitioned_fsi_utilities.hpp:404
void ComputeNodeByNodeResidual(ModelPart &rInterfaceModelPart, const Variable< TValueType > &rOriginalVariable, const Variable< TValueType > &rModifiedVariable, const Variable< TValueType > &rErrorStorageVariable)
Definition: partitioned_fsi_utilities.hpp:800
virtual ~PartitionedFSIUtilities()=default
void CalculateTractionFromPressureValues(ModelPart &rModelPart, const Variable< double > &rPressureVariable, const Variable< array_1d< double, 3 >> &rTractionVariable, const bool SwapTractionSign)
Definition: partitioned_fsi_utilities.hpp:619
TSpace::MatrixType MatrixType
Definition: partitioned_fsi_utilities.hpp:76
virtual void AuxSetLocalValue(VectorType &rInterfaceResidual, const double &rResidualValue, const int AuxPosition)
Auxiliar call to SetLocalValue for double type This method serves as an auxiliar call to the SetLocal...
Definition: partitioned_fsi_utilities.hpp:329
virtual void CheckCurrentCoordinatesFluid(ModelPart &rModelPart, const double tolerance)
Definition: partitioned_fsi_utilities.hpp:528
void ComputeConsistentResidual(ModelPart &rInterfaceModelPart, const Variable< TValueType > &rOriginalVariable, const Variable< TValueType > &rModifiedVariable, const Variable< TValueType > &rErrorStorageVariable)
Definition: partitioned_fsi_utilities.hpp:735
void CreateCouplingSkin(const ModelPart &rOriginInterfaceModelPart, ModelPart &rDestinationInterfaceModelPart)
Create a coupling condition-based skin object This method creates an condition-based skin model part ...
Definition: partitioned_fsi_utilities.hpp:112
virtual double GetLocalValue(const VectorType &rVector, int LocalRow) const
Definition: partitioned_fsi_utilities.hpp:823
virtual void ComputeInterfaceResidualVector(ModelPart &rInterfaceModelPart, const Variable< TValueType > &rOriginalVariable, const Variable< TValueType > &rModifiedVariable, const Variable< TValueType > &rResidualVariable, VectorType &rInterfaceResidual, const std::string ResidualType="nodal", const Variable< double > &rResidualNormVariable=FSI_INTERFACE_RESIDUAL_NORM)
Compute array variable interface residual vector This function computes (and stores in a vector) the ...
Definition: partitioned_fsi_utilities.hpp:240
int GetInterfaceResidualSize(ModelPart &rInterfaceModelPart)
Definition: partitioned_fsi_utilities.hpp:158
TSpace::MatrixPointerType MatrixPointerType
Definition: partitioned_fsi_utilities.hpp:79
virtual void SetLocalValue(VectorType &rVector, int LocalRow, double Value) const
Definition: partitioned_fsi_utilities.hpp:818
PartitionedFSIUtilities()
Definition: partitioned_fsi_utilities.hpp:91
Variable class contains all information needed to store and retrive data from a data container.
Definition: variable.h:63
const TDataType & Zero() const
This method returns the zero value of the variable type.
Definition: variable.h:346
This class implements a set of auxiliar, already parallelized, methods to perform some common tasks r...
Definition: variable_utils.h:63
void SetVariable(const TVarType &rVariable, const TDataType &rValue, NodesContainerType &rNodes, const unsigned int Step=0)
Sets the nodal value of a scalar variable.
Definition: variable_utils.h:675
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
Vector VectorType
Definition: geometrical_transformation_utilities.h:56
Matrix MatrixType
Definition: geometrical_transformation_utilities.h:55
TSpaceType::VectorPointerType CreateEmptyVectorPointer(TSpaceType &dummy)
Definition: add_strategies_to_python.cpp:187
double TwoNorm(SparseSpaceType &dummy, SparseSpaceType::VectorType &x)
Definition: add_strategies_to_python.cpp:164
TSpaceType::IndexType Size(TSpaceType &dummy, typename TSpaceType::VectorType const &rV)
Definition: add_strategies_to_python.cpp:111
Parameters GetValue(Parameters &rParameters, const std::string &rEntry)
Definition: add_kratos_parameters_to_python.cpp:53
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
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
AMatrix::MatrixRow< const TExpressionType > row(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression, std::size_t RowIndex)
Definition: amatrix_interface.h:649
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
Tool to evaluate the normals on nodes based on the normals of a set of surface conditions.
def SetValue(entity, variable, value)
Definition: coupling_interface_data.py:256
w_gauss
Definition: generate_convection_diffusion_explicit_element.py:136
int n_nodes
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:15
int block_size
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:16
int k
Definition: quadrature.py:595
A
Definition: sensitivityMatrix.py:70
N
Definition: sensitivityMatrix.py:29
integer i
Definition: TensorModule.f:17