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.
enrich_2d_2dofs.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 authors: Pablo Becker
11 //
12 //
13 
14 
15 #if !defined(KRATOS_ENRICHMENT_2D_UTILITIES_INCLUDED )
16 #define KRATOS_ENRICHMENT_2D_UTILITIES_INCLUDED
17 
18 
19 
20 // System includes
21 #include <string>
22 #include <iostream>
23 #include <algorithm>
24 #include <limits>
25 
26 // External includes
27 
28 
29 // Project includes
30 #include "includes/define.h"
31 //#include "utilities/split_tetrahedra.h"
32 
33 namespace Kratos
34 {
35 
41 {
42 public:
43 
84  //with some added vectors, to be used when we need information about the interfase between the 2 elements
85  template<class TMatrixType, class TVectorType, class TGradientType>
86  static int CalculateTriangleEnrichedShapeFuncions(TMatrixType const& rPoints, TGradientType const& DN_DX,
87  TVectorType rDistances, TVectorType& rVolumes, TMatrixType& rGPShapeFunctionValues,
88  TVectorType& rPartitionsSign, std::vector<TMatrixType>& rGradientsValue, TMatrixType& NEnriched, //and information about the interfase:
89  TVectorType& face_gauss_N, TVectorType& face_gauss_Nenriched, double& face_Area, TVectorType& face_n ,unsigned int& type_of_cut)
90  {
92 
93  //unsigned int i,j,k;
94  unsigned int i_aux,j_aux,k_aux; //
95  type_of_cut = 0; // 0 means no cuts, 1 means element is cut through edges ij,ik; 2 ij,jk ; 3 ik , kj ; INTERFASES ON nodes are not contemplated
96  const double one_third=1.0/3.0;
97  BoundedMatrix<double, 3, 3 > coord_subdomain; //used to pass arguments when we must calculate areas, shape functions, etc
98  double Area;//area of the complete element
99  rGPShapeFunctionValues(0,0)=one_third; rGPShapeFunctionValues(0,1)=one_third; rGPShapeFunctionValues(0,2)=one_third; //default, when no interfase has been found
100  Area = CalculateVolume2D( rPoints );
101 
102 
103  //to begin with we must check whether our element is cut or not by the interfase.
104  if( (rDistances(0)*rDistances(1))>0.0 && (rDistances(0)*rDistances(2))>0.0 ) //it means that this element IS NOT cut by the interfase. we must return data of a normal, non-enriched element
105  {
106  rVolumes(0)=Area;
107  rGPShapeFunctionValues(0,0)=one_third; rGPShapeFunctionValues(0,1)=one_third; rGPShapeFunctionValues(0,2)=one_third;
108  NEnriched(0,0) = 0.0;
109  type_of_cut=1;
110  for (int j = 0; j < 3; j++)
111  rGradientsValue[0](0, j) = 0.0;
112  if (rDistances(0) < 0.0) rPartitionsSign[0] = -1;
113  else rPartitionsSign[0] = 1.0;
114  //KRATOS_WATCH("one element not in the intefase")
115  return 1;
116  }
117 
118  else //we must create the enrichement, it can be in 2 or 3 parts. we'll start with 3 always.
119  {
120  //KRATOS_WATCH("one element IS in the intefase")
121  if ((rDistances(0)*rDistances(1))<0.0) //edge 12 is cut
122  {
123  if ((rDistances(0)*rDistances(2))<0.0) //edge 13 is cut.
124  {
125  //check distances later to see if they're close to nodes and belong to case 4,5or6. for the moment we suppose all edges are cut (cases 1-3)
126  type_of_cut=1;
127  }
128  else
129  {
130  type_of_cut=2;
131  }
132  }
133  else //edge ij is not cut
134  {
135  type_of_cut=3;
136  }
137  }
138 
139  //KRATOS_WATCH(type_of_cut)
140  switch (type_of_cut)
141  {
142  case 1: // edge 12 and 13 is cut
143  i_aux=0;
144  j_aux=1;
145  k_aux=2;
146 
147  break;
148  case 2: // edge 12 and 23 is cut
149  i_aux=1;
150  j_aux=2;
151  k_aux=0;
152  break;
153  case 3: // edge 23 and 13 is cut
154  i_aux=2;
155  j_aux=0;
156  k_aux=1;
157  break;
158  }
159  /*
160  KRATOS_WATCH(i_aux)
161  KRATOS_WATCH(j_aux)
162  KRATOS_WATCH(k_aux)
163  */
164  //const double dist12=abs(rDistances(0)-rDistances(1) );
165  if (rDistances(i_aux) < 0.0)
166  {
167  rPartitionsSign[0] = -1.0;
168  rPartitionsSign[1] = 1.0;
169  rPartitionsSign[2] = 1.0;
170  }
171  else
172  {
173  rPartitionsSign[0] = 1.0;
174  rPartitionsSign[1] = -1.0;
175  rPartitionsSign[2] = -1.0;
176  }
177 
178  //'TRICK' TO AVOID HAVING THE INTERFASE TOO CLOSE TO THE NODES:
179  //since we cannot collapse node because we have to contemplate the possibility of discontinuities, we will move a little the intefase so that it is not that close.
180 
181  const double unsigned_distance0=fabs(rDistances(0));
182  const double unsigned_distance1=fabs(rDistances(1));
183  const double unsigned_distance2=fabs(rDistances(2));
184  //we begin by finding the largest distance:
185  double longest_distance=fabs(unsigned_distance0);
186  if (unsigned_distance1>longest_distance)
187  longest_distance=unsigned_distance1;
188  if (unsigned_distance2>longest_distance)
189  longest_distance=unsigned_distance2;
190  //Now we set a maximum relative distance
191  const double tolerable_distance =longest_distance*0.000001; // (1/1,000,000 seems to have good results)
192 
193  //and now we check if a distance is too small:
194  if (unsigned_distance0<tolerable_distance)
195  rDistances[0]=tolerable_distance*(rDistances[0]/fabs(rDistances[0]));
196  if (unsigned_distance1<tolerable_distance)
197  rDistances[1]=tolerable_distance*(rDistances[1]/fabs(rDistances[1]));
198  if (unsigned_distance2<tolerable_distance)
199  rDistances[2]=tolerable_distance*(rDistances[2]/fabs(rDistances[2]));
200 
201  //END OF TRICK. REMEMBER TO OVERWRITE THE DISTANCE VARIABLE IN THE ELEMENT IN CASE THESE LINES HAVE MODIFIED THEM (distances)
202 
203 
204  //for (int jj = 0; jj < 3; jj++)
205  // KRATOS_WATCH(rDistances(jj));
206 
207  const double node4_relative_position=fabs(rDistances(j_aux)/(rDistances(i_aux)-rDistances(j_aux) ) ) ; //position in 'natural' coordinates of edge 12, 0 when it passes over node 2. (it is over the edge 12)
208  const double node5_relative_position=fabs(rDistances(k_aux)/(rDistances(i_aux)-rDistances(k_aux) ) ) ; //position in 'natural' coordinates of edge 12, 0 when it passes over node 2. (it is over the edge 23)
209  //KRATOS_WATCH(node4_relative_position);
210  //KRATOS_WATCH(node5_relative_position);
211 
212  //Standard Shape function values in the 'new nodes' created by the interfase:
213  const double Ni_aux_node4 = node4_relative_position;
214  const double Nj_aux_node4 = (1.0-node4_relative_position);
215  //Nk_aux_node_4 is zero (we are on the ij edge)
216  const double Ni_aux_node5 = node5_relative_position;
217  //Nj_aux_node_5 is zero (we are on the ik edge)
218  const double Nk_aux_node5 = (1.0-node5_relative_position);
219 
220  //location of the midpoint of the interface : halfway between the two points
221  const double x_midpoint=((rPoints(i_aux,0)*Ni_aux_node4+rPoints(j_aux,0)*Nj_aux_node4)+
222  (rPoints(i_aux,0)*Ni_aux_node5+rPoints(k_aux,0)*Nk_aux_node5))*0.5;
223  const double y_midpoint=((rPoints(i_aux,1)*Ni_aux_node4+rPoints(j_aux,1)*Nj_aux_node4)+
224  (rPoints(i_aux,1)*Ni_aux_node5+rPoints(k_aux,1)*Nk_aux_node5))*0.5;
225  const double z_midpoint=0.0;
226 
227  //now we look for the shape function values in the midpoint:
228  coord_subdomain = rPoints;
230  bool is_found = CalculatePosition ( coord_subdomain , x_midpoint,y_midpoint,z_midpoint, N);
231  face_gauss_N = N;
232 
233  //we will adimensionalize the new shape functions so that the value is one on the midpoint on the interfase:
234  const double adim_Nenriched_i_aux = 1.0 /(face_gauss_N(i_aux)); //for partitions 2 and 3
235  //also the other 2 shape fuctions must be resized so that the new enrichment is constant along the interfase:
236  const double adim_Nenriched_j_aux = adim_Nenriched_i_aux * Ni_aux_node4 / Nj_aux_node4 ; //to have a constant value in the interfase at node 4: =N_j_aux_node4 / N_j_aux when adimensionalized
237  const double adim_Nenriched_k_aux = adim_Nenriched_i_aux * Ni_aux_node5 / Nk_aux_node5 ; //to have a constant value in the interfase at node 5: = N_k_aux_node4 / N_k_aux when adimensionalized
238 
239  //for the jump, we will create a shape function that holds a constant difference of 2 along the interfase:
240  const double adim_Nenriched_j_aux_b = (2.0 - node4_relative_position * adim_Nenriched_i_aux) / Nj_aux_node4;
241  const double adim_Nenriched_k_aux_b = (2.0 - node5_relative_position * adim_Nenriched_i_aux) / Nk_aux_node5;
242 
243 
244  //value of the shape functions in the interfase
245  face_gauss_Nenriched(i_aux)= 1.0;
246  face_gauss_Nenriched(j_aux)= 0.0; //actualy it's not defined, it's a discontinous function
247 
248  //first partition
249  rGradientsValue[0](0,0)=DN_DX(j_aux,0)*adim_Nenriched_j_aux+DN_DX(k_aux,0)*adim_Nenriched_k_aux;
250  rGradientsValue[0](0,1)=DN_DX(j_aux,1)*adim_Nenriched_j_aux+DN_DX(k_aux,1)*adim_Nenriched_k_aux; // i j,k i j,k
251 
252  rGradientsValue[0](1,0)=DN_DX(j_aux,0)*adim_Nenriched_j_aux_b+DN_DX(k_aux,0)*adim_Nenriched_k_aux_b; //the shape function are: 1: ___/\____ 2: ___/ ___
253  rGradientsValue[0](1,1)=DN_DX(j_aux,1)*adim_Nenriched_j_aux_b+DN_DX(k_aux,1)*adim_Nenriched_k_aux_b; // /
254  //now we must calculate the position of the new nodes to get the area.
255  coord_subdomain(0,0)=rPoints(i_aux,0);
256  coord_subdomain(0,1)=rPoints(i_aux,1);
257  coord_subdomain(1,0)=rPoints(i_aux,0)*Ni_aux_node4+rPoints(j_aux,0)*Nj_aux_node4;
258  coord_subdomain(1,1)=rPoints(i_aux,1)*Ni_aux_node4+rPoints(j_aux,1)*Nj_aux_node4;
259  coord_subdomain(2,0)=rPoints(i_aux,0)*Ni_aux_node5+rPoints(k_aux,0)*Nk_aux_node5;
260  coord_subdomain(2,1)=rPoints(i_aux,1)*Ni_aux_node5+rPoints(k_aux,1)*Nk_aux_node5;
261  rVolumes(0)=CalculateVolume2D(coord_subdomain);
262  //we look for the gauss point of the partition:
263  double x_GP_partition = one_third * ( coord_subdomain(0,0) + coord_subdomain(1,0) + coord_subdomain(2,0) );
264  double y_GP_partition = one_third * ( coord_subdomain(0,1) + coord_subdomain(1,1) + coord_subdomain(2,1) );
265  double z_GP_partition = 0.0;
266  //we reset the coord_subdomain matrix so that we have the whole element again:
267  coord_subdomain = rPoints;
268  //and we calculate its shape function values
269  is_found = CalculatePosition ( coord_subdomain , x_GP_partition ,y_GP_partition ,z_GP_partition , N);
270  rGPShapeFunctionValues(0,0)=N(0);
271  rGPShapeFunctionValues(0,1)=N(1);
272  rGPShapeFunctionValues(0,2)=N(2);
273  NEnriched(0,0)=rGPShapeFunctionValues(0,j_aux)*adim_Nenriched_j_aux+rGPShapeFunctionValues(0,k_aux)*adim_Nenriched_k_aux;
274  NEnriched(0,1)=NEnriched(0,0);
275  //KRATOS_WATCH(rVolumes(0));
276 
277  //now the face area(actually it's just the distance from point 4 to 5.
278  face_Area=sqrt(pow((coord_subdomain(2,0)-coord_subdomain(1,0)),2)+pow((coord_subdomain(2,1)-coord_subdomain(1,1)),2));
279  //and the normal vector. face_Area already has the modulus of the vector, so:
280  face_n(0)=(coord_subdomain(2,1)-coord_subdomain(1,1))/face_Area;
281  face_n(1)=-(coord_subdomain(2,0)-coord_subdomain(1,0))/face_Area;
282 
283  /*
284  KRATOS_WATCH(coord_subdomain(0,0));
285  KRATOS_WATCH(coord_subdomain(0,1));
286  KRATOS_WATCH(coord_subdomain(1,0));
287  KRATOS_WATCH(coord_subdomain(1,1));
288  KRATOS_WATCH(coord_subdomain(2,0));
289  KRATOS_WATCH(coord_subdomain(2,1));
290  KRATOS_WATCH(rGPShapeFunctionValues(0,i_aux));
291  KRATOS_WATCH(rGPShapeFunctionValues(0,j_aux));
292  KRATOS_WATCH(rGPShapeFunctionValues(0,k_aux));
293  KRATOS_WATCH( rGradientsValue[0](0,0))
294  KRATOS_WATCH( rGradientsValue[0](0,1))
295  */
296 
297  //second partition and second GP
298  rGradientsValue[1](0,0)=DN_DX(i_aux,0)*adim_Nenriched_i_aux;
299  rGradientsValue[1](0,1)=DN_DX(i_aux,1)*adim_Nenriched_i_aux;
300 
301  //for the jump we invert the sign of the partition.
302  rGradientsValue[1](1,0)= -rGradientsValue[1](0,0);
303  rGradientsValue[1](1,1)= -rGradientsValue[1](0,1);
304 
305 
306  //now we must calculate the position of the new nodes to get the area.
307  //coord_subdomain = rPoints; //easier to start this way. node 2 is already ok.
308  coord_subdomain(0,0) = rPoints(j_aux,0);
309  coord_subdomain(0,1) = rPoints(j_aux,1);
310  coord_subdomain(1,0) = rPoints(k_aux,0);
311  coord_subdomain(1,1) = rPoints(k_aux,1);
312  coord_subdomain(2,0) = rPoints(i_aux,0)*Ni_aux_node5+rPoints(k_aux,0)*Nk_aux_node5;
313  coord_subdomain(2,1) = rPoints(i_aux,1)*Ni_aux_node5+rPoints(k_aux,1)*Nk_aux_node5;
314  rVolumes(1)=CalculateVolume2D(coord_subdomain);
315  //we look for the gauss point of the partition:
316  x_GP_partition = one_third * ( coord_subdomain(0,0) + coord_subdomain(1,0) + coord_subdomain(2,0) );
317  y_GP_partition = one_third * ( coord_subdomain(0,1) + coord_subdomain(1,1) + coord_subdomain(2,1) );
318  z_GP_partition = 0.0;
319  //we reset the coord_subdomain matrix so that we have the whole element again:
320  coord_subdomain = rPoints;
321  //and we calculate the shape functions at it
322  is_found = CalculatePosition ( coord_subdomain , x_GP_partition ,y_GP_partition ,z_GP_partition , N);
323  rGPShapeFunctionValues(1,0)=N(0);
324  rGPShapeFunctionValues(1,1)=N(1);
325  rGPShapeFunctionValues(1,2)=N(2);
326  NEnriched(1,0) = rGPShapeFunctionValues(1,i_aux)*adim_Nenriched_i_aux;
327  NEnriched(1,1) = -NEnriched(1,0);
328  /*
329  KRATOS_WATCH(rVolumes(1));
330  KRATOS_WATCH(coord_subdomain(0,0));
331  KRATOS_WATCH(coord_subdomain(0,1));
332  KRATOS_WATCH(coord_subdomain(1,0));
333  KRATOS_WATCH(coord_subdomain(1,1));
334  KRATOS_WATCH(coord_subdomain(2,0));
335  KRATOS_WATCH(coord_subdomain(2,1));
336  KRATOS_WATCH(rGPShapeFunctionValues(1,i_aux));
337  KRATOS_WATCH(rGPShapeFunctionValues(1,j_aux));
338  KRATOS_WATCH(rGPShapeFunctionValues(1,k_aux));
339  KRATOS_WATCH( rGradientsValue[1](0,0))
340  KRATOS_WATCH( rGradientsValue[1](0,1))
341  */
342 
343  //NOT A PARTITION, just the volume of a different conectivity:
344  //just replacing the third node. Useful only to recover information, for example N(i,j,k) of node5
345  coord_subdomain(2,0) = rPoints(i_aux,0)*Ni_aux_node4+rPoints(j_aux,0)*Nj_aux_node4;
346  coord_subdomain(2,1) = rPoints(i_aux,1)*Ni_aux_node4+rPoints(j_aux,1)*Nj_aux_node4;
347  rVolumes(3)=CalculateVolume2D(coord_subdomain);
348 
349  //third partition:
350  rGradientsValue[2](0,0)=DN_DX(i_aux,0)*adim_Nenriched_i_aux;
351  rGradientsValue[2](0,1)=DN_DX(i_aux,1)*adim_Nenriched_i_aux;
352  //for the jump we invert the sign of the partition.
353  rGradientsValue[2](1,0)= -rGradientsValue[2](0,0);
354  rGradientsValue[2](1,1)= -rGradientsValue[2](0,1);
355 
356 
357 
358  coord_subdomain(0,0) = rPoints(j_aux,0);
359  coord_subdomain(0,1) = rPoints(j_aux,1);
360  coord_subdomain(1,0)=rPoints(i_aux,0)*Ni_aux_node5+rPoints(k_aux,0)*Nk_aux_node5;
361  coord_subdomain(1,1)=rPoints(i_aux,1)*Ni_aux_node5+rPoints(k_aux,1)*Nk_aux_node5;
362  coord_subdomain(2,0)=rPoints(i_aux,0)*Ni_aux_node4+rPoints(j_aux,0)*Nj_aux_node4;
363  coord_subdomain(2,1)=rPoints(i_aux,1)*Ni_aux_node4+rPoints(j_aux,1)*Nj_aux_node4;
364  rVolumes(2)=Area-rVolumes(0)-rVolumes(1);
365  x_GP_partition = one_third * ( coord_subdomain(0,0) + coord_subdomain(1,0) + coord_subdomain(2,0) );
366  y_GP_partition = one_third * ( coord_subdomain(0,1) + coord_subdomain(1,1) + coord_subdomain(2,1) );
367  z_GP_partition = 0.0;
368  coord_subdomain = rPoints;
369  is_found = CalculatePosition ( coord_subdomain , x_GP_partition ,y_GP_partition ,z_GP_partition , N);
370  rGPShapeFunctionValues(2,0)=N(0);
371  rGPShapeFunctionValues(2,1)=N(1);
372  rGPShapeFunctionValues(2,2)=N(2);
373  NEnriched(2,0)= rGPShapeFunctionValues(2,i_aux)*adim_Nenriched_i_aux;
374  NEnriched(2,1)= -NEnriched(2,0);
375 
376  /*
377  KRATOS_WATCH(rVolumes(2));
378  KRATOS_WATCH(coord_subdomain(0,0));
379  KRATOS_WATCH(coord_subdomain(0,1));
380  KRATOS_WATCH(coord_subdomain(1,0));
381  KRATOS_WATCH(coord_subdomain(1,1));
382  KRATOS_WATCH(coord_subdomain(2,0));
383  KRATOS_WATCH(coord_subdomain(2,1));
384  KRATOS_WATCH(rGPShapeFunctionValues(2,i_aux));
385  KRATOS_WATCH(rGPShapeFunctionValues(2,j_aux));
386  KRATOS_WATCH(rGPShapeFunctionValues(2,k_aux));
387  KRATOS_WATCH( rGradientsValue[2](0,0))
388  KRATOS_WATCH( rGradientsValue[2](0,1))
389  */
390  /*
391  std::cout <<"GAUSS POINTS" << '\n';
392  for (unsigned int ji=0; ji<3; ji++)
393  std::cout <<rGPShapeFunctionValues(ji,0)<< " " << rGPShapeFunctionValues(ji,1) << " " << rGPShapeFunctionValues(ji,2) <<'\n';
394 
395  std::cout <<"GRADIENTS" << '\n';
396  for (unsigned int ji=0; ji<3; ji++)
397  {
398  std::cout << "first Shape function" << '\n';
399  std::cout << rGradientsValue[ji](0,0) << " " <<rGradientsValue[ji](0,1) <<'\n';
400  std::cout << "second Shape function" << '\n';
401  std::cout << rGradientsValue[ji](1,0) << " " <<rGradientsValue[ji](1,1) <<'\n';
402  }
403  */
404  return 3;
405  KRATOS_CATCH("");
406 
407  }
408 
409 
410 
417  private:
418 
419  static inline void CalculateGeometryData(
420  const BoundedMatrix<double, 3, 3 > & coordinates,
423  double& Area)
424  {
425  double x10 = coordinates(1,0) - coordinates(0,0);
426  double y10 = coordinates(1,1) - coordinates(0,1);
427 
428  double x20 = coordinates(2,0) - coordinates(0,0);
429  double y20 = coordinates(2,1) - coordinates (0,1);
430 
431  //Jacobian is calculated:
432  // |dx/dxi dx/deta| |x1-x0 x2-x0|
433  //J=| |= | |
434  // |dy/dxi dy/deta| |y1-y0 y2-y0|
435 
436 
437  double detJ = x10 * y20-y10 * x20;
438 
439  DN_DX(0,0) = -y20 + y10;
440  DN_DX(0,1) = x20 - x10;
441  DN_DX(1,0) = y20 ;
442  DN_DX(1,1) = -x20 ;
443  DN_DX(2,0) = -y10 ;
444  DN_DX(2,1) = x10 ;
445 
446  DN_DX /= detJ;
447  N[0] = 0.333333333333333;
448  N[1] = 0.333333333333333;
449  N[2] = 0.333333333333333;
450 
451  Area = 0.5*detJ;
452  }
453 
454  //template<class TMatrixType, class TVectorType, class TGradientType>
455  static inline double CalculateVolume2D(
456  const BoundedMatrix<double, 3, 3 > & coordinates)
457  {
458  double x10 = coordinates(1,0) - coordinates(0,0);
459  double y10 = coordinates(1,1) - coordinates(0,1);
460 
461  double x20 = coordinates(2,0) - coordinates(0,0);
462  double y20 = coordinates(2,1) - coordinates (0,1);
463  double detJ = x10 * y20-y10 * x20;
464  return 0.5*detJ;
465  }
466 
467  static inline bool CalculatePosition(const BoundedMatrix<double, 3, 3 > & coordinates,
468  const double xc, const double yc, const double zc,
469  array_1d<double, 3 > & N
470  )
471  {
472  double x0 = coordinates(0,0);
473  double y0 = coordinates(0,1);
474  double x1 = coordinates(1,0);
475  double y1 = coordinates(1,1);
476  double x2 = coordinates(2,0);
477  double y2 = coordinates(2,1);
478 
479  double area = CalculateVol(x0, y0, x1, y1, x2, y2);
480  double inv_area = 0.0;
481  if (area == 0.0)
482  {
483  KRATOS_THROW_ERROR(std::logic_error, "element with zero area found", "");
484  } else
485  {
486  inv_area = 1.0 / area;
487  }
488 
489 
490  N[0] = CalculateVol(x1, y1, x2, y2, xc, yc) * inv_area;
491  N[1] = CalculateVol(x2, y2, x0, y0, xc, yc) * inv_area;
492  N[2] = CalculateVol(x0, y0, x1, y1, xc, yc) * inv_area;
493  //KRATOS_WATCH(N);
494 
495  if (N[0] >= 0.0 && N[1] >= 0.0 && N[2] >= 0.0 && N[0] <= 1.0 && N[1] <= 1.0 && N[2] <= 1.0) //if the xc yc is inside the triangle return true
496  return true;
497 
498  return false;
499  }
500 
501  static inline double CalculateVol(const double x0, const double y0,
502  const double x1, const double y1,
503  const double x2, const double y2
504  )
505  {
506  return 0.5 * ((x1 - x0)*(y2 - y0)- (y1 - y0)*(x2 - x0));
507  }
508 
509  };
510 
511 } // namespace Kratos.
512 
513 #endif // KRATOS_ENRICHMENT_UTILITIES_INCLUDED defined
514 
515 
This utility can be used to calculate the enriched shape function for tetrahedra element.
Definition: enrich_2d_2dofs.h:41
static int CalculateTriangleEnrichedShapeFuncions(TMatrixType const &rPoints, TGradientType const &DN_DX, TVectorType rDistances, TVectorType &rVolumes, TMatrixType &rGPShapeFunctionValues, TVectorType &rPartitionsSign, std::vector< TMatrixType > &rGradientsValue, TMatrixType &NEnriched, TVectorType &face_gauss_N, TVectorType &face_gauss_Nenriched, double &face_Area, TVectorType &face_n, unsigned int &type_of_cut)
Definition: enrich_2d_2dofs.h:86
Definition: amatrix_interface.h:41
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
x2
Definition: generate_frictional_mortar_condition.py:122
x1
Definition: generate_frictional_mortar_condition.py:121
int j
Definition: quadrature.py:648
float xc
Definition: rotating_cone.py:77
float yc
Definition: rotating_cone.py:78
N
Definition: sensitivityMatrix.py:29