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.
calculate_contact_angle.h
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 author: Alex Jarauta
11 // Co-author : Elaf Mahrous
12 
13 
14 #if !defined(CALCULATE_CONTACT_ANGLE_INCLUDED )
15 #define CALCULATE_CONTACT_ANGLE_INCLUDED
16 
17 
18 
19 // System includes
20 #include <string>
21 #include <iostream>
22 #include <algorithm>
23 
24 // External includes
25 
26 
27 // Project includes
28 #include <pybind11/pybind11.h>
29 #include "includes/define.h"
30 #include "includes/define_python.h"
31 
32 #include "includes/model_part.h"
33 #include "includes/node.h"
34 #include "utilities/math_utils.h"
35 #include "utilities/geometry_utilities.h"
36 #include "processes/process.h"
37 #include "includes/condition.h"
38 #include "includes/element.h"
39 #include "ULF_application.h"
40 
41 
42 
43 namespace Kratos
44 {
45 
48 
52 
53 
57 
61 
65 
67 
74  : public Process
75  {
76  public:
77 
80 
83 
87 
90  {
91  }
92 
95  {
96  }
97 
98 
102 
103  // void operator()()
104  // {
105  // MergeParts();
106  // }
107 
108 
112 
113  void CalculateContactAngle2D(ModelPart& ThisModelPart)
114  {
115  KRATOS_TRY
116 
117  double theta = 0.0;
118  double pi = 3.14159265359;
119 
120 // ProcessInfo& CurrentProcessInfo = ThisModelPart.GetProcessInfo();
121 // double theta_s = CurrentProcessInfo[CONTACT_ANGLE_STATIC];
122 // double delta_t = CurrentProcessInfo[DELTA_TIME];
123 // double theta_adv = theta_s + 10.0;
124 // double theta_rec = theta_s - 10.0;
125 
126  for(ModelPart::NodesContainerType::iterator im = ThisModelPart.NodesBegin() ;
127  im != ThisModelPart.NodesEnd() ; im++)
128  {
129  //Find the neighbours of TRIPLE_POINT at the boundary
130  if ((im->FastGetSolutionStepValue(TRIPLE_POINT))*1000 != 0.0)
131  {
132  GlobalPointersVector< Node >& neighb = im->GetValue(NEIGHBOUR_NODES);
133  double x0 = im->X();
134  double y0 = im->Y();
135  double x1 = 0.0;
136  double y1 = 0.0;
137  double x2 = 0.0;
138  double y2 = 0.0;
139 // double vx1 = 0.0;
140  int neighnum = 0;
141  for (unsigned int i = 0; i < neighb.size(); i++)
142  {
143  if (neighb[i].FastGetSolutionStepValue(IS_BOUNDARY) != 0.0)
144  {
145 // if (neighnum == 0)
146  if (neighnum < 1e-15)
147  {
148  x1 = neighb[i].X();
149  y1 = neighb[i].Y();
150  }
151  if (neighnum == 1)
152  {
153  x2 = neighb[i].X();
154  y2 = neighb[i].Y();
155  }
156  neighnum++;
157 // if (neighb[i].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
158 // {
159 // vx1 = neighb[i].FastGetSolutionStepValue(VELOCITY_X);
160 // }
161  }
162  }
163 
164  //Obtain the vectors pointing from node 0 to node 1 (r10) and from 0 to 2 (r20)
167  r10[0] = x1 - x0;
168  r10[1] = y1 - y0;
169  r20[0] = x2 - x0;
170  r20[1] = y2 - y0;
171  double norm10 = sqrt(r10[0]*r10[0] + r10[1]*r10[1]);
172  double norm20 = sqrt(r20[0]*r20[0] + r20[1]*r20[1]);
173 
174  double costheta = (r10[0]*r20[0] + r10[1]*r20[1])/(norm10*norm20);
175  theta = acos(costheta)*180.0/pi;
176  im->FastGetSolutionStepValue(CONTACT_ANGLE) = theta;
177 
178 // if(theta > theta_adv || theta < theta_rec)
179 // {
180 // im->FastGetSolutionStepValue(DISPLACEMENT_X) = vx1*delta_t;
181 // }
182  }
183  else
184  im->FastGetSolutionStepValue(CONTACT_ANGLE) = 0.0;
185  }
186  /*
187  //Now we check that there are only TWO nodes with CONTACT_ANGLE != 0.0
188  int num_trip = 0;
189  double min_x = 0.0;
190  double max_x = 0.0;
191  for(ModelPart::NodesContainerType::iterator im = ThisModelPart.NodesBegin() ; im != ThisModelPart.NodesEnd() ; im++)
192  {
193  if (im->FastGetSolutionStepValue(CONTACT_ANGLE) != 0.0)
194  {
195  ++num_trip;
196  if (num_trip < 2)
197  {
198  min_x = im->X();
199  max_x = min_x;
200  }
201  }
202  }
203  if (num_trip > 2)
204  {
205  for(ModelPart::NodesContainerType::iterator im = ThisModelPart.NodesBegin() ; im != ThisModelPart.NodesEnd() ; im++)
206  {
207  if (im->FastGetSolutionStepValue(CONTACT_ANGLE) != 0.0)
208  {
209  if (im->X() < min_x) //left triple point
210  {
211  min_x = im->X();
212  }
213  if (im->X() > max_x) //right triple point
214  {
215  max_x = im->X();
216  }
217  }
218  }
219  //Now we have the coordinates of the true left and right triple points -> remove others
220  for(ModelPart::NodesContainerType::iterator im = ThisModelPart.NodesBegin() ; im != ThisModelPart.NodesEnd() ; im++)
221  {
222  if (im->FastGetSolutionStepValue(CONTACT_ANGLE) != 0.0)
223  {
224  if (im->X() > min_x && im->X() < max_x)
225  im->FastGetSolutionStepValue(CONTACT_ANGLE) = 0.0;
226  }
227  }
228  }
229  */
230 
231  KRATOS_CATCH("")
232  }
233 
234  void CalculateContactAngle3D(ModelPart& ThisModelPart)
235  {
236  KRATOS_TRY
237 
238  double theta = 0.0;
239  double pi = 3.14159265359;
240  double theta_eq = ThisModelPart.GetProcessInfo()[CONTACT_ANGLE_STATIC];
241  double theta_rad = theta_eq*pi/180.0;
242 
243  for(ModelPart::NodesContainerType::iterator im = ThisModelPart.NodesBegin() ; im != ThisModelPart.NodesEnd() ; im++)
244  {
245  if (im->FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
246  {
248  // For node i, you find all its neighbor conditions. This is a set of triangles (faces)
249  // around node i. Only faces with two IS_FREE_SURFACE nodes will be used to obtain contact angle
250  // For every face, cross product with the two adjacent nodes j and k gives the vector normal
251  // to the face -> ALWAYS do it such that this vector points outwards the domain:
252  // if (rij X rik) ยท NORMAL_GEOMETRIC < 0 -> vector is pointing inwards -> do rik X rij
254 
255  double xi = im->X();
256  double yi = im->Y();
257  double zi = im->Z();
258  double xj, yj, zj, xk, yk, zk;
259  xj = yj = zj = xk = yk = zk = 0.0;
260  int idx_j = 6;
261  int idx_k = 7;
262 
265  array_1d<double,3> cross_prod_ijk = ZeroVector(3);
266  array_1d<double,3> normal_geom = ZeroVector(3);
267  array_1d<double,3> normal_tp = ZeroVector(3);
268  normal_geom = im->FastGetSolutionStepValue(NORMAL_GEOMETRIC);
269  double dot_prod = 0.0;
270 
271  im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE) = ZeroVector(3);
274 
275  int neighnum_tp = 0;
276  int neighnum_caf = 0; //caf == contact angle face
277  int visited = 0;
278  double num_faces = 0.0;
279  GlobalPointersVector< Condition >& neighb_faces = im->GetValue(NEIGHBOUR_CONDITIONS);
280  //Loop over faces -> find faces that two IS_FREE_SURFACE nodes
281  for (unsigned int i = 0; i < neighb_faces.size(); i++)
282  {
283  neighnum_tp = 0;
284  neighnum_caf = 0;
285  visited = 0;
286  for (unsigned int k = 0; k < neighb_faces[i].GetGeometry().size(); k++)
287  {
288  neighnum_tp += neighb_faces[i].GetGeometry()[k].FastGetSolutionStepValue(TRIPLE_POINT);
289  neighnum_caf += neighb_faces[i].GetGeometry()[k].FastGetSolutionStepValue(IS_FREE_SURFACE);
290  }
291 
292  num_faces++;
293 
294  if (neighnum_caf == 2)
295  {
296 
297  for (unsigned int j = 0; j < neighb_faces[i].GetGeometry().size() ; j++)
298  {
299  if (neighb_faces[i].GetGeometry()[j].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
300  {
301 // if (visited == 0)
302  if (visited < 1e-15)
303  {
304  xj = neighb_faces[i].GetGeometry()[j].X();
305  yj = neighb_faces[i].GetGeometry()[j].Y();
306  zj = neighb_faces[i].GetGeometry()[j].Z();
307  idx_j = j;
308  }
309  else
310  {
311  xk = neighb_faces[i].GetGeometry()[j].X();
312  yk = neighb_faces[i].GetGeometry()[j].Y();
313  zk = neighb_faces[i].GetGeometry()[j].Z();
314  idx_k = j;
315  }
316  visited++;
317  }
318  }
319  }
320 
321  if (neighnum_caf == 1)
322  {
323  for (unsigned int j = 0; j < neighb_faces[i].GetGeometry().size() ; j++)
324  {
325  if (neighb_faces[i].GetGeometry()[j].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
326  {
327  xj = neighb_faces[i].GetGeometry()[j].X();
328  yj = neighb_faces[i].GetGeometry()[j].Y();
329  zj = neighb_faces[i].GetGeometry()[j].Z();
330  }
331  if (neighb_faces[i].GetGeometry()[j].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0 && neighb_faces[i].GetGeometry()[j].Id() != im->Id())
332  {
333  xk = neighb_faces[i].GetGeometry()[j].X();
334  yk = neighb_faces[i].GetGeometry()[j].Y();
335  zk = neighb_faces[i].GetGeometry()[j].Z();
336  }
337  }
338  }
339 
340  //Now we have neighbor nodes of considered face -> obtain normal vector
341  Vector3D(xi,yi,zi,xj,yj,zj,rij);
342  Vector3D(xi,yi,zi,xk,yk,zk,rik);
343  CrossProduct3D(rij, rik, cross_prod_ijk);
344  dot_prod = DotProduct3D(cross_prod_ijk,normal_geom);
345  if (dot_prod < 0.0)
346  CrossProduct3D(rik, rij, cross_prod_ijk);
347  //We add this vector to the normal_tp
348  normal_tp[0] += cross_prod_ijk[0];
349  normal_tp[1] += cross_prod_ijk[1];
350  normal_tp[2] += cross_prod_ijk[2];
351  //Finally, contact angle is obtained -> it is simply acos(dotproduct(cross_prod_ijk,(0,0,1))/norm(cross_prod_ijk))
352  NormalizeVec3D(cross_prod_ijk);
353  theta = acos(cross_prod_ijk[2])*180.0/pi;
354  im->FastGetSolutionStepValue(CONTACT_ANGLE) += theta;
355 
356  //Normal to the contact line
357  if (neighnum_caf == 1)
358  im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE) += rij;
359  if (neighnum_caf == 2)
360  im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE) += 0.5*(rij+rik);
361 
362  }
363  NormalizeVec3D(normal_tp);
364  im->FastGetSolutionStepValue(NORMAL_TRIPLE_POINT_X) = normal_tp[0];
365  im->FastGetSolutionStepValue(NORMAL_TRIPLE_POINT_Y) = normal_tp[1];
366  im->FastGetSolutionStepValue(NORMAL_TRIPLE_POINT_Z) = normal_tp[2];
367 
368  aux[0] = normal_tp[0];
369  aux[1] = normal_tp[1];
370  NormalizeVec2D(aux);
371  NormalizeVec3D(im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE));
372  temp = im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE);
373 
374  im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE_X) = cos(asin(temp[2]))*aux[0];
375  im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE_Y) = cos(asin(temp[2]))*aux[1];
376  NormalizeVec3D(im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE));
377 
378  if (num_faces != 0.0)
379  im->FastGetSolutionStepValue(CONTACT_ANGLE) /= num_faces;
380 
381  if((im->FastGetSolutionStepValue(CONTACT_ANGLE)) < 90.0)
382  {
383  im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE_X) *= -1.0;
384  im->FastGetSolutionStepValue(NORMAL_CONTACT_LINE_Y) *= -1.0;
385  }
386  }
387  }
388 
389  KRATOS_CATCH("")
390  }
391 
395 
396  void Vector2D(const double x0, const double y0, const double x1, const double y1, array_1d<double,2>& r01)
397  {
398  r01[0] = x1 - x0;
399  r01[1] = y1 - y0;
400  }
401  void Vector3D(const double x0, const double y0, const double z0,
402  const double x1, const double y1, const double z1, array_1d<double,3>& r01)
403  {
404  r01[0] = x1 - x0;
405  r01[1] = y1 - y0;
406  r01[2] = z1 - z0;
407  }
408 
409  double Norm2D(const array_1d<double,2>& a)
410  {
411  return sqrt(a[0]*a[0] + a[1]*a[1]);
412  }
413 
414  double Norm3D(const array_1d<double,3>& a)
415  {
416  return sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
417  }
418 
420  {
421  return (a[0]*b[0] + a[1]*b[1]);
422  }
423 
425  {
426  return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
427  }
428 
430  {
431  c[0] = a[1]*b[2] - a[2]*b[1];
432  c[1] = a[2]*b[0] - a[0]*b[2];
433  c[2] = a[0]*b[1] - a[1]*b[0];
434  }
435 
437  {
438  double norm = Norm2D(input);
439  if (norm != 0.0)
440  {
441  input[0] /= norm;
442  input[1] /= norm;
443  }
444  return input;
445  }
446 
448  {
449  double norm = Norm3D(input);
450  if (norm != 0.0)
451  {
452  input[0] /= norm;
453  input[1] /= norm;
454  input[2] /= norm;
455  }
456  }
457 
458 
459 
463 
464 
466 
467 protected:
470 
471 
475 
476 
480 
481 
485 
486 
490 
491 
495 
496 
500 
501 
503 
504 private:
507 
508 
512 
513 
517 
518 
522 
523 
527 
528 
532 
533 
537 
539 // CalculateContactAngle& operator=(CalculateContactAngle const& rOther);
540 
542 // CalculateContactAngle(CalculateContactAngle const& rOther);
543 
544 
546 
547 }; // Class CalculateContactAngle
548 
550 
553 
554 
558 
559 
561 inline std::istream& operator >> (std::istream& rIStream,
562  CalculateContactAngle& rThis);
563 
565 inline std::ostream& operator << (std::ostream& rOStream,
566  const CalculateContactAngle& rThis)
567 {
568  rThis.PrintInfo(rOStream);
569  rOStream << std::endl;
570  rThis.PrintData(rOStream);
571 
572  return rOStream;
573 }
575 
576 
577 
578 } // namespace Kratos.
579 
580 #endif // KRATOS_CREATE_INTERFACE_CONDITIONS_PROCESS_INCLUDED defined
581 
582 
Short class definition.
Definition: calculate_contact_angle.h:75
double DotProduct2D(const array_1d< double, 2 > &a, const array_1d< double, 2 > &b)
Definition: calculate_contact_angle.h:419
void CrossProduct3D(const array_1d< double, 3 > &a, const array_1d< double, 3 > &b, array_1d< double, 3 > &c)
Definition: calculate_contact_angle.h:429
double DotProduct3D(const array_1d< double, 3 > &a, const array_1d< double, 3 > &b)
Definition: calculate_contact_angle.h:424
void Vector3D(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, array_1d< double, 3 > &r01)
Definition: calculate_contact_angle.h:401
void CalculateContactAngle2D(ModelPart &ThisModelPart)
Definition: calculate_contact_angle.h:113
double Norm3D(const array_1d< double, 3 > &a)
Definition: calculate_contact_angle.h:414
void CalculateContactAngle3D(ModelPart &ThisModelPart)
Definition: calculate_contact_angle.h:234
array_1d< double, 2 > NormalizeVec2D(array_1d< double, 2 > &input)
Definition: calculate_contact_angle.h:436
double Norm2D(const array_1d< double, 2 > &a)
Definition: calculate_contact_angle.h:409
CalculateContactAngle()
Default constructor.
Definition: calculate_contact_angle.h:89
void NormalizeVec3D(array_1d< double, 3 > &input)
Definition: calculate_contact_angle.h:447
~CalculateContactAngle() override
Destructor.
Definition: calculate_contact_angle.h:94
KRATOS_CLASS_POINTER_DEFINITION(CalculateContactAngle)
Pointer definition of PushStructureProcess.
void Vector2D(const double x0, const double y0, const double x1, const double y1, array_1d< double, 2 > &r01)
AUXILIAR FUNCTIONS //////////////////////////////////////////////////////////////////////////////////...
Definition: calculate_contact_angle.h:396
This class is a vector which stores global pointers.
Definition: global_pointers_vector.h:61
size_type size() const
Definition: global_pointers_vector.h:307
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
NodeIterator NodesBegin(IndexType ThisIndex=0)
Definition: model_part.h:487
ProcessInfo & GetProcessInfo()
Definition: model_part.h:1746
NodeIterator NodesEnd(IndexType ThisIndex=0)
Definition: model_part.h:497
The base class for all processes in Kratos.
Definition: process.h:49
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: process.h:204
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: process.h:210
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
im
Definition: GenerateCN.py:100
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
input
Definition: generate_frictional_mortar_condition.py:435
x2
Definition: generate_frictional_mortar_condition.py:122
x1
Definition: generate_frictional_mortar_condition.py:121
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
float temp
Definition: rotating_cone.py:85
integer i
Definition: TensorModule.f:17
double precision, public pi
Definition: TensorModule.f:16
e
Definition: run_cpp_mpi_tests.py:31