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.
split_tetrahedra_utilities.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: Riccardo Rossi
11 //
12 //
13 
14 #if !defined(KRATOS_SPLIT_TETRAHEDRA_UTILITIES_INCLUDED )
15 #define KRATOS_SPLIT_TETRAHEDRA_UTILITIES_INCLUDED
16 
17 // System includes
18 #include <string>
19 #include <iostream>
20 #include <algorithm>
21 #include <limits>
22 
23 // External includes
24 
25 // Project includes
26 #include "includes/define.h"
28 
29 namespace Kratos
30 {
31 
45 {
46 public:
65  template<class TMatrixType, class TVectorType, class TGradientType>
66  static int CalculateSplitTetrahedraShapeFuncions(TMatrixType const& rPoints, TGradientType const& DN_DX, TVectorType& rDistances,
67  TVectorType& rVolumes, TMatrixType& rShapeFunctionValues,
68  TVectorType& rPartitionsSign, TVectorType& rEdgeAreas)
69  {
71 
72  const int n_nodes = 4; // it works only for tetrahedra
73  const int n_edges = 6; // it works only for tetrahedra
74 
75  const int edge_i[] = {0, 0, 0, 1, 1, 2};
76  const int edge_j[] = {1, 2, 3, 2, 3, 3};
77 
78 
79  int number_of_partitions = 1;
80 
81  array_1d<double, n_edges> edges_dx; // It will be initialize later
82  array_1d<double, n_edges> edges_dy; // It will be initialize later
83  array_1d<double, n_edges> edges_dz; // It will be initialize later
84  array_1d<double, n_edges> edges_length; // It will be initialize later
85  // The divided part length from first node of edge respect to the edge length
86  array_1d<double, n_edges> edge_division_i = ZeroVector(n_edges); // The 0 is for no split
87  // The divided part length from second node of edge respect to the edge length
88  array_1d<double, n_edges> edge_division_j = ZeroVector(n_edges); // The 0 is for no split
89 
90  BoundedMatrix<double, 8, 3 > aux_coordinates; //8 is the max number of nodes and aux_nodes
91  for (unsigned int i = 0; i < 4; i++)
92  for (unsigned int j = 0; j < 3; j++)
93  aux_coordinates(i, j) = rPoints(i, j);
94  for (unsigned int i = 4; i < 8; i++)
95  for (unsigned int j = 0; j < 3; j++)
96  aux_coordinates(i, j) = -10000.0; //set to a large number so that errors will be evident
97 
98  int split_edge[] = {0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1};
99  int new_node_id = 4;
101 
102  int n_negative_distance_nodes = 0;
103  int n_positive_distance_nodes = 0;
104  array_1d<int,4> signs(4,-2);//[] = {-2, -2, -2, -2};
105  //int zero_distance_nodes[] = {-1, -1, -1, -1};
106  array_1d<int,4> negative_distance_nodes(4,-1);//[] = {-1, -1, -1, -1};
107  array_1d<int,4> positive_distance_nodes(4,-1);//[] = {-1, -1, -1, -1};
108 
109  array_1d<double, n_nodes> exact_distance = rDistances;
111 
112  //compute edge lenghts and max_lenght
113  double max_lenght = 0.0;
114  for (int edge = 0; edge < n_edges; edge++)
115  {
116  const int i = edge_i[edge];
117  const int j = edge_j[edge];
118 
119  double dx = rPoints(j, 0) - rPoints(i, 0);
120  double dy = rPoints(j, 1) - rPoints(i, 1);
121  double dz = rPoints(j, 2) - rPoints(i, 2);
122 
123  double l = sqrt(dx * dx + dy * dy + dz * dz);
124 
125  edges_dx[edge] = dx;
126  edges_dy[edge] = dy;
127  edges_dz[edge] = dz;
128  edges_length[edge] = l;
129 
130  if(l > max_lenght)
131  max_lenght = l;
132  }
133 
134  //~ //modify the distances to avoid zeros
135  //~ for(unsigned int i=0; i<4;i++)
136  //~ {
137  //~ if(fabs(rDistances[i]) < 1e-4*max_lenght)
138  //~ {
139  //~ std::cout << "Modifying distance to avoid zero, node " << i << " distance " << rDistances[i] << " to " << 1e-4*max_lenght << std::endl;
140  //~ rDistances[i]=1e-4*max_lenght;
141  //~ }
142  //~ }
143 
144  //modify the distances to avoid not properly defined element intersections
145  //a not properly defined intersection is understood as a division whose positive distance volume is too small compared against the negative one
146  //~ double max_neg_d = -1e-10; // maximum negative distance
147  //~ double max_pos_d = 1e-10; // maximum positive distance
148 
149  //~ //get the maximum negative distance value
150  //~ for (unsigned int i=0; i<4; i++)
151  //~ {
152  //~ max_neg_d = std::min(max_neg_d, rDistances[i]);
153  //~ max_pos_d = std::max(max_pos_d, rDistances[i]);
154  //~ }
155 
156  //~ //modify the positve distance values to avoid undesired cuts
157  //~ double tol_rel_d = 1e-3; // relative tolerance for the max and min distances comparison
158 
159  //~ for (unsigned int i=0; i<4; i++)
160  //~ {
161  //~ //check the positive distance nodes
162  //~ if (rDistances[i] > 0.0)
163  //~ {
164  //~ //modify the distance if it is below the relative treshold
165  //~ if (fabs(rDistances[i]/max_neg_d) < tol_rel_d)
166  //~ {
167  //~ std::cout << "Distance modified from " << rDistances[i] << " to " << rDistances[i]+0.00001*max_lenght*(max_pos_d - max_neg_d) << std::endl;
168  //~ std::cout << "max_neg_d = " << max_neg_d << " max_pos_d = " << max_pos_d << std::endl;
169  //~ rDistances[i] += 0.00001*max_lenght*(max_pos_d - max_neg_d);
170  //~ }
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  //compute the abs exact distance for all of the nodes
208  if(new_node_id > 4) //at least one edge is cut
209  {
210  array_1d<double,3> base_point;
211  base_point[0] = aux_coordinates(4,0);
212  base_point[1] = aux_coordinates(4,1);
213  base_point[2] = aux_coordinates(4,2);
214 
215  for (int i_node = 0; i_node < n_nodes; i_node++)
216  {
217  double d = (rPoints(i_node,0) - base_point[0]) * grad_d[0] +
218  (rPoints(i_node,1) - base_point[1]) * grad_d[1] +
219  (rPoints(i_node,2) - base_point[2]) * grad_d[2] ;
220  abs_distance[i_node] = fabs(d);
221  }
222  }
223 
224 
225  for (int i_node = 0; i_node < n_nodes; i_node++)
226  {
227  if (rDistances[i_node] < 0.00)
228  {
229  signs[i_node] = -1;
230  negative_distance_nodes[n_negative_distance_nodes++] = i_node;
231  }
232  else
233  {
234  signs[i_node] = 1;
235  positive_distance_nodes[n_positive_distance_nodes++] = i_node;
236  }
237  }
238 
239  //assign correct sign to exact distance
240  for (int i = 0; i < n_nodes; i++)
241  {
242  if (rDistances[i] < 0.0)
243  exact_distance[i] = -abs_distance[i];
244  else
245  exact_distance[i] = abs_distance[i];
246  }
247 
248  //compute exact distance gradients
249  array_1d<double, 3 > exact_distance_gradient;
250  noalias(exact_distance_gradient) = prod(trans(DN_DX), exact_distance);
251 
252  array_1d<double, 3 > abs_distance_gradient;
253  noalias(abs_distance_gradient) = prod(trans(DN_DX), abs_distance);
254 
255  int number_of_splitted_edges = new_node_id - 4; //number of splitted edges
256 
257  double volume = edges_dx[0] * edges_dy[1] * edges_dz[2] -
258  edges_dx[0] * edges_dz[1] * edges_dy[2] +
259  edges_dy[0] * edges_dz[1] * edges_dx[2] -
260  edges_dy[0] * edges_dx[1] * edges_dz[2] +
261  edges_dz[0] * edges_dx[1] * edges_dy[2] -
262  edges_dz[0] * edges_dy[1] * edges_dx[2];
263 
264  const double one_sixth = 1.00 / 6.00;
265  volume *= one_sixth;
266 
267 
268  if (number_of_splitted_edges == 0) // no splitting
269  {
270 
271  //take the sign from the node with min distance
272  double min_distance = 1e9;
273  for (int j = 0; j < 4; j++)
274  if(exact_distance[j] < min_distance) min_distance = exact_distance[j];
275 
276  if(min_distance < 0.0)
277  rPartitionsSign[0] = -1.0;
278  else
279  rPartitionsSign[0] = 1.0;
280 
282 
283  if(rShapeFunctionValues.size1() != 4 || rShapeFunctionValues.size2() != 4)
284  rShapeFunctionValues.resize(4,4,false);
285  }
286  else //if (number_of_splitted_edges == 4)
287  {
288  //define the splitting mode for the tetrahedra
289  int edge_ids[6];
290  TetrahedraSplit::TetrahedraSplitMode(split_edge, edge_ids);
291  int nel; //number of elements generated
292  int n_splitted_edges; //number of splitted edges
293  int nint; //number of internal nodes
294  int t[56];
295  TetrahedraSplit::Split_Tetrahedra(edge_ids, t, &nel, &n_splitted_edges, &nint);
296 
297  if (nint != 0)
298  KRATOS_THROW_ERROR(std::logic_error, "requiring an internal node for splitting ... can not accept this", "");
299 
300  //now obtain the tetras and compute their center coordinates and volume
301  if(rShapeFunctionValues.size1() != (unsigned int)(nel)*4 || rShapeFunctionValues.size2() != 4)
302  rShapeFunctionValues.resize(nel*4,4,false);
303 
304  std::vector< array_1d<double, 3 > >center_position(4);
305  Vector gauss_volumes(4);
306  if(rVolumes.size() != (unsigned int)(nel)*4)
307  rVolumes.resize(nel*4,false);
308 
309  array_1d<double,4> local_subtet_indices;
310  noalias(rEdgeAreas) = ZeroVector(6);
311 
312  for (int i = 0; i < nel; i++)
313  {
314  int i0, i1, i2, i3; //indices of the subtetrahedra
315  TetrahedraSplit::TetrahedraGetNewConnectivityGID(i, t, split_edge, &i0, &i1, &i2, &i3);
316 
317  //~ ComputeSubTetraVolumeAndGaussPoints(aux_coordinates, gauss_volumes, center_position, i0, i1, i2, i3);
318  double sub_volume = ComputeSubTetraVolumeAndGaussPoints(aux_coordinates, gauss_volumes, center_position, i0, i1, i2, i3);
319 
320  local_subtet_indices[0] = t[i*4];
321  local_subtet_indices[1] = t[i*4+1];
322  local_subtet_indices[2] = t[i*4+2];
323  local_subtet_indices[3] = t[i*4+3];
324 
325  AddToEdgeAreas3D(rEdgeAreas,exact_distance,local_subtet_indices,sub_volume);
326 
327  for(unsigned int k=0; k<4; k++)
328  {
329  rVolumes[i*4+k] = gauss_volumes[k];
330 
332  ComputeElementCoordinates(N, center_position[k], rPoints, volume);
333 
334  for (int j = 0; j < 4; j++)
335  rShapeFunctionValues(i*4+k, j) = N[j];
336  }
337  }
338 
339  number_of_partitions = nel;
340 
341  }
342 
343  if (number_of_partitions > 1) // we won't calculate the N and its gradients for element without partitions
344  {
345  //compute the maximum absolute distance on the cut so to normalize the shape functions
346  //now decide splitting pattern
347  double max_aux_dist_on_cut = -1;
348  for (int edge = 0; edge < n_edges; edge++)
349  {
350  const int i = edge_i[edge];
351  const int j = edge_j[edge];
352  if (rDistances[i] * rDistances[j] < 0.0)
353  {
354  const double tmp = fabs(rDistances[i]) / (fabs(rDistances[i]) + fabs(rDistances[j]));
355 
356  //compute the position of the edge node
357  double abs_dist_on_cut = abs_distance[i] * tmp + abs_distance[j] * (1.00 - tmp);
358 
359  if(abs_dist_on_cut > max_aux_dist_on_cut) max_aux_dist_on_cut = abs_dist_on_cut;
360 
361  }
362  }
363 
364  if(max_aux_dist_on_cut < 1e-9*max_lenght)
365  max_aux_dist_on_cut = 1e-9*max_lenght;
366 
367  if(rPartitionsSign.size() != (unsigned int)(number_of_partitions)*4)
368  rPartitionsSign.resize(number_of_partitions*4,false);
369 
370  for (int i = 0; i < number_of_partitions*4; i++) //i is the gauss point number
371  {
372  //compute enriched shape function values
373  double dist = 0.0;
374  double abs_dist = 0.0;
375  for (int j = 0; j < 4; j++)
376  {
377  dist += rShapeFunctionValues(i, j) * exact_distance[j];
378  abs_dist += rShapeFunctionValues(i, j) * abs_distance[j];
379  }
380 
381  if (dist < 0.0)
382  rPartitionsSign[i] = -1.0;
383  else
384  rPartitionsSign[i] = 1.0;
385  }
386  }
387 
388  return number_of_partitions;
389  KRATOS_CATCH("");
390  }
391 
392 private:
393 
394  //compute 1 gauss point per subtetra
395  static double ComputeSubTetraVolumeAndCenter(const BoundedMatrix<double, 3, 8 > & aux_coordinates,
396  array_1d<double, 3 > & center_position,
397  const int i0, const int i1, const int i2, const int i3)
398  {
399  double x10 = aux_coordinates(i1, 0) - aux_coordinates(i0, 0); //geom[1].X() - geom[0].X();
400  double y10 = aux_coordinates(i1, 1) - aux_coordinates(i0, 1); // geom[1].Y() - geom[0].Y();
401  double z10 = aux_coordinates(i1, 2) - aux_coordinates(i0, 2); // geom[1].Z() - geom[0].Z();
402 
403  double x20 = aux_coordinates(i2, 0) - aux_coordinates(i0, 0); // geom[2].X() - geom[0].X();
404  double y20 = aux_coordinates(i2, 1) - aux_coordinates(i0, 1); // geom[2].Y() - geom[0].Y();
405  double z20 = aux_coordinates(i2, 2) - aux_coordinates(i0, 2); // geom[2].Z() - geom[0].Z();
406 
407  double x30 = aux_coordinates(i3, 0) - aux_coordinates(i0, 0); // geom[3].X() - geom[0].X();
408  double y30 = aux_coordinates(i3, 1) - aux_coordinates(i0, 1); // geom[3].Y() - geom[0].Y();
409  double z30 = aux_coordinates(i3, 2) - aux_coordinates(i0, 2); // geom[3].Z() - geom[0].Z();
410 
411  double detJ = x10 * y20 * z30 - x10 * y30 * z20 + y10 * z20 * x30 - y10 * x20 * z30 + z10 * x20 * y30 - z10 * y20 * x30;
412  double vol = detJ * 0.1666666666666666666667;
413 
414  for (unsigned int i = 0; i < 3; i++)
415  {
416  center_position[i] = aux_coordinates(i0, i) + aux_coordinates(i1, i) + aux_coordinates(i2, i) + aux_coordinates(i3, i);
417  }
418  center_position *= 0.25;
419 
420  return vol;
421  }
422 
423 
424  //compute 4 gauss point per subtetra
425  static double ComputeSubTetraVolumeAndGaussPoints(const BoundedMatrix<double, 3, 8 > & aux_coordinates,
426  Vector& volumes,
427  std::vector< array_1d<double, 3 > >& center_position,
428  const int i0, const int i1, const int i2, const int i3)
429  {
430  double x10 = aux_coordinates(i1, 0) - aux_coordinates(i0, 0); // geom[1].X() - geom[0].X();
431  double y10 = aux_coordinates(i1, 1) - aux_coordinates(i0, 1); // geom[1].Y() - geom[0].Y();
432  double z10 = aux_coordinates(i1, 2) - aux_coordinates(i0, 2); // geom[1].Z() - geom[0].Z();
433 
434  double x20 = aux_coordinates(i2, 0) - aux_coordinates(i0, 0); // geom[2].X() - geom[0].X();
435  double y20 = aux_coordinates(i2, 1) - aux_coordinates(i0, 1); // geom[2].Y() - geom[0].Y();
436  double z20 = aux_coordinates(i2, 2) - aux_coordinates(i0, 2); // geom[2].Z() - geom[0].Z();
437 
438  double x30 = aux_coordinates(i3, 0) - aux_coordinates(i0, 0); // geom[3].X() - geom[0].X();
439  double y30 = aux_coordinates(i3, 1) - aux_coordinates(i0, 1); // geom[3].Y() - geom[0].Y();
440  double z30 = aux_coordinates(i3, 2) - aux_coordinates(i0, 2); // geom[3].Z() - geom[0].Z();
441 
442  double detJ = x10 * y20 * z30 - x10 * y30 * z20 + y10 * z20 * x30 - y10 * x20 * z30 + z10 * x20 * y30 - z10 * y20 * x30;
443  double vol = detJ * 0.1666666666666666666667;
444 
445  for (unsigned int i = 0; i < 4; i++)
446  {
447  volumes[i] = 0.25*vol;
448  }
449 
450  //gauss point 0
451  for (unsigned int i = 0; i < 3; i++)
452  {
453  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);
454  }
455  //gauss point 1
456  for (unsigned int i = 0; i < 3; i++)
457  {
458  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);
459  }
460 
461  //gauss point 2
462  for (unsigned int i = 0; i < 3; i++)
463  {
464  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);
465  }
466 
467  //gauss point 3
468  for (unsigned int i = 0; i < 3; i++)
469  {
470  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);
471  }
472 
473  return vol;
474  }
475 
476 
477  template<class TMatrixType>
478  static void ComputeElementCoordinates(array_1d<double, 4 > & N,
479  const array_1d<double, 3 > & center_position,
480  const TMatrixType& rPoints,
481  const double vol)
482  {
483  double x0 = rPoints(0, 0); //geom[0].X();
484  double y0 = rPoints(0, 1); //geom[0].Y();
485  double z0 = rPoints(0, 2); //geom[0].Z();
486  double x1 = rPoints(1, 0); //geom[1].X();
487  double y1 = rPoints(1, 1); //geom[1].Y();
488  double z1 = rPoints(1, 2); //geom[1].Z();
489  double x2 = rPoints(2, 0); //geom[2].X();
490  double y2 = rPoints(2, 1); //geom[2].Y();
491  double z2 = rPoints(2, 2); //geom[2].Z();
492  double x3 = rPoints(3, 0); //geom[3].X();
493  double y3 = rPoints(3, 1); //geom[3].Y();
494  double z3 = rPoints(3, 2); //geom[3].Z();
495 
496  double xc = center_position[0];
497  double yc = center_position[1];
498  double zc = center_position[2];
499 
500  double inv_vol = 1.0 / vol;
501  // N[0] = CalculateVol(x1, y1, z1, x3, y3, z3, x2, y2, z2, xc, yc, zc) * inv_vol;
502  // N[1] = CalculateVol(x0, y0, z0, x1, y1, z1, x2, y2, z2, xc, yc, zc) * inv_vol;
503  // N[2] = CalculateVol(x3, y3, z3, x1, y1, z1, x0, y0, z0, xc, yc, zc) * inv_vol;
504  // N[3] = CalculateVol(x3, y3, z3, x0, y0, z0, x2, y2, z2, xc, yc, zc) * inv_vol;
505  N[0] = CalculateVol(x1, y1, z1, x3, y3, z3, x2, y2, z2, xc, yc, zc) * inv_vol;
506  N[1] = CalculateVol(x0, y0, z0, x2, y2, z2, x3, y3, z3, xc, yc, zc) * inv_vol;
507  N[2] = CalculateVol(x3, y3, z3, x1, y1, z1, x0, y0, z0, xc, yc, zc) * inv_vol;
508  N[3] = CalculateVol(x1, y1, z1, x2, y2, z2, x0, y0, z0, xc, yc, zc) * inv_vol;
509 
510  }
511 
512 
513  static inline double CalculateVol(const double x0, const double y0, const double z0,
514  const double x1, const double y1, const double z1,
515  const double x2, const double y2, const double z2,
516  const double x3, const double y3, const double z3)
517  {
518  double x10 = x1 - x0;
519  double y10 = y1 - y0;
520  double z10 = z1 - z0;
521 
522  double x20 = x2 - x0;
523  double y20 = y2 - y0;
524  double z20 = z2 - z0;
525 
526  double x30 = x3 - x0;
527  double y30 = y3 - y0;
528  double z30 = z3 - z0;
529 
530  double detJ = x10 * y20 * z30 - x10 * y30 * z20 + y10 * z20 * x30 - y10 * x20 * z30 + z10 * x20 * y30 - z10 * y20 * x30;
531  return detJ * 0.1666666666666666666667;
532  }
533 
534 
535  template<class TVectorType>
536  static void AddToEdgeAreas3D(TVectorType& rEdgeAreas,
537  const array_1d<double, 3+1 >& exact_distance,
538  const array_1d<double, 3+1 >& indices,
539  const double sub_volume)
540  {
541  //check if the element has 3 "nodes" on the cut surface and if the remaining one is positive
542  //to do so, remember that edge nodes are marked with an id greater than 3
543  unsigned int ncut=0, pos=0, positive_pos=0;
544  for(unsigned int i=0; i<3+1; i++)
545  {
546  if(indices[i] > 3)
547  {
548  ncut++;
549  }
550  else if(exact_distance[indices[i]] > 0)
551  {
552  positive_pos = indices[i];
553  pos++;
554  }
555  }
556 
557  if(ncut == 3 && pos==1) //cut face with a positive node!!
558  {
559  double edge_area = sub_volume*3.0/fabs(exact_distance[positive_pos]);
560  edge_area /= static_cast<double>(3);
561  for(unsigned int i=0; i<3+1; i++)
562  {
563  if( indices[i] > 3)
564  {
565  int edge_index = indices[i] - 3 - 1;
566  rEdgeAreas[edge_index] += edge_area;
567  }
568  }
569  }
570  }
571 
572 };
573 
574 } // namespace Kratos.
575 
576 #endif // KRATOS_SPLIT_TETRAHEDRA_UTILITIES_INCLUDED defined
577 
578 
Definition: amatrix_interface.h:41
Definition: split_tetrahedra_utilities.h:45
static int CalculateSplitTetrahedraShapeFuncions(TMatrixType const &rPoints, TGradientType const &DN_DX, TVectorType &rDistances, TVectorType &rVolumes, TMatrixType &rShapeFunctionValues, TVectorType &rPartitionsSign, TVectorType &rEdgeAreas)
Definition: split_tetrahedra_utilities.h:66
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