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.
trilinos_cutting_app.h
Go to the documentation of this file.
1 // Project Name: Kratos
2 // Last Modified by: $Author: Pablo $
3 // Date: $Date: 2010-05-12 $
4 // Revision: $Revision: 1.0 $
5 //
6 //
7 
8 #if !defined(KRATOS_TRILINOS_LOCAL_CUTTING_APP)
9 #define KRATOS_TRILINOS_LOCAL_CUTTING_APP
10 
11 // System includes
12 
13 /* Project includes */
14 #include "utilities/math_utils.h"
19 
20 #include "Epetra_Vector.h"
21 #include "Epetra_Map.h"
22 #include "Epetra_SerialDenseMatrix.h"
23 #include "Epetra_MpiComm.h"
24 #include "Epetra_FECrsGraph.h"
25 #include "Epetra_FECrsMatrix.h"
26 
27 #include "Epetra_FEVector.h"
28 
29 #include "Epetra_Import.h"
30 #include "Epetra_MpiComm.h"
31 
32 
33 
34 namespace Kratos
35 {
37 
46 {
47 public:
48 
52  typedef vector<Matrix> Matrix_Order_Tensor;
53  typedef vector<Vector> Vector_Order_Tensor;
54  typedef vector<Vector_Order_Tensor> Node_Vector_Order_Tensor;
55  typedef Node PointType;
56  typedef Node ::Pointer PointPointerType;
57  typedef std::vector<PointType::Pointer> PointVector;
58  typedef PointVector::iterator PointIterator;
59 
65  TrilinosCuttingApplication(Epetra_MpiComm& Comm) : mrComm(Comm)
66  {
67  smallest_edge=1.0;
69  } //
70 
72  {
73  }
74 
75 
76 
77 
78 
80 
86  void FindSmallestEdge(ModelPart& mr_model_part)
87  {
88  ModelPart& this_model_part = mr_model_part;
89  ElementsArrayType& rElements = this_model_part.Elements();
90  ElementsArrayType::iterator it_begin = rElements.ptr_begin();
91  ElementsArrayType::iterator it_end = rElements.ptr_end();
92  double dist_node_neigh; //distance between the two nodes of the edge
93  array_1d<double, 3 > node_coord; //
94  array_1d<double, 3 > neigh_coord; //
95  double local_smallest_edge = 1000000000000000000000000000.0; //maybe the mesh is huge, setting a big number just in case
96  smallest_edge = local_smallest_edge; //giving it a value, just in case.
97  for (ElementsArrayType::iterator it = it_begin; it != it_end; ++it) //looping all the elements
98  {
99  Geometry<Node >&geom = it->GetGeometry(); //geometry of the element
100  for(unsigned int i = 0; i < it->GetGeometry().size() ; i++) //edge i
101  {
102  node_coord[0] = geom[i].X();
103  node_coord[1] = geom[i].Y();
104  node_coord[2] = geom[i].Z();
105  for(unsigned int j = 0; j < it->GetGeometry().size() ; j++) //edge i
106  {
107  neigh_coord[0] = geom[j].X();
108  neigh_coord[1] = geom[j].Y();
109  neigh_coord[2] = geom[j].Z();
110  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
111  if ((dist_node_neigh<local_smallest_edge) && (i!=j)) local_smallest_edge=dist_node_neigh; //saving the smallest found up to now
112  }//closing j loop
113  } //closing i loop
114  } //closing element loop
115  //KRATOS_WATCH(local_smallest_edge);
116  mrComm.MinAll(&local_smallest_edge, &smallest_edge, 1); //using the global one.
117  if (mrComm.MyPID() == 0) KRATOS_WATCH(smallest_edge);
118  } //closing function
119 
120 
121 
122 
123 
124 
125 
128 
129 
131 
138  void AddSkinConditions(ModelPart& mr_model_part, ModelPart& mr_new_model_part, int plane_number )
139  {
140  ModelPart& this_model_part = mr_model_part;
141  ModelPart& new_model_part = mr_new_model_part;
142 
143  if (mMPICommSetup_is_defined==false)
144  {
147  }
148 
149  if (mrComm.MyPID() == 0)
150  {
151  std::cout <<"Adding Skin Conditions to the new model part, added in layer:"<<std::endl;
152  KRATOS_WATCH(plane_number);
153  }
154  KRATOS_TRY
155 
156 
157  NodesArrayType& rNodes_old = this_model_part.Nodes(); //needed to find the position of the node in the node array
158  NodesArrayType::iterator it_begin_node_old = rNodes_old.ptr_begin();
159 
160  int nlocal_nodes = this_model_part.GetCommunicator().LocalMesh().Nodes().size(); //only local nodes
161  int nnodes = this_model_part.Nodes().size(); //both local nodes and the ones belonging to other CPU
162 
163  //first we create a non overlapping map (only local nodes)
164  int *local_ids = new int[nlocal_nodes];
165  int k = 0;
166  for (ModelPart::NodesContainerType::iterator it = this_model_part.GetCommunicator().LocalMesh().NodesBegin(); it != this_model_part.GetCommunicator().LocalMesh().NodesEnd(); it++)
167  {
168  local_ids[k] = it->Id() - 1;
169  k++;
170  }
171  Kratos::shared_ptr<Epetra_Map> pmy_map = Kratos::make_shared<Epetra_Map >(-1, nlocal_nodes, local_ids, 0, mrComm);
172  delete [] local_ids;
173 
174  //now create a map that has overlapping elements ... that is both local and ghosts
175  //generate a map with the ids of the nodes
176  int *ids = new int[nnodes];
177  k = 0;
178  for (ModelPart::NodesContainerType::iterator it = this_model_part.NodesBegin(); it != this_model_part.NodesEnd(); it++)
179  {
180  ids[k] = it->Id() - 1;
181  k++;
182  }
183  Kratos::shared_ptr<Epetra_Map> pmy_ov_map = Kratos::make_shared<Epetra_Map> (-1, nnodes, ids, 0, mrComm);
184  delete [] ids;
185 
186 
187  //now we create a non overlapping vector:aux_non_overlapping_graph
188  //this one will store which processor is the owner of each of the node's we'll be creating
189  Kratos::shared_ptr<Epetra_FEVector> aux_non_overlapping_graph = Kratos::make_shared<Epetra_FEVector>(*pmy_map,1,false);
190 
191  aux_non_overlapping_graph->PutScalar(-1.0); //zero means this node will not have to be cloned into the new model part
192 
193  //the id of our processor:
194  double this_partition_index = double(mrComm.MyPID());
195 
196  //here we'll store the nodes that will be cloned. NOT ids but position in the nodes array (full, not only owned)
197  bool* used_nodes = new bool [nnodes];
198  for (int index = 0; index!=nnodes; ++index) used_nodes[index]=false; //starting as zero (no needed nodes)
199 
200 
201  //now we have to search for the conditions. they can only be triangles, otherwise -> not stored
202  int number_of_local_conditions=0;
203  int aux_ids;
204  for (ModelPart::ConditionsContainerType::iterator it = this_model_part.ConditionsBegin(); it != this_model_part.ConditionsEnd(); it++)
205  {
206  Geometry<Node >& geom = it->GetGeometry();
207  if (geom.size()==3)
208  {
209  ++number_of_local_conditions; //conditions are always owned
210  for (unsigned int i = 0; i < geom.size(); i++)
211  {
212  aux_ids = geom[i].Id() - 1;
213  int node_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)
214  used_nodes[node_position]=true; //we will have to clone this node into the new model part, no matter if owned or not.
215  int ierr = aux_non_overlapping_graph->ReplaceGlobalValues( 1 , &aux_ids, &this_partition_index,0); // saving that this processor owns this node
216  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
217  }
218  }
219  }
220 
221 
222  int ierr = -1;
223  ierr = aux_non_overlapping_graph->GlobalAssemble(Insert,true); //Epetra_CombineMode mode=Add);
224  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
225  //now in our local graph we have also the nodes that are required by other processors
226 
227 
228  double* local_non_ov = new double [nlocal_nodes]; //a human readeable copy of the FEvector
229  ierr = aux_non_overlapping_graph->ExtractCopy(local_non_ov,nlocal_nodes);
230  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
231 
232 
233  int n_owned_nonzeros = 0;
234 
235  for (int index=0; index!=nlocal_nodes; ++index)
236  {
237  if (local_non_ov[index]>(-0.5))
238  {
239  //counting the number of new nodes this processor will own
240  ++n_owned_nonzeros;
241  }
242  }
243 
244 
245  // COUNTING THE NUMBER OF NODES AND CONDITIONS THAT WILL BE CREATED BY PREVIOUS PROCESSES OF THE CONDITIONS
246  int nodes_before;
247  mrComm.ScanSum(&n_owned_nonzeros, &nodes_before, 1);
248  nodes_before -= n_owned_nonzeros; //number of nodes created by other previous processors used for conditions
249 
250  int conditions_before = -1; // same but for conditions
251  mrComm.ScanSum(&number_of_local_conditions, &conditions_before, 1);
252  conditions_before -=number_of_local_conditions;
253 
254  //NOW WE COUNT THE NUMBER OF NODES AND TRIANGLES CREATED BY PREVIOUS CUTTING PLANES *from the new model part
255  //find our the total number of nodes
256  int number_of_local_nodes = new_model_part.Nodes().size(); // CHANGED from THIS_MODEL_PART to NEW_MODEL_PART. these are the nodes that i have from previous cuts
257  int number_of_old_nodes = -1; //we're also counting ghost nodes! there will be 'holes' in the node ids between each cutting plane and the following one. ( = ghost nodes)
258  mrComm.SumAll(&number_of_local_nodes, &number_of_old_nodes, 1);
259  if (number_of_old_nodes < 0) number_of_old_nodes = 0;
260 
261  int number_of_local_old_conditions = new_model_part.Conditions().size(); // CHANGED from THIS_MODEL_PART to NEW_MODEL_PART. these are the nodes that i have from previous cuts
262  int number_of_old_conditions = -1; //we're also counting ghost nodes! there will be 'holes' in the node ids between each cutting plane and the following one. ( = ghost nodes)
263  mrComm.SumAll(&number_of_local_old_conditions, &number_of_old_conditions, 1);
264  //KRATOS_WATCH(total_number_of_nodes)
265  if (number_of_old_conditions < 0) number_of_old_conditions = 0;
266 
267 
268  if (!new_model_part.GetNodalSolutionStepVariablesList().Has(FATHER_NODES) ||
269  !new_model_part.GetNodalSolutionStepVariablesList().Has(WEIGHT_FATHER_NODES) )
270  KRATOS_ERROR << "The cut model part was not initialized. "
271  "Please call AddVariablesToCutModelPart before AddSkinConditions."
272  << std::endl;
273 
274 
275  //info from the original model part
276  ConditionsArrayType& rConditions = this_model_part.Conditions();
277 // ConditionsArrayType::iterator cond_it_begin = rConditions.ptr_begin();
278 // ConditionsArrayType::iterator cond_it_end = rConditions.ptr_end();
279 
280 // ConditionsArrayType& rConditions_new = new_model_part.Conditions();
281 // ConditionsArrayType::iterator cond_it_end_new = rConditions_new.ptr_end();
282 // ConditionsArrayType::iterator cond_it_begin_new = rConditions_new.ptr_begin();
283 
284 // NodesArrayType& rNodes_new = new_model_part.Nodes(); //i need the model part just to check the id of the new nodes.
285 // NodesArrayType::iterator it_end_node_new = rNodes_new.ptr_end();
286 // NodesArrayType::iterator it_begin_node_new = rNodes_new.ptr_begin();
287 
288 
289  Kratos::shared_ptr<Epetra_FEVector > IDs_non_overlapping_graph = Kratos::make_shared<Epetra_FEVector>(*pmy_map,1,false); //name self explaining
290  //KRATOS_WATCH(number_of_old_nodes) ; KRATOS_WATCH(nodes_before);
291  int node_id=number_of_old_nodes+nodes_before; //nodes we have previously.
292  for (int index=0; index!=nlocal_nodes; ++index)
293  {
294  if (local_non_ov[index]>(-0.5)) //actually it can only belong to this processor, otherwise it has a -1, meaning it doesnt have to be cloned
295  {
296  ++node_id;
297  double node_id_double=double(node_id);
298  ierr = IDs_non_overlapping_graph->ReplaceMyValue ( index , 0 , node_id_double ); //saving the ID
299  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
300  }
301  }
302 
303  ierr = -1;
304  ierr = IDs_non_overlapping_graph->GlobalAssemble(Insert,true); //Epetra_CombineMode mode=Add);
305  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
306 
307  //KRATOS_WATCH('line333')
308 
309  //NOW WE MUST CREATE THE VECTOR CONTAINING BOTH OWNED AND NOT OWNED NODES.
310  //ACTUALLY THEY'RE CREATED THE SAME WAY, BUT THE OWNER PROCESSOR IS THE ONE THAT SETS THE IDS
311  //ONCE DONE, THESE IDs ARE SHARED AND NODES THAT ARE REAPETED ARE CREATED TWICE BY DIFFERENT PROCESSOR BUT WITH THE SAME ID number.
312  Epetra_Import importer(*pmy_ov_map, *pmy_map);
313  Kratos::shared_ptr<Epetra_FEVector > IDs_overlap = Kratos::make_shared<Epetra_FEVector>(*pmy_ov_map,1,false);
314 
315  ierr = IDs_overlap->Import(*IDs_non_overlapping_graph, importer, Insert);
316  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
317 
318  double* local_IDs_ov = new double [nnodes]; //copy in a human readeable format. the FEvector refuses to use the operator []
319  ierr = IDs_overlap->ExtractCopy(local_IDs_ov,nnodes);
320  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
321 
322  //we must now create an overlapping fevector with te partition index:
323  Kratos::shared_ptr<Epetra_FEVector > Partition_overlap = Kratos::make_shared<Epetra_FEVector>(*pmy_ov_map,1,false);
324 
325  ierr = Partition_overlap->Import(*aux_non_overlapping_graph, importer, Insert);
326  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
327 
328  double* local_Partition_ov = new double [nnodes]; //copy in a human readeable format. the FEvector refuses to use the operator []
329  ierr = Partition_overlap->ExtractCopy(local_Partition_ov,nnodes);
330  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
331 
333 
334  for (int index=0; index!=nnodes; ++index) //now we have to save the nodes!.
335  {
336  //KRATOS_WATCH(auxiliar);
337  if (used_nodes[index]==true)
338  {
339  //KRATOS_WATCH(index)
340  int node_number= int(local_IDs_ov[index]);
341 
342  ModelPart::NodesContainerType::iterator it_node = this_model_part.Nodes().begin()+index; //CHANGE THIS! this only work if the nodes in the original model part are consecutive. or??
343 
344  //Node ::Pointer pnode = new_model_part.CreateNewNode(node_number, it_node->X(), it_node->Y(), it_node->Z()); //recordar que es el nueevo model part!!
345  Node::Pointer pnode = Node ::Pointer (new Node(node_number, it_node->X(), it_node->Y(), it_node->Z()));
346  pnode->SetSolutionStepVariablesList(&(new_model_part.GetNodalSolutionStepVariablesList()));
347 
348  pnode->SetBufferSize(this_model_part.NodesBegin()->GetBufferSize());
349  pnode->GetValue(FATHER_NODES).resize(0);
350  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
351  pnode->GetValue(FATHER_NODES).push_back( Node::WeakPointer( *it_node.base() ) );
352  pnode-> GetValue(WEIGHT_FATHER_NODES) = 1.0; //
353  pnode->X0() = it_node->X0();
354  pnode->Y0() = it_node->Y0();
355  pnode->Z0() = it_node->Z0();
356  //pnode->FastGetSolutionStepValue(PARTITION_INDEX)=local_Partition_ov[index];
357  pnode->FastGetSolutionStepValue(PARTITION_INDEX)= it_node->FastGetSolutionStepValue(PARTITION_INDEX);
358  new_model_part.Nodes().push_back(pnode);
359  //if (mrComm.MyPID()==0)
360  //std::cout << mrComm.MyPID() << " " << pnode->Id() <<" " << pnode->FastGetSolutionStepValue(PARTITION_INDEX) <<std::endl;
361  }
362  }
363  new_model_part.Nodes().Sort();
364 
365  new_model_part.Nodes().Unique();
366 
367  //KRATOS_WATCH('line404')
368 
369  //NOW WE MUST COPY THE CONDITIONS
370  int triangle_ID = number_of_old_conditions + conditions_before;
371  vector<int> triangle_nodes(3); //here we'll save the nodes' ids with the new node names
372  Condition const& rReferenceCondition = KratosComponents<Condition>::Get("SurfaceCondition3D3N"); //condition type
373  Properties::Pointer properties = this_model_part.GetMesh().pGetProperties(plane_number); //this will allow us later to turn this layer on/off in GID
374 
375  for(ModelPart::ConditionsContainerType::iterator i_condition = rConditions.begin() ; i_condition != rConditions.end() ; i_condition++) //looping all the conditions
376  {
377  Geometry<Node >&geom = i_condition->GetGeometry(); //current condition(nodes, etc)
378  if (geom.size()==3)
379  {
380  for(unsigned int i = 0; i < i_condition->GetGeometry().size() ; i++) //looping the nodes
381  {
382  int position = (geom[i].Id()) - 1; //the id of the node minus one is the position in the Condition_Node array (position0 = node1)
383  int local_position = (*pmy_ov_map).LID(position); //changing from global id to local id
384  triangle_nodes[i]=local_IDs_ov[local_position] ; // saving the i nodeId
385  } //nodes id saved. now we have to create the element.
386  Triangle3D3<Node > geometry(
387  new_model_part.Nodes()(triangle_nodes[0]), //condition to be added
388  new_model_part.Nodes()(triangle_nodes[1]),
389  new_model_part.Nodes()(triangle_nodes[2])
390  );
391  ++triangle_ID;
392  Condition::Pointer p_condition = rReferenceCondition.Create(triangle_ID, geometry, properties);
393  new_model_part.Conditions().push_back(p_condition); //and done! added a new triangloe to the new model part
394  }
395  }
396 
397  Clear();
398  //KRATOS_WATCH(new_model_part)
399  ParallelFillCommunicator(new_model_part, this_model_part.GetCommunicator().GetDataCommunicator()).Execute(); //changed from PrintDebugInfo to Execute
400  //ParallelFillCommunicator(new_model_part).PrintDebugInfo(); //changed from PrintDebugInfo to Execute
401 
402  if (mrComm.MyPID() == 0) std::cout << "copyng conditions and recalculation plan have been completed" << std::endl;
403  KRATOS_CATCH("")
404  }
405 
406 
408 
413  const ModelPart& rModelPart,
414  ModelPart& rNewModelPart) const
415  {
417  rNewModelPart.AddNodalSolutionStepVariable(FATHER_NODES);
418  rNewModelPart.AddNodalSolutionStepVariable(WEIGHT_FATHER_NODES);
419  }
420 
421 
424 
426 
436  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)
437  {
438  KRATOS_TRY
439 
440  if (mMPICommSetup_is_defined==false)
441  {
444  }
445 
446  if (mrComm.MyPID() == 0)
447  {
448  std::cout <<"Generating Cutting plane with the following data:"<<std::endl;
449  KRATOS_WATCH(versor);
450  KRATOS_WATCH(Xp);
451  }
452 
453  if (!mr_new_model_part.GetNodalSolutionStepVariablesList().Has(FATHER_NODES) ||
454  !mr_new_model_part.GetNodalSolutionStepVariablesList().Has(WEIGHT_FATHER_NODES) )
455  KRATOS_ERROR << "The cut model part was not initialized. "
456  "Please call AddVariablesToCutModelPart before GenerateCut."
457  << std::endl;
458 
459  ModelPart& this_model_part = mr_model_part;
460  //ModelPart& new_model_part = mr_new_model_part;
461 
462  vector<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)
463  int number_of_triangles = 0;
464  double tolerance = tolerance_factor*smallest_edge; //if Find_Smallest_Edge is not run , then the tolerance is absolute
465 
466  Kratos::shared_ptr<Epetra_FECrsMatrix> p_edge_ids; //helper matrix to assign ids to the edges to be refined
467  Kratos::shared_ptr<Epetra_FECrsMatrix> p_partition_ids; //helper matrix to assign a partition to the edges
468  vector<int> List_New_Nodes;
469  vector<int> partition_new_nodes;
470  vector<array_1d<int, 2 > > father_node_ids;
471  vector< array_1d<double, 3 > > Coordinate_New_Node;
472  Kratos::shared_ptr<Epetra_FECrsMatrix> used_nodes_matrix;
473 
474 
475  PointerVector< Element > New_Elements;
476  PointerVector< Condition > New_Conditions;
477 
478  CSR_Row_Matrix(mr_model_part, p_edge_ids, used_nodes_matrix);
479  MPI_Barrier(MPI_COMM_WORLD);
480  //if (mrComm.MyPID() == 0) std::cout << "index matrix constructed" << std::endl;
481 
482  FirstLoop(mr_model_part, p_edge_ids, p_partition_ids, versor, Xp, number_of_triangles, Elems_In_Plane, tolerance, used_nodes_matrix);
483  MPI_Barrier(MPI_COMM_WORLD);
484  //if (mrComm.MyPID() == 0) std::cout << "Search_Edge_To_Be_Refined completed" << std::endl;
485 
486  Create_List_Of_New_Nodes(mr_model_part, mr_new_model_part, p_edge_ids, p_partition_ids, List_New_Nodes, partition_new_nodes, father_node_ids, used_nodes_matrix);
487  MPI_Barrier(MPI_COMM_WORLD);
488  //if (mrComm.MyPID() == 0) std::cout << "Create_List_Of_New_Nodes completed" << std::endl;
489 
490  Calculate_Coordinate_And_Insert_New_Nodes(mr_model_part, mr_new_model_part, father_node_ids, List_New_Nodes, partition_new_nodes, versor, Xp, tolerance);
491  MPI_Barrier(MPI_COMM_WORLD);
492  //if (mrComm.MyPID() == 0) std::cout << "Calculate_Coordinate_And_Insert_New_Nodes completed" << std::endl;
493 
494  GenerateElements(mr_model_part, mr_new_model_part, Elems_In_Plane, p_edge_ids, versor, plane_number, number_of_triangles);
495  MPI_Barrier(MPI_COMM_WORLD);
496  //if (mrComm.MyPID() == 0) std::cout << "finished generating elements" << std::endl;
497 
498 
499 
500  //fill the communicator
501  ParallelFillCommunicator(mr_new_model_part, this_model_part.GetCommunicator().GetDataCommunicator()).Execute();
502  if (mrComm.MyPID() == 0) std::cout << "recalculation of communication plan completed" << std::endl;
503 
504  //clean up the data
505  Clear();
506 
507  KRATOS_CATCH("")
508  }
509 
510 
511 
512  void Clear()
513  {
514  KRATOS_TRY
516  empty_map.swap(mp_non_overlapping_map);
517 
519 
521  mp_non_overlapping_graph.swap(empty1);
522 
524  mp_overlapping_graph.swap(empty2);
525 
526 
527  KRATOS_CATCH("");
528  }
529 
530 
531 
533  ModelPart& this_model_part,
535  Kratos::shared_ptr<Epetra_FECrsMatrix>& used_nodes_matrix)
536  {
537  KRATOS_TRY
538 
539  //generate a map with the ids of the nodes
540  int nlocal_nodes = this_model_part.GetCommunicator().LocalMesh().Nodes().size();
541  int *local_ids = new int[nlocal_nodes];
542  int k = 0;
543  for (ModelPart::NodesContainerType::iterator it = this_model_part.GetCommunicator().LocalMesh().NodesBegin(); it != this_model_part.GetCommunicator().LocalMesh().NodesEnd(); it++)
544  {
545  local_ids[k++] = it->Id() - 1;
546  }
547 
548  Kratos::shared_ptr<Epetra_Map> pmy_map = Kratos::make_shared<Epetra_Map>(-1, nlocal_nodes, local_ids, 0, mrComm);
549  mp_non_overlapping_map.swap(pmy_map);
550  delete [] local_ids;
551 
552  //now create a matrix that has overlapping elements ... that is both local and ghosts
553  //generate a map with the ids of the nodes
554  int nnodes = this_model_part.Nodes().size();
555  int *ids = new int[nnodes];
556  k = 0;
557  for (ModelPart::NodesContainerType::iterator it = this_model_part.NodesBegin(); it != this_model_part.NodesEnd(); it++)
558  {
559  ids[k++] = it->Id() - 1;
560  }
561 
562  Kratos::shared_ptr<Epetra_Map> pmy_ov_map = Kratos::make_shared<Epetra_Map>(-1, nnodes, ids, 0, mrComm);
563  mp_overlapping_map.swap(pmy_ov_map);
564  delete [] ids;
565 
566  //generate the graph
567  int guess_row_size = 20;
568  Kratos::shared_ptr<Epetra_FECrsGraph > aux_non_overlapping_graph = Kratos::make_shared<Epetra_FECrsGraph>(Copy, *mp_non_overlapping_map, guess_row_size);
569  aux_non_overlapping_graph.swap(mp_non_overlapping_graph);
570 
571  int aux_ids[4];
572  for (ModelPart::ElementsContainerType::iterator it = this_model_part.ElementsBegin(); it != this_model_part.ElementsEnd(); it++)
573  {
574  Geometry<Node >& geom = it->GetGeometry();
575  for (unsigned int i = 0; i < geom.size(); i++)
576  aux_ids[i] = geom[i].Id() - 1;
577 
578  int ierr = mp_non_overlapping_graph->InsertGlobalIndices(geom.size(), aux_ids, geom.size(), aux_ids);
579  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
580  }
581  for (ModelPart::ConditionsContainerType::iterator it = this_model_part.ConditionsBegin(); it != this_model_part.ConditionsEnd(); it++)
582  {
583  Geometry<Node >& geom = it->GetGeometry();
584  for (unsigned int i = 0; i < geom.size(); i++)
585  aux_ids[i] = geom[i].Id() - 1;
586 
587  int ierr = mp_non_overlapping_graph->InsertGlobalIndices(geom.size(), aux_ids, geom.size(), aux_ids);
588  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
589  }
590  mp_non_overlapping_graph->GlobalAssemble();
591 
592 
593  //fill the edge_matrix
594  Kratos::shared_ptr<Epetra_FECrsMatrix> pA = Kratos::make_shared<Epetra_FECrsMatrix>(Copy, *mp_non_overlapping_graph);
595  pA->PutScalar(-1.0);
596 
597  pA.swap(p_edge_ids);
598 
599 
600  Kratos::shared_ptr<Epetra_FECrsMatrix> pB = Kratos::make_shared<Epetra_FECrsMatrix>(Copy, *mp_overlapping_map, guess_row_size);
601  pB->PutScalar(0.0);
602 
603  pB.swap(used_nodes_matrix);
604 
605  KRATOS_CATCH("")
606 
607  }
610 
611  void FirstLoop(ModelPart& this_model_part, Kratos::shared_ptr<Epetra_FECrsMatrix>& p_edge_ids,
613  array_1d<double, 3 > Xp, int& number_of_triangles, vector<int>& Elems_In_Plane, double tolerance,
614  Kratos::shared_ptr<Epetra_FECrsMatrix>& used_nodes_matrix)//
615  {
616  KRATOS_TRY
617  ElementsArrayType& rElements = this_model_part.Elements();
618 
619  Kratos::shared_ptr<Epetra_FECrsMatrix> p_nonoverlapping_partitions
620  = Kratos::make_shared<Epetra_FECrsMatrix>(Copy, *mp_non_overlapping_graph);
621  p_nonoverlapping_partitions->PutScalar(-1.0);
622 
623  double this_partition_index = double(mrComm.MyPID());
624 
625  //first of all create a matrix with no overlap
626  ElementsArrayType::iterator it_begin = rElements.ptr_begin(); //+element_partition[k];
627  ElementsArrayType::iterator it_end = rElements.ptr_end(); //+element_partition[k+1];
628 
629  double dist_node_point; // node to closest point in the plane
630  double dist_neigh_point; //other node of the edge (neighbour) to closest point in the plane
631  //double dist_node_neigh; //distance between the two nodes of the edge
632  array_1d<double, 3 > temp_dist; //aux segment
633  array_1d<double, 3 > node_coord; //
634  array_1d<double, 3 > neigh_coord; //
635  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)
636  unsigned int exact_nodes = 0;
637  number_of_triangles = 0;
638  int current_element = 0; //current element. it's a position. NOT ID!
639  int number_of_cuts = 0; //this is the counter explained in the following lines
640 
641  for (ElementsArrayType::iterator it = it_begin; it != it_end; ++it)
642  {
643  ++current_element;
644  number_of_cuts = 0;
645  exact_nodes = 0;
646  Geometry<Node >&geom = it->GetGeometry(); //geometry of the element
647  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.
648  //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)
649  {
650  node_coord[0] = geom[i].X();
651  node_coord[1] = geom[i].Y();
652  node_coord[2] = geom[i].Z();
653  noalias(temp_dist) = node_coord;
654  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
655  dist_node_point = inner_prod(temp_dist, versor); // dist = (xnode-xp)*versor closest point-plane distance
656  for (unsigned int j = 0; j < it->GetGeometry().size(); j++) // looping on the neighbours
657  {
658  if (i != j) //(cant link node with itself)
659  {
660  neigh_coord[0] = geom[j].X();
661  neigh_coord[1] = geom[j].Y();
662  neigh_coord[2] = geom[j].Z();
663  noalias(temp_dist) = neigh_coord;
664  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
665  dist_neigh_point = inner_prod(temp_dist, versor); // dist = (xnode-xp)*versor closest point-plane distance
666  //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
667  //now that we have the two points of the edge defined we can check whether it is cut by the plane or not
668  bool isovernode = false; // if true, then it can't be between the nodes
669 
670  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 .
671  {
672  int index_i = geom[i].Id() - 1; // i node id
673  double value = -1.0;
674  double true_value = -1.0;
675  int ierr = p_edge_ids->SumIntoGlobalValues(1, &index_i, 1, &index_i, &value);
676  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 235", "");
677  ierr = p_nonoverlapping_partitions->ReplaceGlobalValues(1, &index_i, 1, &index_i, &this_partition_index);
678  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 237", "");
679  ierr = used_nodes_matrix->ReplaceGlobalValues(1, &index_i, 1, &index_i, &true_value);
680  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 237", "");
681  isovernode = true;
682  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),
683  ++exact_nodes;
684  list_matching_nodes[i] = geom[i].Id();
685  break; //we exit the j loop.
686  }
687  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!
688  {
689  int index_i = geom[i].Id() - 1; //i node id
690  int index_j = geom[j].Id() - 1; //j node id
691  double value = -1.0;
692  double true_value = -1.0;
693  ++number_of_cuts;
694  if (index_j > index_i)
695  {
696  int ierr = p_edge_ids->SumIntoGlobalValues(1, &index_i, 1, &index_j, &value);
697  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 235", "");
698  ierr = p_nonoverlapping_partitions->ReplaceGlobalValues(1, &index_i, 1, &index_j, &this_partition_index);
699  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 237", "");
700  ierr = used_nodes_matrix->ReplaceGlobalValues(1, &index_i, 1, &index_j, &true_value);
701  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 237", "");
702  // Coord(index_i, index_j) = -2;
703  }
704  }
705  } //closing the i!=j if
706  } //closing the neighbour (j) loop
707  } //closing the nodes (i) loop
708 
709 
710  //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
711  Elems_In_Plane[current_element - 1] = 0; //we initialize as 0
712  if (exact_nodes != 3) //this means at least one new node has to be generated
713  {
714  if (number_of_cuts == 6) //it can be 8, in that case we have 2 triangles (the cut generates a square)
715  {
716  number_of_triangles += 1;
717  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
718  }
719  else if (number_of_cuts == 8) // 2 triangles in the element!
720  {
721  number_of_triangles += 2;
722  Elems_In_Plane[ current_element - 1] = 2;
723  }
724  }
725  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)
726  {
727  bool found_fourth_node = true; //this is the node that defines the normal of the element
728  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.
729  {
730  found_fourth_node = true;
731  for (unsigned int aux_index = 0; aux_index != 4; ++aux_index) // we define our plane now
732  {
733  if (geom[i].Id() == list_matching_nodes[aux_index] && list_matching_nodes[aux_index] != 0)
734  {
735  found_fourth_node = false;
736  //break; //ok, we have the coordinates of the new node. now we have to mame sure
737  }
738  }
739  if (found_fourth_node == true)
740  {
741  node_coord[0] = geom[i].X();
742  node_coord[1] = geom[i].Y();
743  node_coord[2] = geom[i].Z();
744  break;
745  }
746  }
747  //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
748  //not that this means that this triangle should be added by the neighbour tetraedra( which would return a positive distance)
749  //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
750  noalias(temp_dist) = node_coord;
751  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
752  dist_node_point = inner_prod(temp_dist, versor); // dist = (xnode-xp)*versor closest point-plane distance
753  if (dist_node_point >= 0.0)
754  {
755  if (number_of_cuts == 6) //this should not be necessary, but it's kept just in case (almost plain elements?)
756  {
757  number_of_triangles += 1;
758  Elems_In_Plane[current_element - 1] = 1;
759  //KRATOS_WATCH("found an element!")
760  }
761  else if (number_of_cuts == 8)
762  {
763  number_of_triangles += 2;
764  Elems_In_Plane[ current_element - 1] = 2;
765  }
766  }
767  }
768  } //closing the elem loop
769 
770 
771 
772  int ierr = -1;
773  ierr = p_edge_ids->GlobalAssemble(true, Add);
774  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 246", "");
775 
776  ierr = p_nonoverlapping_partitions->GlobalAssemble(true, Insert);
777  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure --> ln 249", "");
778 
779  //import the non overlapping matrix into the overlapping one
780  int MaxNumEntries = p_edge_ids->MaxNumEntries() + 5;
781  Epetra_Import importer(*mp_overlapping_map, *mp_non_overlapping_map);
782 
783  Kratos::shared_ptr<Epetra_FECrsMatrix> pAoverlap = Kratos::make_shared<Epetra_FECrsMatrix>(Copy, *mp_overlapping_map, MaxNumEntries);
784  Kratos::shared_ptr<Epetra_FECrsMatrix> paux = Kratos::make_shared<Epetra_FECrsMatrix>(Copy, *mp_overlapping_map, MaxNumEntries);
785 
786  ierr = pAoverlap->Import(*p_edge_ids, importer, Insert);
787  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
788  ierr = pAoverlap->FillComplete();
789  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
790 
791  ierr = paux->Import(*p_nonoverlapping_partitions, importer, Insert);
792  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
793  ierr = paux->FillComplete();
794  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
795 
796  //perform a pointer swap - after this we have overlapping matrices with the values syncronized
797  pAoverlap.swap(p_edge_ids);
798  paux.swap(p_partition_ids);
799 
800  //sace the overlapping graph
801  Kratos::shared_ptr<Epetra_CrsGraph > pg = Kratos::make_shared<Epetra_CrsGraph>(p_edge_ids->Graph());
802  mp_overlapping_graph.swap(pg);
803  //KRATOS_WATCH(number_of_triangles)
804  KRATOS_CATCH("")
805  }
806 
809 
810 
811 
812  void Create_List_Of_New_Nodes(ModelPart& this_model_part, ModelPart& new_model_part,
815  vector<int> &List_New_Nodes,
816  vector<int> &partition_new_nodes,
817  vector<array_1d<int, 2 > >& father_node_ids,
818  Kratos::shared_ptr<Epetra_FECrsMatrix>& used_nodes_matrix)
819  {
820  KRATOS_TRY
821  //here we count the new nodes on the local mesh
822  int NumMyRows = p_edge_ids->NumMyRows();
823  int Row; // iterator on rows
824  int Col; // iterator on cols
825  int MaxNumEntries = p_edge_ids->MaxNumEntries();
826  double * id_values = new double[MaxNumEntries];
827  double * partition_values = new double[MaxNumEntries];
828  //double * used_nodes_matrix_row = new double[MaxNumEntries];
829  int * Indices = new int[MaxNumEntries];
830  int NumEntries;
831  int GlobalRow;
832 
833  int NumEntries_aux;
834  int * Indices_aux = new int[MaxNumEntries];
835  double * id_values_aux = new double[MaxNumEntries];
836 
837  int n_owned_nonzeros = 0;
838  int n_new_nonzeros = 0; //this are the nonzeros owned or not, but that must be known
839  double this_partition_index = mrComm.MyPID();
840 
841  for (Row = 0; Row < NumMyRows; ++Row)
842  {
843  GlobalRow = p_edge_ids->GRID(Row);
844  int ierr = p_edge_ids->ExtractGlobalRowCopy(GlobalRow, MaxNumEntries, NumEntries, id_values, Indices);
845  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
846 
847  ierr = p_partition_ids->ExtractGlobalRowCopy(GlobalRow, MaxNumEntries, NumEntries, partition_values, Indices);
848  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
849 
850  for (Col = 0; Col != NumEntries; Col++)
851  {
852  if (Indices[Col] >= Row)
853  if (id_values[Col] < -1.5 && mp_overlapping_map->MyGID(Indices[Col]) == true)
854  {
855  n_new_nonzeros = n_new_nonzeros + 1;
856  if (partition_values[Col] == this_partition_index)
857  n_owned_nonzeros = n_owned_nonzeros + 1;
858  }
859 
860  }
861  }
862  //use the scan sum
863  int nodes_before = -1;
864  mrComm.ScanSum(&n_owned_nonzeros, &nodes_before, 1);
865  nodes_before = nodes_before - n_owned_nonzeros;
866  if (nodes_before < 0)
867  KRATOS_THROW_ERROR(std::logic_error, "problem with scan sum ... giving a negative number of nodes before", "")
868 
869  //find our the total number of nodes
870  int number_of_local_nodes = new_model_part.Nodes().size(); // CHANGED from THIS_MODEL_PART to NEW_MODEL_PART. these are the nodes that i have from previous cuts
871  int total_number_of_nodes = -1;
872  mrComm.SumAll(&number_of_local_nodes, &total_number_of_nodes, 1);
873  //KRATOS_WATCH(total_number_of_nodes)
874  if (total_number_of_nodes < 0) total_number_of_nodes = 0; //this means we're in the first cutting plane.
875  mtotal_number_of_existing_nodes = total_number_of_nodes;
876  //the ids of the new nodes we will create AND OWN will be between
877  //start_id and end_id;
878  //non local nodes may have ids out of this limits
879  int start_id = total_number_of_nodes + nodes_before + 1;
880  int end_id = start_id + n_owned_nonzeros;
881 
882  //now distribute the ids of the new nodes so that they will be the same over all of the processors.
883  Kratos::shared_ptr<Epetra_FECrsMatrix> plocal_ids = Kratos::make_shared<Epetra_FECrsMatrix>(Copy, *mp_non_overlapping_graph);
884  plocal_ids->PutScalar(-1);
885 
886  int id = start_id;
887 
888  for (Row = 0; Row < NumMyRows; ++Row)
889  {
890  GlobalRow = p_edge_ids->GRID(Row);
891 
892  int ierr = p_edge_ids->ExtractGlobalRowCopy(GlobalRow, MaxNumEntries, NumEntries, id_values, Indices);
893  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
894 
895  ierr = p_partition_ids->ExtractGlobalRowCopy(GlobalRow, MaxNumEntries, NumEntries, partition_values, Indices);
896  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
897 
898  for (Col = 0; Col < NumEntries; ++Col)
899  {
900  if (Indices[Col] >= Row)
901  if (id_values[Col] < -1.5 &&
902  partition_values[Col] == this_partition_index &&
903  mp_overlapping_map->MyGID(Indices[Col]) == true)
904  {
905  double did = double(id);
906  plocal_ids->ReplaceGlobalValues(1, &GlobalRow, 1, &(Indices[Col]), &did);
907  id++;
908  }
909  }
910  }
911  plocal_ids->GlobalAssemble(true, Insert);
912 
913  if (id != end_id) KRATOS_THROW_ERROR(std::logic_error, "the own node count is not verified...some error occurred", "");
914  //now import the non local elements
915  Epetra_Import importer(*mp_overlapping_map, *mp_non_overlapping_map);
916 
917 
918  int ierr = p_edge_ids->Import(*plocal_ids, importer, Insert);
919  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
920  p_edge_ids->FillComplete();
921  if (ierr < 0) KRATOS_THROW_ERROR(std::logic_error, "epetra failure", "");
922  // paux.swap(p_edge_ids);
923 
925  List_New_Nodes.resize(n_new_nonzeros);
926  partition_new_nodes.resize(n_new_nonzeros);
927  father_node_ids.resize(n_new_nonzeros);
928 
929 
930  int k = 0;
931  for (Row = 0; Row < NumMyRows; ++Row)
932  {
933  GlobalRow = p_edge_ids->GRID(Row);
934  int num_id_entries = -1;
935  int ierr = p_edge_ids->ExtractGlobalRowCopy(GlobalRow, MaxNumEntries, num_id_entries, id_values, Indices);
936  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
937 
938  ierr = p_partition_ids->ExtractGlobalRowCopy(GlobalRow, MaxNumEntries, NumEntries, partition_values, Indices);
939  KRATOS_ERROR_IF(ierr < 0) << "epetra failure" << std::endl;
940 
941  if (NumEntries != num_id_entries) KRATOS_THROW_ERROR(std::logic_error, "we should have the same number of new_ids and of partition_values", "");
942  for (Col = 0; Col < NumEntries; ++Col)
943  {
944  if (Indices[Col] >= Row)
945  {
946  //nodes are to be created only if they are identified by a positive ID
947  if (id_values[Col] >= 0 && mp_overlapping_map->MyGID(Indices[Col]) == true)
948  {
949  List_New_Nodes[k] = id_values[Col];
950  partition_new_nodes[k] = partition_values[Col];
951 
952  father_node_ids[k][0] = GlobalRow + 1;
953  father_node_ids[k][1] = Indices[Col] + 1; //+1;
954  int IsNeeded = GetUpperTriangularMatrixValue(used_nodes_matrix, GlobalRow , (Indices[Col]), MaxNumEntries, NumEntries_aux, Indices_aux, id_values_aux);
955  if (IsNeeded ==0)
956  {
957  father_node_ids[k][0] = -1;
958  father_node_ids[k][1] = -1;
959  }
960  k++;
961  }
962  if (id_values[Col] < -1.5) //at this point every edge to be refined should have an Id!!
963  KRATOS_THROW_ERROR(std::logic_error, "edge to be refined without id assigned", "")
964  }
965  }
966  }
967  if (k != int(n_new_nonzeros)) KRATOS_THROW_ERROR(std::logic_error, "number of new nodes check failed", "")
968 
969 
970  delete [] Indices;
971  delete [] id_values;
972  delete [] partition_values;
973 
974  //KRATOS_WATCH(n_new_nonzeros)
975  KRATOS_CATCH("")
976 
977  }
978 
981  // insert the new nodes in the model part and interopolate the variables
982 
983  void Calculate_Coordinate_And_Insert_New_Nodes(ModelPart& this_model_part, ModelPart& new_model_part,
984  const vector<array_1d<int, 2 > >& father_node_ids,
985  const vector<int> &List_New_Nodes,
986  const vector<int> &partition_new_nodes,
987  array_1d<double, 3 > versor, array_1d<double, 3 > Xp, double tolerance)
988  {
989  KRATOS_TRY
990  array_1d<double, 3 > Coord_Node_1;
991  array_1d<double, 3 > Coord_Node_2;
994  array_1d<double, 3 > intersection;
995  array_1d<double, 3 > temp_dist;
996  double dist_node_point;
997  //double dist_node_neigh;
998  double dist_node_intersect;
999  double weight;
1000  vector< array_1d<double, 3 > > Coordinate_New_Node;
1001  Coordinate_New_Node.resize(father_node_ids.size());
1002 
1003  PointerVector< Node > new_nodes;
1004 
1005  MPI_Barrier(MPI_COMM_WORLD);
1006  if ((father_node_ids.size())!=0)
1007  {
1008  for (unsigned int i = 0; i < father_node_ids.size(); i++)
1009  {
1011 
1012  //getting father node 1
1013  const int& node_i = father_node_ids[i][0];
1014  const int& node_j = father_node_ids[i][1];
1015  if (node_i>0)
1016  {
1017  ModelPart::NodesContainerType::iterator it_node1 = this_model_part.Nodes().find(node_i);
1018  if (it_node1 == this_model_part.NodesEnd())
1019  {
1020  std::cout << "- father node 1 - looking for Id " << node_i << " " << node_j << std::endl;
1021  KRATOS_THROW_ERROR(std::logic_error, "error inexisting node", "")
1022  }
1023  noalias(Coord_Node_1) = it_node1->Coordinates();
1024 
1025  //getting father node 2
1026  ModelPart::NodesContainerType::iterator it_node2 = this_model_part.Nodes().find(node_j);
1027  if (it_node2 == this_model_part.NodesEnd())
1028  {
1029  std::cout << "- father node 2 - looking for Id " << node_i << " " << node_j << std::endl;
1030  KRATOS_THROW_ERROR(std::logic_error, "error inexisting node", "")
1031  }
1032  noalias(Coord_Node_2) = it_node2->Coordinates();
1033 
1034  noalias(temp_dist) = Coord_Node_1;
1035  noalias(temp_dist) -= Xp; //temp_dist =node_coord-Xpoint
1036  dist_node_point = inner_prod(temp_dist, versor); // dist = (xnode-xp)*versor closest point-plane distance
1037  dist_node_point = fabs(dist_node_point);
1038 
1039  Xp_1 = Xp - Coord_Node_1;
1040  Xp_2 = Coord_Node_2 - Coord_Node_1;
1041  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
1042  //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
1043  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
1044  weight = (1.0 - dist_node_intersect); // dist_node_neigh;
1045 
1046  if (weight > 1.05) KRATOS_WATCH("**** something's wrong! weight higher than 1! ****");
1047 
1048  for (unsigned int index = 0; index != 3; ++index) //we loop the 3 coordinates)
1049  if (father_node_ids[i][0] != father_node_ids[i][1])
1050  Coordinate_New_Node[i][index] = Coord_Node_1[index] + (dist_node_intersect) * (Coord_Node_2[index] - Coord_Node_1[index]);
1051  else
1052  Coordinate_New_Node[i][index] = Coord_Node_1[index]; //when both nodes are the same it doesnt make any sense to interpolate
1053 
1054  //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!!
1055  Node::Pointer pnode = Node ::Pointer (new Node(List_New_Nodes[i], Coordinate_New_Node[i][0], Coordinate_New_Node[i][1], Coordinate_New_Node[i][2]));
1056  pnode->SetSolutionStepVariablesList(&(new_model_part.GetNodalSolutionStepVariablesList()));
1057  pnode->SetBufferSize(this_model_part.NodesBegin()->GetBufferSize());
1058  pnode->GetValue(FATHER_NODES).resize(0);
1059  pnode->GetValue(FATHER_NODES).push_back(Node ::WeakPointer(*it_node1.base()));
1060  pnode->GetValue(FATHER_NODES).push_back(Node ::WeakPointer(*it_node2.base()));
1061  pnode-> GetValue(WEIGHT_FATHER_NODES) = weight;
1062 
1063  pnode->X0() = weight * (it_node1->X0()) + (1.0 - weight) * it_node2->X0();
1064  pnode->Y0() = weight * (it_node1->Y0()) + (1.0 - weight) * it_node2->Y0();
1065  pnode->Z0() = weight * (it_node1->Z0()) + (1.0 - weight) * it_node2->Z0();
1066  pnode->FastGetSolutionStepValue(PARTITION_INDEX) = partition_new_nodes[i];
1067  new_model_part.Nodes().push_back(pnode);
1068  }
1069 
1070  }
1071  new_model_part.Nodes().Sort();
1072  unsigned int current_size = new_model_part.Nodes().size();
1073  new_model_part.Nodes().Unique();
1074 
1075  if(current_size != new_model_part.Nodes().size())
1076  KRATOS_THROW_ERROR(std::logic_error,"some node was duplicated! error","");
1077 
1078 
1079  }//closing the if we have nodes
1080  // else {KRATOS_WATCH("no nodes found here")}
1081 
1082  KRATOS_CATCH("")
1083  }
1084 
1085 
1089 
1091  ModelPart& this_model_part, ModelPart& new_model_part, vector<int> Elems_In_Plane,
1092  const Kratos::shared_ptr<Epetra_FECrsMatrix> p_edge_ids,
1093  //PointerVector< Element >& New_Elements,
1094  //bool interpolate_internal_variables
1095  array_1d<double, 3 > versor, int plane_number, int& number_of_triangles
1096  )
1097  {
1098  KRATOS_TRY
1099 
1100  array_1d<double, 3 > temp_vector1;
1101  array_1d<double, 3 > temp_vector2;
1102  array_1d<double, 3 > temp_vector3;
1103  array_1d<double, 3 > temp_vector4;
1104  array_1d<double, 3 > temp_vector5;
1105  array_1d<int, 6 > nodes_for_2triang; //to be used when there are 2 triangles
1106  double dist2; //to be used when there are 2 triangles in the tetraedra
1107  double dist3;
1108  double control;
1109  unsigned int temp_int;
1110 
1111  DenseMatrix<int> new_conectivity;
1112 
1113  int total_existing_elements = -1; //warning, they're conditions, not elements!
1114  int local_existing_elements = new_model_part.Conditions().size();
1115  mrComm.SumAll(&local_existing_elements, &total_existing_elements, 1);
1116 
1117  if (total_existing_elements < 0) total_existing_elements = 0;
1118 
1119  Element const rReferenceElement;
1120  PointerVector< Element > Old_Elements;
1121 
1122  int MaxNumEntries = p_edge_ids->MaxNumEntries();
1123  double * id_values = new double[MaxNumEntries];
1124  int * Indices = new int[MaxNumEntries];
1125  int NumEntries;
1126 
1127  ElementsArrayType& rElements_old = this_model_part.Elements();
1128  ElementsArrayType::iterator it_begin_old = rElements_old.ptr_begin();
1129  ElementsArrayType::iterator it_end_old = rElements_old.ptr_end();
1130 
1131  Condition const& rReferenceCondition = KratosComponents<Condition>::Get("SurfaceCondition3D3N");
1132  Properties::Pointer properties = this_model_part.GetMesh().pGetProperties(plane_number);
1133 
1134  int triangle_id_int = 0; //counter for the new elements generated
1135  int current_element = 0; // counter to know in which thetraedra we are in.
1136  unsigned int triangle_nodes = 0; // number of nodes already saved (of the current element)
1137  bool new_node = false; //used to check whether the current node has been saved or not
1138 
1139  array_1d<int, 4 > TriangleNodesArray; //nodes of the element to be generated. 4 in case they're 2 triangles
1140  for (unsigned int k = 0; k != 4; ++k)
1141  {
1142  TriangleNodesArray[k] = -1;
1143  } //initializing in -1, meaning we have no nodes yet
1144 
1145  int elements_before = -1;
1146  mrComm.ScanSum(&number_of_triangles, &elements_before, 1); //the elements that have already been created in previous threads. (but not in previous cuts, that is stored in total_existing_elements
1147  if (elements_before < 0) elements_before = 0;
1148  else elements_before-=number_of_triangles;
1149 
1151  for (ElementsArrayType::iterator it = it_begin_old; it != it_end_old; ++it)
1152  {
1153  ++current_element;
1154  triangle_nodes = 0; //starting, no nodes yet
1156  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
1157  {
1158  //checking element conectivities
1159  for (unsigned int i = 0; i < it->GetGeometry().size(); i++)
1160  {
1161  Geometry<Node >&geom = it->GetGeometry(); //i node of the element
1162  for (unsigned int j = 0; j < it->GetGeometry().size(); j++) //j node of the element
1163  {
1164  new_node = true; //by default it's a new node
1165  int index_i = geom[i].Id() - 1; //i node id
1166  int index_j = geom[j].Id() - 1;
1167  int NodeId = GetUpperTriangularMatrixValue(p_edge_ids, index_i, index_j, MaxNumEntries, NumEntries, Indices, id_values);
1168 
1169  for (unsigned int l = 0; l != 3; ++l)
1170  {
1171  if (TriangleNodesArray[l] == NodeId //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)
1172  || NodeId < 1)
1173  new_node = false;
1174  }
1175  //if it's a new node and the indexes are correct:
1176  if (new_node && index_i <= index_j)
1177  {
1178  TriangleNodesArray[triangle_nodes] = NodeId;
1179  triangle_nodes++;
1180  }
1181  if (triangle_nodes == 3) break; //if we have already found 3 nodes then we can exit
1182  } //closing j node loop
1183  if (triangle_nodes == 3) break; //egal
1184  } //closing j node loop
1185  //now we have to check that the normal of the element matches the one of the plane (they could have opposite directions)
1186  ModelPart::NodesContainerType::iterator it_node1 = new_model_part.Nodes().find(TriangleNodesArray[0]);
1187  noalias(temp_vector1) = it_node1->Coordinates(); //node 1
1188 
1189  it_node1 = new_model_part.Nodes().find(TriangleNodesArray[1]);
1190  noalias(temp_vector2) = it_node1->Coordinates(); //node 2
1191 
1192  it_node1 = new_model_part.Nodes().find(TriangleNodesArray[2]);
1193  noalias(temp_vector3) = it_node1->Coordinates(); //nodo 3
1194 
1195  temp_vector3 -= temp_vector1; //first edge
1196  temp_vector2 -= temp_vector1; //second edge
1197 
1198 
1199  MathUtils<double>::CrossProduct(temp_vector4, temp_vector2, temp_vector3); //multiplying the 2 edges gives us a normal vector to the element
1200 
1201  if (inner_prod(temp_vector4, versor) < 0.0) //if the signs do not match then they have opposite directions
1202  {
1203  temp_int = TriangleNodesArray[2];
1204  TriangleNodesArray[2] = TriangleNodesArray[1];
1205  TriangleNodesArray[1] = temp_int; //we switch 2 nodes and ready
1206  }
1207 
1208  //generate new Elements
1209  Triangle3D3<Node > geom(
1210  new_model_part.Nodes()(TriangleNodesArray[0]),
1211  new_model_part.Nodes()(TriangleNodesArray[1]),
1212  new_model_part.Nodes()(TriangleNodesArray[2])
1213  );
1214 
1215  Condition::Pointer p_condition = rReferenceCondition.Create(triangle_id_int + 1 + elements_before + total_existing_elements, 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
1216  new_model_part.Conditions().push_back(p_condition);
1217  ++triangle_id_int;
1218 
1219  for (int counter = 0; counter != 4; ++counter) TriangleNodesArray[counter] = 0;
1220  }//closing if (1 triangle)
1221 
1222 
1224  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
1225  {
1226  //to fix this we'll first create a plane. see below
1227 
1228  //checking conectivities to find nodes
1229  for (unsigned int i = 0; i < it->GetGeometry().size(); i++) //nodo i
1230  {
1231  Geometry<Node >&geom = it->GetGeometry();
1232  for (unsigned int j = 0; j < it->GetGeometry().size(); j++) //nodo j
1233  {
1234  new_node = true;
1235  int index_i = geom[i].Id() - 1;
1236  int index_j = geom[j].Id() - 1;
1237  int NodeId = GetUpperTriangularMatrixValue(p_edge_ids, index_i, index_j, MaxNumEntries, NumEntries, Indices, id_values);
1238 
1239  for (unsigned int l = 0; l != 3; ++l)
1240  {
1241  if (TriangleNodesArray[l] == NodeId //same as the part with only one triangle (look above)
1242  || NodeId < 1)
1243  {
1244  new_node = false;
1245  }
1246  }
1247  if (new_node && index_i < index_j)
1248  {
1249  TriangleNodesArray[triangle_nodes] = NodeId;
1250  triangle_nodes++;
1251  }
1252  if (triangle_nodes == 4) break; //once we've found the 4 nodes we can exit
1253  } //closing i loop
1254  if (triangle_nodes == 4) break;
1255  }
1256 
1257  //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
1258  // using crossproduct we get a perpendicular plane. (either point can be used as origin).
1259  //since the cuadrilateral is created by the cut of teatraedra,
1260  //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)
1261  //otherwise this edge is just an edge of the cuadrilateral and we have to look for another.
1262  //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)
1263  ModelPart::NodesContainerType::iterator it_node1 = new_model_part.Nodes().find(TriangleNodesArray[0]);
1264  noalias(temp_vector1) = it_node1->Coordinates(); //nodo 1 (origin)
1265  int jjj;
1266  int kkk;
1267 
1268  for (int iii = 1; iii != 4; ++iii) //end node of the segment that will be used to create the plane (will be contained too)
1269  {
1270  it_node1 = new_model_part.Nodes().find(TriangleNodesArray[iii]); //i node. we always keep node 0 as origin
1271  noalias(temp_vector2) = it_node1->Coordinates(); //node2 (end)
1272  noalias(temp_vector3) = temp_vector2 - temp_vector1; //segment 1-2
1273  //now i have to create the new plane
1274  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
1275  //the origin of the plane is temp_vector1 (temp_vector2 could also be used)
1276  //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)
1277  if (iii == 1)
1278  {
1279  jjj = 2;
1280  kkk = 3;
1281  }
1282  else if (iii == 2)
1283  {
1284  jjj = 3;
1285  kkk = 1;
1286  }
1287  else
1288  {
1289  jjj = 2;
1290  kkk = 1;
1291  }
1292 
1293  it_node1 = new_model_part.Nodes().find(TriangleNodesArray[jjj]);
1294  noalias(temp_vector2) = it_node1->Coordinates(); //one of the remaining nodes;
1295 
1296  it_node1 = new_model_part.Nodes().find(TriangleNodesArray[kkk]);
1297  noalias(temp_vector3) = it_node1->Coordinates(); //the other remaining node;
1298 
1299  noalias(temp_vector2) -= temp_vector1; // minus origin point of the plane
1300  noalias(temp_vector3) -= temp_vector1;
1301 
1302  dist2 = inner_prod(temp_vector2, temp_vector4); // dot product
1303  dist3 = inner_prod(temp_vector3, temp_vector4);
1304  control = dist2*dist3;
1305  //and that's it. we now have to check if the distance have different signs. to do so we multiply :
1306  if (control < 0.0) //we have the right one! one node on each side of the plane generated by nodes 0 and iii
1307  {
1308  nodes_for_2triang[0] = TriangleNodesArray[0];
1309  nodes_for_2triang[1] = TriangleNodesArray[jjj];
1310  nodes_for_2triang[2] = TriangleNodesArray[iii]; //finish first triangle
1311  nodes_for_2triang[3] = TriangleNodesArray[iii];
1312  nodes_for_2triang[4] = TriangleNodesArray[kkk];
1313  nodes_for_2triang[5] = TriangleNodesArray[0]; //finish 2nd triangle
1314  // KRATOS_WATCH(nodes_for_2triang);
1315  break; //no need to keep looking, we can exit the loop
1316 
1317  } //closing the if
1318 
1319  }//by the time this finishes i should already have TriangleNodesArray
1320 
1321 
1322  //checking if the normal to our element is oriented correctly, just as we did when we had only 1 triangle (not commented here)
1323  for (int index = 0; index != 2; ++index) //for triangle 1 and 2
1324  {
1325 
1326  it_node1 = new_model_part.Nodes().find(nodes_for_2triang[index * 3 + 0]);
1327  noalias(temp_vector1) = it_node1->Coordinates(); //node 1
1328 
1329  it_node1 = new_model_part.Nodes().find(nodes_for_2triang[index * 3 + 1]);
1330  noalias(temp_vector2) = it_node1->Coordinates(); //node 2
1331 
1332  it_node1 = new_model_part.Nodes().find(nodes_for_2triang[index * 3 + 2]);
1333  noalias(temp_vector3) = it_node1->Coordinates(); //node 3
1334 
1335  temp_vector3 -= temp_vector1;
1336  temp_vector2 -= temp_vector1;
1337  MathUtils<double>::CrossProduct(temp_vector4, temp_vector2, temp_vector3);
1338 
1339  if (inner_prod(temp_vector4, versor) < 0.0)
1340  {
1341  temp_int = nodes_for_2triang[index * 3 + 2];
1342  nodes_for_2triang[index * 3 + 2] = nodes_for_2triang[index * 3 + 1];
1343  nodes_for_2triang[index * 3 + 1] = temp_int;
1344  }
1345 
1346  Triangle3D3<Node > geom(
1347  new_model_part.Nodes()(nodes_for_2triang[index * 3 + 0]),
1348  new_model_part.Nodes()(nodes_for_2triang[index * 3 + 1]),
1349  new_model_part.Nodes()(nodes_for_2triang[index * 3 + 2])
1350  );
1351 
1352  Condition::Pointer p_condition = rReferenceCondition.Create(triangle_id_int + 1 + elements_before + total_existing_elements, geom, properties);
1353 
1354  new_model_part.Conditions().push_back(p_condition);
1355  ++triangle_id_int;
1356 
1357  for (int counter = 0; counter != 4; ++counter) TriangleNodesArray[counter] = 0; //resetting, just in case
1358  }//cierro el index
1359  }//closing if elems_in_plane=2
1360 
1361  }//closing element loops
1362 
1363 
1364  KRATOS_CATCH("")
1365 
1366 
1367 
1368  }
1369 
1372 
1373  void UpdateCutData(ModelPart& new_model_part, ModelPart& old_model_part)
1374  {
1375  if (mrComm.MyPID() == 0) std::cout <<"Updating cut data:"<<std::endl;
1376  int step_data_size = old_model_part.GetNodalSolutionStepDataSize();
1377 
1378  //looping the nodes, no data is assigned to elements
1379  for (ModelPart::NodesContainerType::iterator it = new_model_part.NodesBegin(); it != new_model_part.NodesEnd(); it++)
1380  {
1381  double* node0_data = it->GetValue(FATHER_NODES)[0].SolutionStepData().Data(0); //current step only, (since we'll call this every timestep
1382  double* node1_data = it->GetValue(FATHER_NODES)[1].SolutionStepData().Data(0);
1383  double weight = it->GetValue(WEIGHT_FATHER_NODES);
1384  double* step_data = (it)->SolutionStepData().Data(0);
1385  int partition_index= it->FastGetSolutionStepValue(PARTITION_INDEX);
1386 
1387  //now we only have to copy the information from node_data to step_data
1388  for (int j = 0; j < step_data_size; j++) //looping all the variables and interpolating using weight
1389  {
1390  step_data[j] = weight * node0_data[j] + (1.0 - weight) * node1_data[j];
1391  }
1392  it->FastGetSolutionStepValue(PARTITION_INDEX)=partition_index;
1393  }//closing node loop
1394  }//closing subroutine
1395 
1396 
1397 
1398 
1399 
1400 protected:
1401 
1404 
1405  Epetra_MpiComm& mrComm;
1409 
1412 
1416 
1417 
1418  double GetValueFromRow(int row, int j, int row_size, int* indices, double* values)
1419  {
1420  for (int i = 0; i < row_size; i++)
1421  {
1422  if (indices[i] == j)
1423  {
1424  return values[i];
1425  }
1426  }
1427  return -1;
1428  //KRATOS_THROW_ERROR(std::logic_error, "expected index not found", "")
1429  }
1430 
1431  double GetUpperTriangularMatrixValue(const Kratos::shared_ptr<Epetra_FECrsMatrix>& p_edge_ids, int index_0, int index_1, int& MaxNumEntries, int& NumEntries, int* Indices, double* values)
1432  {
1433  double value;
1434  if (index_0 > index_1)
1435  {
1436  p_edge_ids->ExtractGlobalRowCopy(index_1, MaxNumEntries, NumEntries, values, Indices); //Coord(index_1, index_0);
1437  value = this->GetValueFromRow(index_1, index_0, NumEntries, Indices, values);
1438  }
1439  else
1440  {
1441  p_edge_ids->ExtractGlobalRowCopy(index_0, MaxNumEntries, NumEntries, values, Indices);
1442  value = this->GetValueFromRow(index_0, index_1, NumEntries, Indices, values);
1443  }
1444  return value;
1445 
1446  }
1447 
1448 
1449 
1450 
1451 
1452 };
1453 
1454 
1455 
1456 
1457 
1458 
1459 
1460 
1461 } // namespace Kratos.
1462 
1463 #endif // KRATOS_TRILINOS_LOCAL_CUTTING_APP defined
1464 
1465 
virtual const DataCommunicator & GetDataCommunicator() const
Definition: communicator.cpp:340
MeshType & LocalMesh()
Returns the reference to the mesh storing all local entities.
Definition: communicator.cpp:245
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
Base class for all Elements.
Definition: element.h:60
Geometry base class.
Definition: geometry.h:71
SizeType size() const
Definition: geometry.h:518
IndexType const & Id() const
Id of this Geometry.
Definition: geometry.h:964
Definition: amatrix_interface.h:41
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
NodesContainerType & Nodes()
Definition: mesh.h:346
NodeIterator NodesEnd()
Definition: mesh.h:336
NodeIterator NodesBegin()
Definition: mesh.h:326
PropertiesType::Pointer pGetProperties(IndexType PropertiesId)
Definition: mesh.h:394
static void SetMPICommunicator(ModelPart &rThisModelPart, const DataCommunicator &rDataCommunicator)
Create and assign an MPICommunicator for a ModelPart instance.
Definition: model_part_communicator_utilities.h:64
This class aims to manage meshes for multi-physics simulations.
Definition: model_part.h:77
ElementIterator ElementsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1169
MeshType::ConditionsContainerType ConditionsContainerType
Condintions container. A vector set of Conditions with their Id's as key.
Definition: model_part.h:183
ConditionIterator ConditionsBegin(IndexType ThisIndex=0)
Definition: model_part.h:1361
SizeType GetNodalSolutionStepDataSize()
Definition: model_part.h:571
MeshType::ElementsContainerType ElementsContainerType
Element container. A vector set of Elements with their Id's as key.
Definition: model_part.h:168
Communicator & GetCommunicator()
Definition: model_part.h:1821
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
ElementsContainerType & Elements(IndexType ThisIndex=0)
Definition: model_part.h:1189
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: model_part.h:128
ElementIterator ElementsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1179
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
ConditionIterator ConditionsEnd(IndexType ThisIndex=0)
Definition: model_part.h:1371
This class defines the node.
Definition: node.h:65
This function recomputes the communication plan for MPI.
Definition: parallel_fill_communicator.h:56
void Execute() override
Execute the communicator fill.
Definition: parallel_fill_communicator.cpp:39
PointerVector is a container like stl vector but using a vector to store pointers to its data.
Definition: pointer_vector.h:72
size_type size() const
Returns the number of elements in the container.
Definition: pointer_vector_set.h:502
A three node 3D triangle geometry with linear shape functions.
Definition: triangle_3d_3.h:77
TRILINOS CUTTING APPLICATION.
Definition: trilinos_cutting_app.h:46
void UpdateCutData(ModelPart &new_model_part, ModelPart &old_model_part)
Definition: trilinos_cutting_app.h:1373
void AddVariablesToCutModelPart(const ModelPart &rModelPart, ModelPart &rNewModelPart) const
Initialize the solution step data container for the cut model part.
Definition: trilinos_cutting_app.h:412
void Clear()
Definition: trilinos_cutting_app.h:512
Kratos::shared_ptr< Epetra_Map > mp_overlapping_map
Definition: trilinos_cutting_app.h:1406
double GetValueFromRow(int row, int j, int row_size, int *indices, double *values)
Definition: trilinos_cutting_app.h:1418
Kratos::shared_ptr< Epetra_Map > mp_non_overlapping_map
Definition: trilinos_cutting_app.h:1407
double smallest_edge
Definition: trilinos_cutting_app.h:1402
ModelPart::NodesContainerType NodesArrayType
Definition: trilinos_cutting_app.h:49
Kratos::shared_ptr< Epetra_FECrsGraph > mp_non_overlapping_graph
Definition: trilinos_cutting_app.h:1410
void CSR_Row_Matrix(ModelPart &this_model_part, Kratos::shared_ptr< Epetra_FECrsMatrix > &p_edge_ids, Kratos::shared_ptr< Epetra_FECrsMatrix > &used_nodes_matrix)
Definition: trilinos_cutting_app.h:532
TrilinosCuttingApplication(Epetra_MpiComm &Comm)
Definition: trilinos_cutting_app.h:65
void FindSmallestEdge(ModelPart &mr_model_part)
This function Creates cutting planes by creating nodes and conditions (to define the conectivities) i...
Definition: trilinos_cutting_app.h:86
int mtotal_number_of_existing_nodes
Definition: trilinos_cutting_app.h:1408
void Calculate_Coordinate_And_Insert_New_Nodes(ModelPart &this_model_part, ModelPart &new_model_part, const vector< array_1d< int, 2 > > &father_node_ids, const vector< int > &List_New_Nodes, const vector< int > &partition_new_nodes, array_1d< double, 3 > versor, array_1d< double, 3 > Xp, double tolerance)
Definition: trilinos_cutting_app.h:983
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: trilinos_cutting_app.h:138
Node ::Pointer PointPointerType
Definition: trilinos_cutting_app.h:56
void Create_List_Of_New_Nodes(ModelPart &this_model_part, ModelPart &new_model_part, Kratos::shared_ptr< Epetra_FECrsMatrix > &p_edge_ids, Kratos::shared_ptr< Epetra_FECrsMatrix > &p_partition_ids, vector< int > &List_New_Nodes, vector< int > &partition_new_nodes, vector< array_1d< int, 2 > > &father_node_ids, Kratos::shared_ptr< Epetra_FECrsMatrix > &used_nodes_matrix)
Definition: trilinos_cutting_app.h:812
PointVector::iterator PointIterator
Definition: trilinos_cutting_app.h:58
Kratos::shared_ptr< Epetra_CrsGraph > mp_overlapping_graph
Definition: trilinos_cutting_app.h:1411
vector< Vector_Order_Tensor > Node_Vector_Order_Tensor
Definition: trilinos_cutting_app.h:54
double GetUpperTriangularMatrixValue(const Kratos::shared_ptr< Epetra_FECrsMatrix > &p_edge_ids, int index_0, int index_1, int &MaxNumEntries, int &NumEntries, int *Indices, double *values)
Definition: trilinos_cutting_app.h:1431
Node PointType
Definition: trilinos_cutting_app.h:55
void FirstLoop(ModelPart &this_model_part, Kratos::shared_ptr< Epetra_FECrsMatrix > &p_edge_ids, Kratos::shared_ptr< Epetra_FECrsMatrix > &p_partition_ids, array_1d< double, 3 > versor, array_1d< double, 3 > Xp, int &number_of_triangles, vector< int > &Elems_In_Plane, double tolerance, Kratos::shared_ptr< Epetra_FECrsMatrix > &used_nodes_matrix)
Definition: trilinos_cutting_app.h:611
ModelPart::ElementsContainerType ElementsArrayType
Definition: trilinos_cutting_app.h:50
Epetra_MpiComm & mrComm
Definition: trilinos_cutting_app.h:1405
ModelPart::ConditionsContainerType ConditionsArrayType
Definition: trilinos_cutting_app.h:51
void GenerateElements(ModelPart &this_model_part, ModelPart &new_model_part, vector< int > Elems_In_Plane, const Kratos::shared_ptr< Epetra_FECrsMatrix > p_edge_ids, array_1d< double, 3 > versor, int plane_number, int &number_of_triangles)
Definition: trilinos_cutting_app.h:1090
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: trilinos_cutting_app.h:436
~TrilinosCuttingApplication()
Definition: trilinos_cutting_app.h:71
bool mMPICommSetup_is_defined
Definition: trilinos_cutting_app.h:1403
std::vector< PointType::Pointer > PointVector
Definition: trilinos_cutting_app.h:57
vector< Matrix > Matrix_Order_Tensor
Definition: trilinos_cutting_app.h:52
vector< Vector > Vector_Order_Tensor
Definition: trilinos_cutting_app.h:53
bool Has(const VariableData &rThisVariable) const
Definition: variables_list.h:372
BOOST_UBLAS_INLINE void resize(size_type array_size, bool preserve=true)
Definition: array_1d.h:242
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#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
#define KRATOS_ERROR_IF(conditional)
Definition: exception.h:162
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
std::shared_ptr< T > shared_ptr
Definition: smart_pointers.h:27
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
AMatrix::MatrixRow< const TExpressionType > row(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression, std::size_t RowIndex)
Definition: amatrix_interface.h:649
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
list values
Definition: bombardelli_test.py:42
Definition: control.py:1
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int node_id
Definition: read_stl.py:12
int counter
Definition: script_THERMAL_CORRECT.py:218
int nnodes
Definition: sensitivityMatrix.py:24
integer i
Definition: TensorModule.f:17
integer l
Definition: TensorModule.f:17