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.
surface_tension.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: Jordi Cotela
11 // author : Alex Jarauta
12 //
13 
14 
15 
16 #if !defined(KRATOS_SURFACE_TENSION_H_INCLUDED)
17 #define KRATOS_SURFACE_TENSION_H_INCLUDED
18 
19 
20 // System includes
21 #include <string>
22 #include <iostream>
23 #include <fstream>
24 #include <vector>
25 #include <ctime>
26 #include <cstdlib>
27 #include <iomanip>
28 #include <cmath>
29 
30 
31 // External includes
32 // #include "boost/smart_ptr.hpp"
33 
34 
35 
36 // Project includes
37 #include <pybind11/pybind11.h>
38 #include "includes/define.h"
39 #include "includes/define_python.h"
40 
41 #include "containers/array_1d.h"
42 
43 #include "includes/checks.h"
44 #include "includes/define.h"
45 #include "includes/element.h"
47 #include "includes/serializer.h"
49 #include "includes/variables.h"
50 // #include "ULF_application_variables.h"
51 #include "includes/cfd_variables.h"
52 #include "utilities/geometry_utilities.h"
54 
55 namespace Kratos
56 {
57 
60 
63 
67 
71 
75 
79 
81 
88 template< unsigned int TDim,
89  unsigned int TNumNodes = TDim + 1 >
90 class SurfaceTension : public Element
91 {
92 public:
95 
98 
101 
103  typedef Node NodeType;
104 
110 
113 
116 
118 
120 
121  typedef std::size_t IndexType;
122 
123  typedef std::size_t SizeType;
124 
125  typedef std::vector<std::size_t> EquationIdVectorType;
126 
127  typedef std::vector< Dof<double>::Pointer > DofsVectorType;
128 
130 
133 
137 
138  //Constructors.
139 
141 
145  Element(NewId)
146  {}
147 
149 
153  SurfaceTension(IndexType NewId, const NodesArrayType& ThisNodes) :
154  Element(NewId, ThisNodes)
155  {}
156 
158 
162  SurfaceTension(IndexType NewId, GeometryType::Pointer pGeometry) :
163  Element(NewId, pGeometry)
164  {}
165 
167 
172  SurfaceTension(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties) :
173  Element(NewId, pGeometry, pProperties)
174  {}
175 
177  ~SurfaceTension() override
178  {}
179 
180 
184 
185 
189 
191 
198  Element::Pointer Create(IndexType NewId, NodesArrayType const& ThisNodes,
199  PropertiesType::Pointer pProperties) const override
200  {
201 
202  return Kratos::make_shared< SurfaceTension<TDim, TNumNodes> >(NewId, GetGeometry().Create(ThisNodes), pProperties);
203 
204  //return Element::Pointer(new SurfaceTension(NewId, GetGeometry().Create(ThisNodes), pProperties));
205  }
206 
207  Element::Pointer Create(IndexType NewId,
208  GeometryType::Pointer pGeom,
209  PropertiesType::Pointer pProperties) const override
210  {
211  return Kratos::make_shared< SurfaceTension<TDim, TNumNodes> >(NewId, pGeom, pProperties);
212  }
213 
215 
224  void CalculateLocalSystem(MatrixType& rLeftHandSideMatrix,
225  VectorType& rRightHandSideVector,
226  ProcessInfo& rCurrentProcessInfo) override
227  {
228  const unsigned int LocalSize = (TDim + 1) * TNumNodes;
229 
230  // Check sizes and initialize matrix
231  if (rLeftHandSideMatrix.size1() != LocalSize)
232  rLeftHandSideMatrix.resize(LocalSize, LocalSize, false);
233 
234  noalias(rLeftHandSideMatrix) = ZeroMatrix(LocalSize, LocalSize);
235 
236  // Calculate RHS
237  this->CalculateRightHandSide(rRightHandSideVector, rCurrentProcessInfo);
238  }
239 
241 
245  void CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix,
246  ProcessInfo& rCurrentProcessInfo) override
247  {
248  const unsigned int LocalSize = (TDim + 1) * TNumNodes;
249 
250  if (rLeftHandSideMatrix.size1() != LocalSize)
251  rLeftHandSideMatrix.resize(LocalSize, LocalSize, false);
252 
253  noalias(rLeftHandSideMatrix) = ZeroMatrix(LocalSize, LocalSize);
254  }
255 
257 
266  void CalculateRightHandSide(VectorType& rRightHandSideVector,
267  ProcessInfo& rCurrentProcessInfo) override
268  {
269  const unsigned int LocalSize = (TDim + 1) * TNumNodes;
270 
271  // Check sizes and initialize
272  if (rRightHandSideVector.size() != LocalSize)
273  rRightHandSideVector.resize(LocalSize, false);
274 
275  noalias(rRightHandSideVector) = ZeroVector(LocalSize);
276 
277  // Calculate this element's geometric parameters
278  double Area;
281  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
282 
283  // Calculate this element's fluid properties
284  double Density;
285  this->EvaluateInPoint(Density, DENSITY, N);
286 
287  // Calculate Momentum RHS contribution
288  this->AddMomentumRHS(rRightHandSideVector, Density, N, Area);
289 
290  // For OSS: Add projection of residuals to RHS
291  if (rCurrentProcessInfo[OSS_SWITCH] == 1)
292  {
293  array_1d<double, 3 > AdvVel;
294  this->GetAdvectiveVel(AdvVel, N);
295 
296  double ElemSize = this->ElementSize(Area);
297  double Viscosity = this->EffectiveViscosity(Density,N,DN_DX,ElemSize,rCurrentProcessInfo);
298 
299  // stabilization parameters
300  double TauOne, TauTwo;
301  this->CalculateTau(TauOne,TauTwo,AdvVel,ElemSize,Density,Viscosity,rCurrentProcessInfo);
302 
303  this->AddProjectionToRHS(rRightHandSideVector, AdvVel, Density, TauOne, TauTwo, N, DN_DX, Area,rCurrentProcessInfo[DELTA_TIME]);
304  }
305  }
306 
308 
315  void CalculateMassMatrix(MatrixType& rMassMatrix, ProcessInfo& rCurrentProcessInfo) override
316  {
317  const unsigned int LocalSize = (TDim + 1) * TNumNodes;
318 
319  // Resize and set to zero
320  if (rMassMatrix.size1() != LocalSize)
321  rMassMatrix.resize(LocalSize, LocalSize, false);
322 
323  rMassMatrix = ZeroMatrix(LocalSize, LocalSize);
324 
325  // Get the element's geometric parameters
326  double Area;
329  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
330 
331  // Calculate this element's fluid properties
332  double Density;
333  this->EvaluateInPoint(Density, DENSITY, N);
334 
335  // Add 'classical' mass matrix (lumped)
336  double Coeff = Density * Area / TNumNodes; //Optimize!
337  this->CalculateLumpedMassMatrix(rMassMatrix, Coeff);
338 
339  /* For ASGS: add dynamic stabilization terms.
340  These terms are not used in OSS, as they belong to the finite element
341  space and cancel out with their projections.
342  */
343  if (rCurrentProcessInfo[OSS_SWITCH] != 1)
344  {
345  double ElemSize = this->ElementSize(Area);
346  double Viscosity = this->EffectiveViscosity(Density,N,DN_DX,ElemSize,rCurrentProcessInfo);
347 
348  // Get Advective velocity
349  array_1d<double, 3 > AdvVel;
350  this->GetAdvectiveVel(AdvVel, N);
351 
352  // stabilization parameters
353  double TauOne, TauTwo;
354  this->CalculateTau(TauOne,TauTwo,AdvVel,ElemSize,Density,Viscosity,rCurrentProcessInfo);
355 
356  // Add dynamic stabilization terms ( all terms involving a delta(u) )
357  this->AddMassStabTerms(rMassMatrix, Density, AdvVel, TauOne, N, DN_DX, Area);
358  }
359  }
360 
362 
371  VectorType& rRightHandSideVector,
372  ProcessInfo& rCurrentProcessInfo) override
373  {
374  const unsigned int LocalSize = (TDim + 1) * TNumNodes;
375 
376  // Resize and set to zero the matrix
377  // Note that we don't clean the RHS because it will already contain body force (and stabilization) contributions
378  if (rDampingMatrix.size1() != LocalSize)
379  rDampingMatrix.resize(LocalSize, LocalSize, false);
380 
381  noalias(rDampingMatrix) = ZeroMatrix(LocalSize, LocalSize);
382 
383  // Get this element's geometric properties
384  double Area;
387  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
388 
389  // Calculate this element's fluid properties
390  double Density;
391  this->EvaluateInPoint(Density, DENSITY, N);
392 
393  double ElemSize = this->ElementSize(Area);
394  double Viscosity = this->EffectiveViscosity(Density,N,DN_DX,ElemSize,rCurrentProcessInfo);
395 
396  // Get Advective velocity
397  array_1d<double, 3 > AdvVel;
398  this->GetAdvectiveVel(AdvVel, N);
399 
400  // stabilization parameters
401  double TauOne, TauTwo;
402  this->CalculateTau(TauOne,TauTwo,AdvVel,ElemSize,Density,Viscosity,rCurrentProcessInfo);
403 
404  this->AddIntegrationPointVelocityContribution(rDampingMatrix, rRightHandSideVector, Density, Viscosity, AdvVel, TauOne, TauTwo, N, DN_DX, Area);
405 
406 
407 
408  // Surface tension contribution
409  int k = 0;
410  if constexpr (TDim < 3)
411  {
412  array_1d<double,3> node_indx;
413  node_indx[0] = 0.0;
414  node_indx[1] = 0.0;
415  node_indx[2] = 0.0;
416  int node_indx_wrong = 5;
417  for(unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
418  {
419  if(this->GetGeometry()[iNode].FastGetSolutionStepValue(MEAN_CURVATURE_2D) != 0.0)
420  k++;
421  if(this->GetGeometry()[iNode].FastGetSolutionStepValue(IS_BOUNDARY) < 0.1)
422  node_indx_wrong = iNode;
423  }
424  if(k > 2 && node_indx_wrong != 5)
425  {
426  this->GetGeometry()[node_indx_wrong].FastGetSolutionStepValue(MEAN_CURVATURE_2D) = 0.0;
427  }
428  k = 0;
429  for(unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
430  {
431  if(this->GetGeometry()[iNode].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0 || this->GetGeometry()[iNode].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
432  {
433  node_indx[k] = iNode;
434  k++;
435  }
436  }
437  if(k > 1)
438  this->ApplySurfaceTensionContribution(rDampingMatrix, rRightHandSideVector, node_indx, k, rCurrentProcessInfo);
439  }
440  else
441  {
442  array_1d<double,4> node_indx;
443  node_indx[0] = 0.0;
444  node_indx[1] = 0.0;
445  node_indx[2] = 0.0;
446  node_indx[3] = 0.0;
447  int node_indx_wrong = 5;
448  for(unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
449  {
450  if(this->GetGeometry()[iNode].FastGetSolutionStepValue(MEAN_CURVATURE_3D) != 0.0)
451  k++;
452  if(this->GetGeometry()[iNode].FastGetSolutionStepValue(IS_BOUNDARY) < 0.1)
453  node_indx_wrong = iNode;
454  }
455  if(k > 2 && node_indx_wrong != 5)
456  {
457  this->GetGeometry()[node_indx_wrong].FastGetSolutionStepValue(MEAN_CURVATURE_3D) = 0.0;
458  }
459  k = 0;
460  for(unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
461  {
462  if(this->GetGeometry()[iNode].FastGetSolutionStepValue(IS_FREE_SURFACE) > 0.999 || this->GetGeometry()[iNode].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
463  {
464  node_indx[k] = iNode;
465  k++;
466  }
467  }
468  if(k >= 3)
469  this->ApplySurfaceTensionContribution3D(rDampingMatrix, rRightHandSideVector, node_indx, k, rCurrentProcessInfo);
470  }
471 
472 
473  // Viscous stress
474  k = 0;
475  for(unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
476  {
477  if(this->GetGeometry()[iNode].FastGetSolutionStepValue(IS_WATER) == 0.0)
478  {
479  k++;
480  }
481  }
482  if constexpr (TDim < 3 && k > 2)
483  this->AddViscousStress2D();
484 
485  // Now calculate an additional contribution to the residual: r -= rDampingMatrix * (u,p)
486  VectorType U = ZeroVector(LocalSize);
487  int LocalIndex = 0;
488 
489  for (unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
490  {
491  array_1d< double, 3 > & rVel = this->GetGeometry()[iNode].FastGetSolutionStepValue(VELOCITY);
492  for (unsigned int d = 0; d < TDim; ++d) // Velocity Dofs
493  {
494  U[LocalIndex] = rVel[d];
495  ++LocalIndex;
496  }
497  U[LocalIndex] = this->GetGeometry()[iNode].FastGetSolutionStepValue(PRESSURE); // Pressure Dof
498  ++LocalIndex;
499  }
500 
501  noalias(rRightHandSideVector) -= prod(rDampingMatrix, U);
502  }
503 
504  void FinalizeNonLinearIteration(ProcessInfo& rCurrentProcessInfo) override
505  {
506  }
507 
509 
521  void Calculate(const Variable<double>& rVariable,
522  double& rOutput,
523  const ProcessInfo& rCurrentProcessInfo) override
524  {
525  if (rVariable == ERROR_RATIO)
526  {
527  rOutput = this->SubscaleErrorEstimate(rCurrentProcessInfo);
528  this->SetValue(ERROR_RATIO,rOutput);
529  }
530  else if (rVariable == NODAL_AREA)
531  {
532  // Get the element's geometric parameters
533  double Area;
536  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
537 
538  // Carefully write results to nodal variables, to avoid parallelism problems
539  for (unsigned int i = 0; i < TNumNodes; ++i)
540  {
541  this->GetGeometry()[i].SetLock(); // So it is safe to write in the node in OpenMP
542  this->GetGeometry()[i].FastGetSolutionStepValue(NODAL_AREA) += Area * N[i];
543  this->GetGeometry()[i].UnSetLock(); // Free the node for other threads
544  }
545  }
546  }
547 
549 
560  void Calculate(const Variable<array_1d<double, 3 > >& rVariable,
561  array_1d<double, 3 > & rOutput,
562  const ProcessInfo& rCurrentProcessInfo) override
563  {
564  if (rVariable == ADVPROJ) // Compute residual projections for OSS
565  {
566  // Get the element's geometric parameters
567  double Area;
570  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
571 
572  // Calculate this element's fluid properties
573  double Density;
574  this->EvaluateInPoint(Density, DENSITY, N);
575 
576  // Get Advective velocity
577  array_1d<double, 3 > AdvVel;
578  this->GetAdvectiveVel(AdvVel, N);
579 
580  // Output containers
581  array_1d< double, 3 > ElementalMomRes(3, 0.0);
582  double ElementalMassRes(0);
583 
584  this->AddProjectionResidualContribution(AdvVel, Density, ElementalMomRes, ElementalMassRes, N, DN_DX, Area);
585 
586  if (rCurrentProcessInfo[OSS_SWITCH] == 1)
587  {
588  // Carefully write results to nodal variables, to avoid parallelism problems
589  for (unsigned int i = 0; i < TNumNodes; ++i)
590  {
591  this->GetGeometry()[i].SetLock(); // So it is safe to write in the node in OpenMP
592  array_1d< double, 3 > & rAdvProj = this->GetGeometry()[i].FastGetSolutionStepValue(ADVPROJ);
593  for (unsigned int d = 0; d < TDim; ++d)
594  rAdvProj[d] += N[i] * ElementalMomRes[d];
595 
596  this->GetGeometry()[i].FastGetSolutionStepValue(DIVPROJ) += N[i] * ElementalMassRes;
597  this->GetGeometry()[i].FastGetSolutionStepValue(NODAL_AREA) += Area * N[i];
598  this->GetGeometry()[i].UnSetLock(); // Free the node for other threads
599  }
600  }
601 
603  rOutput = ElementalMomRes;
604  }
605  else if (rVariable == SUBSCALE_VELOCITY)
606  {
607  // Get the element's geometric parameters
608  double Area;
611  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
612 
613  // Calculate this element's fluid properties
614  double Density;
615  this->EvaluateInPoint(Density, DENSITY, N);
616 
617  // Get Advective velocity
618  array_1d<double, 3 > AdvVel;
619  this->GetAdvectiveVel(AdvVel, N);
620 
621  // Output containers
622  array_1d< double, 3 > ElementalMomRes(3,0.0);
623  double ElementalMassRes(0.0);
624 
625  this->AddProjectionResidualContribution(AdvVel, Density, ElementalMomRes, ElementalMassRes, N, DN_DX, Area);
626 
627  if (rCurrentProcessInfo[OSS_SWITCH] == 1)
628  {
629  /* Projections of the elemental residual are computed with
630  * Newton-Raphson iterations of type M(lumped) dx = ElemRes - M(consistent) * x
631  */
632  const double Weight = ConsistentMassCoef(Area); // Consistent mass matrix is Weigth * ( Ones(TNumNodes,TNumNodes) + Identity(TNumNodes,TNumNodes) )
633  // Carefully write results to nodal variables, to avoid parallelism problems
634  for (unsigned int i = 0; i < TNumNodes; ++i)
635  {
636  this->GetGeometry()[i].SetLock(); // So it is safe to write in the node in OpenMP
637 
638  // Add elemental residual to RHS
639  array_1d< double, 3 > & rMomRHS = this->GetGeometry()[i].GetValue(ADVPROJ);
640  double& rMassRHS = this->GetGeometry()[i].GetValue(DIVPROJ);
641  for (unsigned int d = 0; d < TDim; ++d)
642  rMomRHS[d] += N[i] * ElementalMomRes[d];
643 
644  rMassRHS += N[i] * ElementalMassRes;
645 
646  // Write nodal area
647  this->GetGeometry()[i].FastGetSolutionStepValue(NODAL_AREA) += Area * N[i];
648 
649  // Substract M(consistent)*x(i-1) from RHS
650  for(unsigned int j = 0; j < TNumNodes; ++j) // RHS -= Weigth * Ones(TNumNodes,TNumNodes) * x(i-1)
651  {
652  for(unsigned int d = 0; d < TDim; ++d)
653  rMomRHS[d] -= Weight * this->GetGeometry()[j].FastGetSolutionStepValue(ADVPROJ)[d];
654  rMassRHS -= Weight * this->GetGeometry()[j].FastGetSolutionStepValue(DIVPROJ);
655  }
656  for(unsigned int d = 0; d < TDim; ++d) // RHS -= Weigth * Identity(TNumNodes,TNumNodes) * x(i-1)
657  rMomRHS[d] -= Weight * this->GetGeometry()[i].FastGetSolutionStepValue(ADVPROJ)[d];
658  rMassRHS -= Weight * this->GetGeometry()[i].FastGetSolutionStepValue(DIVPROJ);
659 
660  this->GetGeometry()[i].UnSetLock(); // Free the node for other threads
661  }
662  }
663 
665  rOutput = ElementalMomRes;
666  }
667  }
668 
669  // The following methods have different implementations depending on TDim
671 
678  ProcessInfo& rCurrentProcessInfo) override;
679 
681 
685  void GetDofList(DofsVectorType& rElementalDofList,
686  ProcessInfo& rCurrentProcessInfo) override;
687 
689 
693  void GetFirstDerivativesVector(Vector& Values, int Step = 0) override;
694 
696 
700  void GetSecondDerivativesVector(Vector& Values, int Step = 0) override;
701 
703 
713  std::vector<array_1d<double, 3 > >& rOutput,
714  const ProcessInfo& rCurrentProcessInfo) override;
715 
717 
729  std::vector<double>& rValues,
730  const ProcessInfo& rCurrentProcessInfo) override
731  {
732  if (rVariable == TAUONE || rVariable == TAUTWO || rVariable == MU || rVariable == TAU)
733  {
734  double Area;
737  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
738 
739  array_1d<double, 3 > AdvVel;
740  this->GetAdvectiveVel(AdvVel, N);
741 
742  double Density;
743  this->EvaluateInPoint(Density,DENSITY,N);
744 
745  double ElemSize = this->ElementSize(Area);
746  double Viscosity = this->EffectiveViscosity(Density,N,DN_DX,ElemSize,rCurrentProcessInfo);
747 
748  // stabilization parameters
749  double TauOne, TauTwo;
750  this->CalculateTau(TauOne,TauTwo,AdvVel,ElemSize,Density,Viscosity,rCurrentProcessInfo);
751 
752 
753  rValues.resize(1, false);
754  if (rVariable == TAUONE)
755  {
756  rValues[0] = TauOne;
757  }
758  else if (rVariable == TAUTWO)
759  {
760  rValues[0] = TauTwo;
761  }
762  else if (rVariable == MU)
763  {
764  rValues[0] = Viscosity;
765  }
766  else if (rVariable == TAU)
767  {
768  double NormS = this->EquivalentStrainRate(DN_DX);
769  rValues[0] = Viscosity*NormS;
770  }
771  }
772  else if (rVariable == EQ_STRAIN_RATE)
773  {
774  double Area;
777  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
778 
779  rValues.resize(1, false);
780  rValues[0] = this->EquivalentStrainRate(DN_DX);
781  }
782  else if(rVariable == SUBSCALE_PRESSURE)
783  {
784  double Area;
787  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
788 
789  array_1d<double, 3 > AdvVel;
790  this->GetAdvectiveVel(AdvVel, N);
791 
792  double Density;
793  this->EvaluateInPoint(Density,DENSITY,N);
794 
795  double ElemSize = this->ElementSize(Area);
796  double Viscosity = this->EffectiveViscosity(Density,N,DN_DX,ElemSize,rCurrentProcessInfo);
797 
798  // stabilization parameters
799  double TauOne, TauTwo;
800  this->CalculateTau(TauOne,TauTwo,AdvVel,ElemSize,Density,Viscosity,rCurrentProcessInfo);
801 
802  double DivU = 0.0;
803  for(unsigned int i=0; i < TNumNodes; i++)
804  {
805  for(unsigned int d = 0; d < TDim; d++)
806  DivU -= DN_DX(i,d) * this->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY)[d];
807  }
808 
809  rValues.resize(1, false);
810  rValues[0] = TauTwo * DivU;
811  if(rCurrentProcessInfo[OSS_SWITCH]==1)
812  {
813  double Proj = 0.0;
814  for(unsigned int i=0; i < TNumNodes; i++)
815  {
816  Proj += N[i]*this->GetGeometry()[i].FastGetSolutionStepValue(DIVPROJ);
817  }
818  rValues[0] -= TauTwo*Proj;
819  }
820  }
821  else if (rVariable == NODAL_AREA && TDim == 3)
822  {
823  MatrixType J = ZeroMatrix(3,3);
824  const array_1d<double,3>& X0 = this->GetGeometry()[0].Coordinates();
825  const array_1d<double,3>& X1 = this->GetGeometry()[1].Coordinates();
826  const array_1d<double,3>& X2 = this->GetGeometry()[2].Coordinates();
827  const array_1d<double,3>& X3 = this->GetGeometry()[3].Coordinates();
828 
829  J(0,0) = X1[0]-X0[0];
830  J(0,1) = X2[0]-X0[0];
831  J(0,2) = X3[0]-X0[0];
832  J(1,0) = X1[1]-X0[1];
833  J(1,1) = X2[1]-X0[1];
834  J(1,2) = X3[1]-X0[1];
835  J(2,0) = X1[2]-X0[2];
836  J(2,1) = X2[2]-X0[2];
837  J(2,2) = X3[2]-X0[2];
838 
839  double DetJ = J(0,0)*( J(1,1)*J(2,2) - J(1,2)*J(2,1) ) + J(0,1)*( J(1,2)*J(2,0) - J(1,0)*J(2,2) ) + J(0,2)*( J(1,0)*J(2,1) - J(1,1)*J(2,0) );
840  rValues.resize(1, false);
841  rValues[0] = DetJ;
842  }
843  else if (rVariable == ERROR_RATIO)
844  {
845  rValues.resize(1,false);
846  rValues[0] = this->SubscaleErrorEstimate(rCurrentProcessInfo);
847  }
848  else // Default behaviour (returns elemental data)
849  {
850  rValues.resize(1, false);
851  /*
852  The cast is done to avoid modification of the element's data. Data modification
853  would happen if rVariable is not stored now (would initialize a pointer to &rVariable
854  with associated value of 0.0). This is catastrophic if the variable referenced
855  goes out of scope.
856  */
857  const SurfaceTension<TDim, TNumNodes>* const_this = static_cast<const SurfaceTension<TDim, TNumNodes>*> (this);
858  rValues[0] = const_this->GetValue(rVariable);
859  }
860  }
861 
864  std::vector<array_1d<double, 6 > >& rValues,
865  const ProcessInfo& rCurrentProcessInfo) override
866  {}
867 
870  std::vector<Vector>& rValues,
871  const ProcessInfo& rCurrentProcessInfo) override
872  {}
873 
876  std::vector<Matrix>& rValues,
877  const ProcessInfo& rCurrentProcessInfo) override
878  {}
879 
883 
887 
889 
897  int Check(const ProcessInfo& rCurrentProcessInfo) override
898  {
899  KRATOS_TRY
900 
901  // Perform basic element checks
902  int ErrorCode = Kratos::Element::Check(rCurrentProcessInfo);
903  if(ErrorCode != 0) return ErrorCode;
904 
905  // Additional variables, only required to print results:
906  // SUBSCALE_VELOCITY, SUBSCALE_PRESSURE, TAUONE, TAUTWO, MU, VORTICITY.
907 
908  // Checks on nodes
909 
910  // Check that the element's nodes contain all required SolutionStepData and Degrees of freedom
911  for(unsigned int i=0; i<this->GetGeometry().size(); ++i)
912  {
913  Node &rNode = this->GetGeometry()[i];
914  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(VELOCITY,rNode);
915  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(PRESSURE,rNode);
916  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(MESH_VELOCITY,rNode);
917  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(ACCELERATION,rNode);
919  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(VISCOSITY,rNode);
920  KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(BODY_FORCE,rNode);
921  // Not checking OSS related variables NODAL_AREA, ADVPROJ, DIVPROJ, which are only required as SolutionStepData if OSS_SWITCH == 1
922 
923  KRATOS_CHECK_DOF_IN_NODE(VELOCITY_X,rNode);
924  KRATOS_CHECK_DOF_IN_NODE(VELOCITY_Y,rNode);
925  if constexpr (TDim == 3) KRATOS_CHECK_DOF_IN_NODE(VELOCITY_Z,rNode);
926  KRATOS_CHECK_DOF_IN_NODE(PRESSURE,rNode);
927  }
928  // Not checking OSS related variables NODAL_AREA, ADVPROJ, DIVPROJ, which are only required as SolutionStepData if OSS_SWITCH == 1
929 
930  // If this is a 2D problem, check that nodes are in XY plane
931  if (this->GetGeometry().WorkingSpaceDimension() == 2)
932  {
933  for (unsigned int i=0; i<this->GetGeometry().size(); ++i)
934  {
935  if (this->GetGeometry()[i].Z() != 0.0)
936  KRATOS_ERROR << "Node " << this->GetGeometry()[i].Id() << "has non-zero Z coordinate." << std::endl; }
937  }
938 
939  return 0;
940 
941  KRATOS_CATCH("");
942  }
943 
947 
948 
952 
954  std::string Info() const override
955  {
956  std::stringstream buffer;
957  buffer << "SurfaceTension #" << Id();
958  return buffer.str();
959  }
960 
962  void PrintInfo(std::ostream& rOStream) const override
963  {
964  rOStream << "SurfaceTension" << TDim << "D";
965  }
966 
967 // /// Print object's data.
968 // virtual void PrintData(std::ostream& rOStream) const;
969 
973 
974 
976 
977 protected:
980 
981 
985 
986 
990 
991 
995 
997 
1009  virtual void CalculateTau(double& TauOne,
1010  double& TauTwo,
1011  const array_1d< double, 3 > & rAdvVel,
1012  const double ElemSize,
1013  const double Density,
1014  const double Viscosity,
1015  const ProcessInfo& rCurrentProcessInfo)
1016  {
1017  // Compute mean advective velocity norm
1018  double AdvVelNorm = 0.0;
1019  for (unsigned int d = 0; d < TDim; ++d)
1020  AdvVelNorm += rAdvVel[d] * rAdvVel[d];
1021 
1022  AdvVelNorm = sqrt(AdvVelNorm);
1023 
1024  double InvTau = Density * ( rCurrentProcessInfo[DYNAMIC_TAU] / rCurrentProcessInfo[DELTA_TIME] + 2.0*AdvVelNorm / ElemSize ) + 4.0*Viscosity/ (ElemSize * ElemSize);
1025  TauOne = 1.0 / InvTau;
1026  TauTwo = Viscosity + 0.5 * Density * ElemSize * AdvVelNorm;
1027  }
1028 
1030 
1040  virtual void CalculateStaticTau(double& TauOne,
1041  const array_1d< double, 3 > & rAdvVel,
1042  const double ElemSize,
1043  const double Density,
1044  const double Viscosity)
1045  {
1046  // Compute mean advective velocity norm
1047  double AdvVelNorm = 0.0;
1048  for (unsigned int d = 0; d < TDim; ++d)
1049  AdvVelNorm += rAdvVel[d] * rAdvVel[d];
1050 
1051  AdvVelNorm = sqrt(AdvVelNorm);
1052 
1053  double InvTau = 2.0*Density*AdvVelNorm / ElemSize + 4.0*Viscosity/ (ElemSize * ElemSize);
1054  TauOne = 1.0 / InvTau;
1055  }
1056 
1058  virtual void AddMomentumRHS(VectorType& F,
1059  const double Density,
1060  const array_1d<double, TNumNodes>& rShapeFunc,
1061  const double Weight)
1062  {
1063  double Coef = Density * Weight;
1064 
1065  array_1d<double, 3 > BodyForce(3, 0.0);
1066  this->EvaluateInPoint(BodyForce, BODY_FORCE, rShapeFunc);
1067 
1068  // Add the results to the velocity components (Local Dofs are vx, vy, [vz,] p for each node)
1069  int LocalIndex = 0;
1070 
1071  for (unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
1072  {
1073  for (unsigned int d = 0; d < TDim; ++d)
1074  {
1075  F[LocalIndex++] += Coef * rShapeFunc[iNode] * BodyForce[d];
1076  }
1077  ++LocalIndex; // Skip pressure Dof
1078  }
1079  }
1080 
1082  virtual void AddProjectionToRHS(VectorType& RHS,
1083  const array_1d<double, 3 > & rAdvVel,
1084  const double Density,
1085  const double TauOne,
1086  const double TauTwo,
1087  const array_1d<double, TNumNodes>& rShapeFunc,
1088  const BoundedMatrix<double, TNumNodes, TDim>& rShapeDeriv,
1089  const double Weight,
1090  const double DeltaTime = 1.0)
1091  {
1092  const unsigned int BlockSize = TDim + 1;
1093 
1095  this->GetConvectionOperator(AGradN, rAdvVel, rShapeDeriv); // Get a * grad(Ni)
1096 
1097  array_1d<double,3> MomProj(3,0.0);
1098  double DivProj = 0.0;
1099  this->EvaluateInPoint(MomProj,ADVPROJ,rShapeFunc);
1100  this->EvaluateInPoint(DivProj,DIVPROJ,rShapeFunc);
1101 
1102  MomProj *= TauOne;
1103  DivProj *= TauTwo;
1104 
1105  unsigned int FirstRow = 0;
1106 
1107  for (unsigned int i = 0; i < TNumNodes; i++)
1108  {
1109  for (unsigned int d = 0; d < TDim; d++)
1110  {
1111  RHS[FirstRow+d] -= Weight * (Density * AGradN[i] * MomProj[d] + rShapeDeriv(i,d) * DivProj); // TauOne * ( a * Grad(v) ) * MomProjection + TauTwo * Div(v) * MassProjection
1112  RHS[FirstRow+TDim] -= Weight * rShapeDeriv(i,d) * MomProj[d]; // TauOne * Grad(q) * MomProjection
1113  }
1114  FirstRow += BlockSize;
1115  }
1116  }
1117 
1119 
1126  const double Mass)
1127  {
1128  unsigned int DofIndex = 0;
1129  for (unsigned int iNode = 0; iNode < TNumNodes; ++iNode)
1130  {
1131  for (unsigned int d = 0; d < TDim; ++d)
1132  {
1133  rLHSMatrix(DofIndex, DofIndex) += Mass;
1134  ++DofIndex;
1135  }
1136  ++DofIndex; // Skip pressure Dof
1137  }
1138  }
1139 
1141  const array_1d<double,TNumNodes>& rShapeFunc,
1142  const double Density,
1143  const double Weight)
1144  {
1145  const unsigned int BlockSize = TDim + 1;
1146 
1147  double Coef = Density * Weight;
1148  unsigned int FirstRow(0), FirstCol(0);
1149  double K; // Temporary results
1150 
1151  // Note: Dof order is (vx,vy,[vz,]p) for each node
1152  for (unsigned int i = 0; i < TNumNodes; ++i)
1153  {
1154  // Loop over columns
1155  for (unsigned int j = 0; j < TNumNodes; ++j)
1156  {
1157  // Delta(u) * TauOne * [ AdvVel * Grad(v) ] in velocity block
1158  K = Coef * rShapeFunc[i] * rShapeFunc[j];
1159 
1160  for (unsigned int d = 0; d < TDim; ++d) // iterate over dimensions for velocity Dofs in this node combination
1161  {
1162  rLHSMatrix(FirstRow + d, FirstCol + d) += K;
1163  }
1164  // Update column index
1165  FirstCol += BlockSize;
1166  }
1167  // Update matrix indices
1168  FirstRow += BlockSize;
1169  FirstCol = 0;
1170  }
1171  }
1172 
1173 
1175 
1187  void AddMassStabTerms(MatrixType& rLHSMatrix,
1188  const double Density,
1189  const array_1d<double, 3 > & rAdvVel,
1190  const double TauOne,
1191  const array_1d<double, TNumNodes>& rShapeFunc,
1192  const BoundedMatrix<double, TNumNodes, TDim>& rShapeDeriv,
1193  const double Weight)
1194  {
1195  const unsigned int BlockSize = TDim + 1;
1196 
1197  double Coef = Weight * TauOne;
1198  unsigned int FirstRow(0), FirstCol(0);
1199  double K; // Temporary results
1200 
1201  // If we want to use more than one Gauss point to integrate the convective term, this has to be evaluated once per integration point
1203  this->GetConvectionOperator(AGradN, rAdvVel, rShapeDeriv); // Get a * grad(Ni)
1204 
1205  // Note: Dof order is (vx,vy,[vz,]p) for each node
1206  for (unsigned int i = 0; i < TNumNodes; ++i)
1207  {
1208  // Loop over columns
1209  for (unsigned int j = 0; j < TNumNodes; ++j)
1210  {
1211  // Delta(u) * TauOne * [ AdvVel * Grad(v) ] in velocity block
1212  K = Coef * Density * AGradN[i] * Density * rShapeFunc[j];
1213 
1214  for (unsigned int d = 0; d < TDim; ++d) // iterate over dimensions for velocity Dofs in this node combination
1215  {
1216  rLHSMatrix(FirstRow + d, FirstCol + d) += K;
1217  // Delta(u) * TauOne * Grad(q) in q * Div(u) block
1218  rLHSMatrix(FirstRow + TDim, FirstCol + d) += Coef * Density * rShapeDeriv(i, d) * rShapeFunc[j];
1219  }
1220  // Update column index
1221  FirstCol += BlockSize;
1222  }
1223  // Update matrix indices
1224  FirstRow += BlockSize;
1225  FirstCol = 0;
1226  }
1227  }
1228 
1231  VectorType& rDampRHS,
1232  const double Density,
1233  const double Viscosity,
1234  const array_1d< double, 3 > & rAdvVel,
1235  const double TauOne,
1236  const double TauTwo,
1237  const array_1d< double, TNumNodes >& rShapeFunc,
1238  const BoundedMatrix<double, TNumNodes, TDim >& rShapeDeriv,
1239  const double Weight)
1240  {
1241  const unsigned int BlockSize = TDim + 1;
1242 
1243  // If we want to use more than one Gauss point to integrate the convective term, this has to be evaluated once per integration point
1245  this->GetConvectionOperator(AGradN, rAdvVel, rShapeDeriv); // Get a * grad(Ni)
1246 
1247  // Build the local matrix and RHS
1248  unsigned int FirstRow(0), FirstCol(0); // position of the first term of the local matrix that corresponds to each node combination
1249  double K, G, PDivV, L, qF; // Temporary results
1250 
1251  array_1d<double,3> BodyForce(3,0.0);
1252  this->EvaluateInPoint(BodyForce,BODY_FORCE,rShapeFunc);
1253  BodyForce *= Density;
1254 
1255  for (unsigned int i = 0; i < TNumNodes; ++i) // iterate over rows
1256  {
1257  for (unsigned int j = 0; j < TNumNodes; ++j) // iterate over columns
1258  {
1259  // Calculate the part of the contributions that is constant for each node combination
1260 
1261  // Velocity block
1262  K = Density * rShapeFunc[i] * AGradN[j]; // Convective term: v * ( a * Grad(u) )
1263  //K = 0.5 * Density * (rShapeFunc[i] * AGradN[j] - AGradN[i] * rShapeFunc[j]); // Skew-symmetric convective term 1/2( v*grad(u)*u - grad(v) uu )
1264  K += TauOne * Density * AGradN[i] * Density * AGradN[j]; // Stabilization: (a * Grad(v)) * TauOne * (a * Grad(u))
1265  K *= Weight;
1266 
1267  // q-p stabilization block (reset result)
1268  L = 0;
1269 
1270  for (unsigned int m = 0; m < TDim; ++m) // iterate over v components (vx,vy[,vz])
1271  {
1272  // Velocity block
1273  //K += Weight * Viscosity * rShapeDeriv(i, m) * rShapeDeriv(j, m); // Diffusive term: Viscosity * Grad(v) * Grad(u)
1274 
1275  // v * Grad(p) block
1276  G = TauOne * Density * AGradN[i] * rShapeDeriv(j, m); // Stabilization: (a * Grad(v)) * TauOne * Grad(p)
1277  PDivV = rShapeDeriv(i, m) * rShapeFunc[j]; // Div(v) * p
1278 
1279  // Write v * Grad(p) component
1280  rDampingMatrix(FirstRow + m, FirstCol + TDim) += Weight * (G - PDivV);
1281  // Use symmetry to write the q * Div(u) component
1282  rDampingMatrix(FirstCol + TDim, FirstRow + m) += Weight * (G + PDivV);
1283 
1284  // q-p stabilization block
1285  L += rShapeDeriv(i, m) * rShapeDeriv(j, m); // Stabilization: Grad(q) * TauOne * Grad(p)
1286 
1287  for (unsigned int n = 0; n < TDim; ++n) // iterate over u components (ux,uy[,uz])
1288  {
1289  // Velocity block
1290  rDampingMatrix(FirstRow + m, FirstCol + n) += Weight * TauTwo * rShapeDeriv(i, m) * rShapeDeriv(j, n); // Stabilization: Div(v) * TauTwo * Div(u)
1291  }
1292 
1293  }
1294 
1295  // Write remaining terms to velocity block
1296  for (unsigned int d = 0; d < TDim; ++d)
1297  rDampingMatrix(FirstRow + d, FirstCol + d) += K;
1298 
1299  // Write q-p stabilization block
1300  rDampingMatrix(FirstRow + TDim, FirstCol + TDim) += Weight * TauOne * L;
1301 
1302 
1303  // Update reference column index for next iteration
1304  FirstCol += BlockSize;
1305  }
1306 
1307  // Operate on RHS
1308  qF = 0.0;
1309  for (unsigned int d = 0; d < TDim; ++d)
1310  {
1311  rDampRHS[FirstRow + d] += Weight * TauOne * Density * AGradN[i] * BodyForce[d]; // ( a * Grad(v) ) * TauOne * (Density * BodyForce)
1312  qF += rShapeDeriv(i, d) * BodyForce[d];
1313  }
1314  rDampRHS[FirstRow + TDim] += Weight * TauOne * qF; // Grad(q) * TauOne * (Density * BodyForce)
1315 
1316  // Update reference indices
1317  FirstRow += BlockSize;
1318  FirstCol = 0;
1319  }
1320 
1321 // this->AddBTransCB(rDampingMatrix,rShapeDeriv,Viscosity*Weight);
1322  this->AddViscousTerm(rDampingMatrix,rShapeDeriv,Viscosity*Weight);
1323  }
1324 
1325 
1326 
1328  // ApplySurfaceTensionContribution(rDampingMatrix, rRightHandSideVector, node_indx, rCurrentProcessInfo);
1329 
1330  void ApplySurfaceTensionContribution(MatrixType& rDampingMatrix, VectorType& rRightHandSideVector,
1331  const array_1d< double, 3 >& node_indx, const int& k, const ProcessInfo& rCurrentProcessInfo)
1332  {
1333  const double gamma = rCurrentProcessInfo[SURFACE_TENSION_COEF]; //surface tension coefficient between air and water [N m-1]
1334 
1335  //adding dissipative_forces varialbes
1336  double zeta_dissapative_JM = rCurrentProcessInfo[DISSIPATIVE_FORCE_COEFF_JM];
1337  double zeta_dissapative_BM = rCurrentProcessInfo[DISSIPATIVE_FORCE_COEFF_BM];
1338  double zeta_dissapative_SM = rCurrentProcessInfo[DISSIPATIVE_FORCE_COEFF_SM];
1339 // double gamma_sl = rCurrentProcessInfo[SOLID_LIQIUD_SURFTENS_COEFF];
1340 // double gamma_sv = rCurrentProcessInfo[SOLID_AIR_SURFTENS_COEFF];
1341 
1342  double dt = rCurrentProcessInfo[DELTA_TIME];
1343 
1344  double theta_s = rCurrentProcessInfo[CONTACT_ANGLE_STATIC];
1345  double pi = 3.14159265359;
1346  theta_s = theta_s*pi/180.0;
1347  double sin_t = sin(theta_s);
1348  double cos_t = cos(theta_s);
1349 
1351 
1352  //Clearing spurious curvatures:
1353  for(unsigned int i = 0; i < 3; i++){
1354  if((this->GetGeometry()[i].FastGetSolutionStepValue(IS_BOUNDARY) == 0.0) || (this->GetGeometry()[i].FastGetSolutionStepValue(IS_FREE_SURFACE) == 0.0))
1355  this->GetGeometry()[i].FastGetSolutionStepValue(MEAN_CURVATURE_2D) = 0.0;
1356  }
1357 
1358  //Flag counter to identify contact element:
1359  double flag_surf = 0.0;
1360  flag_surf += this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE);
1361  flag_surf += this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_FREE_SURFACE);
1362  flag_surf += this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(IS_FREE_SURFACE);
1363  double flag_trip = 0.0;
1364  flag_trip += (this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0);
1365  flag_trip += (this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0);
1366  flag_trip += (this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0);
1367  double flag_struct = 0.0;
1368  flag_struct += (this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_STRUCTURE) != 0.0);
1369  flag_struct += (this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_STRUCTURE) != 0.0);
1370  flag_struct += (this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(IS_STRUCTURE) != 0.0);
1371 
1372  int ii = 5;
1373  int jj = 6;
1374  int kk = 7;
1375  double avg_curv = 0.0;
1376 
1378  //Set the indexes as follows:
1379  // node "ii" -> triple point, if the element has one
1380  // node "jj" -> node with flag IS_FREE_SURFACE
1381  // node "kk" -> in elements with 3 nodes at the boundary:
1382  // - if "ii" is TRIPLE_POINT, "kk" has flag IS_STRUCTURE (besides IS_FREE_SURFACE)
1383  // - if there is no TRIPLE_POINT, "kk" is another IS_FREE_SURFACE node
1385  if(k < 3) //General element with two nodes at the interface
1386  {
1387  //Step to detect triple point. Node with index ii is TRIPLE_POINT, and node with index jj is IS_FREE_SURFACE
1388  ii = node_indx[0];
1389  jj = node_indx[1];
1390 
1391  if(flag_trip > 0 && (this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT))*1000 == 0.0)
1392 // if(flag_trip > 0 && (this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT)) < 1e-15)
1393  {
1394  ii = node_indx[1];
1395  jj = node_indx[0];
1396  }
1397  }
1398  else //Element with three nodes at the free surface OR one at free surface, one triple point and one at the structure
1399  {
1400  if(flag_trip == 0.0) //three nodes at interface
1401  {
1402  if(flag_struct == 0.0)
1403  {
1404  for(int i = 0; i < 3; i++)
1405  {
1406  avg_curv += 0.333333333333*(this->GetGeometry()[i].FastGetSolutionStepValue(MEAN_CURVATURE_2D));
1407  }
1408  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_2D) > avg_curv)
1409  {
1410  ii = node_indx[1];
1411  jj = node_indx[2];
1412  kk = node_indx[0];
1413  }
1414  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_2D) > avg_curv)
1415  {
1416  ii = node_indx[0];
1417  jj = node_indx[2];
1418  kk = node_indx[1];
1419  }
1420  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_2D) > avg_curv)
1421  {
1422  ii = node_indx[0];
1423  jj = node_indx[1];
1424  kk = node_indx[2];
1425  }
1426  }
1427  else //first time step, TRIPLE_POINT has not been set yet, but the element has a TRIPLE_POINT
1428  {
1429  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1430  {
1431  jj = node_indx[0];
1432  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_2D) > 1.0)
1433  {
1434  ii = node_indx[1]; //TRIPLE_POINT
1435  kk = node_indx[2]; //IS_STRUCTURE
1436  }
1437  else
1438  {
1439  ii = node_indx[2]; //TRIPLE_POINT
1440  kk = node_indx[1]; //IS_STRUCTURE
1441  }
1442  }
1443  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1444  {
1445  jj = node_indx[1];
1446  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_2D) > 1.0)
1447  {
1448  ii = node_indx[0]; //TRIPLE_POINT
1449  kk = node_indx[2]; //IS_STRUCTURE
1450  }
1451  else
1452  {
1453  ii = node_indx[2]; //TRIPLE_POINT
1454  kk = node_indx[0]; //IS_STRUCTURE
1455  }
1456  }
1457  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1458  {
1459  jj = node_indx[2];
1460  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_2D) > 1.0)
1461  {
1462  ii = node_indx[0]; //TRIPLE_POINT
1463  kk = node_indx[1]; //IS_STRUCTURE
1464  }
1465  else
1466  {
1467  ii = node_indx[1]; //TRIPLE_POINT
1468  kk = node_indx[0]; //IS_STRUCTURE
1469  }
1470  }
1471  }
1472  }
1473  else //Element has one node with TRIPLE_POINT
1474  {
1475  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
1476  {
1477  ii = node_indx[0];
1478  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1479  {
1480  jj = node_indx[1];
1481  kk = node_indx[2]; //IS_STRUCTURE
1482  }
1483  else
1484  {
1485  jj = node_indx[2];
1486  kk = node_indx[1]; //IS_STRUCTURE
1487  }
1488  }
1489  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
1490  {
1491  ii = node_indx[1];
1492  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1493  {
1494  jj = node_indx[0];
1495  kk = node_indx[2]; //IS_STRUCTURE
1496  }
1497  else
1498  {
1499  jj = node_indx[2];
1500  kk = node_indx[0]; //IS_STRUCTURE
1501  }
1502  }
1503  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
1504  {
1505  ii = node_indx[2];
1506  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1507  {
1508  jj = node_indx[0];
1509  kk = node_indx[1];
1510  }
1511  else
1512  {
1513  jj = node_indx[1];
1514  kk = node_indx[0];
1515  }
1516  }
1517  }
1518  }
1519 
1520  array_1d<double,2> An1;
1521  array_1d<double,2> An2;
1522  An1[0] = this->GetGeometry()[ii].FastGetSolutionStepValue(NORMAL_X);
1523  An1[1] = this->GetGeometry()[ii].FastGetSolutionStepValue(NORMAL_Y);
1524  double norm1 = sqrt(An1[0]*An1[0] + An1[1]*An1[1]);
1525  An1 /= norm1;
1526  An2[0] = this->GetGeometry()[jj].FastGetSolutionStepValue(NORMAL_X);
1527  An2[1] = this->GetGeometry()[jj].FastGetSolutionStepValue(NORMAL_Y);
1528  double norm2 = sqrt(An2[0]*An2[0] + An2[1]*An2[1]);
1529  An2 /= norm2;
1530 
1531  double x1 = this->GetGeometry()[ii].X();
1532  double y1 = this->GetGeometry()[ii].Y();
1533  double x2 = this->GetGeometry()[jj].X();
1534  double y2 = this->GetGeometry()[jj].Y();
1535  //vector x12 is the vector pointing from node 1 [ii] to node 2 [jj]
1536  array_1d<double,2> x12;
1537  x12[0] = x2 - x1;
1538  x12[1] = y2 - y1;
1539  double dl = sqrt(x12[0]*x12[0] + x12[1]*x12[1]);
1540  x12 /= dl;
1541 
1542  double curv1 = this->GetGeometry()[ii].FastGetSolutionStepValue(MEAN_CURVATURE_2D);
1543  double curv2 = this->GetGeometry()[jj].FastGetSolutionStepValue(MEAN_CURVATURE_2D);
1544 
1545  array_1d<double,2> norm_eq;
1546 
1547  //elemental variables for the laplacian
1548  BoundedMatrix<double,3,3> msWorkMatrix;
1549  msWorkMatrix = ZeroMatrix(3,3);
1550  BoundedMatrix<double,3,2> msDN_Dx;
1551  msDN_Dx = ZeroMatrix(3,2);
1552  array_1d<double,3> msN; //dimension = number of nodes
1553  msN = ZeroVector(3);
1554  double Area;
1555  GeometryUtils::CalculateGeometryData(this->GetGeometry(),msDN_Dx,msN,Area);
1556  // 3 by 3 matrix that stores the laplacian
1557  msWorkMatrix = 0.5 * gamma * dl * prod(msDN_Dx,trans(msDN_Dx)) * dt;
1558 
1559 
1560 
1561  if(flag_trip == 0)
1562  {
1563  if(this->GetGeometry()[ii].FastGetSolutionStepValue(IS_STRUCTURE) == 0.0)
1564  {
1565  //CSF:
1566  rRightHandSideVector[3*ii] -= 0.5*gamma*curv1*An1[0]*dl;
1567  rRightHandSideVector[3*ii+1] -= 0.5*gamma*curv1*An1[1]*dl;
1568 
1569  //Output force:
1570  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_X) = -gamma*curv1*An1[0]*dl;
1571  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_Y) = -gamma*curv1*An1[1]*dl;
1572  }
1573  }
1574  else
1575  {
1576  if (this->GetGeometry()[ii].FastGetSolutionStepValue(NORMAL_X) > 0.0)
1577  {
1578  m[0] = -cos_t;
1579  m[1] = sin_t;
1580  }
1581  else
1582  {
1583  m[0] = cos_t;
1584  m[1] = sin_t;
1585  }
1586  if(k < 3)
1587  {
1588 
1589  if (this->GetGeometry()[ii].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
1590  {
1591  double coef = 1.0;
1592  //MODEL 1 - contact angle condition with vector tangent to the surface:
1593  rRightHandSideVector[3*ii] -= coef*gamma*(m[0]-x12[0]);
1594  rRightHandSideVector[3*ii+1] -= coef*gamma*(m[1]-x12[1]);
1595  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_X) = -coef*gamma*(m[0] - x12[0]);
1596 
1597 // this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_Y) = -coef*gamma*(m[1] - x12[1]);
1598 
1599  //start of adding dissipative force: where v_clx here is the x_velocity at the contact line; and v_cly is the y_velocity at the contact line
1600  double v_clx = this->GetGeometry()[ii].FastGetSolutionStepValue(VELOCITY_X);
1601  double v_cly = this->GetGeometry()[ii].FastGetSolutionStepValue(VELOCITY_Y);
1602 //
1603  double mu;
1604  mu = this->GetGeometry()[ii].FastGetSolutionStepValue(VISCOSITY);
1605 
1606  //capillary
1607  double v_clx_abs = fabs (v_clx);
1608  double v_cly_abs = fabs (v_cly) ;
1609 
1610  double cap_x = mu * v_clx_abs / gamma;
1611  double cap_y = mu * v_cly_abs / gamma;
1612  // using Jiang's Model : gamma tanh(4.96 Ca^(0.702))
1613  rRightHandSideVector[3*ii] -= zeta_dissapative_JM*gamma*tanh(4.96 * pow(cap_x,0.702));
1614  rRightHandSideVector[3*ii+1] -= zeta_dissapative_JM*gamma*tanh(4.96 * pow(cap_y,0.702));
1615 //
1616 // // using Bracke's model : gamma 2.24 ca ^(0.54)
1617  rRightHandSideVector[3*ii] -= zeta_dissapative_BM*gamma* 2.24 * pow(cap_x,0.54);
1618  rRightHandSideVector[3*ii+1] -= zeta_dissapative_BM*gamma* 2.24 * pow(cap_y,0.54);
1619 //
1620 // // using Seeberg's model : gamm 2.24 ca ^(0.54) for Ca > 10^(-3), otherwise, 4.47 Ca^(0.42)
1621  double cap = sqrt((cap_x * cap_x) + (cap_y * cap_y));
1622  if (cap > 0.01)
1623  {
1624  rRightHandSideVector[3*ii] -= zeta_dissapative_SM*gamma* 2.24 * pow(cap_x,0.54);
1625  rRightHandSideVector[3*ii+1] -= zeta_dissapative_SM*gamma* 2.24 * pow(cap_y,0.54);
1626  }
1627  else
1628  {
1629  rRightHandSideVector[3*ii] -= zeta_dissapative_SM*gamma* 4.47 * pow(cap_x,0.42);
1630  rRightHandSideVector[3*ii+1] -= zeta_dissapative_SM*gamma* 4.47 * pow(cap_y,0.42);
1631  }
1632  // end of adding disppative force
1633 
1634  }
1635  else
1636  {
1637  this->GetGeometry()[ii].FastGetSolutionStepValue(VELOCITY_X) = 0.0;
1638  }
1639  }
1640  }
1641 
1642  //CSF:
1643  rRightHandSideVector[3*jj] -= 0.5*gamma*curv2*An2[0]*dl;
1644  rRightHandSideVector[3*jj+1] -= 0.5*gamma*curv2*An2[1]*dl;
1645 
1646  //Output force:
1647  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_X) = -gamma*curv2*An2[0]*dl;
1648  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_Y) = -gamma*curv2*An2[1]*dl;
1649 
1650  rDampingMatrix(3*ii,3*ii) += msWorkMatrix(ii,ii);
1651  rDampingMatrix(3*ii+1,3*ii+1) += msWorkMatrix(ii,ii);
1652 
1653  rDampingMatrix(3*ii,3*jj) += msWorkMatrix(ii,jj);
1654  rDampingMatrix(3*ii+1,3*jj+1) += msWorkMatrix(ii,jj);
1655 //
1656  rDampingMatrix(3*jj,3*ii) += msWorkMatrix(jj,ii);
1657  rDampingMatrix(3*jj+1,3*ii+1) += msWorkMatrix(jj,ii);
1658 
1659  rDampingMatrix(3*jj,3*jj) += msWorkMatrix(jj,jj);
1660  rDampingMatrix(3*jj+1,3*jj+1) += msWorkMatrix(jj,jj);
1661 
1662 
1663  if(k > 2 && this->GetGeometry()[kk].FastGetSolutionStepValue(IS_STRUCTURE) == 0.0)
1664  {
1665  array_1d<double,2> An3;
1666  An3[0] = this->GetGeometry()[kk].FastGetSolutionStepValue(NORMAL_X);
1667  An3[1] = this->GetGeometry()[kk].FastGetSolutionStepValue(NORMAL_Y);
1668  double norm3 = sqrt(An3[0]*An3[0] + An3[1]*An3[1]);
1669  An3 /= norm3;
1670  double curv3 = this->GetGeometry()[kk].FastGetSolutionStepValue(MEAN_CURVATURE_2D);
1671 
1672  double x3 = this->GetGeometry()[kk].X();
1673  double y3 = this->GetGeometry()[kk].Y();
1674  array_1d<double,2> x31;
1675  array_1d<double,2> x32;
1676  x31[0] = x1 - x3;
1677  x31[1] = y1 - y3;
1678  double dl1 = sqrt(x31[0]*x31[0] + x31[1]*x31[1]);
1679  x32[0] = x2 - x3;
1680  x32[1] = y2 - y3;
1681  double dl2 = sqrt(x32[0]*x32[0] + x32[1]*x32[1]);
1682  dl = dl1 + dl2;
1683 
1684  //CSF:
1685  rRightHandSideVector[3*kk] -= gamma*curv3*An3[0]*dl;
1686  rRightHandSideVector[3*kk+1] -= gamma*curv3*An3[1]*dl;
1687  msWorkMatrix = 1.0 * gamma * dl * prod(msDN_Dx,trans(msDN_Dx)) * dt;
1688 
1689 
1690 //
1691  rDampingMatrix(3*kk,3*kk) += msWorkMatrix(kk,kk);
1692  rDampingMatrix(3*kk+1,3*kk+1) += msWorkMatrix(kk,kk);
1693 
1694 
1695 
1696  }
1697 
1698  //Clean spurious force values
1699  for(unsigned int i = 0; i < 3; i++)
1700  {
1701  if(this->GetGeometry()[i].FastGetSolutionStepValue(IS_BOUNDARY) == 0.0)
1702  {
1703  this->GetGeometry()[i].FastGetSolutionStepValue(FORCE_X) = 0.0;
1704  this->GetGeometry()[i].FastGetSolutionStepValue(FORCE_Y) = 0.0;
1705  this->GetGeometry()[i].FastGetSolutionStepValue(FORCE_Z) = 0.0;
1706  }
1707  }
1708  }
1709 
1710 
1711  void ApplySurfaceTensionContribution3D(MatrixType& rDampingMatrix, VectorType& rRightHandSideVector,
1712  const array_1d< double, 4 >& node_indx, const int& k, const ProcessInfo& rCurrentProcessInfo)
1713  {
1714  double dt = rCurrentProcessInfo[DELTA_TIME];
1715  double gamma = rCurrentProcessInfo[SURFACE_TENSION_COEF];
1716  double theta_s = rCurrentProcessInfo[CONTACT_ANGLE_STATIC];
1717 
1718  //Flag counter to identify contact element:
1719  double flag_surf = 0.0;
1720  flag_surf += this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE);
1721  flag_surf += this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_FREE_SURFACE);
1722  flag_surf += this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(IS_FREE_SURFACE);
1723  flag_surf += this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(IS_FREE_SURFACE);
1724  double flag_trip = 0.0;
1725  flag_trip += (this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0);
1726  flag_trip += (this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0);
1727  flag_trip += (this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0);
1728  flag_trip += (this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0);
1729  double flag_struct = 0.0;
1730  flag_struct += (this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_STRUCTURE) != 0.0);
1731  flag_struct += (this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_STRUCTURE) != 0.0);
1732  flag_struct += (this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(IS_STRUCTURE) != 0.0);
1733  flag_struct += (this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(IS_STRUCTURE) != 0.0);
1734 
1735  int ii = 5;
1736  int jj = 6;
1737  int kk = 7;
1738  int ll = 8;
1739  double avg_curv = 0.0;
1740 
1742  //Set the indexes as follows:
1743  // node "ii" and "jj" -> triple point, if the element has (at least) two (those with one are not taken into account)
1744  // node "kk" -> node with flag either TRIPLE_POINT (corner element) or IS_FREE_SURFACE
1745  // node "ll" -> in elements with 4 nodes at the boundary:
1746  // - if "ii" and "jj" are TRIPLE_POINT, "ll" has flag IS_STRUCTURE (besides IS_FREE_SURFACE)
1747  // - if there is no TRIPLE_POINT, "ll" is another IS_FREE_SURFACE node
1749  if(k == 3) //General element with three nodes at the interface
1750  {
1751  //Step to detect triple point. Nodes with index ii and jj are TRIPLE_POINT, and node with index kk is IS_FREE_SURFACE
1752  ii = node_indx[0];
1753  jj = node_indx[1];
1754  kk = node_indx[2];
1755 
1756  if(flag_trip == 1)
1757  {
1758  if ((this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT))*1000 != 0.0)
1759 // if ((this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT)) < 1e-15)
1760  {
1761  ii = node_indx[1];
1762  jj = node_indx[0];
1763  }
1764  if ((this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT))*1000 != 0.0)
1765 // if ((this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT)) < 1e-15 )
1766  {
1767  ii = node_indx[2];
1768  kk = node_indx[0];
1769  }
1770  }
1771  if(flag_trip > 1)
1772  {
1773  if ((this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT))*1000 == 0.0)
1774 // if ((this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT)) < 1e-15 )
1775  {
1776  ii = node_indx[1];
1777  jj = node_indx[2];
1778  kk = node_indx[0];
1779  }
1780  if ((this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT))*1000 == 0.0)
1781 // if ((this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT)) < 1e-15 )
1782  {
1783  jj = node_indx[2];
1784  kk = node_indx[1];
1785  }
1786  }
1787  }
1788  else //Element with four nodes at the free surface OR one at free surface, two triple point and one at the structure OR one at free surface and three triple points
1789  {
1790  ii = node_indx[0];
1791  jj = node_indx[1];
1792  kk = node_indx[2];
1793  ll = node_indx[3];
1794  if(flag_trip == 0.0) //four nodes at interface
1795 // if(flag_trip < 1e-15)
1796  {
1797  if(flag_struct == 0.0) //four nodes that are free surface
1798 // if(flag_struct < 1e-15)
1799  {
1800  for(int i = 0; i < 4; i++)
1801  {
1802  avg_curv += 0.25*(this->GetGeometry()[i].FastGetSolutionStepValue(MEAN_CURVATURE_3D));
1803  }
1804  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > avg_curv)
1805  {
1806  ii = node_indx[0];
1807  jj = node_indx[1];
1808  kk = node_indx[2];
1809  ll = node_indx[3];
1810  }
1811  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > avg_curv)
1812  {
1813  ii = node_indx[1];
1814  jj = node_indx[0];
1815  kk = node_indx[2];
1816  ll = node_indx[3];
1817  }
1818  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > avg_curv)
1819  {
1820  ii = node_indx[2];
1821  jj = node_indx[0];
1822  kk = node_indx[1];
1823  ll = node_indx[3];
1824  }
1825  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > avg_curv)
1826  {
1827  ii = node_indx[3];
1828  jj = node_indx[0];
1829  kk = node_indx[1];
1830  ll = node_indx[2];
1831  }
1832  }
1833  else //first time step, TRIPLE_POINT has not been set yet, but the element has three IS_STRUCTURE nodes
1834  {
1835  //OPTION 1
1836  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1837  {
1838  kk = node_indx[0];
1839  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1840  {
1841  ii = node_indx[1]; //TRIPLE_POINT
1842  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1843  {
1844  jj = node_indx[2]; //TRIPLE_POINT
1845  ll = node_indx[3]; //IS_STRUCTURE
1846  }
1847  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1848  {
1849  jj = node_indx[3]; //TRIPLE_POINT
1850  ll = node_indx[2]; //IS_STRUCTURE
1851  }
1852  }
1853  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1854  {
1855  ii = node_indx[2]; //TRIPLE_POINT
1856  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1857  {
1858  jj = node_indx[1]; //TRIPLE_POINT
1859  ll = node_indx[3]; //IS_STRUCTURE
1860  }
1861  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1862  {
1863  jj = node_indx[3]; //TRIPLE_POINT
1864  ll = node_indx[1]; //IS_STRUCTURE
1865  }
1866  }
1867  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1868  {
1869  ii = node_indx[3]; //TRIPLE_POINT
1870  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1871  {
1872  jj = node_indx[1]; //TRIPLE_POINT
1873  ll = node_indx[2]; //IS_STRUCTURE
1874  }
1875  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1876  {
1877  jj = node_indx[2]; //TRIPLE_POINT
1878  ll = node_indx[1]; //IS_STRUCTURE
1879  }
1880  }
1881  }
1882 
1883  //OPTION 2
1884  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1885  {
1886  kk = node_indx[1];
1887  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1888  {
1889  ii = node_indx[0]; //TRIPLE_POINT
1890  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1891  {
1892  jj = node_indx[2]; //TRIPLE_POINT
1893  ll = node_indx[3]; //IS_STRUCTURE
1894  }
1895  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1896  {
1897  jj = node_indx[3]; //TRIPLE_POINT
1898  ll = node_indx[2]; //IS_STRUCTURE
1899  }
1900  }
1901  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1902  {
1903  ii = node_indx[2]; //TRIPLE_POINT
1904  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1905  {
1906  jj = node_indx[0]; //TRIPLE_POINT
1907  ll = node_indx[3]; //IS_STRUCTURE
1908  }
1909  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1910  {
1911  jj = node_indx[3]; //TRIPLE_POINT
1912  ll = node_indx[0]; //IS_STRUCTURE
1913  }
1914  }
1915  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1916  {
1917  ii = node_indx[3]; //TRIPLE_POINT
1918  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1919  {
1920  jj = node_indx[0]; //TRIPLE_POINT
1921  ll = node_indx[2]; //IS_STRUCTURE
1922  }
1923  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1924  {
1925  jj = node_indx[2]; //TRIPLE_POINT
1926  ll = node_indx[0]; //IS_STRUCTURE
1927  }
1928  }
1929  }
1930 
1931  //OPTION 3
1932  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1933  {
1934  kk = node_indx[2];
1935  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1936  {
1937  ii = node_indx[1]; //TRIPLE_POINT
1938  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1939  {
1940  jj = node_indx[0]; //TRIPLE_POINT
1941  ll = node_indx[3]; //IS_STRUCTURE
1942  }
1943  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1944  {
1945  jj = node_indx[3]; //TRIPLE_POINT
1946  ll = node_indx[0]; //IS_STRUCTURE
1947  }
1948  }
1949  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1950  {
1951  ii = node_indx[0]; //TRIPLE_POINT
1952  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1953  {
1954  jj = node_indx[1]; //TRIPLE_POINT
1955  ll = node_indx[3]; //IS_STRUCTURE
1956  }
1957  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1958  {
1959  jj = node_indx[3]; //TRIPLE_POINT
1960  ll = node_indx[1]; //IS_STRUCTURE
1961  }
1962  }
1963  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1964  {
1965  ii = node_indx[3]; //TRIPLE_POINT
1966  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1967  {
1968  jj = node_indx[1]; //TRIPLE_POINT
1969  ll = node_indx[0]; //IS_STRUCTURE
1970  }
1971  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1972  {
1973  jj = node_indx[0]; //TRIPLE_POINT
1974  ll = node_indx[1]; //IS_STRUCTURE
1975  }
1976  }
1977  }
1978 
1979  //OPTION 4
1980  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
1981  {
1982  kk = node_indx[3];
1983  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1984  {
1985  ii = node_indx[1]; //TRIPLE_POINT
1986  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1987  {
1988  jj = node_indx[2]; //TRIPLE_POINT
1989  ll = node_indx[0]; //IS_STRUCTURE
1990  }
1991  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1992  {
1993  jj = node_indx[0]; //TRIPLE_POINT
1994  ll = node_indx[2]; //IS_STRUCTURE
1995  }
1996  }
1997  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
1998  {
1999  ii = node_indx[2]; //TRIPLE_POINT
2000  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
2001  {
2002  jj = node_indx[1]; //TRIPLE_POINT
2003  ll = node_indx[0]; //IS_STRUCTURE
2004  }
2005  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
2006  {
2007  jj = node_indx[0]; //TRIPLE_POINT
2008  ll = node_indx[1]; //IS_STRUCTURE
2009  }
2010  }
2011  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
2012  {
2013  ii = node_indx[0]; //TRIPLE_POINT
2014  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
2015  {
2016  jj = node_indx[1]; //TRIPLE_POINT
2017  ll = node_indx[2]; //IS_STRUCTURE
2018  }
2019  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(MEAN_CURVATURE_3D) > 1.0)
2020  {
2021  jj = node_indx[2]; //TRIPLE_POINT
2022  ll = node_indx[1]; //IS_STRUCTURE
2023  }
2024  }
2025  }
2026 
2027  }
2028  }
2029  if (flag_trip == 2) //Element has two nodes with TRIPLE_POINT (those with one are not taken into accounts)
2030  {
2031  //OPTION 1
2032  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2033  {
2034  ii = node_indx[0];
2035  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2036  {
2037  jj = node_indx[1];
2038  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
2039  {
2040  kk = node_indx[2]; //IS_FREE_SURFACE
2041  ll = node_indx[3]; //IS_STRUCTURE
2042  }
2043  else
2044  {
2045  kk = node_indx[3]; //IS_FREE_SURFACE
2046  ll = node_indx[2]; //IS_STRUCTURE
2047  }
2048  }
2049  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2050  {
2051  jj = node_indx[2];
2052  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
2053  {
2054  kk = node_indx[1]; //IS_FREE_SURFACE
2055  ll = node_indx[3]; //IS_STRUCTURE
2056  }
2057  else
2058  {
2059  kk = node_indx[3]; //IS_FREE_SURFACE
2060  ll = node_indx[1]; //IS_STRUCTURE
2061  }
2062  }
2063  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2064  {
2065  jj = node_indx[3];
2066  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
2067  {
2068  kk = node_indx[1]; //IS_FREE_SURFACE
2069  ll = node_indx[2]; //IS_STRUCTURE
2070  }
2071  else
2072  {
2073  kk = node_indx[2]; //IS_FREE_SURFACE
2074  ll = node_indx[1]; //IS_STRUCTURE
2075  }
2076  }
2077  }
2078  //OPTION 2
2079  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2080  {
2081  ii = node_indx[1];
2082  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2083  {
2084  jj = node_indx[2];
2085  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
2086  {
2087  kk = node_indx[0]; //IS_FREE_SURFACE
2088  ll = node_indx[3]; //IS_STRUCTURE
2089  }
2090  else
2091  {
2092  kk = node_indx[3]; //IS_FREE_SURFACE
2093  ll = node_indx[0]; //IS_STRUCTURE
2094  }
2095  }
2096  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2097  {
2098  jj = node_indx[3];
2099  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
2100  {
2101  kk = node_indx[0]; //IS_FREE_SURFACE
2102  ll = node_indx[2]; //IS_STRUCTURE
2103  }
2104  else
2105  {
2106  kk = node_indx[2]; //IS_FREE_SURFACE
2107  ll = node_indx[0]; //IS_STRUCTURE
2108  }
2109  }
2110  }
2111  //OPTION 3
2112  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2113  {
2114  ii = node_indx[2];
2115  if(this->GetGeometry()[node_indx[3]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2116  {
2117  jj = node_indx[3];
2118  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(IS_FREE_SURFACE) != 0.0)
2119  {
2120  kk = node_indx[0]; //IS_FREE_SURFACE
2121  ll = node_indx[1]; //IS_STRUCTURE
2122  }
2123  else
2124  {
2125  kk = node_indx[1]; //IS_FREE_SURFACE
2126  ll = node_indx[0]; //IS_STRUCTURE
2127  }
2128  }
2129  }
2130  }
2131  if (flag_trip == 3) //Element has three nodes with TRIPLE_POINT (those with one are not taken into account)
2132  {
2133  //OPTION 1
2134  if(this->GetGeometry()[node_indx[0]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2135  {
2136  ii = node_indx[0];
2137  if(this->GetGeometry()[node_indx[1]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2138  {
2139  jj = node_indx[1];
2140  if(this->GetGeometry()[node_indx[2]].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2141  {
2142  kk = node_indx[2]; //TRIPLE_POINT
2143  ll = node_indx[3]; //IS_FREE_SURFACE
2144  }
2145  else
2146  {
2147  kk = node_indx[3]; //TRIPLE_POINT
2148  ll = node_indx[2]; //IS_FREE_SURFACE
2149  }
2150  }
2151  else //if second node is not triple point, the only option is that the rest are triple points and this one is free surface
2152  {
2153  jj = node_indx[2];
2154  kk = node_indx[3];
2155  ll = node_indx[1];
2156  }
2157  }
2158  else //if first node is not triple point, the only option is that the rest are triple points and this one is free surface
2159  {
2160  ii = node_indx[1];
2161  jj = node_indx[2];
2162  kk = node_indx[3];
2163  ll = node_indx[0];
2164  }
2165  }
2166  }
2167 
2168  array_1d<double,3> An1 = this->GetGeometry()[ii].FastGetSolutionStepValue(NORMAL_GEOMETRIC);
2169  array_1d<double,3> An2 = this->GetGeometry()[jj].FastGetSolutionStepValue(NORMAL_GEOMETRIC);
2170  array_1d<double,3> An3 = this->GetGeometry()[kk].FastGetSolutionStepValue(NORMAL_GEOMETRIC);
2171 
2172  array_1d<double,3> m1 = - this->GetGeometry()[ii].FastGetSolutionStepValue(NORMAL_CONTACT_LINE) + this->GetGeometry()[ii].FastGetSolutionStepValue(NORMAL_CONTACT_LINE_EQUILIBRIUM);
2173  array_1d<double,3> m2 = - this->GetGeometry()[jj].FastGetSolutionStepValue(NORMAL_CONTACT_LINE) + this->GetGeometry()[jj].FastGetSolutionStepValue(NORMAL_CONTACT_LINE_EQUILIBRIUM);
2174  array_1d<double,3> m3 = - this->GetGeometry()[kk].FastGetSolutionStepValue(NORMAL_CONTACT_LINE) + this->GetGeometry()[kk].FastGetSolutionStepValue(NORMAL_CONTACT_LINE_EQUILIBRIUM);
2175 
2176  double fsign1 = this->GetGeometry()[ii].FastGetSolutionStepValue(CONTACT_ANGLE) - theta_s;
2177  fsign1 = 1.0;//fsign1/sqrt(fsign1*fsign1);
2178  double fsign2 = this->GetGeometry()[jj].FastGetSolutionStepValue(CONTACT_ANGLE) - theta_s;
2179  fsign2 = 1.0;//fsign2/sqrt(fsign2*fsign2);
2180  double fsign3 = this->GetGeometry()[kk].FastGetSolutionStepValue(CONTACT_ANGLE) - theta_s;
2181  fsign3 = 1.0;//fsign3/sqrt(fsign3*fsign3);
2182 
2183  //Check if there is a node with TRIPLE_POINT flag which shouldn't be
2184  if (flag_trip == 3)
2185  {
2186  double temp = 0.0;
2187  array_1d<double,3> vec_temp = ZeroVector(3);
2188  for(unsigned int i_node = 0; i_node < 4; ++i_node)
2189  {
2190  vec_temp = this->GetGeometry()[i_node].FastGetSolutionStepValue(NORMAL);
2191  NormalizeVec3D(vec_temp);
2192  temp = -(vec_temp[2]);
2193  if ( temp > 0.99 && this->GetGeometry()[i_node].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2194  this->GetGeometry()[i_node].FastGetSolutionStepValue(TRIPLE_POINT) = 0.0;
2195  }
2196  }
2197 
2198  double curv1 = this->GetGeometry()[ii].FastGetSolutionStepValue(MEAN_CURVATURE_3D);
2199  double curv2 = this->GetGeometry()[jj].FastGetSolutionStepValue(MEAN_CURVATURE_3D);
2200  double curv3 = this->GetGeometry()[kk].FastGetSolutionStepValue(MEAN_CURVATURE_3D);
2201 
2202  double nlen1 = this->GetGeometry()[ii].FastGetSolutionStepValue(NODAL_LENGTH);
2203  double nlen2 = this->GetGeometry()[jj].FastGetSolutionStepValue(NODAL_LENGTH);
2204  double nlen3 = this->GetGeometry()[kk].FastGetSolutionStepValue(NODAL_LENGTH);
2205 
2206  double x1 = this->GetGeometry()[ii].X();
2207  double y1 = this->GetGeometry()[ii].Y();
2208  double z1 = this->GetGeometry()[ii].Z();
2209  double x2 = this->GetGeometry()[jj].X();
2210  double y2 = this->GetGeometry()[jj].Y();
2211  double z2 = this->GetGeometry()[jj].Z();
2212  double x3 = this->GetGeometry()[kk].X();
2213  double y3 = this->GetGeometry()[kk].Y();
2214  double z3 = this->GetGeometry()[kk].Z();
2215 
2216  array_1d<double,3> r12 = Vector3D(x1,y1,z1,x2,y2,z2);
2217  array_1d<double,3> r13 = Vector3D(x1,y1,z1,x3,y3,z3);
2218  array_1d<double,3> r23 = Vector3D(x2,y2,z2,x3,y3,z3);
2219  array_1d<double,3> cprod = CrossProduct3D(r12,r13);
2220  double area_tr = 0.5*Norm3D(cprod);
2221 
2222 
2223 
2224  //elemental variables for the laplacian
2225  BoundedMatrix<double,4,4> msWorkMatrix = ZeroMatrix(4,4);
2226  BoundedMatrix<double,4,3> msDN_Dx = ZeroMatrix(4,3);
2227  array_1d<double,4> msN = ZeroVector(4); //dimension = number of nodes
2228  double Volume;
2229  GeometryUtils::CalculateGeometryData(this->GetGeometry(),msDN_Dx,msN,Volume);
2230  // 4 by 4 matrix that stores the laplacian
2231  msWorkMatrix = 0.333333333333 * gamma * area_tr * prod(msDN_Dx,trans(msDN_Dx)) * dt;
2232 
2233  double coef_i = 0.333333333333; // 0.333333333333 | (1/num_neighs_i) | 1.0/(num_neighs_i-1)
2234  double coef_j = 0.333333333333; // 0.333333333333 | (1/num_neighs_j) | 1.0/(num_neighs_j-1)
2235  double coef_k = 0.333333333333; // 0.333333333333 | (1/num_neighs_k) | 1.0/(num_neighs_k-1)
2236 
2237  if(flag_trip == 0)
2238 // if(flag_trip < 1e-15)
2239  {
2240  rRightHandSideVector[4*ii] -= coef_i*gamma*curv1*An1[0]*area_tr;
2241  rRightHandSideVector[4*ii+1] -= coef_i*gamma*curv1*An1[1]*area_tr;
2242  rRightHandSideVector[4*ii+2] -= coef_i*gamma*curv1*An1[2]*area_tr;
2243  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_X) = -coef_i*gamma*curv1*An1[0]*area_tr;
2244  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_Y) = -coef_i*gamma*curv1*An1[1]*area_tr;
2245  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_Z) = -coef_i*gamma*curv1*An1[2]*area_tr;
2246 
2247  rRightHandSideVector[4*jj] -= coef_j*gamma*curv2*An2[0]*area_tr;
2248  rRightHandSideVector[4*jj+1] -= coef_j*gamma*curv2*An2[1]*area_tr;
2249  rRightHandSideVector[4*jj+2] -= coef_j*gamma*curv2*An2[2]*area_tr;
2250  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_X) = -coef_j*gamma*curv2*An2[0]*area_tr;
2251  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_Y) = -coef_j*gamma*curv2*An2[1]*area_tr;
2252  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_Z) = -coef_j*gamma*curv2*An2[2]*area_tr;
2253 
2254  rRightHandSideVector[4*kk] -= coef_k*gamma*curv3*An3[0]*area_tr;
2255  rRightHandSideVector[4*kk+1] -= coef_k*gamma*curv3*An3[1]*area_tr;
2256  rRightHandSideVector[4*kk+2] -= coef_k*gamma*curv3*An3[2]*area_tr;
2257  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_X) = -coef_k*gamma*curv3*An3[0]*area_tr;
2258  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_Y) = -coef_k*gamma*curv3*An3[1]*area_tr;
2259  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_Z) = -coef_k*gamma*curv3*An3[2]*area_tr;
2260  }
2261 
2262  double beta = 1.0;
2263  if(flag_trip >= 1)
2264  {
2265  if(this->GetGeometry()[ii].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2266  {
2267  coef_i = 0.5;
2268  rRightHandSideVector[4*ii] -= coef_i*beta*fsign1*(gamma*m1[0]*nlen1);// + this->GetGeometry()[ii].FastGetSolutionStepValue(ADHESION_FORCE_X));
2269  rRightHandSideVector[4*ii+1] -= coef_i*beta*fsign1*(gamma*m1[1]*nlen1);// + this->GetGeometry()[ii].FastGetSolutionStepValue(ADHESION_FORCE_Y));
2270  rRightHandSideVector[4*ii+2] -= coef_i*beta*fsign1*(gamma*m1[2]*nlen1);// + this->GetGeometry()[ii].FastGetSolutionStepValue(ADHESION_FORCE_Z));
2271  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE) = -coef_i*beta*fsign1*(gamma*m1*nlen1);
2272  // + this->GetGeometry()[ii].FastGetSolutionStepValue(ADHESION_FORCE_X));
2273 
2274 
2275  rDampingMatrix(4*ii,4*ii) += 0.5*gamma*dt*msN[ii]*msN[ii]*nlen1 - msWorkMatrix(ii,ii);
2276  rDampingMatrix(4*ii+1,4*ii+1) += 0.5*gamma*dt*msN[ii]*msN[ii]*nlen1 - msWorkMatrix(ii,ii);
2277  rDampingMatrix(4*ii+2,4*ii+2) += 0.5*gamma*dt*msN[ii]*msN[ii]*nlen1 - msWorkMatrix(ii,ii);
2278  rDampingMatrix(4*ii,4*jj) += 0.5*gamma*dt*msN[ii]*msN[jj]*0.5*(nlen1 + nlen2) - msWorkMatrix(ii,jj);
2279  rDampingMatrix(4*ii+1,4*jj+1) += 0.5*gamma*dt*msN[ii]*msN[jj]*0.5*(nlen1 + nlen2) - msWorkMatrix(ii,jj);
2280  rDampingMatrix(4*ii+2,4*jj+2) += 0.5*gamma*dt*msN[ii]*msN[jj]*0.5*(nlen1 + nlen2) - msWorkMatrix(ii,jj);
2281  }
2282  else
2283  {
2284  rRightHandSideVector[4*ii] -= coef_i*beta*gamma*curv1*An1[0]*area_tr;
2285  rRightHandSideVector[4*ii+1] -= coef_i*beta*gamma*curv1*An1[1]*area_tr;
2286  rRightHandSideVector[4*ii+2] -= coef_i*beta*gamma*curv1*An1[2]*area_tr;
2287  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_X) = -coef_i*beta*gamma*curv1*An1[0]*area_tr;
2288  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_Y) = -coef_i*beta*gamma*curv1*An1[1]*area_tr;
2289  this->GetGeometry()[ii].FastGetSolutionStepValue(FORCE_Z) = -coef_i*beta*gamma*curv1*An1[2]*area_tr;
2290  }
2291 
2292 // beta = 1.0;
2293  if(this->GetGeometry()[jj].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2294  {
2295  coef_j = 0.5;
2296  rRightHandSideVector[4*jj] -= coef_j*beta*fsign2*(gamma*m2[0]*nlen2);// + this->GetGeometry()[jj].FastGetSolutionStepValue(ADHESION_FORCE_X));
2297  rRightHandSideVector[4*jj+1] -= coef_j*beta*fsign2*(gamma*m2[1]*nlen2);// + this->GetGeometry()[jj].FastGetSolutionStepValue(ADHESION_FORCE_Y));
2298  rRightHandSideVector[4*jj+2] -= coef_j*beta*fsign2*(gamma*m2[2]*nlen2);// + this->GetGeometry()[jj].FastGetSolutionStepValue(ADHESION_FORCE_Z));
2299  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE) = -coef_j*beta*fsign2*(gamma*m2*nlen2);// + this->GetGeometry()[jj].FastGetSolutionStepValue(ADHESION_FORCE_X));
2300 
2301  rDampingMatrix(4*jj,4*jj) += 0.5*gamma*dt*msN[jj]*msN[jj]*nlen2 - msWorkMatrix(jj,jj);
2302  rDampingMatrix(4*jj+1,4*jj+1) += 0.5*gamma*dt*msN[jj]*msN[jj]*nlen2 - msWorkMatrix(jj,jj);
2303  rDampingMatrix(4*jj+2,4*jj+2) += 0.5*gamma*dt*msN[jj]*msN[jj]*nlen2 - msWorkMatrix(jj,jj);
2304  rDampingMatrix(4*jj,4*ii) += 0.5*gamma*dt*msN[jj]*msN[ii]*0.5*(nlen1 + nlen2) - msWorkMatrix(jj,ii);
2305  rDampingMatrix(4*jj+1,4*ii+1) += 0.5*gamma*dt*msN[jj]*msN[ii]*0.5*(nlen1 + nlen2) - msWorkMatrix(jj,ii);
2306  rDampingMatrix(4*jj+2,4*ii+2) += 0.5*gamma*dt*msN[jj]*msN[ii]*0.5*(nlen1 + nlen2) - msWorkMatrix(jj,ii);
2307  }
2308  else
2309  {
2310  rRightHandSideVector[4*jj] -= coef_j*beta*gamma*curv2*An2[0]*area_tr;
2311  rRightHandSideVector[4*jj+1] -= coef_j*beta*gamma*curv2*An2[1]*area_tr;
2312  rRightHandSideVector[4*jj+2] -= coef_j*beta*gamma*curv2*An2[2]*area_tr;
2313  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_X) = -coef_j*beta*gamma*curv2*An2[0]*area_tr;
2314  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_Y) = -coef_j*beta*gamma*curv2*An2[1]*area_tr;
2315  this->GetGeometry()[jj].FastGetSolutionStepValue(FORCE_Z) = -coef_j*beta*gamma*curv2*An2[2]*area_tr;
2316  }
2317 
2318 // beta = 1.0;
2319  if(this->GetGeometry()[kk].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2320  {
2321  coef_k = 0.5;
2322  rRightHandSideVector[4*kk] -= coef_k*beta*fsign3*(gamma*m3[0]*nlen3);// + this->GetGeometry()[kk].FastGetSolutionStepValue(ADHESION_FORCE_X));
2323  rRightHandSideVector[4*kk+1] -= coef_k*beta*fsign3*(gamma*m3[1]*nlen3);// + this->GetGeometry()[kk].FastGetSolutionStepValue(ADHESION_FORCE_Y));
2324  rRightHandSideVector[4*kk+2] -= coef_k*beta*fsign3*(gamma*m3[2]*nlen3);// + this->GetGeometry()[kk].FastGetSolutionStepValue(ADHESION_FORCE_Z));
2325  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_X) = -coef_k*beta*fsign3*(gamma*m3[0]*nlen3);// + this->GetGeometry()[kk].FastGetSolutionStepValue(ADHESION_FORCE_X));
2326  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_Y) = -coef_k*beta*fsign3*(gamma*m3[1]*nlen3);// + this->GetGeometry()[kk].FastGetSolutionStepValue(ADHESION_FORCE_Y));
2327  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_Z) = -coef_k*beta*fsign3*(gamma*m3[2]*nlen3);// + this->GetGeometry()[kk].FastGetSolutionStepValue(ADHESION_FORCE_Z));
2328  }
2329  else
2330  {
2331  rRightHandSideVector[4*kk] -= coef_k*beta*gamma*curv3*An3[0]*area_tr;
2332  rRightHandSideVector[4*kk+1] -= coef_k*beta*gamma*curv3*An3[1]*area_tr;
2333  rRightHandSideVector[4*kk+2] -= coef_k*beta*gamma*curv3*An3[2]*area_tr;
2334  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_X) = -coef_k*beta*gamma*curv3*An3[0]*area_tr;
2335  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_Y) = -coef_k*beta*gamma*curv3*An3[1]*area_tr;
2336  this->GetGeometry()[kk].FastGetSolutionStepValue(FORCE_Z) = -coef_k*beta*gamma*curv3*An3[2]*area_tr;
2337  }
2338  }
2339 
2340  //Implicit treatment of surface tension
2341  rDampingMatrix(4*ii,4*ii) += msWorkMatrix(ii,ii);
2342  rDampingMatrix(4*ii+1,4*ii+1) += msWorkMatrix(ii,ii);
2343  rDampingMatrix(4*ii+2,4*ii+2) += msWorkMatrix(ii,ii);
2344 
2345  rDampingMatrix(4*ii,4*jj) += msWorkMatrix(ii,jj);
2346  rDampingMatrix(4*ii+1,4*jj+1) += msWorkMatrix(ii,jj);
2347  rDampingMatrix(4*ii+2,4*jj+2) += msWorkMatrix(ii,jj);
2348 
2349  rDampingMatrix(4*ii,4*kk) += msWorkMatrix(ii,kk);
2350  rDampingMatrix(4*ii+1,4*kk+1) += msWorkMatrix(ii,kk);
2351  rDampingMatrix(4*ii+2,4*kk+2) += msWorkMatrix(ii,kk);
2352 
2353  rDampingMatrix(4*jj,4*ii) += msWorkMatrix(jj,ii);
2354  rDampingMatrix(4*jj+1,4*ii+1) += msWorkMatrix(jj,ii);
2355  rDampingMatrix(4*jj+2,4*ii+2) += msWorkMatrix(jj,ii);
2356 
2357  rDampingMatrix(4*kk,4*ii) += msWorkMatrix(kk,ii);
2358  rDampingMatrix(4*kk+1,4*ii+1) += msWorkMatrix(kk,ii);
2359  rDampingMatrix(4*kk+2,4*ii+2) += msWorkMatrix(kk,ii);
2360 
2361  rDampingMatrix(4*jj,4*jj) += msWorkMatrix(jj,jj);
2362  rDampingMatrix(4*jj+1,4*jj+1) += msWorkMatrix(jj,jj);
2363  rDampingMatrix(4*jj+2,4*jj+2) += msWorkMatrix(jj,jj);
2364 
2365  rDampingMatrix(4*jj,4*kk) += msWorkMatrix(jj,kk);
2366  rDampingMatrix(4*jj+1,4*kk+1) += msWorkMatrix(jj,kk);
2367  rDampingMatrix(4*jj+2,4*kk+2) += msWorkMatrix(jj,kk);
2368 
2369  rDampingMatrix(4*kk,4*jj) += msWorkMatrix(kk,jj);
2370  rDampingMatrix(4*kk+1,4*jj+1) += msWorkMatrix(kk,jj);
2371  rDampingMatrix(4*kk+2,4*jj+2) += msWorkMatrix(kk,jj);
2372 
2373  rDampingMatrix(4*kk,4*kk) += msWorkMatrix(kk,kk);
2374  rDampingMatrix(4*kk+1,4*kk+1) += msWorkMatrix(kk,kk);
2375  rDampingMatrix(4*kk+2,4*kk+2) += msWorkMatrix(kk,kk);
2376 
2377 
2378  if(k > 3 && ll != 8)
2379  {
2380  array_1d<double,3> An4 = this->GetGeometry()[ll].FastGetSolutionStepValue(NORMAL_GEOMETRIC);
2381  array_1d<double,3> m4 = this->GetGeometry()[ll].FastGetSolutionStepValue(NORMAL_EQUILIBRIUM) - this->GetGeometry()[ll].FastGetSolutionStepValue(NORMAL_TRIPLE_POINT);
2382 
2383  double fsign4 = this->GetGeometry()[ll].FastGetSolutionStepValue(CONTACT_ANGLE) - theta_s;
2384  fsign4 = fsign4/abs(fsign4);
2385 
2386  int num_neighs_l = 0;
2387  GlobalPointersVector< Node >& neighb_l = this->GetGeometry()[ll].GetValue(NEIGHBOUR_NODES);
2388  for (unsigned int i = 0; i < neighb_l.size(); i++)
2389  {
2390  if (neighb_l[i].FastGetSolutionStepValue(IS_BOUNDARY) != 0.0)
2391  num_neighs_l++;
2392  }
2393  double coef_l = 0.333333333333; // 0.333333333333 | (1/num_neighs_l) | 1.0/(num_neighs_l-1)
2394 
2395  double curv4 = this->GetGeometry()[ll].FastGetSolutionStepValue(MEAN_CURVATURE_3D);
2396  double nlen4 = this->GetGeometry()[ll].FastGetSolutionStepValue(NODAL_LENGTH);
2397 
2398 // beta = 1.0;
2399  if(this->GetGeometry()[ll].FastGetSolutionStepValue(TRIPLE_POINT) != 0.0)
2400  {
2401  coef_l = 0.5;
2402  rRightHandSideVector[4*ll] -= coef_l*beta*fsign4*(gamma*m4[0]*nlen4);// + this->GetGeometry()[ll].FastGetSolutionStepValue(ADHESION_FORCE_X));
2403  rRightHandSideVector[4*ll+1] -= coef_l*beta*fsign4*(gamma*m4[1]*nlen4);// + this->GetGeometry()[ll].FastGetSolutionStepValue(ADHESION_FORCE_Y));
2404  rRightHandSideVector[4*ll+2] -= coef_l*beta*fsign4*(gamma*m4[2]*nlen4);// + this->GetGeometry()[ll].FastGetSolutionStepValue(ADHESION_FORCE_Z));
2405  this->GetGeometry()[ll].FastGetSolutionStepValue(FORCE_X) = -coef_l*beta*fsign4*(gamma*m4[0]*nlen4);// + this->GetGeometry()[ll].FastGetSolutionStepValue(ADHESION_FORCE_X));
2406  this->GetGeometry()[ll].FastGetSolutionStepValue(FORCE_Y) = -coef_l*beta*fsign4*(gamma*m4[1]*nlen4);// + this->GetGeometry()[ll].FastGetSolutionStepValue(ADHESION_FORCE_Y));
2407  this->GetGeometry()[ll].FastGetSolutionStepValue(FORCE_Z) = -coef_l*beta*fsign4*(gamma*m4[2]*nlen4);// + this->GetGeometry()[ll].FastGetSolutionStepValue(ADHESION_FORCE_Z));
2408  }
2409  else
2410  {
2411  rRightHandSideVector[4*ll] -= coef_l*beta*gamma*curv4*An4[0]*area_tr;
2412  rRightHandSideVector[4*ll+1] -= coef_l*beta*gamma*curv4*An4[1]*area_tr;
2413  rRightHandSideVector[4*ll+2] -= coef_l*beta*gamma*curv4*An4[2]*area_tr;
2414  this->GetGeometry()[ll].FastGetSolutionStepValue(FORCE) = -coef_l*beta*gamma*curv4*An4*area_tr;
2415  }
2416  }
2417 
2418  }
2419 
2421  // AddViscousStress2D();
2423  {
2426  double Area;
2427  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
2428 
2429  double x1 = this->GetGeometry()[0].X();
2430  double y1 = this->GetGeometry()[0].Y();
2431  double x2 = this->GetGeometry()[1].X();
2432  double y2 = this->GetGeometry()[1].Y();
2433  double x3 = this->GetGeometry()[2].X();
2434  double y3 = this->GetGeometry()[2].Y();
2435 
2436  double u1 = this->GetGeometry()[0].FastGetSolutionStepValue(VELOCITY_X);
2437  double v1 = this->GetGeometry()[0].FastGetSolutionStepValue(VELOCITY_Y);
2438  double u2 = this->GetGeometry()[1].FastGetSolutionStepValue(VELOCITY_X);
2439  double v2 = this->GetGeometry()[1].FastGetSolutionStepValue(VELOCITY_Y);
2440  double u3 = this->GetGeometry()[2].FastGetSolutionStepValue(VELOCITY_X);
2441  double v3 = this->GetGeometry()[2].FastGetSolutionStepValue(VELOCITY_Y);
2442 
2443  double x13 = x1 - x3;
2444  double x23 = x2 - x3;
2445  double y13 = y1 - y3;
2446  double y23 = y2 - y3;
2447 
2448  double du_dx = (0.5/Area)*(y23*(u1 - u3) - y13*(u2 - u3));
2449  double du_dy = (0.5/Area)*(-x23*(u1 - u3) + x13*(u2 - u3));
2450  double dv_dx = (0.5/Area)*(y23*(v1 - v3) - y13*(v2 - v3));
2451  double dv_dy = (0.5/Area)*(-x23*(v1 - v3) + x13*(y2 - y3));
2452 
2453  double mu,rho;
2454  for(unsigned int i = 0; i < TNumNodes; ++i)
2455  {
2456  mu = this->GetGeometry()[i].FastGetSolutionStepValue(VISCOSITY);
2457  rho = this->GetGeometry()[i].FastGetSolutionStepValue(DENSITY);
2458  mu *= rho;
2459  this->GetGeometry()[i].FastGetSolutionStepValue(VISCOUS_STRESSX_X) += mu * ( 2*du_dx );
2460  this->GetGeometry()[i].FastGetSolutionStepValue(VISCOUS_STRESSY_X) += mu * ( du_dy + dv_dx );
2461  this->GetGeometry()[i].FastGetSolutionStepValue(VISCOUS_STRESSX_Y) += mu * ( dv_dx + du_dy );
2462  this->GetGeometry()[i].FastGetSolutionStepValue(VISCOUS_STRESSY_Y) += mu * ( 2*dv_dy );
2463  }
2464 
2465  }
2466 
2468 
2473  const double Density,
2474  array_1d< double, 3 > & rElementalMomRes,
2475  double& rElementalMassRes,
2476  const array_1d< double, TNumNodes >& rShapeFunc,
2477  const BoundedMatrix<double, TNumNodes, TDim >& rShapeDeriv,
2478  const double Weight)
2479  {
2480  // If we want to use more than one Gauss point to integrate the convective term, this has to be evaluated once per integration point
2482  this->GetConvectionOperator(AGradN, rAdvVel, rShapeDeriv); // Get a * grad(Ni)
2483 
2484  // Compute contribution to Kij * Uj, with Kij = Ni * Residual(Nj); Uj = (v,p)Node_j (column vector)
2485  for (unsigned int i = 0; i < TNumNodes; ++i) // Iterate over element nodes
2486  {
2487 
2488  // Variable references
2489  const array_1d< double, 3 > & rVelocity = this->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY);
2490  const array_1d< double, 3 > & rBodyForce = this->GetGeometry()[i].FastGetSolutionStepValue(BODY_FORCE);
2491  const double& rPressure = this->GetGeometry()[i].FastGetSolutionStepValue(PRESSURE);
2492 
2493  // Compute this node's contribution to the residual (evaluated at inegration point)
2494  for (unsigned int d = 0; d < TDim; ++d)
2495  {
2496  rElementalMomRes[d] += Weight * (Density * (rShapeFunc[i] * rBodyForce[d] - AGradN[i] * rVelocity[d]) - rShapeDeriv(i, d) * rPressure);
2497  rElementalMassRes -= Weight * rShapeDeriv(i, d) * rVelocity[d];
2498  }
2499  }
2500  }
2501 
2503 
2513  const double Density,
2514  array_1d< double, 3 > & rElementalMomRes,
2515  const array_1d< double, TNumNodes >& rShapeFunc,
2516  const BoundedMatrix<double, TNumNodes, TDim >& rShapeDeriv,
2517  const double Weight)
2518  {
2519  // If we want to use more than one Gauss point to integrate the convective term, this has to be evaluated once per integration point
2521  this->GetConvectionOperator(AGradN, rAdvVel, rShapeDeriv); // Get a * grad(Ni)
2522 
2523  // Compute contribution to Kij * Uj, with Kij = Ni * Residual(Nj); Uj = (v,p)Node_j (column vector)
2524  for (unsigned int i = 0; i < TNumNodes; ++i) // Iterate over element nodes
2525  {
2526 
2527  // Variable references
2528  const array_1d< double, 3 > & rVelocity = this->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY);
2529  const array_1d< double, 3 > & rAcceleration = this->GetGeometry()[i].FastGetSolutionStepValue(ACCELERATION);
2530  const array_1d< double, 3 > & rBodyForce = this->GetGeometry()[i].FastGetSolutionStepValue(BODY_FORCE);
2531  const double& rPressure = this->GetGeometry()[i].FastGetSolutionStepValue(PRESSURE);
2532 
2533  // Compute this node's contribution to the residual (evaluated at inegration point)
2534  for (unsigned int d = 0; d < TDim; ++d)
2535  {
2536  rElementalMomRes[d] += Weight * (Density * (rShapeFunc[i] * (rBodyForce[d] - rAcceleration[d]) - AGradN[i] * rVelocity[d]) - rShapeDeriv(i, d) * rPressure);
2537  }
2538  }
2539  }
2540 
2542 
2552  const double Density,
2553  array_1d< double, 3 > & rElementalMomRes,
2554  const array_1d< double, TNumNodes >& rShapeFunc,
2555  const BoundedMatrix<double, TNumNodes, TDim >& rShapeDeriv,
2556  const double Weight)
2557  {
2558  // If we want to use more than one Gauss point to integrate the convective term, this has to be evaluated once per integration point
2560  this->GetConvectionOperator(AGradN, rAdvVel, rShapeDeriv); // Get a * grad(Ni)
2561 
2562  // Compute contribution to Kij * Uj, with Kij = Ni * Residual(Nj); Uj = (v,p)Node_j (column vector)
2563  for (unsigned int i = 0; i < TNumNodes; ++i) // Iterate over element nodes
2564  {
2565 
2566  // Variable references
2567  const array_1d< double, 3 > & rVelocity = this->GetGeometry()[i].FastGetSolutionStepValue(VELOCITY);
2568  const array_1d< double, 3 > & rBodyForce = this->GetGeometry()[i].FastGetSolutionStepValue(BODY_FORCE);
2569  const array_1d< double, 3 > & rProjection = this->GetGeometry()[i].FastGetSolutionStepValue(ADVPROJ);
2570  const double& rPressure = this->GetGeometry()[i].FastGetSolutionStepValue(PRESSURE);
2571 
2572  // Compute this node's contribution to the residual (evaluated at inegration point)
2573  for (unsigned int d = 0; d < TDim; ++d)
2574  {
2575  rElementalMomRes[d] += Weight * (Density * (rShapeFunc[i] * rBodyForce[d] - AGradN[i] * rVelocity[d]) - rShapeDeriv(i, d) * rPressure);
2576  rElementalMomRes[d] -= Weight * rShapeFunc[i] * rProjection[d];
2577  }
2578  }
2579  }
2580 
2581 
2597  virtual double EffectiveViscosity(double Density,
2600  double ElemSize,
2601  const ProcessInfo &rProcessInfo)
2602  {
2603  const double Csmag = (static_cast< const SurfaceTension<TDim> * >(this) )->GetValue(C_SMAGORINSKY);
2604  double Viscosity = 0.0;
2605  this->EvaluateInPoint(Viscosity,VISCOSITY,rN);
2606 
2607  if (Csmag > 0.0)
2608  {
2609  double StrainRate = this->EquivalentStrainRate(rDN_DX); // (2SijSij)^0.5
2610  double LengthScale = Csmag*ElemSize;
2611  LengthScale *= LengthScale; // square
2612  Viscosity += 2.0*LengthScale*StrainRate;
2613  }
2614 
2615  return Density*Viscosity;
2616  }
2617 
2618 
2619 
2630 
2631 
2633 
2640  const array_1d< double, TNumNodes >& rShapeFunc)
2641  {
2642  // Compute the weighted value of the advective velocity in the (Gauss) Point
2643  GeometryType& rGeom = this->GetGeometry();
2644  rAdvVel = rShapeFunc[0] * (rGeom[0].FastGetSolutionStepValue(VELOCITY) - rGeom[0].FastGetSolutionStepValue(MESH_VELOCITY));
2645  for (unsigned int iNode = 1; iNode < TNumNodes; ++iNode)
2646  rAdvVel += rShapeFunc[iNode] * (rGeom[iNode].FastGetSolutionStepValue(VELOCITY) - rGeom[iNode].FastGetSolutionStepValue(MESH_VELOCITY));
2647  }
2648 
2650 
2657  virtual void GetAdvectiveVel(array_1d< double, 3 > & rAdvVel,
2658  const array_1d< double, TNumNodes >& rShapeFunc,
2659  const std::size_t Step)
2660  {
2661  // Compute the weighted value of the advective velocity in the (Gauss) Point
2662  GeometryType& rGeom = this->GetGeometry();
2663  rAdvVel = rShapeFunc[0] * (rGeom[0].FastGetSolutionStepValue(VELOCITY, Step) - rGeom[0].FastGetSolutionStepValue(MESH_VELOCITY, Step));
2664  for (unsigned int iNode = 1; iNode < TNumNodes; ++iNode)
2665  rAdvVel += rShapeFunc[iNode] * (rGeom[iNode].FastGetSolutionStepValue(VELOCITY, Step) - rGeom[iNode].FastGetSolutionStepValue(MESH_VELOCITY, Step));
2666  }
2667 
2669 
2677  const array_1d< double, 3 > & rVelocity,
2678  const BoundedMatrix<double, TNumNodes, TDim >& rShapeDeriv)
2679  {
2680  // Evaluate (and weight) the a * Grad(Ni) operator in the integration point, for each node i
2681  for (unsigned int iNode = 0; iNode < TNumNodes; ++iNode) // Loop over nodes
2682  {
2683  // Initialize result
2684  rResult[iNode] = rVelocity[0] * rShapeDeriv(iNode, 0);
2685  for (unsigned int d = 1; d < TDim; ++d) // loop over components
2686  rResult[iNode] += rVelocity[d] * rShapeDeriv(iNode, d);
2687  }
2688  }
2689 
2691 
2700  virtual void EvaluateInPoint(double& rResult,
2701  const Variable< double >& rVariable,
2702  const array_1d< double, TNumNodes >& rShapeFunc)
2703  {
2704  // Compute the weighted value of the nodal variable in the (Gauss) Point
2705  GeometryType& rGeom = this->GetGeometry();
2706  rResult = rShapeFunc[0] * rGeom[0].FastGetSolutionStepValue(rVariable);
2707  for (unsigned int iNode = 1; iNode < TNumNodes; ++iNode)
2708  rResult += rShapeFunc[iNode] * rGeom[iNode].FastGetSolutionStepValue(rVariable);
2709  }
2710 
2711 
2713 
2721  virtual void EvaluateInPoint(array_1d< double, 3 > & rResult,
2722  const Variable< array_1d< double, 3 > >& rVariable,
2723  const array_1d< double, TNumNodes >& rShapeFunc)
2724  {
2725  // Compute the weighted value of the nodal variable in the (Gauss) Point
2726  GeometryType& rGeom = this->GetGeometry();
2727  rResult = rShapeFunc[0] * rGeom[0].FastGetSolutionStepValue(rVariable);
2728  for (unsigned int iNode = 1; iNode < TNumNodes; ++iNode)
2729  rResult += rShapeFunc[iNode] * rGeom[iNode].FastGetSolutionStepValue(rVariable);
2730  }
2731 
2733 
2740  double ElementSize(const double);
2741 
2742 
2744 
2750  virtual void AddViscousTerm(MatrixType& rDampingMatrix,
2751  const BoundedMatrix<double, TNumNodes, TDim >& rShapeDeriv,
2752  const double Weight);
2753 
2755 
2765  void AddBTransCB(MatrixType& rDampingMatrix,
2767  const double Weight)
2768  {
2769  BoundedMatrix<double, (TDim * TNumNodes)/2, TDim*TNumNodes > B;
2770  BoundedMatrix<double, (TDim * TNumNodes)/2, (TDim*TNumNodes)/2 > C;
2771  this->CalculateB(B,rShapeDeriv);
2772  this->CalculateC(C,Weight);
2773 
2774  const unsigned int BlockSize = TDim + 1;
2775  const unsigned int StrainSize = (TDim*TNumNodes)/2;
2776 
2777  vector<unsigned int> aux(TDim*TNumNodes);
2778  for(unsigned int i=0; i<TNumNodes; i++)
2779  {
2780  int base_index = TDim*i;
2781  int aux_index = BlockSize*i;
2782  for(unsigned int j=0; j<TDim; j++)
2783  {
2784  aux[base_index+j] = aux_index+j;
2785  }
2786  }
2787 
2788  for(unsigned int k=0; k< StrainSize; k++)
2789  {
2790  for(unsigned int l=0; l< StrainSize; l++)
2791  {
2792  const double Ckl = C(k,l);
2793  for (unsigned int i = 0; i < TDim*TNumNodes; ++i) // iterate over v components (vx,vy[,vz])
2794  {
2795  const double Bki=B(k,i);
2796  for (unsigned int j = 0; j < TDim*TNumNodes; ++j) // iterate over u components (ux,uy[,uz])
2797  {
2798  rDampingMatrix(aux[i],aux[j]) += Bki*Ckl*B(l,j);
2799  }
2800 
2801  }
2802 
2803  }
2804  }
2805  }
2806 
2809  const double Weight)
2810  {
2811  const GeometryType& rGeom = this->GetGeometry();
2812 
2813  // Velocity gradient
2814  MatrixType GradU = ZeroMatrix(TDim,TDim);
2815  for (unsigned int n = 0; n < TNumNodes; n++)
2816  {
2817  const array_1d<double,3>& rVel = this->GetGeometry()[n].FastGetSolutionStepValue(VELOCITY);
2818  for (unsigned int i = 0; i < TDim; i++)
2819  for (unsigned int j = 0; j < TDim; j++)
2820  GradU(i,j) += rDN_DX(n,j)*rVel[i];
2821  }
2822 
2823  // Element lengths
2824  array_1d<double,3> Delta(3,0.0);
2825  Delta[0] = std::fabs(rGeom[TNumNodes-1].X()-rGeom[0].X());
2826  Delta[1] = std::fabs(rGeom[TNumNodes-1].Y()-rGeom[0].Y());
2827  Delta[2] = std::fabs(rGeom[TNumNodes-1].Z()-rGeom[0].Z());
2828 
2829  for (unsigned int n = 1; n < TNumNodes; n++)
2830  {
2831  double hx = std::fabs(rGeom[n].X()-rGeom[n-1].X());
2832  if (hx > Delta[0]) Delta[0] = hx;
2833  double hy = std::fabs(rGeom[n].Y()-rGeom[n-1].Y());
2834  if (hy > Delta[1]) Delta[1] = hy;
2835  double hz = std::fabs(rGeom[n].Z()-rGeom[n-1].Z());
2836  if (hz > Delta[2]) Delta[2] = hz;
2837  }
2838 
2839  double AvgDeltaSq = Delta[0];
2840  for (unsigned int d = 1; d < TDim; d++)
2841  AvgDeltaSq *= Delta[d];
2842  AvgDeltaSq = std::pow(AvgDeltaSq,2./TDim);
2843 
2844  Delta[0] = Delta[0]*Delta[0]/12.0;
2845  Delta[1] = Delta[1]*Delta[1]/12.0;
2846  Delta[2] = Delta[2]*Delta[2]/12.0;
2847 
2848  // Gij
2849  MatrixType G = ZeroMatrix(TDim,TDim);
2850  for (unsigned int i = 0; i < TDim; i++)
2851  for (unsigned int j = 0; j < TDim; j++)
2852  for (unsigned int d = 0; d < TDim; d++)
2853  G(i,j) += Delta[d]*GradU(i,d)*GradU(j,d);
2854 
2855  // Gij:Sij
2856  double GijSij = 0.0;
2857  for (unsigned int i = 0; i < TDim; i++)
2858  for (unsigned int j = 0; j < TDim; j++)
2859  GijSij += 0.5*G(i,j)*( GradU(i,j) + GradU(j,i) );
2860 
2861  if (GijSij < 0.0) // Otherwise model term is clipped
2862  {
2863  // Gkk
2864  double Gkk = G(0,0);
2865  for (unsigned int d = 1; d < TDim; d++)
2866  Gkk += G(d,d);
2867 
2868  // C_epsilon
2869  const double Ce = 1.0;
2870 
2871  // ksgs
2872  double ksgs = -4*AvgDeltaSq*GijSij/(Ce*Ce*Gkk);
2873 
2874  // Assembly of model term
2875  unsigned int RowIndex = 0;
2876  unsigned int ColIndex = 0;
2877 
2878  for (unsigned int i = 0; i < TNumNodes; i++)
2879  {
2880  for (unsigned int j = 0; j < TNumNodes; j++)
2881  {
2882  for (unsigned int d = 0; d < TDim; d++)
2883  {
2884  double Aux = rDN_DX(i,d) * Delta[0] * G(d,0)*rDN_DX(j,0);
2885  for (unsigned int k = 1; k < TDim; k++)
2886  Aux += rDN_DX(i,d) *Delta[k] * G(d,k)*rDN_DX(j,k);
2887  rDampingMatrix(RowIndex+d,ColIndex+d) += Weight * 2.0*ksgs * Aux;
2888  }
2889 
2890  ColIndex += TDim;
2891  }
2892  RowIndex += TDim;
2893  ColIndex = 0;
2894  }
2895  }
2896 
2897  }
2898 
2900 
2905  void CalculateB( BoundedMatrix<double, (TDim * TNumNodes) / 2, TDim * TNumNodes >& rB,
2906  const BoundedMatrix<double, TNumNodes, TDim >& rShapeDeriv);
2907 
2909 
2916  virtual void CalculateC( BoundedMatrix<double, (TDim * TNumNodes) / 2, (TDim * TNumNodes) / 2 >& rC,
2917  const double Viscosity);
2918 
2919  double ConsistentMassCoef(const double Area);
2920 
2921 
2922  double SubscaleErrorEstimate(const ProcessInfo& rProcessInfo)
2923  {
2924  // Get the element's geometric parameters
2925  double Area;
2928  GeometryUtils::CalculateGeometryData(this->GetGeometry(), DN_DX, N, Area);
2929 
2930  // Calculate this element's fluid properties
2931  double Density;
2932  this->EvaluateInPoint(Density, DENSITY, N);
2933 
2934  double ElemSize = this->ElementSize(Area);
2935  double Viscosity = this->EffectiveViscosity(Density,N,DN_DX,ElemSize,rProcessInfo);
2936 
2937  // Get Advective velocity
2938  array_1d<double, 3 > AdvVel;
2939  this->GetAdvectiveVel(AdvVel, N);
2940 
2941  // Output container
2942  array_1d< double, 3 > ElementalMomRes(3, 0.0);
2943 
2944  // Calculate stabilization parameter. Note that to estimate the subscale velocity, the dynamic coefficient in TauOne is assumed zero.
2945  double TauOne;
2946  this->CalculateStaticTau(TauOne,AdvVel,ElemSize,Density,Viscosity);
2947 
2948  if ( rProcessInfo[OSS_SWITCH] != 1 ) // ASGS
2949  {
2950  this->ASGSMomResidual(AdvVel,Density,ElementalMomRes,N,DN_DX,1.0);
2951  ElementalMomRes *= TauOne;
2952  }
2953  else // OSS
2954  {
2955  this->OSSMomResidual(AdvVel,Density,ElementalMomRes,N,DN_DX,1.0);;
2956  ElementalMomRes *= TauOne;
2957  }
2958 
2959  // Error estimation ( ||U'|| / ||Uh_gauss|| ), taking ||U'|| = TauOne ||MomRes||
2960  double ErrorRatio(0.0);//, UNorm(0.0);
2961  //array_1d< double, 3 > UGauss(3, 0.0);
2962  //this->EvaluateInPoint(UGauss,VELOCITY,N);
2963 
2964  for (unsigned int i = 0; i < TDim; ++i)
2965  {
2966  ErrorRatio += ElementalMomRes[i] * ElementalMomRes[i];
2967  //UNorm += UGauss[i] * UGauss[i];
2968  }
2969  ErrorRatio = sqrt(ErrorRatio*Area);// / UNorm);
2970  //ErrorRatio /= Density;
2971  //this->SetValue(ERROR_RATIO, ErrorRatio);
2972  return ErrorRatio;
2973  }
2974 
2975 
2976 
2977  array_1d<double,2> Vector2D(const double x0, const double y0, const double x1, const double y1)
2978  {
2979  array_1d<double,2> r01;
2980  r01[0] = x1 - x0;
2981  r01[1] = y1 - y0;
2982  return (r01);
2983  }
2984 
2985  array_1d<double,3> Vector3D(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1)
2986  {
2987  array_1d<double,3> r01;
2988  r01[0] = x1 - x0;
2989  r01[1] = y1 - y0;
2990  r01[2] = z1 - z0;
2991  return (r01);
2992  }
2993 
2995  {
2997  c[0] = a[1]*b[2] - a[2]*b[1];
2998  c[1] = a[2]*b[0] - a[0]*b[2];
2999  c[2] = a[0]*b[1] - a[1]*b[0];
3000  return (c);
3001  }
3002 
3003  double Norm2D(const array_1d<double,2>& a)
3004  {
3005  return sqrt(a[0]*a[0] + a[1]*a[1]);
3006  }
3007 
3008  double Norm3D(const array_1d<double,3>& a)
3009  {
3010  return sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
3011  }
3012 
3014  {
3015  double norm = Norm2D(input);
3016  if (norm != 0.0)
3017  {
3018  input[0] /= norm;
3019  input[1] /= norm;
3020  }
3021  }
3022 
3024  {
3025  double norm = Norm3D(input);
3026  if (norm != 0.0)
3027  {
3028  input[0] /= norm;
3029  input[1] /= norm;
3030  input[2] /= norm;
3031  }
3032  }
3033 
3035  {
3036  return (a[0]*b[0] + a[1]*b[1]);
3037  }
3038 
3040  {
3041  return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
3042  }
3043 
3047 
3048 
3052 
3053 
3057 
3058 
3060 
3061 private:
3064 
3065 
3069 
3073 
3074  friend class Serializer;
3075 
3076 
3077 
3078 
3079  void save(Serializer& rSerializer) const override
3080  {
3082  }
3083 
3084  void load(Serializer& rSerializer) override
3085  {
3087  }
3088 
3092 
3093 
3097 
3098 
3102 
3103 
3107 
3108 
3112 
3114  SurfaceTension & operator=(SurfaceTension const& rOther);
3115 
3117  SurfaceTension(SurfaceTension const& rOther);
3118 
3120 
3121 }; // Class SurfaceTension
3122 
3124 
3127 
3128 
3132 
3133 
3135 template< unsigned int TDim,
3136  unsigned int TNumNodes >
3137 inline std::istream& operator >>(std::istream& rIStream,
3139 {
3140  return rIStream;
3141 }
3142 
3144 template< unsigned int TDim,
3145  unsigned int TNumNodes >
3146 inline std::ostream& operator <<(std::ostream& rOStream,
3147  const SurfaceTension<TDim, TNumNodes>& rThis)
3148 {
3149  rThis.PrintInfo(rOStream);
3150  rOStream << std::endl;
3151  rThis.PrintData(rOStream);
3152 
3153  return rOStream;
3154 }
3156 
3158 
3159 } // namespace Kratos.
3160 
3161 #endif // KRATOS_ST_H_INCLUDED defined
PeriodicInterfaceProcess & operator=(const PeriodicInterfaceProcess &)=delete
Base class for all Elements.
Definition: element.h:60
std::vector< DofType::Pointer > DofsVectorType
Definition: element.h:100
void PrintData(std::ostream &rOStream) const override
Print object's data.
Definition: element.h:1135
virtual int Check(const ProcessInfo &rCurrentProcessInfo) const
Definition: element.h:904
std::vector< std::size_t > EquationIdVectorType
Definition: element.h:98
std::size_t IndexType
Definition: flags.h:74
TVariableType::Type & GetValue(const TVariableType &rThisVariable)
Definition: geometrical_object.h:248
GeometryType & GetGeometry()
Returns the reference of the geometry.
Definition: geometrical_object.h:158
void SetValue(const TVariableType &rThisVariable, typename TVariableType::Type const &rValue)
Definition: geometrical_object.h:238
Geometry base class.
Definition: geometry.h:71
SizeType size() const
Definition: geometry.h:518
IndexType const & Id() const
Id of this Geometry.
Definition: geometry.h:964
TVariableType::Type & GetValue(const TVariableType &rThisVariable)
Definition: geometry.h:627
virtual Pointer Create(PointsArrayType const &rThisPoints) const
Creates a new geometry pointer.
Definition: geometry.h:813
static void CalculateGeometryData(const GeometryType &rGeometry, BoundedMatrix< double, 4, 3 > &rDN_DX, array_1d< double, 4 > &rN, double &rVolume)
This function is designed to compute the shape function derivatives, shape functions and volume in 3D...
Definition: geometry_utilities.h:176
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 object defines an indexed object.
Definition: indexed_object.h:54
IndexType Id() const
Definition: indexed_object.h:107
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
This class defines the node.
Definition: node.h:65
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.h:72
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
Properties encapsulates data shared by different Elements or Conditions. It can store any type of dat...
Definition: properties.h:69
The serialization consists in storing the state of an object into a storage format like data file or ...
Definition: serializer.h:123
A stabilized element for the incompressible Navier-Stokes equations, utilizing lagrangian_Eulerian ap...
Definition: surface_tension.h:91
double ElementSize(const double)
Return an estimate for the element size h, used to calculate the stabilization parameters.
virtual void GetAdvectiveVel(array_1d< double, 3 > &rAdvVel, const array_1d< double, TNumNodes > &rShapeFunc, const std::size_t Step)
Write the advective velocity evaluated at this point to an array.
Definition: surface_tension.h:2657
void GetValueOnIntegrationPoints(const Variable< Vector > &rVariable, std::vector< Vector > &rValues, const ProcessInfo &rCurrentProcessInfo) override
Empty implementation of unused CalculateOnIntegrationPoints overloads to avoid compilation warning.
Definition: surface_tension.h:869
void AddIntegrationPointVelocityContribution(MatrixType &rDampingMatrix, VectorType &rDampRHS, const double Density, const double Viscosity, const array_1d< double, 3 > &rAdvVel, const double TauOne, const double TauTwo, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Add a the contribution from a single integration point to the velocity contribution.
Definition: surface_tension.h:1230
Properties PropertiesType
Definition: surface_tension.h:109
void Calculate(const Variable< double > &rVariable, double &rOutput, const ProcessInfo &rCurrentProcessInfo) override
Implementation of Calculate to compute an error estimate.
Definition: surface_tension.h:521
void EquationIdVector(EquationIdVectorType &rResult, ProcessInfo &rCurrentProcessInfo) override
Provides the global indices for each one of this element's local rows.
SurfaceTension(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties)
Constuctor using geometry and properties.
Definition: surface_tension.h:172
void CalculateLumpedMassMatrix(MatrixType &rLHSMatrix, const double Mass)
Add lumped mass matrix.
Definition: surface_tension.h:1125
double Norm3D(const array_1d< double, 3 > &a)
Definition: surface_tension.h:3008
array_1d< double, TNumNodes > ShapeFunctionsType
Definition: surface_tension.h:131
virtual void EvaluateInPoint(array_1d< double, 3 > &rResult, const Variable< array_1d< double, 3 > > &rVariable, const array_1d< double, TNumNodes > &rShapeFunc)
Write the value of a variable at a point inside the element to a double.
Definition: surface_tension.h:2721
virtual void AddProjectionToRHS(VectorType &RHS, const array_1d< double, 3 > &rAdvVel, const double Density, const double TauOne, const double TauTwo, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight, const double DeltaTime=1.0)
Add OSS projection terms to the RHS.
Definition: surface_tension.h:1082
virtual double EffectiveViscosity(double Density, const array_1d< double, TNumNodes > &rN, const BoundedMatrix< double, TNumNodes, TDim > &rDN_DX, double ElemSize, const ProcessInfo &rProcessInfo)
EffectiveViscosity Calculate the viscosity at given integration point, using Smagorinsky if enabled.
Definition: surface_tension.h:2597
void NormalizeVec3D(array_1d< double, 3 > &input)
Definition: surface_tension.h:3023
void ApplySurfaceTensionContribution3D(MatrixType &rDampingMatrix, VectorType &rRightHandSideVector, const array_1d< double, 4 > &node_indx, const int &k, const ProcessInfo &rCurrentProcessInfo)
Definition: surface_tension.h:1711
array_1d< double, 2 > Vector2D(const double x0, const double y0, const double x1, const double y1)
Definition: surface_tension.h:2977
std::vector< std::size_t > EquationIdVectorType
Definition: surface_tension.h:125
void ApplySurfaceTensionContribution(MatrixType &rDampingMatrix, VectorType &rRightHandSideVector, const array_1d< double, 3 > &node_indx, const int &k, const ProcessInfo &rCurrentProcessInfo)
Add the surface tension term to the velocity contribution.
Definition: surface_tension.h:1330
Vector VectorType
Definition: surface_tension.h:117
virtual void AddMomentumRHS(VectorType &F, const double Density, const array_1d< double, TNumNodes > &rShapeFunc, const double Weight)
Add the momentum equation contribution to the RHS (body forces)
Definition: surface_tension.h:1058
double Norm2D(const array_1d< double, 2 > &a)
Definition: surface_tension.h:3003
Matrix MatrixType
Definition: surface_tension.h:119
void AddMassStabTerms(MatrixType &rLHSMatrix, const double Density, const array_1d< double, 3 > &rAdvVel, const double TauOne, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Add mass-like stabilization terms to LHS.
Definition: surface_tension.h:1187
IndexedObject BaseType
base type: an IndexedObject that automatically has a unique number
Definition: surface_tension.h:100
Node NodeType
definition of node type (default is: Node)
Definition: surface_tension.h:103
PointerVectorSet< Dof< double >, IndexedObject > DofsArrayType
Definition: surface_tension.h:129
void AddConsistentMassMatrixContribution(MatrixType &rLHSMatrix, const array_1d< double, TNumNodes > &rShapeFunc, const double Density, const double Weight)
Definition: surface_tension.h:1140
KRATOS_CLASS_INTRUSIVE_POINTER_DEFINITION(SurfaceTension)
Pointer definition of SurfaceTension.
array_1d< double, 3 > CrossProduct3D(const array_1d< double, 3 > &a, const array_1d< double, 3 > &b)
Definition: surface_tension.h:2994
void ASGSMomResidual(const array_1d< double, 3 > &rAdvVel, const double Density, array_1d< double, 3 > &rElementalMomRes, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Assemble the contribution from an integration point to the element's residual.
Definition: surface_tension.h:2512
SurfaceTension(IndexType NewId, GeometryType::Pointer pGeometry)
Constructor using a geometry object.
Definition: surface_tension.h:162
double ConsistentMassCoef(const double Area)
SurfaceTension(IndexType NewId=0)
Default constuctor.
Definition: surface_tension.h:144
double DotProduct3D(const array_1d< double, 3 > &a, const array_1d< double, 3 > &b)
Definition: surface_tension.h:3039
void OSSMomResidual(const array_1d< double, 3 > &rAdvVel, const double Density, array_1d< double, 3 > &rElementalMomRes, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Assemble the contribution from an integration point to the element's residual.
Definition: surface_tension.h:2551
void CalculateLocalVelocityContribution(MatrixType &rDampingMatrix, VectorType &rRightHandSideVector, ProcessInfo &rCurrentProcessInfo) override
Computes the local contribution associated to 'new' velocity and pressure values.
Definition: surface_tension.h:370
void PrintInfo(std::ostream &rOStream) const override
Print information about this object.
Definition: surface_tension.h:962
void GetDofList(DofsVectorType &rElementalDofList, ProcessInfo &rCurrentProcessInfo) override
Returns a list of the element's Dofs.
double SubscaleErrorEstimate(const ProcessInfo &rProcessInfo)
Definition: surface_tension.h:2922
double EquivalentStrainRate(const BoundedMatrix< double, TNumNodes, TDim > &rDN_DX) const
EquivalentStrainRate Calculate the second invariant of the strain rate tensor GammaDot = (2SijSij)^0....
array_1d< double, 3 > Vector3D(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1)
Definition: surface_tension.h:2985
void GetSecondDerivativesVector(Vector &Values, int Step=0) override
Returns ACCELERATION_X, ACCELERATION_Y, (ACCELERATION_Z,) 0 for each node.
void GetValueOnIntegrationPoints(const Variable< array_1d< double, 3 > > &rVariable, std::vector< array_1d< double, 3 > > &rOutput, const ProcessInfo &rCurrentProcessInfo) override
Obtain an array_1d<double,3> elemental variable, evaluated on gauss points.
Element::Pointer Create(IndexType NewId, GeometryType::Pointer pGeom, PropertiesType::Pointer pProperties) const override
It creates a new element pointer.
Definition: surface_tension.h:207
void GetConvectionOperator(array_1d< double, TNumNodes > &rResult, const array_1d< double, 3 > &rVelocity, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv)
Write the convective operator evaluated at this point (for each nodal funciton) to an array.
Definition: surface_tension.h:2676
std::vector< Dof< double >::Pointer > DofsVectorType
Definition: surface_tension.h:127
void GetValueOnIntegrationPoints(const Variable< double > &rVariable, std::vector< double > &rValues, const ProcessInfo &rCurrentProcessInfo) override
Obtain a double elemental variable, evaluated on gauss points.
Definition: surface_tension.h:728
void AddBTransCB(MatrixType &rDampingMatrix, BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Adds the contribution of the viscous term to the momentum equation (alternate).
Definition: surface_tension.h:2765
void AddViscousStress2D()
Add the viscous stress to air domain in two dimensions.
Definition: surface_tension.h:2422
std::string Info() const override
Turn back information as a string.
Definition: surface_tension.h:954
void AddProjectionResidualContribution(const array_1d< double, 3 > &rAdvVel, const double Density, array_1d< double, 3 > &rElementalMomRes, double &rElementalMassRes, const array_1d< double, TNumNodes > &rShapeFunc, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Assemble the contribution from an integration point to the element's residual.
Definition: surface_tension.h:2472
void CalculateLocalSystem(MatrixType &rLeftHandSideMatrix, VectorType &rRightHandSideVector, ProcessInfo &rCurrentProcessInfo) override
Provides local contributions from body forces and OSS projection terms.
Definition: surface_tension.h:224
void GetValueOnIntegrationPoints(const Variable< array_1d< double, 6 > > &rVariable, std::vector< array_1d< double, 6 > > &rValues, const ProcessInfo &rCurrentProcessInfo) override
Empty implementation of unused CalculateOnIntegrationPoints overloads to avoid compilation warning.
Definition: surface_tension.h:863
void ModulatedGradientDiffusion(MatrixType &rDampingMatrix, const BoundedMatrix< double, TNumNodes, TDim > &rDN_DX, const double Weight)
Definition: surface_tension.h:2807
void CalculateB(BoundedMatrix< double,(TDim *TNumNodes)/2, TDim *TNumNodes > &rB, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv)
Calculate the strain rate matrix.
Element::Pointer Create(IndexType NewId, NodesArrayType const &ThisNodes, PropertiesType::Pointer pProperties) const override
Create a new element of this type.
Definition: surface_tension.h:198
Geometry< NodeType >::PointsArrayType NodesArrayType
definition of nodes container type, redefined from GeometryType
Definition: surface_tension.h:115
Geometry< NodeType > GeometryType
definition of the geometry type with given NodeType
Definition: surface_tension.h:112
void CalculateLeftHandSide(MatrixType &rLeftHandSideMatrix, ProcessInfo &rCurrentProcessInfo) override
Returns a zero matrix of appropiate size (provided for compatibility with scheme)
Definition: surface_tension.h:245
int Check(const ProcessInfo &rCurrentProcessInfo) override
Checks the input and that all required Kratos variables have been registered.
Definition: surface_tension.h:897
double DotProduct2D(const array_1d< double, 2 > &a, const array_1d< double, 2 > &b)
Definition: surface_tension.h:3034
void FinalizeNonLinearIteration(ProcessInfo &rCurrentProcessInfo) override
Definition: surface_tension.h:504
virtual void CalculateTau(double &TauOne, double &TauTwo, const array_1d< double, 3 > &rAdvVel, const double ElemSize, const double Density, const double Viscosity, const ProcessInfo &rCurrentProcessInfo)
Calculate Stabilization parameters.
Definition: surface_tension.h:1009
virtual void CalculateC(BoundedMatrix< double,(TDim *TNumNodes)/2,(TDim *TNumNodes)/2 > &rC, const double Viscosity)
Calculate a matrix that provides the stress given the strain rate.
virtual void EvaluateInPoint(double &rResult, const Variable< double > &rVariable, const array_1d< double, TNumNodes > &rShapeFunc)
Write the value of a variable at a point inside the element to a double.
Definition: surface_tension.h:2700
std::size_t IndexType
Definition: surface_tension.h:121
std::size_t SizeType
Definition: surface_tension.h:123
void NormalizeVec2D(array_1d< double, 2 > &input)
Definition: surface_tension.h:3013
void CalculateMassMatrix(MatrixType &rMassMatrix, ProcessInfo &rCurrentProcessInfo) override
Computes local contributions to the mass matrix.
Definition: surface_tension.h:315
BoundedMatrix< double, TNumNodes, TDim > ShapeFunctionDerivativesType
Definition: surface_tension.h:132
void CalculateRightHandSide(VectorType &rRightHandSideVector, ProcessInfo &rCurrentProcessInfo) override
Provides local contributions from body forces and projections to the RHS.
Definition: surface_tension.h:266
~SurfaceTension() override
Destructor.
Definition: surface_tension.h:177
void Calculate(const Variable< array_1d< double, 3 > > &rVariable, array_1d< double, 3 > &rOutput, const ProcessInfo &rCurrentProcessInfo) override
Implementation of Calculate to compute the local OSS projections.
Definition: surface_tension.h:560
void GetValueOnIntegrationPoints(const Variable< Matrix > &rVariable, std::vector< Matrix > &rValues, const ProcessInfo &rCurrentProcessInfo) override
Empty implementation of unused CalculateOnIntegrationPoints overloads to avoid compilation warning.
Definition: surface_tension.h:875
SurfaceTension(IndexType NewId, const NodesArrayType &ThisNodes)
Constructor using an array of nodes.
Definition: surface_tension.h:153
virtual void CalculateStaticTau(double &TauOne, const array_1d< double, 3 > &rAdvVel, const double ElemSize, const double Density, const double Viscosity)
Calculate momentum stabilization parameter (without time term).
Definition: surface_tension.h:1040
void GetAdvectiveVel(array_1d< double, 3 > &rAdvVel, const array_1d< double, TNumNodes > &rShapeFunc)
Write the advective velocity evaluated at this point to an array.
Definition: surface_tension.h:2639
virtual void AddViscousTerm(MatrixType &rDampingMatrix, const BoundedMatrix< double, TNumNodes, TDim > &rShapeDeriv, const double Weight)
Adds the contribution of the viscous term to the momentum equation.
void GetFirstDerivativesVector(Vector &Values, int Step=0) override
Returns VELOCITY_X, VELOCITY_Y, (VELOCITY_Z,) PRESSURE for each node.
#define KRATOS_SERIALIZE_SAVE_BASE_CLASS(Serializer, BaseType)
Definition: define.h:812
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_SERIALIZE_LOAD_BASE_CLASS(Serializer, BaseType)
Definition: define.h:815
#define KRATOS_ERROR
Definition: exception.h:161
#define KRATOS_CHECK_DOF_IN_NODE(TheVariable, TheNode)
Definition: checks.h:176
#define KRATOS_CHECK_VARIABLE_IN_NODAL_DATA(TheVariable, TheNode)
Definition: checks.h:171
dt
Definition: DEM_benchmarks.py:173
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
AMatrix::MatrixProductExpression< TExpression1Type, TExpression2Type > prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:568
std::istream & operator>>(std::istream &rIStream, LinearMasterSlaveConstraint &rThis)
input stream function
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
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
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
rho
Definition: generate_droplet_dynamics.py:86
u2
Definition: generate_frictional_mortar_condition.py:76
input
Definition: generate_frictional_mortar_condition.py:435
x2
Definition: generate_frictional_mortar_condition.py:122
mu
Definition: generate_frictional_mortar_condition.py:127
u1
Definition: generate_frictional_mortar_condition.py:75
X2
Definition: generate_frictional_mortar_condition.py:120
x1
Definition: generate_frictional_mortar_condition.py:121
X1
Definition: generate_frictional_mortar_condition.py:119
int C
Definition: generate_hyper_elastic_simo_taylor_neo_hookean.py:27
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
float gamma
Definition: generate_two_fluid_navier_stokes.py:131
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
F
Definition: hinsberg_optimization.py:144
float zeta_dissapative_BM
Definition: lagrangian_droplet_test.py:134
float zeta_dissapative_SM
Definition: lagrangian_droplet_test.py:135
float zeta_dissapative_JM
this is for sessile droplets####
Definition: lagrangian_droplet_test.py:133
def load(f)
Definition: ode_solve.py:307
int L
Definition: ode_solve.py:390
int d
Definition: ode_solve.py:397
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
float temp
Definition: rotating_cone.py:85
int m
Definition: run_marine_rain_substepping.py:8
J
Definition: sensitivityMatrix.py:58
N
Definition: sensitivityMatrix.py:29
K
Definition: sensitivityMatrix.py:73
B
Definition: sensitivityMatrix.py:76
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17
subroutine m1(phi, M)
Definition: TensorModule.f:789
double precision, public pi
Definition: TensorModule.f:16