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.
enrichment_utilities_duplicate_dofs.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_UTILITIES_DUPLICATE_DOFS_INCLUDED )
16 #define KRATOS_ENRICHMENT_UTILITIES_DUPLICATE_DOFS_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"
32 
33 
34 namespace Kratos
35 {
36 
63 {
64 public:
65 
88  template<class TMatrixType, class TVectorType, class TGradientType>
89  static int CalculateTetrahedraEnrichedShapeFuncions(TMatrixType const& rPoints, TGradientType const& DN_DX,
90  TVectorType& rDistances, TVectorType& rVolumes, TMatrixType& rShapeFunctionValues,
91  TVectorType& rPartitionsSign, std::vector<TMatrixType>& rGradientsValue, TMatrixType& NEnriched)
92  {
94 
95  const int n_nodes = 4; // it works only for tetrahedra
96  const int n_edges = 6; // it works only for tetrahedra
97 
98  const int edge_i[] = {0, 0, 0, 1, 1, 2};
99  const int edge_j[] = {1, 2, 3, 2, 3, 3};
100 
101 
102  int number_of_partitions = 1;
103 
104  array_1d<double, n_edges> edges_dx; // It will be initialize later
105  array_1d<double, n_edges> edges_dy; // It will be initialize later
106  array_1d<double, n_edges> edges_dz; // It will be initialize later
107  array_1d<double, n_edges> edges_length; // It will be initialize later
108  // The divided part length from first node of edge respect to the edge length
109  array_1d<double, n_edges> edge_division_i = ZeroVector(n_edges); // The 0 is for no split
110  // The divided part length from second node of edge respect to the edge length
111  array_1d<double, n_edges> edge_division_j = ZeroVector(n_edges); // The 0 is for no split
112 
113  BoundedMatrix<double, 8, 3 > aux_coordinates; //8 is the max number of nodes and aux_nodes
114  for (unsigned int i = 0; i < 4; i++)
115  for (unsigned int j = 0; j < 3; j++)
116  aux_coordinates(i, j) = rPoints(i, j);
117  for (unsigned int i = 4; i < 8; i++)
118  for (unsigned int j = 0; j < 3; j++)
119  aux_coordinates(i, j) = -10000.0; //set to a large number so that errors will be evident
120 
121  int split_edge[] = {0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1};
122  int new_node_id = 4;
124 
125  //int n_zero_distance_nodes = 0;
126  int n_negative_distance_nodes = 0;
127  int n_positive_distance_nodes = 0;
128  array_1d<int,4> signs(4,-2);//[] = {-2, -2, -2, -2};
129  //int zero_distance_nodes[] = {-1, -1, -1, -1};
130  array_1d<int,4> negative_distance_nodes(4,-1);//[] = {-1, -1, -1, -1};
131  array_1d<int,4> positive_distance_nodes(4,-1);//[] = {-1, -1, -1, -1};
132 
133 // for (int i = 0; i < 6; i++)
134 // for (int j = 0; j < n_nodes; j++)
135 // rShapeFunctionValues(i, j) = 0.25;
136 
137 
138 
139 
140 
141 
142  array_1d<double, n_nodes> exact_distance = rDistances;
144  //double sub_volumes_sum = 0.00;
145 
146  //compute edge lenghts and max_lenght
147  double max_lenght = 0.0;
148  for (int edge = 0; edge < n_edges; edge++)
149  {
150  const int i = edge_i[edge];
151  const int j = edge_j[edge];
152 
153  double dx = rPoints(j, 0) - rPoints(i, 0);
154  double dy = rPoints(j, 1) - rPoints(i, 1);
155  double dz = rPoints(j, 2) - rPoints(i, 2);
156 
157  double l = sqrt(dx * dx + dy * dy + dz * dz);
158 
159  edges_dx[edge] = dx;
160  edges_dy[edge] = dy;
161  edges_dz[edge] = dz;
162  edges_length[edge] = l;
163 
164  if(l > max_lenght)
165  max_lenght = l;
166  }
167 
168  //modify the distances to avoid zeros
169  for(unsigned int i=0; i<4;i++)
170  if(fabs(rDistances[i]) < 1e-4*max_lenght) rDistances[i]=1e-4*max_lenght;
171 
172 
173 
174  for (unsigned int i = 0; i < 4; i++)
175  abs_distance[i] = fabs(rDistances[i]);
176 
177  //compute the gradient of the distance and normalize it
178  array_1d<double, 3 > grad_d;
179  noalias(grad_d) = prod(trans(DN_DX), rDistances);
180  double norm = norm_2(grad_d);
181 
182  if(norm < 1e-10) norm=1e-10;
183 
184  grad_d /= (norm);
185 
186  //now decide splitting pattern
187  for (int edge = 0; edge < n_edges; edge++)
188  {
189  const int i = edge_i[edge];
190  const int j = edge_j[edge];
191  if (rDistances[i] * rDistances[j] < 0.0)
192  {
193  const double tmp = fabs(rDistances[i]) / (fabs(rDistances[i]) + fabs(rDistances[j]));
194 
195  split_edge[edge + 4] = new_node_id;
196  edge_division_i[edge] = tmp;
197  edge_division_j[edge] = 1.00 - tmp;
198 
199  //compute the position of the edge node
200  for (unsigned int k = 0; k < 3; k++)
201  aux_coordinates(new_node_id, k) = rPoints(i, k) * edge_division_j[edge] + rPoints(j, k) * edge_division_i[edge];
202 
203  new_node_id++;
204 
205  }
206  }
207 
208  //compute the abs exact distance for all of the nodes
209  if(new_node_id > 4) //at least one edge is cut
210  {
211  array_1d<double,3> base_point;
212  base_point[0] = aux_coordinates(4,0);
213  base_point[1] = aux_coordinates(4,1);
214  base_point[2] = aux_coordinates(4,2);
215 
216 
217  for (int i_node = 0; i_node < n_nodes; i_node++)
218  {
219  double d = (rPoints(i_node,0) - base_point[0]) * grad_d[0] +
220  (rPoints(i_node,1) - base_point[1]) * grad_d[1] +
221  (rPoints(i_node,2) - base_point[2]) * grad_d[2] ;
222  abs_distance[i_node] = fabs(d);
223  }
224 
225  }
226 
227 
228  for (int i_node = 0; i_node < n_nodes; i_node++)
229  {
230 // if (collapsed_node[i_node] == true)
231 // {
232 // abs_distance[i_node] = 0.0;
233 // signs[i_node] = 1;
234 // positive_distance_nodes[n_negative_distance_nodes++] = i_node;
235 // // zero_distance_nodes[n_zero_distance_nodes++] = i_node;
236 // }
237 // else
238  if (rDistances[i_node] < 0.00)
239  {
240  signs[i_node] = -1;
241  negative_distance_nodes[n_negative_distance_nodes++] = i_node;
242  }
243  else
244  {
245  signs[i_node] = 1;
246  positive_distance_nodes[n_positive_distance_nodes++] = i_node;
247  }
248  }
249 
250  //assign correct sign to exact distance
251  for (int i = 0; i < n_nodes; i++)
252  {
253  if (rDistances[i] < 0.0)
254  exact_distance[i] = -abs_distance[i];
255  else
256  exact_distance[i] = abs_distance[i];
257  }
258 
259  //compute exact distance gradients
260  array_1d<double, 3 > exact_distance_gradient;
261  noalias(exact_distance_gradient) = prod(trans(DN_DX), exact_distance);
262 
263  array_1d<double, 3 > abs_distance_gradient;
264  noalias(abs_distance_gradient) = prod(trans(DN_DX), abs_distance);
265 
266  int number_of_splitted_edges = new_node_id - 4; //number of splitted edges
267 
268  double volume = edges_dx[0] * edges_dy[1] * edges_dz[2] -
269  edges_dx[0] * edges_dz[1] * edges_dy[2] +
270  edges_dy[0] * edges_dz[1] * edges_dx[2] -
271  edges_dy[0] * edges_dx[1] * edges_dz[2] +
272  edges_dz[0] * edges_dx[1] * edges_dy[2] -
273  edges_dz[0] * edges_dy[1] * edges_dx[2];
274 
275  const double one_sixth = 1.00 / 6.00;
276  volume *= one_sixth;
277 
278 
279  // KRATOS_WATCH(volume)
280  if (number_of_splitted_edges == 0) // no splitting
281  {
282 // rVolumes.resize(1,false)
283 // rVolumes[0] = volume;
284 // sub_volumes_sum = volume;
285 // // Looking for the first node with sign not zero to get the sign of the element.
286 // for (int i_node = 0; i_node < n_nodes; i_node++)
287 // if (signs[i_node] != 0) {
288 // rPartitionsSign[0] = signs[i_node];
289 // break;
290 // }
291  //take the sign from the node with min distance
292  double min_distance = 1e9;
293  for (int j = 0; j < 4; j++)
294  if(exact_distance[j] < min_distance) min_distance = exact_distance[j];
295 
296 // KRATOS_/*WATCH*/("line 358")
297 
298 
299  if(min_distance < 0.0)
300  rPartitionsSign[0] = -1.0;
301  else
302  rPartitionsSign[0] = 1.0;
303 
305 
306  if(rShapeFunctionValues.size1() != 4 || rShapeFunctionValues.size2() != 4)
307  rShapeFunctionValues.resize(4,4,false);
308 
309 // for (int j = 0; j < 4; j++)
310 // rShapeFunctionValues(0, j) = 0.25;
311 // KRATOS_WATCH("line 374")
312 
313  if(NEnriched.size1() != 0 || NEnriched.size2() != 0)
314  NEnriched.resize(0,0,false);
315 // KRATOS_WATCH("line 377")
316 
317  if(rGradientsValue.size() !=0)
318  rGradientsValue.resize(0);
319 // KRATOS_WATCH("line 382")
320 
321 // for (int j = 0; j < number_of_partitions; j++)
322 // NEnriched(j, 0) = 0.0;
323 
324 // rGradientsValue[0] = ZeroMatrix(1,3);
325  }
326  else //if (number_of_splitted_edges == 4)
327  {
328  //define the splitting mode for the tetrahedra
329  int edge_ids[6];
330  TetrahedraSplit::TetrahedraSplitMode(split_edge, edge_ids);
331  int nel=0; //number of elements generated
332  int n_splitted_edges; //number of splitted edges
333  int nint; //number of internal nodes
334  int t[56];
335  TetrahedraSplit::Split_Tetrahedra(edge_ids, t, &nel, &n_splitted_edges, &nint);
336 
337 // KRATOS_WATCH("line 395")
338 
339 
340  if (nint != 0)
341  KRATOS_THROW_ERROR(std::logic_error, "requiring an internal node for splitting ... can not accept this", "");
342 
343 
344  //now obtain the tetras and compute their center coordinates and volume
345  if(rShapeFunctionValues.size1() != (unsigned int)(nel)*4 || rShapeFunctionValues.size2() != 4)
346  rShapeFunctionValues.resize(nel*4,4,false);
347 
348  std::vector< array_1d<double, 3 > >center_position(4);
349  Vector gauss_volumes(4);
350  if(rVolumes.size() != (unsigned int)(nel)*4)
351  rVolumes.resize(nel*4,false);
352 
353  for (int i = 0; i < nel; i++)
354  {
355  int i0, i1, i2, i3; //indices of the subtetrahedra
356  TetrahedraSplit::TetrahedraGetNewConnectivityGID(i, t, split_edge, &i0, &i1, &i2, &i3);
357 
358 
359 // double sub_volume = ComputeSubTetraVolumeAndCenter(aux_coordinates, center_position, i0, i1, i2, i3);
360  ComputeSubTetraVolumeAndGaussPoints(aux_coordinates, gauss_volumes, center_position, i0, i1, i2, i3);
361 // KRATOS_WATCH("line 414")
362  for(unsigned int k=0; k<4; k++)
363  {
364  rVolumes[i*4+k] = gauss_volumes[k];
365 
367  ComputeElementCoordinates(N, center_position[k], rPoints, volume);
368 
369  for (int j = 0; j < 4; j++)
370  rShapeFunctionValues(i*4+k, j) = N[j];
371  }
372 
373 // KRATOS_WATCH("line 426")
374 
375 
376 
377  }
378 
379  number_of_partitions = nel;
380 
381  }
382 
383 // if(fabs(sub_volumes_sum/volume - 1.0) > 1e-9)
384 // {
385 // KRATOS_WATCH(volume);
386 // KRATOS_WATCH(rVolumes);
387 // KRATOS_WATCH(sub_volumes_sum);
388 // KRATOS_THROW_ERROR(std::logic_error,"the elemental volume does not match the sum of the sub volumes","")
389 // }
390 // KRATOS_WATCH(exact_distance);
391 // KRATOS_WATCH(abs_distance);
392 
393  //double verify_volume = 0.0;
394  if (number_of_partitions > 1) // we won't calculate the N and its gradients for element without partitions
395  {
396  if(NEnriched.size1() != (unsigned int)(number_of_partitions)*4 || NEnriched.size2() != 4)
397  NEnriched.resize(number_of_partitions*4,4,false);
398 
399  //compute the maximum absolute distance on the cut so to normalize the shape functions
400  //now decide splitting pattern
401  double max_aux_dist_on_cut = -1;
402  for (int edge = 0; edge < n_edges; edge++)
403  {
404  const int i = edge_i[edge];
405  const int j = edge_j[edge];
406  if (rDistances[i] * rDistances[j] < 0.0)
407  {
408  const double tmp = fabs(rDistances[i]) / (fabs(rDistances[i]) + fabs(rDistances[j]));
409 
410  //compute the position of the edge node
411  double abs_dist_on_cut = abs_distance[i] * tmp + abs_distance[j] * (1.00 - tmp);
412 
413  if(abs_dist_on_cut > max_aux_dist_on_cut) max_aux_dist_on_cut = abs_dist_on_cut;
414 
415  }
416  }
417 
418  /* if(max_aux_dist_on_cut < 1e-10)
419  max_aux_dist_on_cut = 1e-10;*/
420  if(max_aux_dist_on_cut < 1e-9*max_lenght)
421  max_aux_dist_on_cut = 1e-9*max_lenght;
422 
423  if(rGradientsValue.size() != (unsigned int)(number_of_partitions)*4)
424  rGradientsValue.resize(number_of_partitions*4);
425 
426  if(rPartitionsSign.size() != (unsigned int)(number_of_partitions)*4)
427  rPartitionsSign.resize(number_of_partitions*4,false);
428 
429 // KRATOS_WATCH(rShapeFunctionValues)
430 
431  for (int i = 0; i < number_of_partitions*4; i++) //i is the gauss point number
432  {
433  //compute enriched shape function values
434  double dist = 0.0;
435  double abs_dist = 0.0;
436  for (int j = 0; j < 4; j++)
437  {
438  dist += rShapeFunctionValues(i, j) * exact_distance[j];
439  abs_dist += rShapeFunctionValues(i, j) * abs_distance[j];
440  }
441 
442  if (dist < 0.0)
443  rPartitionsSign[i] = -1.0;
444  else
445  rPartitionsSign[i] = 1.0;
446 
447  rGradientsValue[i] = DN_DX;
448 
449  double disc_factor;
450  for( unsigned int j = 0 ; j<rShapeFunctionValues.size2(); j++)
451  {
452  if(exact_distance[j]*dist > 0) //shape function corresponding to a node on the same side as the gauss point
453  disc_factor = 0.0;
454  else
455  disc_factor = 1.0;
456 
457  //if( fabs(dist) < relatively_close)
458  // disc_factor = 0.0;
459 
460  NEnriched(i,j) = disc_factor * rShapeFunctionValues(i,j);
461 
462 
463  for(unsigned int k=0; k<3; k++)
464  {
465  rGradientsValue[i](j, k) *= disc_factor;
466  }
467  }
468 
469 
470 
471 
472  }
473  }
474 // else
475 // {
476 // if(NEnriched.size1() != 6 || NEnriched.size2() != 1)
477 // NEnriched.resize(1,1,false);
478 //
479 // //compute multiplier
480 // NEnriched(0,0) = 0.0;
481 //
482 // for (int j = 0; j < 3; j++)
483 // rGradientsValue[0](0, j) = 0.0;
484 // }
485 
486  return number_of_partitions;
487  KRATOS_CATCH("");
488 }
489 
490 
491 
492 private:
493 
494 
495 static double ComputeSubTetraVolumeAndCenter(const BoundedMatrix<double, 3, 8 > & aux_coordinates,
496  array_1d<double, 3 > & center_position,
497  const int i0, const int i1, const int i2, const int i3)
498 {
499  double x10 = aux_coordinates(i1, 0) - aux_coordinates(i0, 0); //geom[1].X() - geom[0].X();
500  double y10 = aux_coordinates(i1, 1) - aux_coordinates(i0, 1); // geom[1].Y() - geom[0].Y();
501  double z10 = aux_coordinates(i1, 2) - aux_coordinates(i0, 2); // geom[1].Z() - geom[0].Z();
502 
503  double x20 = aux_coordinates(i2, 0) - aux_coordinates(i0, 0); // geom[2].X() - geom[0].X();
504  double y20 = aux_coordinates(i2, 1) - aux_coordinates(i0, 1); // geom[2].Y() - geom[0].Y();
505  double z20 = aux_coordinates(i2, 2) - aux_coordinates(i0, 2); // geom[2].Z() - geom[0].Z();
506 
507  double x30 = aux_coordinates(i3, 0) - aux_coordinates(i0, 0); // geom[3].X() - geom[0].X();
508  double y30 = aux_coordinates(i3, 1) - aux_coordinates(i0, 1); // geom[3].Y() - geom[0].Y();
509  double z30 = aux_coordinates(i3, 2) - aux_coordinates(i0, 2); // geom[3].Z() - geom[0].Z();
510 
511  double detJ = x10 * y20 * z30 - x10 * y30 * z20 + y10 * z20 * x30 - y10 * x20 * z30 + z10 * x20 * y30 - z10 * y20 * x30;
512  double vol = detJ * 0.1666666666666666666667;
513 
514  for (unsigned int i = 0; i < 3; i++)
515  {
516  center_position[i] = aux_coordinates(i0, i) + aux_coordinates(i1, i) + aux_coordinates(i2, i) + aux_coordinates(i3, i);
517  }
518  center_position *= 0.25;
519 
520  return vol;
521 }
522 
523 //compute 4 gauss point per subtetra
524 static void ComputeSubTetraVolumeAndGaussPoints(const BoundedMatrix<double, 3, 8 > & aux_coordinates,
525  Vector& volumes,
526  std::vector< array_1d<double, 3 > >& center_position,
527  const int i0, const int i1, const int i2, const int i3)
528 {
529  double x10 = aux_coordinates(i1, 0) - aux_coordinates(i0, 0); //geom[1].X() - geom[0].X();
530  double y10 = aux_coordinates(i1, 1) - aux_coordinates(i0, 1); // geom[1].Y() - geom[0].Y();
531  double z10 = aux_coordinates(i1, 2) - aux_coordinates(i0, 2); // geom[1].Z() - geom[0].Z();
532 
533  double x20 = aux_coordinates(i2, 0) - aux_coordinates(i0, 0); // geom[2].X() - geom[0].X();
534  double y20 = aux_coordinates(i2, 1) - aux_coordinates(i0, 1); // geom[2].Y() - geom[0].Y();
535  double z20 = aux_coordinates(i2, 2) - aux_coordinates(i0, 2); // geom[2].Z() - geom[0].Z();
536 
537  double x30 = aux_coordinates(i3, 0) - aux_coordinates(i0, 0); // geom[3].X() - geom[0].X();
538  double y30 = aux_coordinates(i3, 1) - aux_coordinates(i0, 1); // geom[3].Y() - geom[0].Y();
539  double z30 = aux_coordinates(i3, 2) - aux_coordinates(i0, 2); // geom[3].Z() - geom[0].Z();
540 
541  double detJ = x10 * y20 * z30 - x10 * y30 * z20 + y10 * z20 * x30 - y10 * x20 * z30 + z10 * x20 * y30 - z10 * y20 * x30;
542  double vol = detJ * 0.1666666666666666666667;
543 
544  for (unsigned int i = 0; i < 4; i++)
545  {
546  volumes[i] = 0.25*vol;
547  }
548 
549  //gauss point 0
550  for (unsigned int i = 0; i < 3; i++)
551  {
552  center_position[0][i] = 0.58541020*aux_coordinates(i0, i) + 0.13819660*aux_coordinates(i1, i) + 0.13819660*aux_coordinates(i2, i) + 0.13819660*aux_coordinates(i3, i);
553  }
554  //gauss point 1
555  for (unsigned int i = 0; i < 3; i++)
556  {
557  center_position[1][i] = 0.13819660*aux_coordinates(i0, i) + 0.58541020*aux_coordinates(i1, i) + 0.13819660*aux_coordinates(i2, i) + 0.13819660*aux_coordinates(i3, i);
558  }
559 
560  //gauss point 2
561  for (unsigned int i = 0; i < 3; i++)
562  {
563  center_position[2][i] = 0.13819660*aux_coordinates(i0, i) + 0.13819660*aux_coordinates(i1, i) + 0.58541020*aux_coordinates(i2, i) + 0.13819660*aux_coordinates(i3, i);
564  }
565 
566  //gauss point 3
567  for (unsigned int i = 0; i < 3; i++)
568  {
569  center_position[3][i] = 0.13819660*aux_coordinates(i0, i) + 0.13819660*aux_coordinates(i1, i) + 0.13819660*aux_coordinates(i2, i) + 0.58541020*aux_coordinates(i3, i);
570  }
571 
572 }
573 
574 
575 template<class TMatrixType>
576 static void ComputeElementCoordinates(array_1d<double, 4 > & N, const array_1d<double, 3 > & center_position, const TMatrixType& rPoints, const double vol)
577 {
578  double x0 = rPoints(0, 0); //geom[0].X();
579  double y0 = rPoints(0, 1); //geom[0].Y();
580  double z0 = rPoints(0, 2); //geom[0].Z();
581  double x1 = rPoints(1, 0); //geom[1].X();
582  double y1 = rPoints(1, 1); //geom[1].Y();
583  double z1 = rPoints(1, 2); //geom[1].Z();
584  double x2 = rPoints(2, 0); //geom[2].X();
585  double y2 = rPoints(2, 1); //geom[2].Y();
586  double z2 = rPoints(2, 2); //geom[2].Z();
587  double x3 = rPoints(3, 0); //geom[3].X();
588  double y3 = rPoints(3, 1); //geom[3].Y();
589  double z3 = rPoints(3, 2); //geom[3].Z();
590 
591  double xc = center_position[0];
592  double yc = center_position[1];
593  double zc = center_position[2];
594 
595  double inv_vol = 1.0 / vol;
596  // N[0] = CalculateVol(x1, y1, z1, x3, y3, z3, x2, y2, z2, xc, yc, zc) * inv_vol;
597  // N[1] = CalculateVol(x0, y0, z0, x1, y1, z1, x2, y2, z2, xc, yc, zc) * inv_vol;
598  // N[2] = CalculateVol(x3, y3, z3, x1, y1, z1, x0, y0, z0, xc, yc, zc) * inv_vol;
599  // N[3] = CalculateVol(x3, y3, z3, x0, y0, z0, x2, y2, z2, xc, yc, zc) * inv_vol;
600  N[0] = CalculateVol(x1, y1, z1, x3, y3, z3, x2, y2, z2, xc, yc, zc) * inv_vol;
601  N[1] = CalculateVol(x0, y0, z0, x2, y2, z2, x3, y3, z3, xc, yc, zc) * inv_vol;
602  N[2] = CalculateVol(x3, y3, z3, x1, y1, z1, x0, y0, z0, xc, yc, zc) * inv_vol;
603  N[3] = CalculateVol(x1, y1, z1, x2, y2, z2, x0, y0, z0, xc, yc, zc) * inv_vol;
604 
605 }
606 
607 static inline double CalculateVol(const double x0, const double y0, const double z0,
608  const double x1, const double y1, const double z1,
609  const double x2, const double y2, const double z2,
610  const double x3, const double y3, const double z3
611  )
612 {
613  double x10 = x1 - x0;
614  double y10 = y1 - y0;
615  double z10 = z1 - z0;
616 
617  double x20 = x2 - x0;
618  double y20 = y2 - y0;
619  double z20 = z2 - z0;
620 
621  double x30 = x3 - x0;
622  double y30 = y3 - y0;
623  double z30 = z3 - z0;
624 
625  double detJ = x10 * y20 * z30 - x10 * y30 * z20 + y10 * z20 * x30 - y10 * x20 * z30 + z10 * x20 * y30 - z10 * y20 * x30;
626  return detJ * 0.1666666666666666666667;
627 }
628 
629 //2d
630 static inline void CalculateGeometryData(
631  const BoundedMatrix<double, 3, 3 > & coordinates,
632  BoundedMatrix<double,3,2>& DN_DX,
633  array_1d<double,3>& N,
634  double& Area)
635 {
636  double x10 = coordinates(1,0) - coordinates(0,0);
637  double y10 = coordinates(1,1) - coordinates(0,1);
638 
639  double x20 = coordinates(2,0) - coordinates(0,0);
640  double y20 = coordinates(2,1) - coordinates (0,1);
641 
642  //Jacobian is calculated:
643  // |dx/dxi dx/deta| |x1-x0 x2-x0|
644  //J=| |= | |
645  // |dy/dxi dy/deta| |y1-y0 y2-y0|
646 
647 
648  double detJ = x10 * y20-y10 * x20;
649 
650  DN_DX(0,0) = -y20 + y10;
651  DN_DX(0,1) = x20 - x10;
652  DN_DX(1,0) = y20 ;
653  DN_DX(1,1) = -x20 ;
654  DN_DX(2,0) = -y10 ;
655  DN_DX(2,1) = x10 ;
656 
657  DN_DX /= detJ;
658  N[0] = 0.333333333333333;
659  N[1] = 0.333333333333333;
660  N[2] = 0.333333333333333;
661 
662  Area = 0.5*detJ;
663 }
664 
665 //template<class TMatrixType, class TVectorType, class TGradientType>
666 static inline double CalculateVolume2D(
667  const BoundedMatrix<double, 3, 3 > & coordinates)
668 {
669  double x10 = coordinates(1,0) - coordinates(0,0);
670  double y10 = coordinates(1,1) - coordinates(0,1);
671 
672  double x20 = coordinates(2,0) - coordinates(0,0);
673  double y20 = coordinates(2,1) - coordinates (0,1);
674  double detJ = x10 * y20-y10 * x20;
675  return 0.5*detJ;
676 }
677 
678 static inline bool CalculatePosition(const BoundedMatrix<double, 3, 3 > & coordinates,
679  const double xc, const double yc, const double zc,
680  array_1d<double, 3 > & N
681  )
682 {
683  double x0 = coordinates(0,0);
684  double y0 = coordinates(0,1);
685  double x1 = coordinates(1,0);
686  double y1 = coordinates(1,1);
687  double x2 = coordinates(2,0);
688  double y2 = coordinates(2,1);
689 
690  double area = CalculateVol(x0, y0, x1, y1, x2, y2);
691  double inv_area = 0.0;
692  if (area == 0.0)
693  {
694  KRATOS_THROW_ERROR(std::logic_error, "element with zero area found", "");
695  }
696  else
697  {
698  inv_area = 1.0 / area;
699  }
700 
701 
702  N[0] = CalculateVol(x1, y1, x2, y2, xc, yc) * inv_area;
703  N[1] = CalculateVol(x2, y2, x0, y0, xc, yc) * inv_area;
704  N[2] = CalculateVol(x0, y0, x1, y1, xc, yc) * inv_area;
705  //KRATOS_WATCH(N);
706 
707  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
708  return true;
709 
710  return false;
711 }
712 
713 static inline double CalculateVol(const double x0, const double y0,
714  const double x1, const double y1,
715  const double x2, const double y2
716  )
717 {
718  return 0.5 * ((x1 - x0)*(y2 - y0)- (y1 - y0)*(x2 - x0));
719 }
720 
721 static inline void CalculateGeometryData(
722  const BoundedMatrix<double, 3, 3 > & coordinates,
723  BoundedMatrix<double,3,2>& DN_DX,
724  double& Area)
725 {
726  double x10 = coordinates(1,0) - coordinates(0,0);
727  double y10 = coordinates(1,1) - coordinates(0,1);
728 
729  double x20 = coordinates(2,0) - coordinates(0,0);
730  double y20 = coordinates(2,1) - coordinates (0,1);
731 
732  //Jacobian is calculated:
733  // |dx/dxi dx/deta| |x1-x0 x2-x0|
734  //J=| |= | |
735  // |dy/dxi dy/deta| |y1-y0 y2-y0|
736 
737 
738  double detJ = x10 * y20-y10 * x20;
739 
740  DN_DX(0,0) = -y20 + y10;
741  DN_DX(0,1) = x20 - x10;
742  DN_DX(1,0) = y20 ;
743  DN_DX(1,1) = -x20 ;
744  DN_DX(2,0) = -y10 ;
745  DN_DX(2,1) = x10 ;
746 
747  DN_DX /= detJ;
748 
749  Area = 0.5*detJ;
750 }
751 
752 
753 };
754 
755 } // namespace Kratos.
756 
757 #endif // KRATOS_ENRICHMENT_UTILITIES_DUPLICATE_DOFS_INCLUDED defined
758 
759 
Definition: enrichment_utilities_duplicate_dofs.h:63
static int CalculateTetrahedraEnrichedShapeFuncions(TMatrixType const &rPoints, TGradientType const &DN_DX, TVectorType &rDistances, TVectorType &rVolumes, TMatrixType &rShapeFunctionValues, TVectorType &rPartitionsSign, std::vector< TMatrixType > &rGradientsValue, TMatrixType &NEnriched)
Definition: enrichment_utilities_duplicate_dofs.h:89
Definition: amatrix_interface.h:41
static int Split_Tetrahedra(const int edges[6], int t[56], int *nel, int *splitted_edges, int *nint)
Function to split a tetrahedron For a given edges splitting pattern, this function computes the inter...
Definition: split_tetrahedra.h:177
static void TetrahedraGetNewConnectivityGID(const int tetra_index, const int t[56], const int aux_ids[11], int *id0, int *id1, int *id2, int *id3)
Returns the ids of a subtetra Provided the splitting connectivities array and the array containing th...
Definition: split_tetrahedra.h:150
static void TetrahedraSplitMode(int aux_ids[11], int edge_ids[6])
Returns the edges vector filled with the splitting pattern. Provided the array of nodal ids,...
Definition: split_tetrahedra.h:91
Short class definition.
Definition: array_1d.h:61
#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
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
Internals::Matrix< double, AMatrix::dynamic, 1 > Vector
Definition: amatrix_interface.h:472
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
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
AMatrix::TransposeMatrix< const T > trans(const T &TheMatrix)
Definition: amatrix_interface.h:486
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
float dist
Definition: edgebased_PureConvection.py:89
x2
Definition: generate_frictional_mortar_condition.py:122
x1
Definition: generate_frictional_mortar_condition.py:121
tuple tmp
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:98
int n_nodes
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:15
int t
Definition: ode_solve.py:392
int d
Definition: ode_solve.py:397
int k
Definition: quadrature.py:595
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
volume
Definition: sp_statistics.py:15
number_of_partitions
Definition: square_domain.py:61
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31