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