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.
cutting_utility.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 #if !defined(KRATOS_CUTTING_UTILITY)
15 #define KRATOS_CUTTING_UTILITY
16 
17 // System includes
18 #ifdef _OPENMP
19 #include <omp.h>
20 #endif
21 #include <string>
22 #include <iostream>
23 #include <cstdlib>
24 #include <cmath>
25 #include <algorithm>
26 
27 // External includes
28 #include <boost/numeric/ublas/matrix.hpp>
29 #include <boost/numeric/ublas/vector.hpp>
30 #include <boost/numeric/ublas/banded.hpp>
31 #include <boost/numeric/ublas/matrix_sparse.hpp>
32 #include <boost/numeric/ublas/triangular.hpp>
33 #include <boost/numeric/ublas/operation.hpp>
34 #include <boost/numeric/ublas/lu.hpp>
35 
36 // Project includes
37 #include "includes/define.h"
38 #include "includes/model_part.h"
39 #include "includes/node.h"
40 #include "includes/dof.h"
41 #include "includes/variables.h"
42 #include "containers/array_1d.h"
45 #include "includes/mesh.h"
46 #include "utilities/math_utils.h"
52 
53 namespace Kratos
54 {
55 
57 
65 {
66 public:
67 
76  typedef Node PointType;
77  typedef Node ::Pointer PointPointerType;
78  typedef std::vector<PointType::Pointer> PointVector;
79  typedef PointVector::iterator PointIterator;
80 
84 
87  {
88  smallest_edge=1.0; //
89  }
90 
92  virtual ~CuttingUtility() {}
93 
94 
96 
100  void FindSmallestEdge(ModelPart& mr_model_part)
101  {
102  ModelPart& this_model_part = mr_model_part;
103  ElementsArrayType& rElements = this_model_part.Elements();
104  ElementsArrayType::iterator it_begin = rElements.ptr_begin();
105  ElementsArrayType::iterator it_end = rElements.ptr_end();
106  double dist_node_neigh; //distance between the two nodes of the edge
107  array_1d<double, 3 > node_coord; //
108  array_1d<double, 3 > neigh_coord; //
109  smallest_edge = 1000000000000000000000000000.0; //maybe the mesh is huge, setting a big number just in case
110  for (ElementsArrayType::iterator it = it_begin; it != it_end; ++it) //looping all the elements
111  {
112  Geometry<Node >&geom = it->GetGeometry(); //geometry of the element
113  for(unsigned int i = 0; i < it->GetGeometry().size() ; i++) //edge i
114  {
115  node_coord[0] = geom[i].X();
116  node_coord[1] = geom[i].Y();
117  node_coord[2] = geom[i].Z();
118  for(unsigned int j = 0; j < it->GetGeometry().size() ; j++) //edge i
119  {
120  neigh_coord[0] = geom[j].X();
121  neigh_coord[1] = geom[j].Y();
122  neigh_coord[2] = geom[j].Z();
123  dist_node_neigh = sqrt( pow((node_coord[0]- neigh_coord[0]),2) + pow((node_coord[1]- neigh_coord[1]),2) + pow((node_coord[2]- neigh_coord[2]),2) ) ; // distance between node and neighbour
124  if ((dist_node_neigh<smallest_edge) && (i!=j)) smallest_edge=dist_node_neigh; //saving the smallest found up to now
125  }//closing j loop
126  } //closing i loop
127  } //closing element loop
128  KRATOS_WATCH(smallest_edge);
129  } //closing function
130 
133 
135 
144  void GenerateCut(ModelPart& mr_model_part, ModelPart& mr_new_model_part, const array_1d<double, 3 >& versor, const array_1d<double, 3 >& Xp, int plane_number ,double tolerance_factor)
145  {
146  KRATOS_WATCH("Generating Cutting plane with the following data:")
147  KRATOS_WATCH(versor);
148  KRATOS_WATCH(Xp);
149  KRATOS_TRY
150 
151  if (!mr_new_model_part.GetNodalSolutionStepVariablesList().Has(FATHER_NODES) ||
152  !mr_new_model_part.GetNodalSolutionStepVariablesList().Has(WEIGHT_FATHER_NODES) )
153  KRATOS_ERROR << "The cut model part was not initialized. "
154  "Please call AddVariablesToCutModelPart before GenerateCut."
155  << std::endl;
156 
157  DenseVector<array_1d<int, 2 > > Position_Node;
158  DenseVector<int> List_New_Nodes;
159 
160  boost::numeric::ublas::compressed_matrix<int> Coord;
161  ModelPart& this_model_part = mr_model_part;
162  ModelPart& new_model_part = mr_new_model_part;
163 
164  DenseVector<int> Elems_In_Plane( this_model_part.Elements().size()); //our (int) vector, where we write 1 when the element is cut by the cutting plane. when it is 2, it means we have 2 triangles (4 cutting points)
165  int number_of_triangles = 0;
166  double tolerance = tolerance_factor*smallest_edge; //if Find_Smallest_Edge is not run , then the tolerance is absolute
167 
168  //finished creating the variables and vector/matrix needed. now we have to call the subroutines.
169  CSR_Row_Matrix_Mod(this_model_part, Coord);
170 
171  FirstLoop(this_model_part, Coord, versor, Xp, number_of_triangles, Elems_In_Plane, tolerance);
172 
173  Create_List_Of_New_Nodes_Mod(this_model_part, new_model_part, Coord, List_New_Nodes, Position_Node);
174 
175  Calculate_Coordinate_And_Insert_New_Nodes_Mod(this_model_part, new_model_part, Position_Node, List_New_Nodes, versor, Xp, tolerance);
176 
177  GenerateElements (this_model_part, new_model_part, Elems_In_Plane, Coord, versor, plane_number);
178 
179 
180  KRATOS_WATCH("Finished generating cutting plane")
181  KRATOS_CATCH("")
182  }
183 
184 
187 
188 
190 
196  void AddSkinConditions(ModelPart& mr_model_part, ModelPart& mr_new_model_part, int plane_number )
197  {
198  ModelPart& this_model_part = mr_model_part;
199  NodesArrayType::iterator it_begin_node_old = this_model_part.Nodes().ptr_begin();
200  ModelPart& new_model_part = mr_new_model_part;
201 
202  std::cout <<"Adding Skin Conditions to the new model part, added in layer:" << std::endl;
203  KRATOS_WATCH(plane_number)
204  KRATOS_TRY
205  DenseVector<int> Condition_Nodes( this_model_part.Nodes().size()); //our (int) vector, where we write -1 when the node is part of the condition faces
206  int number_of_triangles = 0; //we set it to zero to start
207  int number_of_nodes = 0; //same as above
208  int number_of_previous_nodes = 0; // nodes from the previous conditions (planes) created
209  int number_of_conditions = 0;
210 
211  if (!new_model_part.GetNodalSolutionStepVariablesList().Has(FATHER_NODES) ||
212  !new_model_part.GetNodalSolutionStepVariablesList().Has(WEIGHT_FATHER_NODES) )
213  KRATOS_ERROR << "The cut model part was not initialized. "
214  "Please call AddVariablesToCutModelPart before AddSkinConditions."
215  << std::endl;
216 
217  ConditionsArrayType& rConditions = this_model_part.Conditions();
218  ConditionsArrayType::iterator cond_it_begin = rConditions.ptr_begin();
219  ConditionsArrayType::iterator cond_it_end = rConditions.ptr_end();
220 
221  ConditionsArrayType& rConditions_new = new_model_part.Conditions();
222  ConditionsArrayType::iterator cond_it_end_new = rConditions_new.ptr_end();
223  ConditionsArrayType::iterator cond_it_begin_new = rConditions_new.ptr_begin();
224  number_of_conditions = cond_it_end - cond_it_begin;
225 
226  if (new_model_part.Nodes().size()!=0) //it means this is not the first plane that has to be created
227  {
228  NodesArrayType& rNodes_new = new_model_part.Nodes(); //i need the model part just to check the id of the new nodes.
229  NodesArrayType::iterator it_end_node_new = rNodes_new.ptr_end();
230  NodesArrayType::iterator it_begin_node_new = rNodes_new.ptr_begin();
231  number_of_previous_nodes=(it_end_node_new-it_begin_node_new);
232  number_of_triangles=cond_it_end_new - cond_it_begin_new ;
233  // KRATOS_WATCH(number_of_triangles)
234  //KRATOS_WATCH(number_of_previous_nodes)
235  //KRATOS_CATCH("")
236  }
237  else //nothing. number of triangles and nodes already set to 0
238  {
239  std::cout <<"First Cutting Plane" << std::endl;
240  }
241 
242 
243  if (number_of_conditions!=0)
244  {
245  for (unsigned int index=0 ; index != this_model_part.Nodes().size() ; ++index) Condition_Nodes[index]=0; //initializing in zero the whole vector (meaning no useful nodes for the condition layer)
246 
247  for(ModelPart::ConditionsContainerType::iterator i_condition = rConditions.begin() ; i_condition != rConditions.end() ; i_condition++)
248  {
249  Geometry<Node >&geom = i_condition->GetGeometry();
250  for(unsigned int i = 0; i < i_condition->GetGeometry().size() ; i++)
251  {
252  //int position = (geom[i].Id()) - 1; //the id of the node minus one is the position in the Condition_Node array (position0 = node1)
253  int position = this_model_part.Nodes().find(geom[i].Id()) - it_begin_node_old; //probably there-s a better way to do this, i only need the position in the array, (not the ID)
254  Condition_Nodes[position] = -1 ; //a -1 means we need this node!
255  }
256  }//done. now we know all the nodes that will have to be added to the new model part.
257 
258  //we loop all the nodes in the old model part and copy the ones used by conditions to the new model part:
259  for (unsigned int index=0 ; index != this_model_part.Nodes().size() ; ++index)
260  {
261  if (Condition_Nodes[index]==-1)
262  {
263  ++number_of_nodes; //one new node!
264  Condition_Nodes[index] = number_of_nodes + number_of_previous_nodes; //we give this node consecutives ids. now we create the new node
265  ModelPart::NodesContainerType::iterator it_node = this_model_part.Nodes().begin()+index;
266  Node ::Pointer pnode = new_model_part.CreateNewNode(number_of_nodes+number_of_previous_nodes, it_node->X(), it_node->Y(), it_node->Z()); //recordar que es el nueevo model part!!
267  pnode->SetBufferSize(this_model_part.NodesBegin()->GetBufferSize());
268  pnode->GetValue(FATHER_NODES).resize(0);
269  pnode->GetValue(FATHER_NODES).push_back( Node::WeakPointer( *it_node.base() ) ); // we keep the same size despite we only need one. to have everyhing with the same size
270  pnode->GetValue(FATHER_NODES).push_back( Node::WeakPointer( *it_node.base() ) );
271  pnode-> GetValue(WEIGHT_FATHER_NODES) = 1.0; //since both father node 1 and 2 are the same, any value between 0 and one would be ok.
272 
273  pnode->X0() = it_node->X0();
274  pnode->Y0() = it_node->Y0();
275  pnode->Z0() = it_node->Z0();
276  }
277  }//finished the list of nodes to be added.
278 
279  //now to the conditions!
280  DenseVector<int> triangle_nodes(3); //here we'll save the nodes' ids with the new node names
281  Condition const& rReferenceCondition = KratosComponents<Condition>::Get("SurfaceCondition3D3N"); //condition type
282  Properties::Pointer properties = this_model_part.GetMesh().pGetProperties(plane_number); //this will allow us later to turn this layer on/off in GID
283 
284  for(ModelPart::ConditionsContainerType::iterator i_condition = rConditions.begin() ; i_condition != rConditions.end() ; i_condition++) //looping all the conditions
285  {
286  Geometry<Node >&geom = i_condition->GetGeometry(); //current condition(nodes, etc)
287  for(unsigned int i = 0; i < i_condition->GetGeometry().size() ; i++) //looping the nodes
288  {
289  int position = this_model_part.Nodes().find(geom[i].Id()) - it_begin_node_old; //the id of the node minus one is the position in the Condition_Node array (position0 = node1)
290  triangle_nodes[i]=Condition_Nodes[position]; // saving the i nodeId
291  } //nodes id saved. now we have to create the element.
292  Triangle3D3<Node > geometry(
293  new_model_part.Nodes()(triangle_nodes[0]), //condition to be added
294  new_model_part.Nodes()(triangle_nodes[1]),
295  new_model_part.Nodes()(triangle_nodes[2])
296  );
297  Condition::Pointer p_condition = rReferenceCondition.Create(number_of_triangles+1, geometry, properties); //está bien? acá la verdad ni idea. sobre todo number_of_triangles (la posición). o debe ser un puntero de elemento en vez de un entero?
298  new_model_part.Conditions().push_back(p_condition);
299  ++number_of_triangles;
300  }
301  }
302  KRATOS_WATCH("Finished copying conditions surfaces")
303  KRATOS_CATCH("")
304 
305  }
306 
308 
313  const ModelPart& rModelPart,
314  ModelPart& rNewModelPart) const
315  {
317  rNewModelPart.AddNodalSolutionStepVariable(FATHER_NODES);
318  rNewModelPart.AddNodalSolutionStepVariable(WEIGHT_FATHER_NODES);
319  }
320 
321 
322  //************************************************************************************************
323  //************************************************************************************************
324 
325 
326  //LIST OF SUBROUTINES
327 
328 
329  void CSR_Row_Matrix_Mod(ModelPart& this_model_part, boost::numeric::ublas::compressed_matrix<int>& Coord)
330  {
331  NodesArrayType& pNodes = this_model_part.Nodes();
332  Coord.resize(pNodes.size(), pNodes.size());
333  NodesArrayType::iterator i_begin = pNodes.ptr_begin();
334  NodesArrayType::iterator i_end = pNodes.ptr_end();
335 
336  std::vector<unsigned int> aux(10000);
337 
338  for (ModelPart::NodeIterator i = i_begin; i != i_end; ++i)
339  {
340  int index_i = i->Id() - 1;
341  GlobalPointersVector< Node >& neighb_nodes = i->GetValue(NEIGHBOUR_NODES);
342  Coord.push_back(index_i, index_i, -1); //only modification added, now the diagonal is filled with -1 too.
343 
344  unsigned int active = 0;
345  for (GlobalPointersVector< Node >::iterator inode = neighb_nodes.begin();
346  inode != neighb_nodes.end(); inode++)
347  {
348  int index_j = inode->Id() - 1;
349  if (index_j > index_i)
350  {
351  aux[active] = index_j;
352  active++;
353  }
354  }
355  std::sort(aux.begin(), aux.begin() + active);
356 
357  for (unsigned int k = 0; k < active; k++)
358  {
359  Coord.push_back(index_i, aux[k], -1);
360 
361  }
362  }
363  }
364 
365  //************************************************************************************************
366 
367  void FirstLoop(ModelPart& this_model_part, boost::numeric::ublas::compressed_matrix<int>& Coord, const array_1d<double, 3 >& versor, const array_1d<double, 3 >& Xp,
368  int number_of_triangles, DenseVector<int>& Elems_In_Plane, double tolerance)//
369  {
370  //Xp is a random point that belongs to the cutting plane
371  //versor is a vector normal to the plane
372 
373  ElementsArrayType& rElements = this_model_part.Elements();
374 
375  ElementsArrayType::iterator it_begin = rElements.ptr_begin();
376  ElementsArrayType::iterator it_end = rElements.ptr_end();
377 
378  double dist_node_point; // node to closest point in the plane
379  double dist_neigh_point; //other node of the edge (neighbour) to closest point in the plane
380  //double dist_node_neigh; //distance between the two nodes of the edge
381  array_1d<double, 3 > temp_dist; //aux segment
382  array_1d<double, 3 > node_coord; //
383  array_1d<double, 3 > neigh_coord; //
384  array_1d<unsigned int, 4 > list_matching_nodes; // used to save the new nodes that match exactly old nodes (very unlikely, but might be 4 for very plane elements)
385  unsigned int exact_nodes=0;
386 
387  number_of_triangles = 0;
388  int current_element= 0; //current element. it's a position. NOT ID!
389 
390  int number_of_cuts= 0; //this is the counter explained in the following lines
391 
392  for (ElementsArrayType::iterator it = it_begin; it != it_end; ++it) //looping all the elements
393  {
394  ++current_element;
395  number_of_cuts = 0 ;
396  exact_nodes = 0 ;
397  Geometry<Node >&geom = it->GetGeometry(); //geometry of the element
398  for(unsigned int i = 0; i < it->GetGeometry().size() ; i++) //size = 4 ; nodes per element. NOTICE WE'LL BE LOOPING THE EDGES TWICE. THIS IS A WASTE OF TIME BUT MAKES IT EASIER TO IDENTITY ELEMENTS. LOOK BELOW.
399  //when we have a triangle inside a thetraedra, its edges (or nodes) must be cut 3 times by the plane. if we loop all 2 times we can have a counter. when it's = 6 then we have a triangle. when tetraedras are cutted 8 times then we have 2 triangles (or a cuatrilateral, the same)
400  {
401  node_coord[0] = geom[i].X();
402  node_coord[1] = geom[i].Y();
403  node_coord[2] = geom[i].Z();
404  noalias(temp_dist) = node_coord;
405  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
406  dist_node_point = inner_prod(temp_dist,versor); // dist = (xnode-xp)*versor closest point-plane distance
407  for(unsigned int j = 0; j < it->GetGeometry().size() ; j++) // looping on the neighbours
408  {
409  if (i != j) //(cant link node with itself)
410  {
411  neigh_coord[0] = geom[j].X();
412  neigh_coord[1] = geom[j].Y();
413  neigh_coord[2] = geom[j].Z();
414  noalias(temp_dist) = neigh_coord;
415  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
416  dist_neigh_point = inner_prod(temp_dist,versor); // dist = (xnode-xp)*versor closest point-plane distance
417  // dist_node_neigh = sqrt( pow((node_coord[0]- neigh_coord[0]),2) + pow((node_coord[1]- neigh_coord[1]),2) + pow((node_coord[2]- neigh_coord[2]),2) ); // looks ugly, doesn't it? it's supposed to calculate the distance
418  //now that we have the two points of the edge defined we can check whether it is cut by the plane or not
419  bool isovernode=false; // if true, then it can't be between the nodes
420 
421  if (fabs(dist_node_point) < (tolerance)) //then our node is part of the plane (this should have been done before the loop on neighbours, but this way it is easier to read .
422  {
423  int index_i = geom[i].Id() -1 ; // i node id
424  Coord(index_i, index_i) = -2; //saving a -2 in the diagonal
425  isovernode=true;
426  number_of_cuts += 2; //since its neighbour wont take this case as a cut, we must save 2 cuts instead of one. (to reach number_of_cuts=6),
427  ++exact_nodes;
428  list_matching_nodes[i]= geom[i].Id();
429  break;
430  }
431  //check this last condition, used to avoid talking points that belong to other node. might cause some problems when the plane is almost paralel to an edge. to be improved! (it seems to be working correcly even when the edge is part of the plane.)
432  if ((dist_node_point*dist_neigh_point) < 0.0 && isovernode==false && (fabs(dist_neigh_point)>(tolerance))) // this means one is on top of the plane and the other on the bottom, no need to do more checks, it's in between!
433  {
434  int index_i = geom[i].Id() - 1; //i node id
435  int index_j = geom[j].Id() - 1; //j node id
436  if (index_j > index_i) Coord(index_i, index_j) = -2; //saving a -2 in the upper side of the matrix
437  else Coord(index_j, index_i) = -2;
438  number_of_cuts += 1;
439  }
440  } //closing the i!=j if
441  } //closing the neighbour loop
442  } //closing the nodes loop
443 
444  //now we have to save the data. we should get a list with the elements that will genereate triangles and the total number of triangles
445  Elems_In_Plane[current_element-1] = 0 ; //we initialize as 0
446  if (exact_nodes!=3) //this means at least one new node has to be generated
447  {
448  if (number_of_cuts == 6) //it can be 8, in that case we have 2 triangles (the cut generates a square)
449  {
450  number_of_triangles +=1;
451  Elems_In_Plane[current_element-1] = 1 ; //i still don't know the number of the node so i'll have to do another loop later to assign to define node id's of each triangular element
452  }
453  else if (number_of_cuts == 8 ) // 2 triangles in the element!
454  {
455  number_of_triangles +=2;
456  Elems_In_Plane[ current_element-1] = 2 ;
457  }
458  }
459  else //ok, now we'll only add the element if the normal of the plane matches the one of the triangle (created poiting towards the fourth node of the tetraedra)
460  {
461  bool found_fourth_node=true; //this is the node that defines the normal of the element
462  for(unsigned int i = 0; i < it->GetGeometry().size() ; i++) //size = 4 ; nodes per element. NOTICE WE'LL BE LOOPING THE EDGES TWICE. THIS IS A WASTE OF TIME BUT MAKES IT EASIER TO IDENTITY ELEMENTS. LOOK BELOW.
463  {
464  found_fourth_node=true;
465  for (unsigned int aux_index=0; aux_index!=4; ++aux_index) // we define our plane now
466  {
467  if (geom[i].Id()==list_matching_nodes[aux_index] && list_matching_nodes[aux_index]!=0)
468  {
469  found_fourth_node=false;
470  //break; //ok, we have the coordinates of the new node. now we have to mame sure
471  }
472  }
473  if (found_fourth_node==true)
474  {
475  node_coord[0] = geom[i].X();
476  node_coord[1] = geom[i].Y();
477  node_coord[2] = geom[i].Z();
478  break;
479  }
480  }
481  //now we check if the point has a positive distance to the plane. if true we will add a new triangle (property of the element). otherwise not
482  //not that this means that this triangle should be added by the neighbour tetraedra( which would return a positive distance)
483  //so if we're in a boundary of the domain, make sure that the (normal of) the cutting plane points towards the model. otherwise you'll have missing triangles
484  noalias(temp_dist) = node_coord;
485  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
486  dist_node_point = inner_prod(temp_dist,versor); // dist = (xnode-xp)*versor closest point-plane distance
487  if (dist_node_point>=0.0)
488  {
489  if (number_of_cuts == 6) //this should not be necessary, but it's kept just in case (almost plain elements?)
490  {
491  number_of_triangles +=1;
492  Elems_In_Plane[current_element-1] = 1 ;
493  }
494  else if (number_of_cuts == 8 )
495  {
496  number_of_triangles +=2;
497  Elems_In_Plane[ current_element-1] = 2 ;
498  }
499  }
500  }
501  } //closing the elem loop
502  KRATOS_WATCH(number_of_triangles);
503 
504  } //closing "FirstLoop"
505 
506 
507 
509 
510  void Create_List_Of_New_Nodes_Mod(ModelPart& this_model_part, ModelPart& new_model_part, boost::numeric::ublas::compressed_matrix<int>& Coord, DenseVector<int> &List_New_Nodes,
511  DenseVector<array_1d<int, 2 > >& Position_Node) //plane number = 1 -- inf (but the first one should be always one!
512  {
513 
514  unsigned int number_of_new_nodes = 0;
515  //NodesArrayType& pNodes = this_model_part.Nodes();
516  typedef boost::numeric::ublas::compressed_matrix<int>::iterator1 i1_t;
517  typedef boost::numeric::ublas::compressed_matrix<int>::iterator2 i2_t;
518 
520  for (i1_t i1 = Coord.begin1(); i1 != Coord.end1(); ++i1)
521  {
522  for (i2_t i2 = i1.begin(); i2 != i1.end(); ++i2)
523  {
524  if (Coord(i2.index1(), i2.index2()) == -2)
525  {
526  number_of_new_nodes++; //this should work without any change
527  }
528  }
529  }
530 
532  List_New_Nodes.resize(number_of_new_nodes);
533  //int total_node = pNodes.size();
534  if (new_model_part.Nodes().size()!=0) //it means this is not the first plane that has to be created
535  {
536  NodesArrayType& rNodes_new = new_model_part.Nodes(); //i need the model part just to check the id of the new nodes.
537  NodesArrayType::iterator it_end_node_new = rNodes_new.ptr_end();
538  NodesArrayType::iterator it_begin_node_new = rNodes_new.ptr_begin();
539  List_New_Nodes[0]=(it_end_node_new-it_begin_node_new)+1;
540  KRATOS_WATCH("New Cutting Plane")
541  first_cutting_plane = false;
542  }
543  else
544  {
545  if (List_New_Nodes.size() > 0)
546  {
547  List_New_Nodes[0]=1;
548  KRATOS_WATCH("First Cutting Plane");
549  first_cutting_plane = true;
550  }
551  }
552 
553  for (unsigned int i = 1; i < number_of_new_nodes; i++)
554  {
555  List_New_Nodes[i] = List_New_Nodes[0] + i; //just a list. necessary because other cutting planes might have been generated before
556  }
557 
559  Position_Node.resize(number_of_new_nodes);
560  unsigned int index = 0;
561  for (i1_t i1 = Coord.begin1(); i1 != Coord.end1(); ++i1)
562  {
563  for (i2_t i2 = i1.begin(); i2 != i1.end(); ++i2)
564  {
565  if (Coord(i2.index1(), i2.index2()) == -2)
566  {
567  Coord(i2.index1(), i2.index2()) = List_New_Nodes[index];
568  Position_Node[index][0] = i2.index1() + 1;
569  Position_Node[index][1] = i2.index2() + 1; //in the diagonal terms both indexes should point to the same node but still should work i guess
570  index++;
571  }
572  }
573  }
574 
575  }
576 
578 
579  void Calculate_Coordinate_And_Insert_New_Nodes_Mod(ModelPart& this_model_part, ModelPart& new_model_part,
580  const DenseVector<array_1d<int, 2 > >& Position_Node,
581  const DenseVector<int> &List_New_Nodes,
582  const array_1d<double, 3 >& versor, const array_1d<double, 3 >& Xp, double tolerance)//,
583  {
584 
585  array_1d<double, 3 > Coord_Node_1;
586  array_1d<double, 3 > Coord_Node_2;
587  array_1d<double, 3 > temp_dist;
590  array_1d<double, 3 > intersection;
591  double dist_node_point;
592 // double dist_node_neigh;
593  //double dist_neigh_point;
594  double dist_node_intersect;
595  double weight;
596  DenseVector< array_1d<double, 3 > > Coordinate_New_Node;
597  Coordinate_New_Node.resize(Position_Node.size());
598  //unsigned int step_data_size = this_model_part.GetNodalSolutionStepDataSize();
599  //Node ::DofsContainerType& reference_dofs = (this_model_part.NodesBegin())->GetDofs();
600 
601  for (unsigned int i = 0; i < Position_Node.size(); i++) //looping the new nodes
602  {
603 
605  const int& node_i = Position_Node[i][0];
606  const int& node_j = Position_Node[i][1];
607  auto it_node1 = this_model_part.Nodes()(node_i);
608  //std::size_t pos1 = it_node1 - this_model_part.NodesBegin();
609  noalias(Coord_Node_1) = it_node1->Coordinates();
610  auto it_node2 = this_model_part.Nodes()(node_j);
611  //std::size_t pos2 = it_node2 - this_model_part.NodesBegin();
612  noalias(Coord_Node_2) = it_node2->Coordinates();
613  //ok, now we have both coordinates. now we must define a weight coefficient based on the distance.
614  //this coeff will be =node_plane_distance/node_neigh_distance (linear interpolation)
615  noalias(temp_dist) = Coord_Node_1;
616  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
617  dist_node_point = inner_prod(temp_dist,versor); // dist = (xnode-xp)*versor closest point-plane distance
618  dist_node_point = fabs (dist_node_point);
619 
620  Xp_1 = Xp - Coord_Node_1;
621  Xp_2 = Coord_Node_2 - Coord_Node_1;
622  dist_node_intersect = (inner_prod(versor,Xp_1)) / (inner_prod(versor,Xp_2)) ; //line-plane interesection, this is a RELATIVE distance. ====> point= Node1 + (Node2-Node1)*dist_node_intersect
623 // dist_node_neigh = sqrt( pow((Coord_Node_1[0]- Coord_Node_2[0]),2) + pow((Coord_Node_1[1]- Coord_Node_2[1]),2) + pow((Coord_Node_1[2]- Coord_Node_2[2]),2) ) ; // distance between node and neighbour
624  if (dist_node_point<=(tolerance)) dist_node_intersect=0.0; // if it's too close to the first node then we just set the weight as 1
625  weight = (1.0 - dist_node_intersect) ; // dist_node_neigh;
626  //weight = dist_node_point / dist_node_neigh ; MAL!
627  //noalias(Weight_New_Nodes[i]) = weight;
628  if (weight > 1.05) KRATOS_WATCH("**** something's wrong! weight higher than 1! ****");
629  //KRATOS_WATCH(i); KRATOS_WATCH(weight);
630  for (unsigned int index=0; index!=3; ++index) //we loop the 3 coordinates)
631  if (Position_Node[i][0]!=Position_Node[i][1])
632  Coordinate_New_Node[i][index] = Coord_Node_1[index] + (dist_node_intersect) * (Coord_Node_2[index] - Coord_Node_1[index]);
633  else
634  Coordinate_New_Node[i][index] = Coord_Node_1[index]; //when both nodes are the same it doesnt make any sense to interpolate
635 
636  temp_dist= Coordinate_New_Node[i] - Xp;
637  dist_node_point = inner_prod(versor,temp_dist);
639  Node ::Pointer pnode = new_model_part.CreateNewNode(List_New_Nodes[i], Coordinate_New_Node[i][0], Coordinate_New_Node[i][1], Coordinate_New_Node[i][2]); //recordar que es el nueevo model part!!
640  pnode->SetBufferSize(this_model_part.NodesBegin()->GetBufferSize());
641 
642  //it_node1 = this_model_part.NodesBegin() + pos1;
643  //it_node2 = this_model_part.NodesBegin() + pos2;
644 
645  pnode->GetValue(FATHER_NODES).resize(0);
646  pnode->GetValue(FATHER_NODES).push_back( Node::WeakPointer( it_node1 ) ); //saving data about fathers in the model part
647  pnode->GetValue(FATHER_NODES).push_back( Node::WeakPointer( it_node2 ) );
648  pnode-> GetValue(WEIGHT_FATHER_NODES) = weight;
649 
650  pnode->X0() = weight * (it_node1->X0()) + (1.0 - weight) * it_node2->X0();
651  pnode->Y0() = weight * (it_node1->Y0()) + (1.0 - weight) * it_node2->Y0();
652  pnode->Z0() = weight * (it_node1->Z0()) + (1.0 - weight) * it_node2->Z0();
653  }
654  }
655 
657 
658 
659  void GenerateElements (ModelPart& this_model_part, ModelPart& new_model_part, DenseVector<int> Elems_In_Plane, boost::numeric::ublas::compressed_matrix<int>& Coord, const array_1d<double, 3 >& versor, int plane_number)
660  {
661  array_1d<double, 3 > temp_vector1;
662  array_1d<double, 3 > temp_vector2;
663  array_1d<double, 3 > temp_vector3;
664  array_1d<double, 3 > temp_vector4;
665  array_1d<double, 3 > temp_vector5;
666  array_1d<int, 6 > nodes_for_2triang; //to be used when there are 2 triangles
667  double dist2; //to be used when there are 2 triangles in the tetraedra
668  double dist3;
669  double control;
670  unsigned int temp_int;
671  unsigned int first_element=0;
672 
673  ElementsArrayType& rElements_old = this_model_part.Elements();
674  ElementsArrayType::iterator it_begin_old = rElements_old.ptr_begin();
675  ElementsArrayType::iterator it_end_old = rElements_old.ptr_end();
676 
677  ElementsArrayType& rElements_new = new_model_part.Elements();
678  ElementsArrayType::iterator it_begin_new = rElements_new.ptr_begin();
679  ElementsArrayType::iterator it_end_new = rElements_new.ptr_end();
680 
681  if (first_cutting_plane == false) //it means this is not the first plane that has to be created
682  {
683  first_element=(it_end_new-it_begin_new);
684  KRATOS_WATCH("New Cutting Plane")
685  KRATOS_WATCH(first_element)
686  }
687  else
688  {
689  first_element=0; //or we're creating the first elements of the model part
690  KRATOS_WATCH("First Cutting Plane");
691  }
692 
693  Condition const& rReferenceCondition = KratosComponents<Condition>::Get("SurfaceCondition3D3N");
694  Properties::Pointer properties = this_model_part.GetMesh().pGetProperties(plane_number);
695 
696  int number_of_triangles = 0;
697  int current_element= 0;
698  unsigned int triangle_nodes= 0; // number of nodes already saved (of the current element)
699  bool new_node = false ; //used to check whether the current node has been saved or not
700 
701  array_1d<int, 4 > TriangleNodesArray; //nodes of the element to be generated. 4 in case they're 2 triangles
702  for (unsigned int k=0; k!=4; ++k)
703  {
704  TriangleNodesArray[k] = -1; //initializing in -1, meaning we have no nodes yet
705  }
706 
708  for (ElementsArrayType::iterator it = it_begin_old; it != it_end_old; ++it)
709  {
710  ++current_element;
711  triangle_nodes = 0; //starting, no nodes yet
713  if (Elems_In_Plane[current_element-1] == 1 ) //do not forget than can be both 1 or 2 triangles per tetraedra. this is the simplest case. no need to check anything, we just create an element with the 3 nodes
714  {
715  //checking element conectivities
716  for(unsigned int i = 0; i < it->GetGeometry().size() ; i++)
717  {
718  Geometry<Node >&geom = it->GetGeometry(); //i node of the element
719  for(unsigned int j = 0; j < it->GetGeometry().size() ; j++) //j node of the element
720  {
721  new_node= true; //by default it's a new node
722  int index_i = geom[i].Id() - 1; //i node id
723  int index_j = geom[j].Id() - 1;
724  for (unsigned int l=0; l!=3; ++l)
725  {
726  if(TriangleNodesArray[l]==Coord(index_i, index_j) //if we have already saved this node or it has not been cutted, then we have no new node to add (coord(i,j)=-1)
727  || Coord(index_i, index_j) <1 )
728  new_node=false;
729  }
730  //if it's a new node and the indexes are correct:
731  if (new_node && index_i<=index_j)
732  {
733  TriangleNodesArray[triangle_nodes]=Coord(index_i, index_j) ;
734  triangle_nodes++;
735  }
736  if (triangle_nodes ==3) break; //if we have already found 3 nodes then we can exit
737  } //closing j node loop
738  if (triangle_nodes ==3) break; //egal
739  } //closing j node loop
740  //now we have to check that the normal of the element matches the one of the plane (they could have opposite directions)
741  ModelPart::NodesContainerType::iterator it_node1 = new_model_part.Nodes().find(TriangleNodesArray[0]);
742  noalias(temp_vector1) = it_node1->Coordinates(); //node 1
743 
744  it_node1 = new_model_part.Nodes().find(TriangleNodesArray[1]);
745  noalias(temp_vector2) = it_node1->Coordinates(); //node 2
746 
747  it_node1 = new_model_part.Nodes().find(TriangleNodesArray[2]);
748  noalias(temp_vector3) = it_node1->Coordinates(); //nodo 3
749 
750  temp_vector3 -=temp_vector1; //first edge
751  temp_vector2 -=temp_vector1; //second edge
752 
753 
754  MathUtils<double>::CrossProduct(temp_vector4, temp_vector2 , temp_vector3) ; //multiplying the 2 edges gives us a normal vector to the element
755 
756  if (inner_prod(temp_vector4,versor)<0.0) //if the signs do not match then they have opposite directions
757  {
758  temp_int= TriangleNodesArray[2];
759  TriangleNodesArray[2] = TriangleNodesArray[1];
760  TriangleNodesArray[1] = temp_int; //we switch 2 nodes and ready
761  }
762 
763  //generate new Elements
764  Triangle3D3<Node > geom(
765  new_model_part.Nodes()(TriangleNodesArray[0]),
766  new_model_part.Nodes()(TriangleNodesArray[1]),
767  new_model_part.Nodes()(TriangleNodesArray[2])
768  );
769 
770  Condition::Pointer p_condition = rReferenceCondition.Create(number_of_triangles+1+first_element, geom, properties); //creating the element using the reference element. notice we are using the first element to avoid overriting nodes created by other cutting planes
771  new_model_part.Conditions().push_back(p_condition);
772  ++number_of_triangles;
773 
774  for (int counter=0; counter!=4; ++counter) TriangleNodesArray[counter]=0;
775  }//closing if elems_in_plane==6 (1 triangle)
776 
777 
779  if (Elems_In_Plane[current_element-1] == 2) //now we have 2 elements. we cant just create 2 elements with a random node order because they might overlap and not cover the whole area defined by the trapezoid
780  {
781  //to fix this we'll first create a plane. see below
782 
783  //checking conectivities to find nodes
784  for(unsigned int i = 0; i < it->GetGeometry().size() ; i++) //nodo i
785  {
786  Geometry<Node >&geom = it->GetGeometry();
787  for(unsigned int j = 0; j < it->GetGeometry().size() ; j++) //nodo j
788  {
789  new_node= true;
790  int index_i = geom[i].Id() - 1;
791  int index_j = geom[j].Id() - 1;
792  for (unsigned int l=0; l!=3; ++l)
793  {
794  if(TriangleNodesArray[l]==Coord(index_i, index_j) //same as the part with only one triangle (look above)
795  || Coord(index_i, index_j) < 1 )
796  {
797  new_node=false;
798  }
799  }
800  if (new_node && index_i<index_j)
801  {
802  TriangleNodesArray[triangle_nodes]=Coord(index_i, index_j) ;
803  triangle_nodes++;
804  }
805  if (triangle_nodes ==4) break; //once we've found the 4 nodes we can exit
806  } //closing i loop
807  if (triangle_nodes ==4) break;
808  }
809 
810  //now we have to start checking the angles. the easiest way (i think) is creating a new plane using the original plane and a segment created by 2 nodes
811  // using crossproduct we get a perpendicular plane. (either point can be used as origin).
812  //since the cuadrilateral is created by the cut of teatraedra,
813  //none of its internal angles can exceed 180 degrees and hence our new plane divides the cuadrilateral into 2 triangles if the distances to the other points have different signs (one on top and the other on the bottom of this new plane)
814  //otherwise this edge is just an edge of the cuadrilateral and we have to look for another.
815  //so let's begin! (we'll keep an origin node and we'll loop different nodes as the end of the segment till we find one that satisfies our criteria)
816  ModelPart::NodesContainerType::iterator it_node1 = new_model_part.Nodes().find(TriangleNodesArray[0]);
817  noalias(temp_vector1) = it_node1->Coordinates(); //nodo 1 (origin)
818  int jjj;
819  int kkk;
820 
821  for (int iii=1; iii!=4; ++iii) //end node of the segment that will be used to create the plane (will be contained too)
822  {
823  // KRATOS_WATCH(iii);
824  it_node1=new_model_part.Nodes().find(TriangleNodesArray[iii]); //i node. we always keep node 0 as origin
825  noalias(temp_vector2) = it_node1->Coordinates(); //node2 (end)
826  noalias(temp_vector3) = temp_vector2 - temp_vector1; //segment 1-2
827  //now i have to create the new plane
828  MathUtils<double>::CrossProduct(temp_vector4, versor , temp_vector3); //done. now temp_vector4 is the (normal to the) new plane, perpendicular to the one containing the triangles
829  //the origin of the plane is temp_vector1 (temp_vector2 could also be used)
830  //now we need to check distances to the other nodes (i+2 (let's call them jjj and i+3=kkk since we can't go futher than i=3)
831  if (iii==1)
832  {
833  jjj=2;
834  kkk=3;
835  }
836  else if (iii==2)
837  {
838  jjj=3;
839  kkk=1;
840  }
841  else
842  {
843  jjj=2;
844  kkk=1;
845  }
846 
847  it_node1=new_model_part.Nodes().find(TriangleNodesArray[jjj]);
848  noalias(temp_vector2) = it_node1->Coordinates(); //one of the remaining nodes;
849 
850  it_node1=new_model_part.Nodes().find(TriangleNodesArray[kkk]);
851  noalias(temp_vector3) = it_node1->Coordinates(); //the other remaining node;
852 
853  noalias(temp_vector2) -=temp_vector1; // minus origin point of the plane
854  noalias(temp_vector3) -=temp_vector1;
855 
856  dist2= inner_prod(temp_vector2,temp_vector4); // dot product
857  dist3= inner_prod(temp_vector3,temp_vector4);
858  control=dist2*dist3;
859  //and that's it. we now have to check if the distance have different signs. to do so we multiply :
860  if (control<0.0) //we have the right one! one node on each side of the plane generated by nodes 0 and iii
861  {
862  nodes_for_2triang[0] = TriangleNodesArray[0] ;
863  nodes_for_2triang[1] = TriangleNodesArray[jjj];
864  nodes_for_2triang[2] = TriangleNodesArray[iii]; //finish first triangle
865  nodes_for_2triang[3] = TriangleNodesArray[iii];
866  nodes_for_2triang[4] = TriangleNodesArray[kkk];
867  nodes_for_2triang[5] = TriangleNodesArray[0]; //finish 2nd triangle
868  // KRATOS_WATCH(nodes_for_2triang);
869  break; //no need to keep looking, we can exit the loop
870 
871  } //closing the if
872 
873  }//by the time this finishes i should already have TriangleNodesArray
874 
875 
876 
877 
878  //checking if the normal to our element is oriented correctly, just as we did when we had only 1 triangle (not commented here)
879  for (int index=0 ; index !=2 ; ++index) //for triangle 1 and 2
880  {
881 
882  it_node1 = new_model_part.Nodes().find(nodes_for_2triang[index*3+0]);
883  noalias(temp_vector1) = it_node1->Coordinates(); //node 1
884 
885  it_node1 = new_model_part.Nodes().find(nodes_for_2triang[index*3+1]);
886  noalias(temp_vector2) = it_node1->Coordinates(); //node 2
887 
888  it_node1 = new_model_part.Nodes().find(nodes_for_2triang[index*3+2]);
889  noalias(temp_vector3) = it_node1->Coordinates(); //node 3
890 
891  temp_vector3 -=temp_vector1;
892  temp_vector2 -=temp_vector1;
893  MathUtils<double>::CrossProduct(temp_vector4, temp_vector2 , temp_vector3) ;
894 
895  if (inner_prod(temp_vector4,versor)<0.0)
896  {
897  temp_int= nodes_for_2triang[index*3+2];
898  nodes_for_2triang[index*3+2] = nodes_for_2triang[index*3+1];
899  nodes_for_2triang[index*3+1] = temp_int;
900  }
901 
902  Triangle3D3<Node > geom(
903  new_model_part.Nodes()(nodes_for_2triang[index*3+0]),
904  new_model_part.Nodes()(nodes_for_2triang[index*3+1]),
905  new_model_part.Nodes()(nodes_for_2triang[index*3+2])
906  );
907 
908  Condition::Pointer p_condition = rReferenceCondition.Create(number_of_triangles+1+first_element, geom, properties);
909 
910  new_model_part.Conditions().push_back(p_condition);
911  ++number_of_triangles;
912 
913  for (int counter=0; counter!=4; ++counter) TriangleNodesArray[counter]=0;//resetting, just in case
914  }//cierro el index
915  }//closing if elems_in_plane=2
916 
917  }//closing element loops
918 
919  }
920 
923 
924 
926 
930  void UpdateCutData( ModelPart& new_model_part, ModelPart& old_model_part)
931  {
932  KRATOS_WATCH("Updating Cut Data");
933  int step_data_size = old_model_part.GetNodalSolutionStepDataSize();
934 
935  //looping the nodes, no data is assigned to elements
936  for (ModelPart::NodesContainerType::iterator it = new_model_part.NodesBegin(); it != new_model_part.NodesEnd(); it++)
937  {
938  double* node0_data = it->GetValue(FATHER_NODES)[0].SolutionStepData().Data(0); //current step only, (since we'll call this every timestep
939  double* node1_data = it->GetValue(FATHER_NODES)[1].SolutionStepData().Data(0);
940  double weight = it->GetValue(WEIGHT_FATHER_NODES);
941  double* step_data = (it)->SolutionStepData().Data(0);
942 
943  //now we only have to copy the information from node_data to step_data
944  for(int j= 0; j< step_data_size; j++) //looping all the variables and interpolating using weight
945  {
946  step_data[j] = weight*node0_data[j] + (1.0-weight)*node1_data[j];
947  }
948  }//closing node loop
949  }//closing subroutine
950 
951 
952 
955 
956 
957 
958 
959 private:
960  double smallest_edge; //
961  bool first_cutting_plane; // to avoid checking again if we're working on the new cutting plane or if some have already been created
962 
963 };
964 }
965 
966 
967 
968 #endif
Base class for all Conditions.
Definition: condition.h:59
virtual Pointer Create(IndexType NewId, NodesArrayType const &ThisNodes, PropertiesType::Pointer pProperties) const
It creates a new condition pointer.
Definition: condition.h:205
CUTTING UTILITY.
Definition: cutting_utility.h:65
void Calculate_Coordinate_And_Insert_New_Nodes_Mod(ModelPart &this_model_part, ModelPart &new_model_part, const DenseVector< array_1d< int, 2 > > &Position_Node, const DenseVector< int > &List_New_Nodes, const array_1d< double, 3 > &versor, const array_1d< double, 3 > &Xp, double tolerance)
‍************************************************************************************************
Definition: cutting_utility.h:579
PointVector::iterator PointIterator
Definition: cutting_utility.h:79
ModelPart::ElementsContainerType ElementsArrayType
Definition: cutting_utility.h:71
DenseVector< Vector > Vector_Order_Tensor
Definition: cutting_utility.h:74
std::vector< PointType::Pointer > PointVector
Definition: cutting_utility.h:78
void GenerateCut(ModelPart &mr_model_part, ModelPart &mr_new_model_part, const array_1d< double, 3 > &versor, const array_1d< double, 3 > &Xp, int plane_number, double tolerance_factor)
This function Creates cutting planes by creating nodes and conditions (to define the conectivities) i...
Definition: cutting_utility.h:144
void FindSmallestEdge(ModelPart &mr_model_part)
This function Creates cutting planes by creating nodes and conditions (to define the conectivities) i...
Definition: cutting_utility.h:100
void FirstLoop(ModelPart &this_model_part, boost::numeric::ublas::compressed_matrix< int > &Coord, const array_1d< double, 3 > &versor, const array_1d< double, 3 > &Xp, int number_of_triangles, DenseVector< int > &Elems_In_Plane, double tolerance)
Definition: cutting_utility.h:367
void Create_List_Of_New_Nodes_Mod(ModelPart &this_model_part, ModelPart &new_model_part, boost::numeric::ublas::compressed_matrix< int > &Coord, DenseVector< int > &List_New_Nodes, DenseVector< array_1d< int, 2 > > &Position_Node)
‍************************************************************************************************
Definition: cutting_utility.h:510
void CSR_Row_Matrix_Mod(ModelPart &this_model_part, boost::numeric::ublas::compressed_matrix< int > &Coord)
Definition: cutting_utility.h:329
Node ::Pointer PointPointerType
Definition: cutting_utility.h:77
void AddVariablesToCutModelPart(const ModelPart &rModelPart, ModelPart &rNewModelPart) const
Initialize the solution step data container for the cut model part.
Definition: cutting_utility.h:312
DenseVector< Matrix > Matrix_Order_Tensor
Definition: cutting_utility.h:73
Node PointType
Definition: cutting_utility.h:76
void GenerateElements(ModelPart &this_model_part, ModelPart &new_model_part, DenseVector< int > Elems_In_Plane, boost::numeric::ublas::compressed_matrix< int > &Coord, const array_1d< double, 3 > &versor, int plane_number)
‍**********************************************************************************
Definition: cutting_utility.h:659
virtual ~CuttingUtility()
Destructor.
Definition: cutting_utility.h:92
CuttingUtility()
Default constructor.
Definition: cutting_utility.h:86
void UpdateCutData(ModelPart &new_model_part, ModelPart &old_model_part)
UPDATECUTDATA: THIS FUNCTION UPDATES THE DATA OF THE NEW MODEL PART READING FROM THE DATA OF THE FATH...
Definition: cutting_utility.h:930
DenseVector< Vector_Order_Tensor > Node_Vector_Order_Tensor
Definition: cutting_utility.h:75
ModelPart::ConditionsContainerType ConditionsArrayType
Definition: cutting_utility.h:72
void AddSkinConditions(ModelPart &mr_model_part, ModelPart &mr_new_model_part, int plane_number)
ADDSKINCONDITIONS: THIS FUNCTION ADDS TO THE NEW MODEL PART THE DATA OF THE CONDITIONS BELONGING TO T...
Definition: cutting_utility.h:196
ModelPart::NodesContainerType NodesArrayType
Definition: cutting_utility.h:70
Geometry base class.
Definition: geometry.h:71
IndexType const & Id() const
Id of this Geometry.
Definition: geometry.h:964
This class is a vector which stores global pointers.
Definition: global_pointers_vector.h:61
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: global_pointers_vector.h:79
iterator begin()
Definition: global_pointers_vector.h:221
iterator end()
Definition: global_pointers_vector.h:229
Definition: amatrix_interface.h:41
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
static const TComponentType & Get(const std::string &rName)
Retrieves a component with the specified name.
Definition: kratos_components.h:114
static T CrossProduct(const T &a, const T &b)
Performs the vector product of the two input vectors a,b.
Definition: math_utils.h:762
PropertiesType::Pointer pGetProperties(IndexType PropertiesId)
Definition: mesh.h:394
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
NodeType::Pointer CreateNewNode(int Id, double x, double y, double z, VariablesList::Pointer pNewVariablesList, IndexType ThisIndex=0)
Definition: model_part.cpp:270
SizeType GetNodalSolutionStepDataSize()
Definition: model_part.h:571
NodeIterator NodesBegin(IndexType ThisIndex=0)
Definition: model_part.h:487
ConditionsContainerType & Conditions(IndexType ThisIndex=0)
Definition: model_part.h:1381
void AddNodalSolutionStepVariable(VariableData const &ThisVariable)
Definition: model_part.h:532
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
NodeIterator NodesEnd(IndexType ThisIndex=0)
Definition: model_part.h:497
MeshType & GetMesh(IndexType ThisIndex=0)
Definition: model_part.h:1791
NodesContainerType & Nodes(IndexType ThisIndex=0)
Definition: model_part.h:507
VariablesList & GetNodalSolutionStepVariablesList()
Definition: model_part.h:549
This class defines the node.
Definition: node.h:65
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
ptr_iterator ptr_end()
Returns an iterator pointing to the end of the underlying data container.
Definition: pointer_vector_set.h:404
boost::indirect_iterator< typename TContainerType::iterator > iterator
Definition: pointer_vector_set.h:95
ptr_iterator ptr_begin()
Returns an iterator pointing to the beginning of the underlying data container.
Definition: pointer_vector_set.h:386
size_type size() const
Returns the number of elements in the container.
Definition: pointer_vector_set.h:502
iterator begin()
Returns an iterator pointing to the beginning of the container.
Definition: pointer_vector_set.h:278
iterator end()
Returns an iterator pointing to the end of the container.
Definition: pointer_vector_set.h:314
A three node 3D triangle geometry with linear shape functions.
Definition: triangle_3d_3.h:77
bool Has(const VariableData &rThisVariable) const
Definition: variables_list.h:372
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_WATCH(variable)
Definition: define.h:806
#define KRATOS_TRY
Definition: define.h:109
#define KRATOS_ERROR
Definition: exception.h:161
Parameters GetValue(Parameters &rParameters, const std::string &rEntry)
Definition: add_kratos_parameters_to_python.cpp:53
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
Definition: control.py:1
active
Definition: generate_frictionless_components_mortar_condition.py:175
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int counter
Definition: script_THERMAL_CORRECT.py:218
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17