Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
RefinementFactory_def.hpp
1#ifndef RefinementFactory_def_hpp
2#define RefinementFactory_def_hpp
3
4#ifndef MESH_TIMER_START
5#define MESH_TIMER_START(A,S) Teuchos::RCP<Teuchos::TimeMonitor> A = Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("Mesh Refinement") + std::string(S))));
6#endif
7
8#ifndef MESH_TIMER_STOP
9#define MESH_TIMER_STOP(A) A.reset();
10#endif
11
12#include "feddlib/core/LinearAlgebra/MultiVector.hpp"
13#include <chrono>
21
22using Teuchos::reduceAll;
23using Teuchos::REDUCE_SUM;
24using Teuchos::REDUCE_MAX;
25using Teuchos::REDUCE_MIN;
26using Teuchos::outArg;
27
28namespace FEDD {
29
30template <class SC, class LO, class GO, class NO>
31RefinementFactory<SC,LO,GO,NO>::RefinementFactory():
32MeshUnstructured<SC,LO,GO,NO>()
33{
34
35
36}
37
38
46
47template <class SC, class LO, class GO, class NO>
48RefinementFactory<SC,LO,GO,NO>::RefinementFactory(CommConstPtr_Type comm, int volumeID):
49MeshUnstructured<SC,LO,GO,NO>(comm,volumeID)
50{
51
52}
53
63
64template <class SC, class LO, class GO, class NO>
65RefinementFactory<SC,LO,GO,NO>::RefinementFactory(CommConstPtr_Type comm, int volumeID, ParameterListPtr_Type parameterListAll):
66MeshUnstructured<SC,LO,GO,NO>(comm,volumeID)
67{
68 this->volumeID_ = volumeID;
69 this->dim_ = parameterListAll->sublist("Parameter").get("Dimension",2);
70 if(this->dim_ == 2){
71 refinementRestriction_ = parameterListAll->sublist("Mesh Refinement").get("Refinement Restriction","Bisection");
72 writeRefinementTime_ = parameterListAll->sublist("Mesh Refinement").get("Write Refinement Time",true);
73 }
74 else{
75 refinementRestriction_ = parameterListAll->sublist("Mesh Refinement").get("Refinement Restriction","BeyIrregular");
76 refinement3DDiagonal_ = parameterListAll->sublist("Mesh Refinement").get("3D regular Refinement Diagonal Pick",0);
77 writeRefinementTime_ = parameterListAll->sublist("Mesh Refinement").get("Write Refinement Time",true);
78 }
79
80}
81
82template <class SC, class LO, class GO, class NO>
83RefinementFactory<SC,LO,GO,NO>::~RefinementFactory(){
84
85}
86
98template <class SC, class LO, class GO, class NO>
99void RefinementFactory<SC,LO,GO,NO>::refineMesh( MeshUnstrPtr_Type meshP1, int iteration, MeshUnstrPtr_Type outputMesh, std::string refinementMode){
100 MESH_TIMER_START(totalTime," Total Time for Mesh Refinement of this Step ");
101
102
103 if(meshP1->FEType_ != "P1" && meshP1->FEType_ != "P2"){
104 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "Mesh Refinement only works for Triangular Elements");
105 }
106
107 currentIter_ = iteration;
108
109 refinementMode_ = refinementMode;
110 if(refinementMode_ == "Bisection")
111 this->refinementRestriction_ = "Bisection";
112
113 this->dim_ = meshP1->getDimension();
114 this->FEType_ =meshP1->FEType_;
115 this->volumeID_ = meshP1->volumeID_;
116 this->rankRange_=meshP1->rankRange_;
117 // necessary entities
118 //EdgeElementsPtr_Type edgeElementsTmp = meshP1->getEdgeElements(); // Edges
119 SurfaceElementsPtr_Type surfaceTriangleElements = meshP1->getSurfaceTriangleElements(); // Surfaces
120 ElementsPtr_Type elementsTmp = meshP1->getElementsC(); // Elements
121
122 EdgeElementsPtr_Type edgeElements =meshP1->getEdgeElements(); //Teuchos::rcp( new EdgeElements(*edgeElementsTmp));
123
124 //EdgeElementsPtr_Type edgeElements=Teuchos::rcp( new EdgeElements(*edgeElementsTmp));
125 ElementsPtr_Type elements =Teuchos::rcp( new Elements(*elementsTmp));
126
127 vec2D_dbl_ptr_Type points = meshP1->getPointsRepeated(); // Points
128 this->elementMap_ = meshP1->elementMap_;
129 this->mapUnique_ = meshP1->mapUnique_;
130 this->mapRepeated_=meshP1->mapRepeated_;
131 this->edgeMap_ = meshP1->edgeMap_;
132 // entities for resulting Elements, Points, Edges, Flags
133 // - Points, Elements and Flags are added to the existding entities
134 // . edges are reset every refinement step
135 this->edgeElements_.reset(new EdgeElements()); // Edges
136 this->surfaceTriangleElements_.reset(new SurfaceElements()); // Surface
137 this->elementsC_.reset(new Elements(*elementsTmp)); // Elements
138 this->pointsRep_.reset(new std::vector<std::vector<double> >(meshP1->pointsRep_->size(),std::vector<double>(this->dim_,-1.)));
139 *this->pointsRep_ = *meshP1->pointsRep_; // Points
140 this->pointsUni_.reset(new std::vector<std::vector<double> >( this->mapUnique_->getNodeNumElements(), std::vector<double>(this->dim_,-1. ) ) );
141 *this->pointsUni_ = *meshP1->pointsUni_;
142 this->bcFlagUni_.reset( new std::vector<int> ( this->mapUnique_->getNodeNumElements(), 0 ) );
143 *this->bcFlagUni_ = *meshP1->bcFlagUni_;
144
145 this->bcFlagRep_.reset(new std::vector<int>(meshP1->bcFlagRep_->size())); // Flags
146 *this->bcFlagRep_ = *meshP1->bcFlagRep_;
147
148
149 this->edgesElementOrder_=meshP1->getEdgeElementOrder();
150
151 this->numElementsGlob_ = meshP1->numElementsGlob_;
152
153 // not all Edges are assigned a Flag yet -> in Order to save a few steps along the way, we assign all Edges the correct flag now
154 // In regular refinement the correct flags are then passed on, so this step is only necessary in Iteration 0
155 if( iteration ==0 ){
156 meshP1->assignEdgeFlags();
157 }
158
159 // Algorithm
160 if (this->dim_ == 2 || this->dim_ == 3){
161
162
163 if(this->comm_->getRank() == 0){
164 std::cout << " \t-- Mesh Refinement -- " << std::endl;
165 std::cout << "\t__________________________________________________________________________________________________________ " << std::endl;
166 std::cout << " " << std::endl;
167 std::cout << " \tStart Iteration " << iteration+1 << " of "<< this->dim_ << "D Mesh Refinement " << std::endl;
168 std::cout << " \tNumber of Elements:\t" << this->elementMap_->getGlobalNumElements() << std::endl;
169 std::cout << " \tNumber of Nodes:\t" << this->mapUnique_->getGlobalNumElements() << std::endl;
170 std::cout << " \tNumber of Edges:\t" << this->edgeMap_->getGlobalNumElements() << std::endl;
171 std::cout << "\t__________________________________________________________________________________________________________ " << std::endl;
172 }
173
174
175
176 // ------------------------------------------------------------------------------------------------------
177 // Part I: Regular Refinement of Mesh
178 // We refine the elements that were determined by our error estimation regular
179 // ------------------------------------------------------------------------------------------------------
180 MESH_TIMER_START(preprocessingTimer," Step 0:\t Preprocessing");
181 const int myRank = this->comm_->getRank();
182 // match the Edges to the Elements for being able to tag the edges of Elements in case of refinement
183 edgeElements->matchEdgesToElements(this->elementMap_);
184
185 // Vector that carry the information which elements belong to an edge in local and global indices
186 vec2D_GO_Type elementsOfEdgeGlobal = edgeElements->getElementsOfEdgeGlobal();
187 vec2D_LO_Type elementsOfEdgeLocal = edgeElements->getElementsOfEdgeLocal();
188
189
190 // Determine current global Interface IDs
191 // As we pass on the interface boolean while refining red,blue,green... we theoretically dont need the whole extend of this function passed the first
192 // refinement, only the globalInterfaceIDs, which can be determined without 'elementsOfEdgeLocal' and 'Global'
193 // (If elementsOfEdgeLocal and Global arent working, this can be taken out, yet is also nice for determining if it works correctly)
194 vec_GO_Type globalInterfaceIDs;
195 if(iteration ==0 ){
196 globalInterfaceIDs = edgeElements->determineInterfaceEdges(this->edgeMap_);
197 for(int i=0; i< elements->numberElements(); i++){
198 this->elementsC_->getElement(i).setPredecessorElement(i);
199 }
200
201 }
202 else {
203 for(int i=0; i< edgeElements->numberElements(); i++){
204 if(edgeElements->getElement(i).isInterfaceElement()){
205 globalInterfaceIDs.push_back(this->edgeMap_->getGlobalElement(i));
206 }
207 }
208 sort(globalInterfaceIDs.begin(), globalInterfaceIDs.end());
209 }
210 globalInterfaceIDs_ = globalInterfaceIDs;
211
212
213 if(this->dim_==3){
214 if(surfaceTriangleElements.is_null()){
215 surfaceTriangleElements.reset(new SurfaceElements()); // Surface
216 this->buildSurfaceTriangleElements(elements,edgeElements, surfaceTriangleElements, this->edgeMap_, this->elementMap_ );
217 //this->buildTriangleMap();
218 }
219 else if(surfaceTriangleElements->numberElements() ==0){
220 this->buildSurfaceTriangleElements(elements,edgeElements, surfaceTriangleElements, this->edgeMap_, this->elementMap_ );
221 }
222 surfaceTriangleElements->matchSurfacesToElements(this->elementMap_);
223 }
224
225 // counting new Points and Elements:
226 int newPoints=0; // total number of new Points
227 int newPointsRepeated= 0; // number of new Points that share an other Processor
228
229 int newElements=0; // new Elements on a Processor
230
231 // Counting new Edges
232 int newEdgesUnique=0;
233 int newEdgesRepeated =0;
234
235 // Loop through Elements in order to determine Elements to refine and refine them regular / red
236 int numPoints=0;
237 MESH_TIMER_STOP(preprocessingTimer);
238
239 MESH_TIMER_START(regularRefinementTimer," Step 1:\t Tagging Edges for Refinement");
240
241 // Depending on dimension we add a certain number of elements in the 2D case it's 3, in the 3D it's 7
242 for(int i=0; i<elements->numberElements();i++){
243 if(elements->getElement(i).isTaggedForRefinement()){
244 numPoints= this->pointsRep_->size();
245 this->bisectEdges( edgeElements, elements, i, surfaceTriangleElements);
246 newPoints=newPoints + this->pointsRep_->size()-numPoints;
247 }
248 }
249
250 MESH_TIMER_STOP(regularRefinementTimer);
251 // ------------------------------------------------------------------------------------------------------
252
253 // ------------------------------------------------------------------------------------------------------
254 // Part II: Communicating the tagged Edges
255 // As it is possible now, that edges were tagged on one processor on the interface between processers
256 // we need communicate tagged edges across the interface
257 // In order to safe time, we only communicate tagged interface Edges
258 // InterfaceEdges can be determined by the vector 'elementsOfEdgesLocal' as the vector carries a -1 for
259 // for each element belonging to an edge that is not on the processor in question
260 // ------------------------------------------------------------------------------------------------------
261 MESH_TIMER_START(commEdgesTimer," Step 2:\t Communicating tagged edges");
262 MapConstPtr_Type edgeMap = this->getEdgeMap();
263
264
265 // Determine the globalInterfaceIDs of tagged edges
266 vec_GO_Type globalInterfaceIDsTagged(0);
267 GO indE;
268 for(int i=0; i<globalInterfaceIDs.size(); i++){
269 indE = edgeMap->getLocalElement(globalInterfaceIDs[i]);
270 if(edgeElements->getElement(indE).isTaggedForRefinement()){
271 globalInterfaceIDsTagged.push_back(globalInterfaceIDs[i]);
272 }
273 }
274
275
276 // Constructing a map of the global IDs of edges and tagged edges
277 Teuchos::ArrayView<GO> globalEdgesInterfaceArray = Teuchos::arrayViewFromVector( globalInterfaceIDs);
278 Teuchos::ArrayView<GO> globalEdgesInterfaceTaggedArray = Teuchos::arrayViewFromVector( globalInterfaceIDsTagged);
279
280 MapPtr_Type mapInterfaceEdges =
281 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), globalEdgesInterfaceArray, 0, this->comm_) );
282 MapPtr_Type mapInterfaceEdgesTagged =
283 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), globalEdgesInterfaceTaggedArray, 0, this->comm_) );
284
285 // Multivector based on interfaceEdges Map with zero entries
286 MultiVectorGOPtr_Type taggedEdgesGlobal = Teuchos::rcp( new MultiVectorGO_Type(mapInterfaceEdges, 1 ) );
287 taggedEdgesGlobal->putScalar(0);
288
289 // Multivector based on taggesEdges Map with one as entries
290 MultiVectorGOPtr_Type isActiveEdge = Teuchos::rcp( new MultiVectorGO_Type( mapInterfaceEdgesTagged, 1 ) );
291 isActiveEdge->putScalar( (LO) 1);
292
293 taggedEdgesGlobal->importFromVector(isActiveEdge, true, "Insert"); // From this we know that -> one signifies a tagged edge -> if we didn't tag it -> refine
294 Teuchos::ArrayRCP< const GO > tags = taggedEdgesGlobal->getData( 0 );
295 //taggedEdgesGlobal->print();
296
297 // Adding Midpoints and tagging the edges that were tagged on other Procs that are on the interface
298 LO ind;
299 for (int i=0; i<tags.size(); i++) {
300 if (tags[i] > 0){
301 ind = edgeMap->getLocalElement(globalInterfaceIDs[i]);
302 newPointsRepeated ++;
303 if(!edgeElements->getElement(ind).isTaggedForRefinement()){
304 edgeElements->getElement(ind).tagForRefinement();
305 this->addMidpoint(edgeElements,ind);
306 // Collecting global IDs we didnt already considered
307 globalInterfaceIDsTagged.push_back(globalInterfaceIDs[i]);
308 newPoints ++;
309 }
310 }
311 }
312 MESH_TIMER_STOP(commEdgesTimer);
313 // ------------------------------------------------------------------------------------------------------
314
315 // ------------------------------------------------------------------------------------------------------
316 // Part III: Checking for Refinement Restrictions
317 // Before we start refining the elements according to their refinement rules, we need to check certain
318 // refinement restrictions
319 // ------------------------------------------------------------------------------------------------------
320
321 MESH_TIMER_START(checkTimer," Step 3:\t Checking Restrictions");
322 this->refinementRestrictions(meshP1, elements ,edgeElements, surfaceTriangleElements, newPoints, newPointsRepeated, globalInterfaceIDsTagged, mapInterfaceEdges, newElements);
323
324 sort(globalInterfaceIDsTagged.begin(), globalInterfaceIDsTagged.end());
325
326 MESH_TIMER_STOP(checkTimer);
327
328
329 // ------------------------------------------------------------------------------------------------------
330 // Part IV: Communicating the added Points and updating the corresponding Maps
331 // generally we keep the nodelist of throughout the refinement steps and only add new points to it
332 // consequently we update the maps for those new points depending on nodes on interface and points unqiuely
333 // on processors
334 // ------------------------------------------------------------------------------------------------------
335 MESH_TIMER_START(nodeTimer," Step 4:\t Updating Node Map");
336 // determine global interface IDs of untagged edges
337 int maxRank = std::get<1>(this->rankRange_);
338 // determine unique map
339
340 // Creating map of all procs on each processor, this map is usefull for distributing the information of new nodes, elements etc.
341 // each processor will then write its own information in a multivector that is based in the localProc-Map (entry is the own proc number)
342 vec_GO_Type globalProcs(0);
343 for (int i=0; i<= maxRank; i++)
344 globalProcs.push_back(i);
345
346 Teuchos::ArrayView<GO> globalProcArray = Teuchos::arrayViewFromVector( globalProcs);
347
348 vec_GO_Type localProc(0);
349 localProc.push_back(this->comm_->getRank());
350 Teuchos::ArrayView<GO> localProcArray = Teuchos::arrayViewFromVector( localProc);
351
352 MapPtr_Type mapGlobalProc =
353 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), globalProcArray, 0, this->comm_) );
354
355 MapPtr_Type mapProc =
356 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), localProcArray, 0, this->comm_) );
357
358 this->buildNodeMap(edgeElements, mapGlobalProc, mapProc, newPoints, newPointsRepeated);
359
360 MESH_TIMER_STOP(nodeTimer);
361
362 // ------------------------------------------------------------------------------------------------------
363
364
365 // ------------------------------------------------------------------------------------------------------
366 // Part V: refineMesh
367 // All edges are tagged and checked for additional restricitions. The mesh can now be refined and regular
368 // and irregular refinement rules can be performed
369 // ------------------------------------------------------------------------------------------------------
370 MESH_TIMER_START(irregRefTimer," Step 5:\t Irregular Refinement");
371 this->refineMeshRegIreg(elements, edgeElements, newElements,edgeMap, surfaceTriangleElements);
372 MESH_TIMER_STOP(irregRefTimer);
373
374 // ------------------------------------------------------------------------------------------------------
375 // Part VI: Updating the Element Map
376 // update elementMap by distributing information of locally added elements and add global IDs based on
377 // that information
378 // the list of elements only extends throughout the refinement steps, so we only neew to allocate the
379 // globalIDs for elements that extend our last element number
380 // ------------------------------------------------------------------------------------------------------
381 MESH_TIMER_START(elementMapTimer," Step 6:\t Updating Element Map");
382 MapConstPtr_Type elementMap = meshP1->getElementMap();
383 // information of new elements
384 MultiVectorLOPtr_Type exportLocalEntry = Teuchos::rcp( new MultiVectorLO_Type( mapProc, 1 ) );
385 exportLocalEntry->putScalar( (LO) newElements );
386
387 // map equal to the original edgeMap with zero entries
388 MultiVectorLOPtr_Type isActiveElement= Teuchos::rcp( new MultiVectorLO_Type( mapGlobalProc, 1 ) );
389 isActiveElement->putScalar( (LO) 0 );
390 isActiveElement->importFromVector( exportLocalEntry, false, "Insert");
391
392 // number of new elements per Processor
393 Teuchos::ArrayRCP< const LO > elementsRank = isActiveElement->getData(0);
394
395 Teuchos::ArrayView<const GO> elementList = elementMap->getNodeElementList();
396 std::vector<GO> vecGlobalIDsElements = Teuchos::createVector( elementList );
397
398 // element offset before refinement
399 int offsetElements = elementMap->getGlobalNumElements();
400
401 // determine the offset for this processor
402 GO procOffsetElements=0;
403 for(int i=0; i< myRank; i++)
404 procOffsetElements = procOffsetElements + elementsRank[i];
405
406 for (int i=0; i<newElements; i++){
407 vecGlobalIDsElements.push_back( i + offsetElements + procOffsetElements);
408 }
409
410 Teuchos::RCP<std::vector<GO> > elementsGlobMapping = Teuchos::rcp( new std::vector<GO>( vecGlobalIDsElements ) );
411 Teuchos::ArrayView<GO> elementsGlobMappingArray = Teuchos::arrayViewFromVector( *elementsGlobMapping);
412
413 this->elementMap_.reset(new Map<LO,GO,NO>( Teuchos::OrdinalTraits<GO>::invalid(), elementsGlobMappingArray, 0, this->comm_) );
414
415 // determine global number of elements
416 this->numElementsGlob_ = this->elementMap_->getMaxAllGlobalIndex()+1;
417 MESH_TIMER_STOP(elementMapTimer);
418 // ------------------------------------------------------------------------------------------------------
419
420 // ------------------------------------------------------------------------------------------------------
421 // Part VII: Making the Edges unique, set global IDs and set elements edges
422 // we need to make the edge list unique as there are redundant edges
423 // furthermore we set up the elementsOfEdgeLocal and elementsOfEdgeGlobal, but the information of other
424 // procs is still missing there (this will be finalized in Part X)
425 // ------------------------------------------------------------------------------------------------------
426
427 MESH_TIMER_START(uniqueEdgesTimer," Step 7:\t Making Edges Unique");
428 vec2D_GO_Type combinedEdgeElements;
429 this->edgeElements_->sortUniqueAndSetGlobalIDsParallel(this->elementMap_,combinedEdgeElements);
430 MESH_TIMER_STOP(uniqueEdgesTimer);
431 //this->comm_->barrier();
432 // ------------------------------------------------------------------------------------------------------
433
434 // ------------------------------------------------------------------------------------------------------
435 // Part VIII: Updating the EdgeMap
436 // The general idea is to indentifiy an edge by their global node indices.
437 // This way two edges on different processors can be indentified and given the same global ID
438 // First we determine the global IDs of non interface edges
439 // Then we determine those of interface edges with the procedure discribed above
440 // ------------------------------------------------------------------------------------------------------
441
442 MESH_TIMER_START(edgeMapTimer," Step 8:\t Creating EdgeMap");
443 this->buildEdgeMap(mapGlobalProc, mapProc);
444 MESH_TIMER_STOP(edgeMapTimer);
445
446 // ------------------------------------------------------------------------------------------------------
447 // Part IX: Updating elementsOfEdgeGlobal and elementsOfEdgeLocal
448 // this step is only necessary if we have more than 1 processor, as the edgeElements function work serially
449 // we started the setup before (sortUniqueAndSetGlobalIDsParallel) an now finalize it with the information of other processors
450 // the edges on the interface need the global element number of the neighbouring processor
451 // ------------------------------------------------------------------------------------------------------
452 MESH_TIMER_START(elementsOfEdgeTimer," Step 9:\t Updating ElementsOfEdgeLocal/Global");
453 this->edgeElements_->setElementsEdges( combinedEdgeElements );
454
455 this->edgeElements_->setUpElementsOfEdge( this->elementMap_, this->edgeMap_);
456
457 this->updateElementsOfEdgesLocalAndGlobal(maxRank, edgeMap);
458
459 MESH_TIMER_STOP(elementsOfEdgeTimer);
460
461 MESH_TIMER_START(elementsOfSurfaceTimer," Step 10: Updating ElementsOfSurfaceLocal/Global");
462
463 vec2D_GO_Type combinedSurfaceElements;
464
465 this->surfaceTriangleElements_->sortUniqueAndSetGlobalIDsParallel(this->elementMap_,combinedSurfaceElements);
466
467 this->surfaceTriangleElements_->setElementsSurface( combinedSurfaceElements );
468
469 this->surfaceTriangleElements_->setUpElementsOfSurface( this->elementMap_, this->edgeMap_, this->edgeElements_);
470
471 MESH_TIMER_STOP(elementsOfSurfaceTimer);
472
473 vec2D_GO_Type elementsOfSurfaceGlobal = this->surfaceTriangleElements_->getElementsOfSurfaceGlobal();
474
475 vec2D_LO_Type elementsOfSurfaceLocal = this->surfaceTriangleElements_->getElementsOfSurfaceLocal();
476
477
478 MESH_TIMER_STOP(totalTime);
479
480
481 if(this->comm_->getRank() == 0){
482 std::cout << "\t__________________________________________________________________________________________________________ " << std::endl;
483 std::cout << " " << std::endl;
484 std::cout << " \t... finished Iteration " << iteration+1 << " of " << this->dim_ << "D Mesh Refinement " << std::endl;
485 std::cout << " \tNumber of new Elements:\t" << this->elementMap_->getGlobalNumElements() - meshP1->elementMap_-> getGlobalNumElements() << std::endl;
486 std::cout << " \tNumber of new Nodes:\t" << this->mapUnique_->getGlobalNumElements()- meshP1->mapUnique_-> getGlobalNumElements() << std::endl;
487 std::cout << " \tNumber of new Edges:\t" << this->edgeMap_->getGlobalNumElements()- meshP1->edgeMap_-> getGlobalNumElements() << std::endl;
488 std::cout << "\t__________________________________________________________________________________________________________ " << std::endl;
489 std::cout << " " << std::endl;
490 }
491
492 if(writeRefinementTime_ )
493 Teuchos::TimeMonitor::report(std::cout,"Mesh Refinement");
494
495 // Finally we set all changed mesh enteties for outputMesh
496
497
498 outputMesh->dim_ = this->dim_ ;
499 outputMesh->FEType_ = this->FEType_ ;
500 outputMesh->rankRange_ = this->rankRange_;
501
502 outputMesh->elementMap_ = this->elementMap_ ;
503 outputMesh->mapUnique_ = this->mapUnique_ ;
504 outputMesh->mapRepeated_ = this->mapRepeated_;
505 outputMesh->edgeMap_ = this->edgeMap_ ;
506
507 outputMesh->elementsC_ = this->elementsC_;
508 outputMesh->edgeElements_ = this->edgeElements_;
509 outputMesh->surfaceTriangleElements_ = this->surfaceTriangleElements_;
510
511 outputMesh->pointsRep_ = this->pointsRep_ ;
512 outputMesh->pointsUni_ = this->pointsUni_;
513
514 outputMesh->bcFlagUni_ = this->bcFlagUni_ ;
515 outputMesh->bcFlagRep_ = this->bcFlagRep_ ;
516
517
518 outputMesh->edgesElementOrder_ = this->edgesElementOrder_;
519 outputMesh->numElementsGlob_ = this->numElementsGlob_ ;
520
521 }
522
523
524}
525
536
537template <class SC, class LO, class GO, class NO>
538vec_bool_Type RefinementFactory<SC,LO,GO,NO>::checkInterfaceSurface( EdgeElementsPtr_Type edgeElements,vec_int_Type originFlag, vec_int_Type edgeNumbers, int indexElement){
539
540 vec_bool_Type interfaceSurface(4);
541
542 if(edgeElements->getElement(edgeNumbers[0]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[1]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[3]).isInterfaceElement() && (originFlag[0] == this->volumeID_))
543 interfaceSurface[0] = true;
544 if(edgeElements->getElement(edgeNumbers[0]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[2]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[4]).isInterfaceElement() && (originFlag[1] == this->volumeID_ ))
545 interfaceSurface[1] = true;
546 if(edgeElements->getElement(edgeNumbers[1]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[2]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[5]).isInterfaceElement() && (originFlag[2] == this->volumeID_))
547 interfaceSurface[2] = true;
548 if(edgeElements->getElement(edgeNumbers[3]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[4]).isInterfaceElement() && edgeElements->getElement(edgeNumbers[5]).isInterfaceElement() && (originFlag[3] == this->volumeID_ ))
549 interfaceSurface[3] = true;
550
551 vec2D_LO_Type elementsOfEdgeLocal = edgeElements->getElementsOfEdgeLocal();
552
553 vec2D_LO_Type edgeNumTri(4,vec_LO_Type(3));
554 edgeNumTri[0] = {edgeNumbers[0],edgeNumbers[1],edgeNumbers[3]};
555 edgeNumTri[1] = {edgeNumbers[0],edgeNumbers[2],edgeNumbers[4]};
556 edgeNumTri[2] = {edgeNumbers[1],edgeNumbers[2],edgeNumbers[5]};
557 edgeNumTri[3] = {edgeNumbers[3],edgeNumbers[4],edgeNumbers[5]};
558
559
560 // We need to check additionally, if maybe all edges are part of the interface, but not the triangle itself.
561 // If we find the element and the neighbouring element that share the triangle on our processor, the triangle is not part of the interface.
562 for(int i=0; i<4 ; i++){
563 if(interfaceSurface[i] == true){
564 vec_LO_Type tmpElements(0);
565 for(int j=0 ; j< elementsOfEdgeLocal[edgeNumTri[i][0]].size() ; j++){
566 if(elementsOfEdgeLocal[edgeNumTri[i][0]][j] != -1)
567 tmpElements.push_back( elementsOfEdgeLocal[edgeNumTri[i][0]][j]);
568 }
569
570 for(int j=0 ; j< elementsOfEdgeLocal[edgeNumTri[i][1]].size() ; j++){
571 if(elementsOfEdgeLocal[edgeNumTri[i][1]][j] != -1)
572 tmpElements.push_back( elementsOfEdgeLocal[edgeNumTri[i][1]][j]);
573 }
574
575
576 sort(tmpElements.begin(),tmpElements.end());
577 bool found =false;
578
579 for(int j=0; j< tmpElements.size()-1; j++){
580 if((tmpElements[j] == tmpElements[j+1] )&& (tmpElements[j] != indexElement) ) {
581 found = true;
582 }
583 }
584 if(found == true)
585 interfaceSurface[i] = false;
586
587
588 }
589 }
590
591 return interfaceSurface;
592}
593
606template <class SC, class LO, class GO, class NO>
607void RefinementFactory<SC,LO,GO,NO>::buildNodeMap(EdgeElementsPtr_Type edgeElements, MapConstPtr_Type mapGlobalProc, MapConstPtr_Type mapProc, int newPoints, int newPointsRepeated){
608 int maxRank = std::get<1>(this->rankRange_);
609 const int myRank = this->comm_->getRank();
610
611 // Collecting the number of new Points and repeated new Points in total on each Proc
612 int globalCountPoints = 0;
613 int globalCountRepeated = 0;
614 reduceAll<int, int> (*this->comm_, REDUCE_SUM, newPoints, outArg (globalCountPoints));
615 reduceAll<int, int> (*this->comm_, REDUCE_SUM, newPointsRepeated, outArg (globalCountRepeated));
616 // Setting Unique newPoints as value for communication
617 MultiVectorLOPtr_Type exportLocalEntry = Teuchos::rcp( new MultiVectorLO_Type( mapProc, 1 ) );
618
619 // Unique Points on each Proc
620 int newPointsUnique= newPoints - newPointsRepeated;
621 exportLocalEntry->putScalar( (LO) newPointsUnique);
622
623 MultiVectorLOPtr_Type isActiveNodeUnique= Teuchos::rcp( new MultiVectorLO_Type( mapGlobalProc, 1 ) );
624 isActiveNodeUnique->putScalar( (LO) 0 );
625 isActiveNodeUnique->importFromVector( exportLocalEntry, true, "Insert");
626 // -> Result: Information on uniquely added Points of each Proc is accessible to all
627
628 Teuchos::ArrayRCP<const LO> nodesUniqueProcList = isActiveNodeUnique-> getData(0);
629
630 // Step 1: Add Nodes that are repeated on the processors
631 // Generally we allocate the first 'n' Points to Proc 0, the following start with (n+1) on Proc 1 and so on -> ProcOffset
632
633 GO refineOffset = this->mapUnique_->getMaxAllGlobalIndex()+1; // Number of Nodes before Refinement
634 int procOffset=0;
635 for(int i=0; i< myRank; i++)
636 procOffset = procOffset + nodesUniqueProcList[i];
637
638 MapConstPtr_Type mapRepeatedP1 = this->getMapRepeated(); // Maps
639 Teuchos::ArrayView<const GO> nodeList = mapRepeatedP1->getNodeElementList();
640 vec_GO_Type vecGlobalIDsOld = Teuchos::createVector( nodeList );
641
642 vec_GO_Type vecGlobalIDs(this->pointsRep_->size(),-1);
643
644 for (int i=0; i<vecGlobalIDsOld.size(); i++){
645 vecGlobalIDs[i] = vecGlobalIDsOld[ i] ; // (i + refineOffset+procOffset);
646 }
647
648 // Add Nodes that are on the interface -> repeated Points
649 int sumPointsUnique = globalCountPoints - globalCountRepeated;
650
651
652 // First we determine a Map only for the interface Nodes
653 // This will reduce the size of the Matrix we build later significantly if only look at the interface edges
654 int numEdges= edgeElements->numberElements();
655 vec2D_GO_Type inzidenzIndices(0,vec_GO_Type(2)); // Vector that stores global IDs of each edge (in Repeated Sense)
656 vec_LO_Type localNodeIndex(0); // stores the local ID of node in question
657 vec_GO_Type id(2);
658
659
660 int interfaceNum=0;
661 for(int i=0; i<numEdges; i++ ){
662 if(edgeElements->getElement(i).isInterfaceElement() && edgeElements->getElement(i).isTaggedForRefinement()){
663 id[0] = this->mapRepeated_->getGlobalElement(edgeElements->getElement(i).getNode(0));
664 id[1] = this->mapRepeated_->getGlobalElement(edgeElements->getElement(i).getNode(1));
665
666 sort(id.begin(),id.end());
667 inzidenzIndices.push_back(id);
668
669 localNodeIndex.push_back(edgeElements->getMidpoint(i));
670
671 }
672 }
673
674
675 // This Matrix is row based, where the row is based on mapInterfaceNodesUnqiue
676 // We then add a '1' Entry when two global Node IDs form an edge
677 MatrixPtr_Type inzidenzMatrix = Teuchos::rcp( new Matrix_Type(this->mapUnique_, 40 ) );
678 Teuchos::Array<GO> index(1);
679 Teuchos::Array<GO> col(1);
680 Teuchos::Array<SC> value(1, Teuchos::ScalarTraits<SC>::one() );
681
682 for(int i=0; i<inzidenzIndices.size(); i++ ){
683
684 index[0] = inzidenzIndices[i][0];
685 col[0] = inzidenzIndices[i][1];
686 inzidenzMatrix->insertGlobalValues(index[0], col(), value());
687
688 }
689 inzidenzMatrix->fillComplete();
690
691 // Now we count the row entries on each processor an set global IDs
692
693 Teuchos::ArrayView<const LO> indices;
694 Teuchos::ArrayView<const SC> values;
695 vec2D_GO_Type inzidenzIndicesUnique(0,vec_GO_Type(2)); // Vector that stores only both global IDs if the first is part of my unique Interface Nodes
696 MapConstPtr_Type colMap = inzidenzMatrix->getMap("col");
697 MapConstPtr_Type rowMap = inzidenzMatrix->getMap("row");
698 int numRows = rowMap->getNodeNumElements();
699 int uniqueEdges =0;
700 for(int i=0; i<numRows; i++ ){
701 inzidenzMatrix->getLocalRowView(i, indices,values);
702 uniqueEdges = uniqueEdges+indices.size();
703 vec_GO_Type edgeTmp(2);
704 for(int j=0; j<indices.size(); j++){
705 edgeTmp[0] = rowMap->getGlobalElement(i);
706 edgeTmp[1] = colMap->getGlobalElement(indices[j]);
707 inzidenzIndicesUnique.push_back(edgeTmp);
708 }
709 }
710
711 exportLocalEntry->putScalar( uniqueEdges );
712 MultiVectorLOPtr_Type newEdgesInterfaceGlobal= Teuchos::rcp( new MultiVectorLO_Type( mapGlobalProc, 1 ) );
713 newEdgesInterfaceGlobal->putScalar( (LO) 0 );
714 newEdgesInterfaceGlobal->importFromVector( exportLocalEntry, true, "Insert");
715
716 // offset EdgesUnique for proc and globally
717 Teuchos::ArrayRCP< const LO > numUniqueInterface = newEdgesInterfaceGlobal->getData(0);
718
719 int procOffsetEdges=0;
720 for(int i=0; i< myRank; i++)
721 procOffsetEdges= procOffsetEdges + numUniqueInterface[i];
722
723 int numInterfaceEdges=0;
724
725 vec_GO_Type uniqueInterfaceIDsList_(inzidenzIndicesUnique.size());
726 for(int i=0; i< uniqueInterfaceIDsList_.size(); i++)
727 uniqueInterfaceIDsList_[i] = procOffsetEdges + i;
728
729 MatrixPtr_Type indMatrix = Teuchos::rcp( new Matrix_Type(this->mapUnique_, 40 ) );
730
731 for(int i=0; i<inzidenzIndicesUnique.size(); i++ ){
732 index[0] = inzidenzIndicesUnique[i][0];
733 col[0] = inzidenzIndicesUnique[i][1];
734 Teuchos::Array<SC> value2(1,uniqueInterfaceIDsList_[i]);
735 indMatrix->insertGlobalValues(index[0], col(), value2());
736 }
737 indMatrix->fillComplete();
738
739 MatrixPtr_Type importMatrix = Teuchos::rcp( new Matrix_Type(this->mapRepeated_, 40 ) );
740
741 importMatrix->importFromVector(indMatrix,false,"Insert");
742 importMatrix->fillComplete();
743
744 // Determine global indices
745 GO edgeID=0;
746 colMap = importMatrix->getMap("col");
747 rowMap = importMatrix->getMap("row");
748
749 LO valueID=0;
750 bool found = false;
751 GO entry =0;
752 for(int i=0; i<inzidenzIndices.size(); i++ ){
753 importMatrix->getLocalRowView(rowMap->getLocalElement(inzidenzIndices[i][0]), indices,values); // Indices and values connected to node i / row i in Matrix
754 // Entries in 'indices' represent the local entry in 'colmap
755 // with 'getGlobalElement' we know the global Node ID that belongs to the first Node that form an edge
756 // vector in with entries only for edges belonging to node i;
757 vec2D_GO_Type indicesTmp(indices.size(),vec_GO_Type(2));
758 vec_GO_Type indTmp(2);
759 for(int j=0; j<indices.size(); j++){
760 indTmp[0] = colMap->getGlobalElement(indices[j]);
761 indTmp[1] = values[j];
762 indicesTmp.push_back(indTmp); // vector with the indices and values belonging to node i
763 }
764 found = false;
765 for(int k=0; k<indicesTmp.size();k++){
766 if(inzidenzIndices[i][1] == indicesTmp[k][0]){
767 entry =k;
768 k = indicesTmp.size();
769 edgeID = indicesTmp[entry][1];
770 vecGlobalIDs[localNodeIndex[i]] = refineOffset+sumPointsUnique + edgeID;
771 found =true;
772 }
773 }
774 if(found == false)
775 std::cout << " Asking for row " << rowMap->getLocalElement(inzidenzIndices[i][0]) << " for Edge [" << inzidenzIndices[i][0] << ", " << inzidenzIndices[i][1] << "], on Proc " << myRank << " but no Value found " <<std::endl;
776 }
777 // --------------------------------------------------------------------------------------------------
778 // --------------------------------------------------------------------------------------------------
779
780
781 // Step 2: Add points that are uniquely on each processor, leftover -1 entries in vecGlobalIDs signal a missing unique entry
782 // all left over entries
783 int count =0;
784 for (int i= vecGlobalIDsOld.size(); i < this->pointsRep_->size() ; i++){
785 if(vecGlobalIDs[i] == -1){
786 vecGlobalIDs[i] = count + refineOffset+procOffset;
787 count ++;
788 }
789 }
790 Teuchos::RCP<std::vector<GO> > pointsRepGlobMapping = Teuchos::rcp( new std::vector<GO>( vecGlobalIDs ) );
791 Teuchos::ArrayView<GO> pointsRepGlobMappingArray = Teuchos::arrayViewFromVector( *pointsRepGlobMapping );
792
793 this->mapRepeated_.reset(new Map<LO,GO,NO>( Teuchos::OrdinalTraits<GO>::invalid(), pointsRepGlobMappingArray, 0, this->comm_) );
794 this->mapUnique_ = this->mapRepeated_->buildUniqueMap( this->rankRange_ );
795
796
797 // Points and Flags Unique
798 this->pointsUni_.reset(new std::vector<std::vector<double> >( this->mapUnique_->getNodeNumElements(), std::vector<double>(this->dim_,-1. ) ) );
799 this->bcFlagUni_.reset( new std::vector<int> ( this->mapUnique_->getNodeNumElements(), 0 ) );
800 for (int i=0; i<this->mapUnique_->getNodeNumElements(); i++) {
801 GO gid = this->mapUnique_->getGlobalElement( i );
802 LO id = this->mapRepeated_->getLocalElement( this->mapUnique_->getGlobalElement( i ) );
803 this->pointsUni_->at(i) = this->pointsRep_->at(id);
804 this->bcFlagUni_->at(i) = this->bcFlagRep_->at(id);
805 }
806
807
808
809}
810
823template <class SC, class LO, class GO, class NO>
824void RefinementFactory<SC,LO,GO,NO>::buildSurfaceTriangleElements(ElementsPtr_Type elements, EdgeElementsPtr_Type edgeElements, SurfaceElementsPtr_Type surfaceTriangleElements, MapConstPtr_Type edgeMap, MapConstPtr_Type elementMap ){
825 TEUCHOS_TEST_FOR_EXCEPTION( elements.is_null(), std::runtime_error, "Elements not initialized!");
826 TEUCHOS_TEST_FOR_EXCEPTION( surfaceTriangleElements.is_null(), std::runtime_error, "Surface Triangle Elements not initialized!");
827
828
829 vec_LO_Type nodeInd(4);
830 vec2D_int_Type newTriangles(4,vec_int_Type(0)); // new Triangles
831
832 vec_GO_Type globalInterfaceIDs = edgeElements->determineInterfaceEdges(edgeMap);
833 //if(edgeElements->getEdgesOfElement(0) ) here we need some sort of test if the function was already used
834 edgeElements->matchEdgesToElements(elementMap);
835
836 for(int T=0; T<elements->numberElements(); T++){
837 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(T); // indeces of edges belonging to element
838
839 // Extract the four points of tetraeder
840 vec_int_Type nodeInd(0);
841 for(int i=0; i<6; i++){
842 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(0));
843 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(1));
844 }
845 sort( nodeInd.begin(), nodeInd.end() );
846 nodeInd.erase( unique( nodeInd.begin(), nodeInd.end() ), nodeInd.end() );
847
848 // With our sorted Nodes we construct edges as follows
849
850 // Edge_0 = [x_0,x_1]
851 // Edge_1 = [x_0,x_2]
852 // Edge_2 = [x_0,x_3]
853 // Edge_3 = [x_1,x_2]
854 // Edge_4 = [x_1,x_3]
855 // Edge_5 = [x_2,x_3]
856
857 vec_int_Type edgeNumbersTmp = edgeNumbers;
858 for(int i=0; i<6; i++){
859 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[0] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[0]){
860 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1])
861 edgeNumbers[0] = edgeNumbersTmp[i];
862 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
863 edgeNumbers[1] = edgeNumbersTmp[i];
864 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
865 edgeNumbers[2] = edgeNumbersTmp[i];
866 }
867 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1]){
868 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
869 edgeNumbers[3] = edgeNumbersTmp[i];
870 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
871 edgeNumbers[4] = edgeNumbersTmp[i];
872 }
873 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2]){
874 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
875 edgeNumbers[5] = edgeNumbersTmp[i];
876 }
877 }
878
879 // We hace 4 Triangles in our Tetraedron
880 // If one or more of those Triangles are Part of the domains' boundaries, they are added to the element in question as subelement
881 // We extract them in follwing pattern:
882
883 // Tri_0 = [x_0,x_1,x_2] -> Edge 0,1,3
884 // Tri_1 = [x_0,x_1,x_3] -> Edge 0,2,4
885 // Tri_2 = [x_0,x_2,x_3] -> Edge 1,2,5
886 // Tri_3 = [x_1,x_2,x_3] -> Edge 3,4,5
887
888 // We check if one or more of these triangles are part of the boundary surface and determine there flag
889
890 vec2D_int_Type originTriangles(4,vec_int_Type(3));
891 originTriangles[0] = {nodeInd[0],nodeInd[1],nodeInd[2]};
892 originTriangles[1] = {nodeInd[0],nodeInd[1],nodeInd[3]};
893 originTriangles[2] = {nodeInd[0],nodeInd[2],nodeInd[3]};
894 originTriangles[3] = {nodeInd[1],nodeInd[2],nodeInd[3]};
895
896
897 vec_int_Type originFlag(4,this->volumeID_); // Triangle Flag
898 int numberSubElSurf=0;
899 vec_LO_Type triTmp(3);
900 vec_int_Type originTriangleTmp(3);
901 int entry;
902 if (elements->getElement(T).subElementsInitialized() ){
903 numberSubElSurf = elements->getElement(T).getSubElements()->numberElements();
904 for(int k=0; k< numberSubElSurf ; k++){
905 //cout << " Flags of Subelements " << elements->getElement(T).getSubElements()->getElement(k).getFlag() << endl;
906 triTmp =elements->getElement(T).getSubElements()->getElement(k).getVectorNodeList();
907 for(int j=0; j<4 ; j++){
908 originTriangleTmp = originTriangles[j];
909 sort(originTriangleTmp.begin(),originTriangleTmp.end());
910 sort(triTmp.begin(),triTmp.end());
911 if(triTmp[0] == originTriangleTmp[0] && triTmp[1] == originTriangleTmp[1] && triTmp[2] == originTriangleTmp[2] )
912 originFlag[j] = elements->getElement(T).getSubElements()->getElement(k).getFlag();
913
914 }
915 }
916 }
917
918 // Furthermore we have to determine whether the triangles are part of the interface between processors, as we need this information to determine if edges
919 // that emerge on the triangles are part of the interface
920 // A triangle is part of the interface if all of its edges are part of the interface (the information if edges are part of the interface was determined
921 // in the beginning of the Mesh Refinement by 'determineInterfaceEdges')
922
923 vec_bool_Type interfaceSurface = checkInterfaceSurface(edgeElements,originFlag, edgeNumbers,T);
924
925 for(int j=0; j<4; j++){
926 sort( newTriangles.at(j).begin(), newTriangles.at(j).end() );
927 FiniteElement feNew(originTriangles[j],originFlag[j]);
928 feNew.setInterfaceElement(interfaceSurface[j]);
929 surfaceTriangleElements->addSurface(feNew, T);
930 }
931 }
932 vec2D_GO_Type combinedSurfaceElements;
933 surfaceTriangleElements->sortUniqueAndSetGlobalIDsParallel(elementMap,combinedSurfaceElements);
934
935 surfaceTriangleElements->setElementsSurface( combinedSurfaceElements );
936
937 surfaceTriangleElements->setUpElementsOfSurface(elementMap,edgeMap, edgeElements);
938}
939
940
941
942
951template <class SC, class LO, class GO, class NO>
952void RefinementFactory<SC,LO,GO,NO>::buildEdgeMap(MapConstPtr_Type mapGlobalProc,MapConstPtr_Type mapProc){
953
954 vec2D_int_Type interfaceEdgesLocalId(1,vec_int_Type(1));
955 int maxRank = std::get<1>(this->rankRange_);
956 const int myRank = this->comm_->getRank();
957
958 MultiVectorLOPtr_Type exportLocalEntry = Teuchos::rcp( new MultiVectorLO_Type( mapProc, 1 ) );
959
960 // (A) First we determine a Map only for the interface Nodes
961 // This will reduce the size of the Matrix we build later significantly if only look at the interface edges
962 int numEdges= this->edgeElements_->numberElements();
963 vec2D_GO_Type inzidenzIndices(0,vec_GO_Type(2)); // Vector that stores global IDs of each edge (in Repeated Sense)
964 vec_LO_Type localEdgeIndex(0); // stores the local ID of edges in question
965 vec_GO_Type id(2);
966 int edgesUnique=0;
967 EdgeElementsPtr_Type edgeElements = this->edgeElements_; // Edges
968
969 vec2D_dbl_ptr_Type points = this->pointsRep_;
970
971 int interfaceNum=0;
972 for(int i=0; i<numEdges; i++ ){
973 if(edgeElements->getElement(i).isInterfaceElement()){
974
975 id[0] = this->mapRepeated_->getGlobalElement(edgeElements->getElement(i).getNode(0));
976 id[1] = this->mapRepeated_->getGlobalElement(edgeElements->getElement(i).getNode(1));
977
978
979
980 sort(id.begin(),id.end());
981 inzidenzIndices.push_back(id);
982
983 localEdgeIndex.push_back(i);
984 interfaceNum++;
985 }
986
987 else{
988 edgesUnique++;
989 }
990
991
992 }
993
994
995 // This Matrix is row based, where the row is based on mapInterfaceNodesUnqiue
996 // We then add a '1' Entry when two global Node IDs form an edge
997 MatrixPtr_Type inzidenzMatrix = Teuchos::rcp( new Matrix_Type(this->mapUnique_, 40 ) );
998 Teuchos::Array<GO> index(1);
999 Teuchos::Array<GO> col(1);
1000 Teuchos::Array<SC> value(1, Teuchos::ScalarTraits<SC>::one() );
1001
1002 for(int i=0; i<inzidenzIndices.size(); i++ ){
1003
1004 index[0] = inzidenzIndices[i][0];
1005 col[0] = inzidenzIndices[i][1];
1006 inzidenzMatrix->insertGlobalValues(index[0], col(), value());
1007
1008 }
1009 inzidenzMatrix->fillComplete(); //mapInterfaceNodesUnique,mapInterfaceNodesUnique);
1010
1011
1012 // ---------------------------------------------------
1013 // 2 .Set unique edges IDs ---------------------------
1014 // Setting the IDs of Edges that are uniquely on one
1015 // Processor
1016 // ---------------------------------------------------
1017 exportLocalEntry->putScalar( (LO) edgesUnique );
1018
1019 MultiVectorLOPtr_Type newEdgesUniqueGlobal= Teuchos::rcp( new MultiVectorLO_Type( mapGlobalProc, 1 ) );
1020 newEdgesUniqueGlobal->putScalar( (LO) 0 );
1021 newEdgesUniqueGlobal->importFromVector( exportLocalEntry, true, "Insert");
1022 // offset EdgesUnique for proc and globally
1023 Teuchos::ArrayRCP< const LO > newEdgesList = newEdgesUniqueGlobal->getData(0);
1024
1025 GO procOffsetEdges=0;
1026 for(int i=0; i< myRank; i++)
1027 procOffsetEdges= procOffsetEdges + newEdgesList[i];
1028
1029 // global IDs for map
1030 vec_GO_Type vecGlobalIDsEdges(this->edgeElements_->numberElements());
1031
1032 // Step 1: adding unique global edge IDs
1033 int count=0;
1034 for(int i=0; i< this->edgeElements_->numberElements(); i++){
1035 if(!this->edgeElements_->getElement(i).isInterfaceElement()){
1036 vecGlobalIDsEdges.at(i) = procOffsetEdges+count;
1037 count++;
1038 }
1039 }
1040
1041 // Now we add the repeated ids, by first turning interfaceEdgesTag into a map
1042 // Offset for interface IDS:
1043 GO offsetInterface=0;
1044 for(int i=0; i< maxRank+1; i++)
1045 offsetInterface= offsetInterface + newEdgesList[i];
1046
1047 //Now we count the row entries on each processor an set global IDs
1048
1049 Teuchos::ArrayView<const LO> indices;
1050 Teuchos::ArrayView<const SC> values;
1051 vec2D_GO_Type inzidenzIndicesUnique(0,vec_GO_Type(2)); // Vector that stores only both global IDs if the first is part of my unique Interface Nodes
1052 MapConstPtr_Type colMap = inzidenzMatrix->getMap("col");
1053 MapConstPtr_Type rowMap = inzidenzMatrix->getMap("row");
1054 int numRows = rowMap->getNodeNumElements();
1055 int uniqueEdges =0;
1056 for(int i=0; i<numRows; i++ ){
1057 inzidenzMatrix->getLocalRowView(i, indices,values);
1058 uniqueEdges = uniqueEdges+indices.size();
1059 vec_GO_Type edgeTmp(2);
1060 for(int j=0; j<indices.size(); j++){
1061 edgeTmp[0] = rowMap->getGlobalElement(i);
1062 edgeTmp[1] = colMap->getGlobalElement(indices[j]);
1063 inzidenzIndicesUnique.push_back(edgeTmp);
1064 }
1065 }
1066
1067 exportLocalEntry->putScalar( uniqueEdges );
1068 MultiVectorLOPtr_Type newEdgesInterfaceGlobal= Teuchos::rcp( new MultiVectorLO_Type( mapGlobalProc, 1 ) );
1069 newEdgesInterfaceGlobal->putScalar( (LO) 0 );
1070 newEdgesInterfaceGlobal->importFromVector( exportLocalEntry, true, "Insert");
1071
1072 // offset EdgesUnique for proc and globally
1073 Teuchos::ArrayRCP< const LO > numUniqueInterface = newEdgesInterfaceGlobal->getData(0);
1074
1075 procOffsetEdges=0;
1076 for(int i=0; i< myRank; i++)
1077 procOffsetEdges= procOffsetEdges + numUniqueInterface[i];
1078
1079 int numInterfaceEdges=0;
1080
1081 vec_GO_Type uniqueInterfaceIDsList_(inzidenzIndicesUnique.size());
1082 for(int i=0; i< uniqueInterfaceIDsList_.size(); i++)
1083 uniqueInterfaceIDsList_[i] = procOffsetEdges + i;
1084
1085 MatrixPtr_Type indMatrix = Teuchos::rcp( new Matrix_Type(this->mapUnique_, 40 ) );
1086
1087 for(int i=0; i<inzidenzIndicesUnique.size(); i++ ){
1088 index[0] = inzidenzIndicesUnique[i][0];
1089 col[0] = inzidenzIndicesUnique[i][1];
1090 Teuchos::Array<SC> value2(1,uniqueInterfaceIDsList_[i]);
1091 indMatrix->insertGlobalValues(index[0], col(), value2());
1092 }
1093 indMatrix->fillComplete();
1094
1095 MatrixPtr_Type importMatrix = Teuchos::rcp( new Matrix_Type(this->mapRepeated_, 40 ) );
1096
1097 importMatrix->importFromVector(indMatrix,false,"Insert");
1098 importMatrix->fillComplete();
1099
1100 // Determine global indices
1101 GO edgeID=0;
1102 colMap = importMatrix->getMap("col");
1103 rowMap = importMatrix->getMap("row");
1104
1105 LO valueID=0;
1106 bool found = false;
1107 GO entry =0;
1108 for(int i=0; i<inzidenzIndices.size(); i++ ){
1109
1110 importMatrix->getLocalRowView(rowMap->getLocalElement(inzidenzIndices[i][0]), indices,values); // Indices and values connected to node i / row i in Matrix
1111 // Entries in 'indices' represent the local entry in 'colmap
1112 // with 'getGlobalElement' we know the global Node ID that belongs to the first Node that form an edge
1113 // vector in with entries only for edges belonging to node i;
1114 vec2D_GO_Type indicesTmp(indices.size(),vec_GO_Type(2));
1115 vec_GO_Type indTmp(2);
1116 for(int j=0; j<indices.size(); j++){
1117 indTmp[0] = colMap->getGlobalElement(indices[j]);
1118 indTmp[1] = values[j];
1119 indicesTmp.push_back(indTmp); // vector with the indices and values belonging to node i
1120 }
1121 //sort(indicesTmp.begin(),indicesTmp.end());
1122 found = false;
1123 for(int k=0; k<indicesTmp.size();k++){
1124 if(inzidenzIndices[i][1] == indicesTmp[k][0]){
1125 entry =k;
1126 k = indicesTmp.size();
1127 edgeID = indicesTmp[entry][1];
1128 vecGlobalIDsEdges.at(localEdgeIndex[i]) = offsetInterface + edgeID;
1129 found =true;
1130 }
1131 }
1132 if(found == false)
1133 std::cout << " Asking for row " << rowMap->getLocalElement(inzidenzIndices[i][0]) << " for Edge [" << inzidenzIndices[i][0] << ", " << inzidenzIndices[i][1] << "], on Proc " << myRank << " but no Value found " <<std::endl;
1134 }
1135
1136
1137 Teuchos::RCP<std::vector<GO>> edgesGlobMapping = Teuchos::rcp( new std::vector<GO>( vecGlobalIDsEdges ) );
1138 Teuchos::ArrayView<GO> edgesGlobMappingArray = Teuchos::arrayViewFromVector( *edgesGlobMapping);
1139
1140 this->edgeMap_.reset(new Map<LO,GO,NO>(Teuchos::OrdinalTraits<GO>::invalid(), edgesGlobMappingArray, 0, this->comm_) );
1141 //this->edgeMap_->print();
1142}
1143
1144
1174
1175template <class SC, class LO, class GO, class NO>
1176void RefinementFactory<SC,LO,GO,NO>::refinementRestrictions(MeshUnstrPtr_Type meshP1, ElementsPtr_Type elements ,EdgeElementsPtr_Type edgeElements,SurfaceElementsPtr_Type surfaceTriangleElements,int& newPoints, int& newPointsCommon, vec_GO_Type& globalInterfaceIDsTagged, MapConstPtr_Type mapInterfaceEdges,int& newElements){
1177
1178 vec2D_dbl_ptr_Type points = meshP1->getPointsRepeated(); // Points
1179 std::string restriction = refinementRestriction_;
1180
1181 if(this->dim_ == 2){
1182 // We determine whether a element that is tagged for green refinement has been refined green in the previous refinement
1183 // If thats is the case, we choose to refine element blue instead by adding a node to the longest edge
1184 vec_int_Type tagCounter(elements->numberElements());
1185
1186 int edgeNum;
1187
1188 MapConstPtr_Type edgeMap = meshP1->getEdgeMap();
1189
1190 // Determine Global Ids of Interface Edges
1191 vec2D_GO_Type elementsOfEdgesGlobal = edgeElements->getElementsOfEdgeGlobal();
1192 vec2D_LO_Type elementsOfEdgesLocal = edgeElements->getElementsOfEdgeLocal();
1193
1194 int entry;
1195
1196 for(int i=0;i<elements->numberElements() ;i++){
1197 for(int j=0;j<3;j++){
1198 edgeNum = edgeElements->getEdgesOfElement(i).at(j);
1199 if(edgeElements->getElement(edgeNum).isTaggedForRefinement()){
1200 tagCounter[i]=tagCounter[i]+1; // We count the tags of element -> one Tag equals green Refinement
1201 }
1202 }
1203 }
1204
1205 int layer =1;
1206 while(layer >0){
1207 vec_GO_Type globalEdges(0);
1208 layer=0;
1209 if(refinementRestriction_ == "Bisection"){
1210 for(int i=0;i<elements->numberElements() ;i++){
1211 if(elements->getElement(i).isTaggedForRefinement()==false){ // only looking at the untagged Elements
1212 if(tagCounter[i]==1){
1213 entry = this->determineLongestEdge(edgeElements,edgeElements->getEdgesOfElement(i),points); // we determine the edge, we would choose for blue Refinement
1214 if(!edgeElements->getElement(entry).isTaggedForRefinement()){ // If the longestest edge is already the tagged one, we leave the Element alone
1215 edgeElements->getElement(entry).tagForRefinement(); // we tag the Element for refinement
1216 this->addMidpoint(edgeElements,entry); // we add the necessary midpoint
1217 newPoints ++; // add new Points
1218 if(elementsOfEdgesLocal.at(entry).size() > 1){
1219 if(elementsOfEdgesLocal.at(entry).at(0) != -1)
1220 tagCounter[elementsOfEdgesLocal.at(entry).at(0)] ++;
1221 else
1222 globalEdges.push_back(edgeMap->getGlobalElement(entry)); // and add the index for communication later
1223 if(elementsOfEdgesLocal.at(entry).at(1) != -1)
1224 tagCounter[elementsOfEdgesLocal.at(entry).at(1)] ++;
1225 else
1226 globalEdges.push_back(edgeMap->getGlobalElement(entry)); // and add the index for communication later
1227 }
1228 else
1229 tagCounter[elementsOfEdgesLocal.at(entry).at(0)] ++;
1230
1231 tagCounter[i] = -1; // This element now has been refined optimally, so no other checks are necessary
1232 layer++;
1233 }
1234 }
1235 if(tagCounter[i]==2){
1236 entry = this->determineLongestEdge(edgeElements,edgeElements->getEdgesOfElement(i),points); // we determine the edge, we would choose for blue Refinement
1237 if(!edgeElements->getElement(entry).isTaggedForRefinement()){ // If the longestest edge is already the tagged one, we leave the Element alone
1238 //std::cout <<" Change to red in k= " << k << std::endl;
1239 edgeElements->getElement(entry).tagForRefinement(); // we tag the Element for refinement
1240 this->addMidpoint(edgeElements,entry); // we add the necessary midpoint
1241 newPoints ++; // add new Points
1242 if(elementsOfEdgesLocal.at(entry).size() > 1){
1243 if(elementsOfEdgesLocal.at(entry).at(0) != -1)
1244 tagCounter[elementsOfEdgesLocal.at(entry).at(0)] ++;
1245 else
1246 globalEdges.push_back(edgeMap->getGlobalElement(entry)); // and add the index for communication later
1247
1248 if(elementsOfEdgesLocal.at(entry).at(1) != -1)
1249 tagCounter[elementsOfEdgesLocal.at(entry).at(1)] ++;
1250 else
1251 globalEdges.push_back(edgeMap->getGlobalElement(entry)); // and add the index for communication later
1252
1253 }
1254 else
1255 tagCounter[elementsOfEdgesLocal.at(entry).at(0)] ++;
1256
1257 tagCounter[i] = -1; // This element now has been refined optimally, so no other checks are necessary
1258 layer++;
1259 }
1260 }
1261 }
1262 }
1263 }
1264
1265 else if (refinementRestriction_ == "GreenTags"){
1266 for(int i=0;i<elements->numberElements() ;i++){
1267
1268 if(elements->getElement(i).isTaggedForRefinement()==false){ // only looking at the untagged Elements
1269
1270 if(tagCounter[i]==1 && elements->getElement(i).getFiniteElementRefinementType() == "green"){
1271 entry = this->determineLongestEdge(edgeElements,edgeElements->getEdgesOfElement(i),points); // we determine the edge, we would choose for blue Refinement
1272 if(!edgeElements->getElement(entry).isTaggedForRefinement()){ // If the longestest edge is already the tagged one, we leave the Element alone
1273 edgeElements->getElement(entry).tagForRefinement(); // we tag the Element for refinement
1274 this->addMidpoint(edgeElements,entry); // we add the necessary midpoint
1275 newPoints ++; // add new Points
1276 if(elementsOfEdgesLocal.at(entry).size() > 1){
1277 if(elementsOfEdgesLocal.at(entry).at(0) != -1)
1278 tagCounter[elementsOfEdgesLocal.at(entry).at(0)] ++;
1279 else
1280 globalEdges.push_back(edgeMap->getGlobalElement(entry)); // and add the index for communication later
1281 if(elementsOfEdgesLocal.at(entry).at(1) != -1)
1282 tagCounter[elementsOfEdgesLocal.at(entry).at(1)] ++;
1283 else
1284 globalEdges.push_back(edgeMap->getGlobalElement(entry)); // and add the index for communication later
1285 }
1286 else
1287 tagCounter[elementsOfEdgesLocal.at(entry).at(0)] ++;
1288
1289 tagCounter[i] = -1; // This element now has been refined optimally, so no other checks are necessary
1290 layer++;
1291 }
1292 }
1293
1294 }
1295 }
1296 }
1297
1298 reduceAll<int, int> (*this->comm_, REDUCE_SUM, layer, outArg (layer));
1299
1300 // Constructing a map of the global IDs of the tagged Edges
1301 Teuchos::ArrayView<GO> globalEdgesArray = Teuchos::arrayViewFromVector( globalEdges);
1302 MapPtr_Type mapEdgesTagged =
1303 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), globalEdgesArray, 0, this->comm_) );
1304 // Multivector based on taggesEdgesMap with one as entries
1305 MultiVectorLOPtr_Type isActiveEdge = Teuchos::rcp( new MultiVectorLO_Type( mapEdgesTagged, 1 ) );
1306 isActiveEdge->putScalar( (LO) 1);
1307 //isActiveEdge->print();
1308
1309 // Creating a Multivector based on the unique edgeMap and repeated edge map with zeros as entries
1310 MultiVectorLOPtr_Type taggedEdgesLocal = Teuchos::rcp( new MultiVectorLO_Type(mapInterfaceEdges, 1 ) );
1311 taggedEdgesLocal->putScalar(0);
1312
1313 taggedEdgesLocal->importFromVector(isActiveEdge, true, "Insert"); // From this we know that -> one signifies a tagged edge -> if we didn't tag it -> refine
1314
1315 //taggedEdgesLocal->print();
1316
1317 Teuchos::ArrayRCP< const LO > tags = taggedEdgesLocal->getData( 0 );
1318
1319 // Adding Midpoints and tagging the edges that were tagged on other Procs an are on the interface
1320 // Collecting global Ids of tagged Interface Edges
1321 LO ind;
1322 GO indG;
1323 //edgeMap->print();
1324 for (int i=0; i<tags.size(); i++) {
1325 if (tags[i] > 0){
1326 indG = mapInterfaceEdges->getGlobalElement(i);
1327 ind = edgeMap->getLocalElement(indG);
1328 globalInterfaceIDsTagged.push_back(indG);
1329 newPointsCommon ++;
1330 if(!edgeElements->getElement(ind).isTaggedForRefinement()){
1331 edgeElements->getElement(ind).tagForRefinement();
1332 this->addMidpoint(edgeElements,ind);
1333 // globalen Index der Kante -> alle Prozessoren haben diese Kante -> die Knoten die hier hinzugefügt werden sind haben auf allen Proc den gleichen Index
1334 newPoints ++;
1335
1336 if(elementsOfEdgesLocal.at(ind).at(0) != -1 ){
1337 if(tagCounter[elementsOfEdgesLocal.at(ind).at(0)] != -1)
1338 tagCounter[elementsOfEdgesLocal.at(ind).at(0)] ++;
1339 }
1340 if(elementsOfEdgesLocal.at(ind).at(1) != -1){
1341 if(tagCounter[elementsOfEdgesLocal.at(ind).at(1)] != -1)
1342 tagCounter[elementsOfEdgesLocal.at(ind).at(1)] ++;
1343 }
1344
1345 }
1346 }
1347
1348 }
1349 }
1350 }
1351
1352
1353 else if(this->dim_== 3){
1354 restriction = refinementRestriction_;
1355 int alright = 0;
1356 MapConstPtr_Type edgeMap = meshP1->getEdgeMap();
1357 int numPoints=0;
1358 int layer =0;
1359 int inputLayer = currentIter_;
1360 while(alright==0){
1361 alright=1;
1362 if(layer == inputLayer &&( restriction == "Bey" || restriction == "BeyIrregular") ){
1363 restriction = "Bey";
1364 }
1365 else if( layer == inputLayer +1)
1366 restriction = "None";
1367 layer++;
1368 vec_GO_Type untaggedIDs(0);
1369 for(int i=0;i<elements->numberElements() ;i++){
1370 vec_int_Type nodeInd(0);
1371 int nodeTag=0;
1372 int edgeTag=0;
1373 vec_GO_Type untaggedIDsTmp(0);
1374 int entry =0;
1375 if(elements->getElement(i).isTaggedForRefinement()==false){ // only looking at the untagged Elements
1376 for(int j=0;j<6;j++){
1377 int edgeNum = edgeElements->getEdgesOfElement(i).at(j);
1378 if(edgeElements->getElement(edgeNum).isTaggedForRefinement()){
1379 nodeInd.push_back(edgeElements->getElement(edgeNum).getNode(0));
1380 nodeInd.push_back(edgeElements->getElement(edgeNum).getNode(1));
1381 edgeTag++;
1382 }
1383 else{
1384 if(edgeElements->getElement(edgeNum).isInterfaceElement())
1385 untaggedIDsTmp.push_back(edgeMap->getGlobalElement(edgeNum));
1386 }
1387 }
1388 sort( nodeInd.begin(), nodeInd.end() );
1389 nodeInd.erase( unique( nodeInd.begin(), nodeInd.end() ), nodeInd.end() );
1390 nodeTag = nodeInd.size();
1391 if(restriction == "BeyIrregular") {
1392 if(edgeTag > 0 && elements->getElement(i).getFiniteElementRefinementType( ) == "irregularRegular" ){
1393 numPoints= this->pointsRep_->size();
1394 elements->getElement(i).tagForRefinement();
1395 elements->getElement(i).setFiniteElementRefinementType("irregular");
1396 this->bisectEdges( edgeElements, elements, i,surfaceTriangleElements, "all");
1397 newPoints=newPoints + this->pointsRep_->size()-numPoints;
1398 alright=0;
1399 for(int j=0; j<untaggedIDsTmp.size(); j++)
1400 untaggedIDs.push_back(untaggedIDsTmp[j]);
1401
1402 }
1403 else if(edgeTag > 0 && elements->getElement(i).getFiniteElementRefinementType( ) == "irregular"){
1404 numPoints= this->pointsRep_->size();
1405 elements->getElement(i).tagForRefinement();
1406 this->bisectEdges( edgeElements, elements, i,surfaceTriangleElements, "all");
1407 newPoints=newPoints + this->pointsRep_->size()-numPoints;
1408 alright=0;
1409 for(int j=0; j<untaggedIDsTmp.size(); j++)
1410 untaggedIDs.push_back(untaggedIDsTmp[j]);
1411
1412 }
1413 }
1414 else if(restriction== "Bey") {
1415 if(edgeTag > 0 && elements->getElement(i).getFiniteElementRefinementType( ) == "irregular" ){
1416 numPoints= this->pointsRep_->size();
1417 elements->getElement(i).tagForRefinement();
1418 this->bisectEdges( edgeElements, elements, i,surfaceTriangleElements, "all");
1419 newPoints=newPoints + this->pointsRep_->size()-numPoints;
1420 alright=0;
1421 for(int j=0; j<untaggedIDsTmp.size(); j++)
1422 untaggedIDs.push_back(untaggedIDsTmp[j]);
1423
1424 }
1425 }
1426 if(nodeTag >3 && edgeTag >2){
1427 numPoints= this->pointsRep_->size();
1428 elements->getElement(i).tagForRefinement();
1429 this->bisectEdges( edgeElements, elements, i,surfaceTriangleElements, "all");
1430 newPoints=newPoints + this->pointsRep_->size()-numPoints;
1431 alright=0;
1432 for(int j=0; j<untaggedIDsTmp.size(); j++)
1433 untaggedIDs.push_back(untaggedIDsTmp[j]);
1434 }
1435
1436 }
1437 }
1438
1439
1440 sort(untaggedIDs.begin(),untaggedIDs.end());
1441 untaggedIDs.erase(unique(untaggedIDs.begin(),untaggedIDs.end()),untaggedIDs.end());
1442 // Constructing a map of the global IDs of the tagged Edges
1443 Teuchos::ArrayView<GO> globalEdgesArray = Teuchos::arrayViewFromVector( untaggedIDs);
1444 MapPtr_Type mapEdgesTagged =
1445 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), globalEdgesArray, 0, this->comm_) );
1446 // Multivector based on taggesEdgesMap with one as entries
1447 MultiVectorLOPtr_Type isActiveEdge = Teuchos::rcp( new MultiVectorLO_Type( mapEdgesTagged, 1 ) );
1448 isActiveEdge->putScalar( (LO) 1);
1449 //isActiveEdge->print();
1450
1451 // Creating a Multivector based on the unique edgeMap and repeated edge map with zeros as entries
1452 MultiVectorLOPtr_Type taggedEdgesLocal = Teuchos::rcp( new MultiVectorLO_Type(mapInterfaceEdges, 1 ) );
1453 taggedEdgesLocal->putScalar(0);
1454
1455 taggedEdgesLocal->importFromVector(isActiveEdge, true, "Insert"); // From this we know that -> one signifies a tagged edge -> if we didn't tag it -> refine
1456
1457 Teuchos::ArrayRCP< const LO > tags = taggedEdgesLocal->getData( 0 );
1458
1459 // Adding Midpoints and tagging the edges that were tagged on other Procs an are on the interface
1460 // Collecting global Ids of tagged Interface Edges
1461 LO ind;
1462 GO indG;
1463
1464 for (int i=0; i<tags.size(); i++) {
1465 if (tags[i] > 0){
1466 indG = mapInterfaceEdges->getGlobalElement(i);
1467 ind = edgeMap->getLocalElement(indG);
1468 globalInterfaceIDsTagged.push_back(indG);
1469 newPointsCommon ++;
1470 if(!edgeElements->getElement(ind).isTaggedForRefinement()){
1471 edgeElements->getElement(ind).tagForRefinement();
1472 this->addMidpoint(edgeElements,ind);
1473 // globalen Index der Kante -> alle Prozessoren haben diese Kante -> die Knoten die hier hinzugefügt werden sind haben auf allen Proc den gleichen Index
1474 newPoints ++;
1475 }
1476 }
1477 }
1478 reduceAll<int, int> (*this->comm_, REDUCE_MIN, alright, outArg (alright));
1479 }
1480 }
1481}
1482
1494
1495template <class SC, class LO, class GO, class NO>
1496void RefinementFactory<SC,LO,GO,NO>::refineMeshRegIreg(ElementsPtr_Type elements, EdgeElementsPtr_Type edgeElements, int& newElements,MapConstPtr_Type edgeMap, SurfaceElementsPtr_Type surfaceTriangleElements)
1497{
1498 if(this->dim_==2){
1499 int edgeNum=0;
1500 vec_int_Type tagCounter2(elements->numberElements());
1501 for(int i=0;i<elements->numberElements() ;i++){
1502 for(int j=0;j<3;j++){
1503 edgeNum = edgeElements->getEdgesOfElement(i).at(j);
1504 if(edgeElements->getElement(edgeNum).isTaggedForRefinement())
1505 tagCounter2[i] ++;
1506 }
1507 if(tagCounter2[i] == 1){
1508 elements->getElement(i).setFiniteElementRefinementType("green");
1509 this->refineGreen(edgeElements, elements, i);
1510 newElements ++;
1511 }
1512 else if(tagCounter2[i] == 2){
1513 elements->getElement(i).setFiniteElementRefinementType("blue");
1514 this->refineBlue(edgeElements, elements, i);
1515 newElements= newElements+2;
1516 }
1517 else if(tagCounter2[i] == 3){
1518 elements->getElement(i).setFiniteElementRefinementType("regular");
1519 if(refinementMode_ == "Bisection"){
1520 this->bisectElement3(edgeElements, elements, i);
1521 }
1522 else
1523 this->refineRegular(edgeElements, elements, i, surfaceTriangleElements);
1524 newElements= newElements+3;
1525 }
1526 else {
1527 // the element in question has not been refined, nor its neighbour -> add edges to edge list
1528 vec_int_Type edgesOfElement = edgeElements->getEdgesOfElement(i);
1529 for(int j=0;j<3;j++){
1530 edgeElements->getElement(edgesOfElement[j]).setFiniteElementRefinementType("unrefined");
1531 edgeElements->getElement(edgesOfElement[j]).setPredecessorElement(edgeMap->getGlobalElement(edgesOfElement[j]));
1532 edgeElements->getElement(edgesOfElement[j]).setInterfaceElement( edgeElements->getElement(edgesOfElement[j]).isInterfaceElement());
1533 this->edgeElements_->addEdge(edgeElements->getElement(edgesOfElement[j]),i);
1534
1535 /*if(edgeElements->getElement(edgesOfElement[j]).getFlag() !=0 && edgeElements->getElement(edgesOfElement[j]).getFlag() !=10){
1536 if ( !this->elementsC_->getElement(i).subElementsInitialized() )
1537 this->elementsC_->getElement(i).initializeSubElements( this->FEType_, this->dim_ -1) ;
1538 this->elementsC_->getElement(i).addSubElement(edgeElements->getElement(edgesOfElement[j]));
1539 }*/
1540
1541 }
1542
1543 }
1544 }
1545 }
1546 // Irregular Refinement algorithm according to Bey
1547 else if(this->dim_==3){
1548 int edgeNum=0;
1549 int nodeTag =0;
1550 int edgeTag =0;
1551 for(int i=0;i<elements->numberElements() ;i++){
1552 vec_int_Type nodeInd(0);
1553 nodeTag=0;
1554 edgeTag=0;
1555 for(int j=0;j<6;j++){
1556 edgeNum = edgeElements->getEdgesOfElement(i).at(j);
1557 if(edgeElements->getElement(edgeNum).isTaggedForRefinement()){
1558 nodeInd.push_back(edgeElements->getElement(edgeNum).getNode(0));
1559 nodeInd.push_back(edgeElements->getElement(edgeNum).getNode(1));
1560 edgeTag++;
1561 }
1562 }
1563 sort( nodeInd.begin(), nodeInd.end() );
1564 nodeInd.erase( unique( nodeInd.begin(), nodeInd.end() ), nodeInd.end() );
1565 nodeTag = nodeInd.size();
1566
1567 if(nodeTag == 3 && edgeTag ==3){
1568 //elements->getElement(i).setFiniteElementRefinementType("Type1");
1569 //std::cout << " Requesting Type 1 Refinement on Processor " << this->comm_->getRank()<< std::endl;
1570 this->refineType1(edgeElements, elements, i,surfaceTriangleElements);
1571 newElements = newElements+3;
1572 }
1573 else if(nodeTag == 2 && edgeTag == 1){
1574 //elements->getElement(i).setFiniteElementRefinementType("Type2");
1575 //std::cout << " Requesting Type 2 Refinement on Processor " << this->comm_->getRank() << std::endl;
1576 this->refineType2(edgeElements, elements, i,surfaceTriangleElements);
1577 newElements ++;
1578
1579 }
1580 else if(nodeTag == 3 && edgeTag == 2){
1581 //elements->getElement(i).setFiniteElementRefinementType("Type3");
1582 //std::cout << " Requesting Type 3 Refinement on Processor " << this->comm_->getRank() << std::endl;
1583 this->refineType3(edgeElements, elements, i,surfaceTriangleElements);
1584
1585 newElements = newElements+2;
1586 }
1587 else if(nodeTag == 4 && edgeTag == 2){
1588 //elements->getElement(i).setFiniteElementRefinementType("Type4");
1589 //std::cout << " Requesting Type 4 Refinement on Processor " << this->comm_->getRank() << std::endl;
1590 this->refineType4(edgeElements, elements, i,surfaceTriangleElements);
1591 newElements = newElements+3;
1592 }
1593 else if(nodeTag == 4 && edgeTag == 6 ){
1594 this->refineRegular(edgeElements, elements, i, surfaceTriangleElements);
1595 newElements = newElements+7;
1596 }
1597 else if(nodeTag >3 && edgeTag >2){
1598 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "RefineMesh: Requesting 3D Refinement Type, that doesn't exist.");
1599 }
1600
1601 else if(edgeTag ==0){
1602 vec_int_Type edgesOfElement = edgeElements->getEdgesOfElement(i);
1603 for(int j=0;j<6;j++){
1604 edgeElements->getElement(edgesOfElement[j]).setFiniteElementRefinementType("unrefined");
1605 edgeElements->getElement(edgesOfElement[j]).setPredecessorElement(edgeMap->getGlobalElement(edgesOfElement[j]));
1606 this->edgeElements_->addEdge(edgeElements->getElement(edgesOfElement[j]),i);
1607
1608 }
1609
1610 vec_int_Type surfacesOfElement = surfaceTriangleElements->getSurfacesOfElement(i);
1611 for(int j=0;j<4;j++){
1612 this->surfaceTriangleElements_->addSurface(surfaceTriangleElements->getElement(surfacesOfElement[j]),i);
1613 }
1614 }
1615 }
1616 }
1617
1618 for(int j=0;j<this->edgeElements_->numberElements();j++){
1619 if(this->edgeElements_->getElement(j).isTaggedForRefinement())
1620 std::cout<< "tagged edge element somehow made it " << std::endl;
1621 }
1622
1623}
1624
1625
1634
1635template <class SC, class LO, class GO, class NO>
1637
1638 if(maxRank >0 && this->dim_ == 2){
1639 vec_GO_Type edgesInterfaceGlobalID(0);
1640 LO id=0;
1641 for(int i=0; i< this->edgeElements_->numberElements(); i++){
1642 if(this->edgeElements_->getElement(i).isInterfaceElement() ){
1643 this->edgeElements_->setElementsOfEdgeLocalEntry(i,-1);
1644 edgesInterfaceGlobalID.push_back(this->edgeMap_->getGlobalElement(i)); // extracting the global IDs of the new interfaceEdges
1645 }
1646
1647 }
1648
1649 // communticating elements across interface
1650 Teuchos::ArrayView<GO> edgesInterfaceGlobalID_ = Teuchos::arrayViewFromVector( edgesInterfaceGlobalID);
1651
1652 MapPtr_Type mapGlobalInterface =
1653 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), edgesInterfaceGlobalID_, 0, this->comm_) );
1654 //mapGlobalInterface->print();
1655
1656 // Global IDs of Procs
1657 // Setting newPoints as to be communicated Values
1658 MultiVectorLOPtr_Type interfaceElements = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterface, 1 ) );
1659 Teuchos::ArrayRCP< LO > interfaceElementsEntries = interfaceElements->getDataNonConst(0);
1660
1661 for(int i=0; i< interfaceElementsEntries.size() ; i++){
1662 interfaceElementsEntries[i] = this->edgeElements_->getElementsOfEdgeGlobal(this->edgeMap_->getLocalElement(edgesInterfaceGlobalID[i])).at(0);
1663 }
1664
1665 MapConstPtr_Type mapGlobalInterfaceUnique = mapGlobalInterface->buildUniqueMap( this->rankRange_ );
1666
1667 MultiVectorLOPtr_Type isInterfaceElement_imp = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterfaceUnique, 1 ) );
1668 isInterfaceElement_imp->putScalar( (LO) 0 );
1669 isInterfaceElement_imp->importFromVector( interfaceElements, false, "Insert");
1670
1671 MultiVectorLOPtr_Type isInterfaceElement_exp = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterfaceUnique, 1 ) );
1672 isInterfaceElement_exp->putScalar( (LO) 0 );
1673 isInterfaceElement_exp->exportFromVector( interfaceElements, false, "Insert");
1674
1675 MultiVectorLOPtr_Type isInterfaceElement2_imp = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterface, 1 ) );
1676 isInterfaceElement2_imp->putScalar( (LO) 0 );
1677 isInterfaceElement2_imp->importFromVector(isInterfaceElement_imp, false, "Insert");
1678
1679 isInterfaceElement2_imp->exportFromVector(isInterfaceElement_exp, false, "Insert");
1680
1681 interfaceElementsEntries = isInterfaceElement2_imp->getDataNonConst(0);
1682
1683 for(int i=0; i< interfaceElementsEntries.size() ; i++){
1684 this->edgeElements_->setElementsOfEdgeGlobalEntry(this->edgeMap_->getLocalElement(edgesInterfaceGlobalID[i]),interfaceElementsEntries[i]);
1685 }
1686
1687 }
1688
1689 // Contrary to the 2D case in 3D an edge can be part of more than two elements
1690 // We need to determine how many elements are connected to an edge and import the global IDs from different Processors
1691 if(maxRank >0 && this->dim_ == 3){
1692
1693 // First we determine the interface edges, which entries in elementsOfEdgesGlobal/Local have to be completed
1694 vec_GO_Type edgesInterfaceGlobalID(0);
1695 vec_int_Type numberElements(0); // represents number of elements the edge is connected to on my Processor
1696
1697 for(int i=0; i< this->edgeElements_->numberElements(); i++){
1698 if(this->edgeElements_->getElement(i).isInterfaceElement() ){
1699 edgesInterfaceGlobalID.push_back(this->edgeMap_->getGlobalElement(i)); // extracting the global IDs of the new interfaceEdges
1700 }
1701 }
1702 sort(edgesInterfaceGlobalID.begin(), edgesInterfaceGlobalID.end());
1703
1704 for(int i=0; i< edgesInterfaceGlobalID.size(); i++){
1705 numberElements.push_back(this->edgeElements_->getElementsOfEdgeGlobal(this->edgeMap_->getLocalElement(edgesInterfaceGlobalID[i])).size());
1706 }
1707
1708
1709 // from this we build a map
1710 Teuchos::ArrayView<GO> edgesInterfaceGlobalID_ = Teuchos::arrayViewFromVector( edgesInterfaceGlobalID);
1711
1712 MapPtr_Type mapGlobalInterface =
1713 Teuchos::rcp( new Map_Type(Teuchos::OrdinalTraits<GO>::invalid(), edgesInterfaceGlobalID_, 0, this->comm_) );
1714
1715 // As edges can be part of multiple elements on different processors we collect the number of elements connected to the edge in total
1716 MultiVectorLOPtr_Type numberInterfaceElements = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterface, 1 ) );
1717 Teuchos::ArrayRCP< LO > numberInterfaceElementsEntries = numberInterfaceElements->getDataNonConst(0);
1718
1719 for(int i=0; i< numberInterfaceElementsEntries.size(); i++)
1720 numberInterfaceElementsEntries[i] = numberElements[i];
1721
1722 MapConstPtr_Type mapGlobalInterfaceUnique = mapGlobalInterface->buildUniqueMap( this->rankRange_ );
1723
1724 // Element are unique to each processor. This means that the number we collect is the number of elements that are connected to my edge on other processors.
1725 // With the following communication we add up all the entries for a certain global Edge ID
1726 // Potential causes of error:
1727 // - if an edge is not identified as an interface edge, of course it will not import nor export its interface Information, making itself and others incomplete
1728
1729 MultiVectorLOPtr_Type isInterfaceElement_exp = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterfaceUnique, 1 ) );
1730 isInterfaceElement_exp->putScalar( (LO) 0 );
1731 isInterfaceElement_exp->exportFromVector( numberInterfaceElements, false, "Add");
1732
1733 MultiVectorLOPtr_Type isInterfaceElement2_imp = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterface, 1 ) );
1734 isInterfaceElement2_imp->putScalar( (LO) 0 );
1735 isInterfaceElement2_imp->importFromVector(isInterfaceElement_exp, true, "Insert");
1736
1737 Teuchos::ArrayRCP< LO > numberInterfaceElementsImportEntries = isInterfaceElement2_imp->getDataNonConst(0);
1738
1739 vec_int_Type missingEntries(numberInterfaceElementsEntries.size());
1740 // With this number we can complete the elementsOfEdgeLocal List with -1 for the elements not on our processor
1741 for(int i=0; i<numberInterfaceElementsEntries.size() ; i++){
1742 for(int j=0; j< numberInterfaceElementsImportEntries[i] - numberInterfaceElementsEntries[i];j++){
1743 this->edgeElements_->setElementsOfEdgeLocalEntry(this->edgeMap_->getLocalElement(edgesInterfaceGlobalID[i]),-1);
1744 missingEntries[i] = numberInterfaceElementsImportEntries[i] -numberInterfaceElementsEntries[i];
1745 }
1746 }
1747
1748 // Next we need to identify the global Element IDs of those missing entries and communicate them
1749 // Hey i got the global Elements ... of edge ... -> exchange
1750 // Elements are uniquely distributed -> you cannot import an element you already have
1751 // I need x number of entries -> import all i need, export all i have
1752 // Global IDs of Procs
1753 // Setting newPoints as to be communicated Values
1754
1755 // Communicating max number of necessary values:
1756 vec_int_Type::iterator it;
1757 it = max_element(numberElements.begin(), numberElements.end());
1758 int myNumberElementsMax = numberElements.at(distance(numberElements.begin(), it)); // accumulate(errorElement.begin(), errorElement.end(),0.0);
1759
1760 reduceAll<int, int> (*this->comm_, REDUCE_MAX, myNumberElementsMax , outArg ( myNumberElementsMax));
1761
1762 MultiVectorLOPtr_Type interfaceElements = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterface, 1 ) );
1763 Teuchos::ArrayRCP< LO > interfaceElementsEntries = interfaceElements->getDataNonConst(0);
1764
1765 vec2D_int_Type importElements(this->edgeElements_->getElementsOfEdgeGlobal().size(),vec_int_Type( 0));
1766
1767 // We extended this function to also consider the ranks. Before we would only exchange the information, but in case one processor received information from more than one processor at
1768 // the same time some of the information would get lost. Now we only send the information one processor holds to the other at the same time and move through the processor only destributing their
1769 // edgeOfElementGlobal Information in a circle like order
1770 for(int k=0; k< maxRank+1 ; k++){
1771
1772 vec_GO_Type edgesInterfaceGlobalIDProc;
1773 if(this->comm_->getRank() == k ){
1774 edgesInterfaceGlobalIDProc = edgesInterfaceGlobalID; // extracting the global IDs of the new interfaceEdges
1775 }
1776
1777
1778 // from this we build a map
1779 Teuchos::ArrayView<GO> edgesInterfaceGlobalIDProc_ = Teuchos::arrayViewFromVector( edgesInterfaceGlobalIDProc);
1780
1781 MapPtr_Type mapGlobalInterfaceProcs =
1782 Teuchos::rcp( new Map_Type( Teuchos::OrdinalTraits<GO>::invalid(), edgesInterfaceGlobalIDProc_, 0, this->comm_) );
1783
1784 for(int j=0; j< myNumberElementsMax; j++){
1785 MultiVectorLOPtr_Type interfaceElements = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterfaceProcs, 1 ) );
1786 Teuchos::ArrayRCP< LO > interfaceElementsEntries = interfaceElements->getDataNonConst(0);
1787
1788 for(int i=0; i< interfaceElementsEntries.size() ; i++){
1789 if(numberElements[i] > j && this->comm_->getRank() == k )
1790 interfaceElementsEntries[i] = this->edgeElements_->getElementsOfEdgeGlobal(this->edgeMap_->getLocalElement(edgesInterfaceGlobalID[i])).at(j);
1791 else
1792 interfaceElementsEntries[i] = -1;
1793 }
1794
1795 MultiVectorLOPtr_Type isInterfaceElement_exp = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterfaceUnique, 1 ) );
1796 isInterfaceElement_exp->putScalar( (LO) -1 );
1797 isInterfaceElement_exp->exportFromVector( interfaceElements, false, "Insert");
1798
1799 if(this->comm_->getRank() == k && mapGlobalInterfaceUnique->getNodeNumElements() > 0){
1800 Teuchos::ArrayRCP< LO > interfaceElementsEntries_exp = isInterfaceElement_exp->getDataNonConst(0);
1801 for(int i=0; i< interfaceElementsEntries_exp.size() ; i++){
1802 LO id = mapGlobalInterface->getLocalElement(mapGlobalInterfaceUnique->getGlobalElement(i));
1803 interfaceElementsEntries_exp[i] = interfaceElementsEntries[id];
1804 }
1805
1806 }
1807
1808
1809 MultiVectorLOPtr_Type isInterfaceElement2_imp = Teuchos::rcp( new MultiVectorLO_Type( mapGlobalInterface, 1 ) );
1810 isInterfaceElement2_imp->putScalar( (LO) 0 );
1811 isInterfaceElement2_imp->importFromVector(isInterfaceElement_exp, false, "Insert");
1812
1813 interfaceElementsEntries = isInterfaceElement2_imp->getDataNonConst(0);
1814
1815 for(int i=0; i< interfaceElementsEntries.size() ; i++){
1816 if(this->comm_->getRank() != k && interfaceElementsEntries[i] != -1)
1817 importElements[i].push_back( interfaceElementsEntries[i]);
1818 }
1819
1820 }
1821
1822 }
1823 for(int i=0; i< interfaceElementsEntries.size() ; i++){
1824 sort(importElements[i].begin(),importElements[i].end());
1825 importElements[i].erase( unique(importElements[i].begin(), importElements[i].end() ), importElements[i].end() );
1826 if(importElements[i].size() != missingEntries[i])
1827 std::cout << " On Processor " << this->comm_->getRank() << " uneven number for edge imported: " << importElements[i].size() << " missing " << missingEntries[i] << " " << edgesInterfaceGlobalID[i] << std::endl; // " something went wrong while updating elementsOfEdgesGlobal as the imported entries do not match the supposed number of imported entries. Please check." << std::endl;
1828 }
1829
1830 for(int i=0; i< interfaceElementsEntries.size() ; i++){
1831 for(int j=0; j < importElements[i].size(); j++){
1832 if(importElements[i][j] != -1)
1833 this->edgeElements_->setElementsOfEdgeGlobalEntry(this->edgeMap_->getLocalElement(edgesInterfaceGlobalID[i]),importElements[i][j]);
1834 }
1835 }
1836
1837 }
1838
1839}
1840
1849
1850template <class SC, class LO, class GO, class NO>
1851void RefinementFactory<SC,LO,GO,NO>::addMidpoint(EdgeElementsPtr_Type edgeElements, int edgeID){
1852
1853 int midPointInd; // indices of midpoints of edges of soon to be refined element
1854 int dim = this->dim_;
1855 vec2D_dbl_Type points2(0, vec_dbl_Type( dim )); // new Points -> depends on already existing point from previously refined neighbouring elements
1856 vec_dbl_Type point(dim); // midpoint on every edge, that will be added to points, will be added to pointsRep_
1857
1858 vec_dbl_Type P1(dim),P2(dim); // points we extract from pointsRep_ in order to determine midPoints
1859
1860 LO p1ID =edgeElements->getElement(edgeID).getNode(0);
1861 LO p2ID =edgeElements->getElement(edgeID).getNode(1);
1862 P1 = this->pointsRep_->at(p1ID);
1863 P2 = this->pointsRep_->at(p2ID);
1864
1865 for (int d=0; d<dim; d++){
1866 point[d]= ( (P1)[d] + (P2)[d] ) / 2.;
1867 }
1868 points2.push_back(point);
1869
1870 // New Flags:
1871 this->bcFlagRep_->push_back(edgeElements->getElement(edgeID).getFlag());
1872
1873 // Mittelpunkte der Kanten setzen
1874 edgeElements->setMidpoint(edgeID, this->pointsRep_->size());
1875
1876 // We have to keep in mind, that the new added points need to be maped to the associated points
1877 this->pointsRep_->insert( this->pointsRep_->end(), points2.begin(), points2.end() );
1878}
1879
1891
1892
1893template <class SC, class LO, class GO, class NO>
1894int RefinementFactory<SC,LO,GO,NO>::determineLongestEdge( EdgeElementsPtr_Type edgeElements, vec_int_Type edgeVec, vec2D_dbl_ptr_Type points){
1895 // We have to determine which edge is longer, as we use the opposite node of the longer edge for the element construction
1896 vec_dbl_Type length(edgeVec.size());
1897 vec_dbl_Type P1(this->dim_),P2(this->dim_);
1898 double maxLength=0.0;
1899 int maxEntry=0;
1900 LO p1ID,p2ID;
1901 vec2D_dbl_Type nodeInd(0,vec_dbl_Type(this->dim_+2));
1902 for(int i=0;i<edgeVec.size();i++){
1903 p1ID =edgeElements->getElement(edgeVec[i]).getNode(0);
1904 p2ID =edgeElements->getElement(edgeVec[i]).getNode(1);
1905 P1 = points->at(p1ID);
1906 P2 = points->at(p2ID);
1907 double sum=0;
1908 for(int j=0; j< P1.size();j++)
1909 sum += std::pow(P1[j]-P2[j],2);
1910
1911 length[i] = std::sqrt(sum);
1912
1913 vec2D_dbl_Type tmpN(0,vec_dbl_Type(this->dim_+1));
1914 vec_dbl_Type tagged(1,2);
1915 if(edgeElements->getElement(edgeVec[i]).isTaggedForRefinement() == true)
1916 tagged[0]=0;
1917 else if(edgeElements->getElement(edgeVec[i]).isMarkedEdge()==true)
1918 tagged[0]=1;
1919
1920 tmpN.push_back(P1);
1921 tmpN.push_back(P2);
1922 sort(tmpN.begin(),tmpN.end());
1923 tmpN[0].push_back(i);
1924 tmpN[0].push_back(length[i]);
1925 nodeInd.push_back(tmpN[0]);
1926 nodeInd[i].insert( nodeInd[i].begin(), tagged.begin(), tagged.end() );
1927 }
1928 sort(nodeInd.begin(), nodeInd.end());
1929 int lInd = nodeInd[0].size()-1;
1930 for(int i=0; i< nodeInd.size(); i++){
1931 if(nodeInd[i][lInd] > maxLength){
1932 maxLength = nodeInd[i][lInd];
1933 maxEntry= (int) nodeInd[i][lInd-1];
1934 }
1935 }
1936
1937
1938 return edgeVec[maxEntry];
1939
1940}
1941
1951template <class SC, class LO, class GO, class NO>
1952void RefinementFactory<SC,LO,GO,NO>::refineBlue(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement){
1953 if(this->dim_ == 2){
1954 // The necessary Point was already added to the nodelist
1955 // now we have to figure out, which node it is -> check the tagged edge for midpoint
1956 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement);
1957
1958 // midpoint index
1959 vec_int_Type midPointInd(0);
1960 vec_int_Type taggedEdge(0);
1961 vec_int_Type untaggedEdge(0);
1962 int oppositeNodeIndL, oppositeNodeIndS; // we need to determine the nodeIndex of the nodes opposite to the refined edges
1963
1964 for(int i=0; i<3; i++) {
1965 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
1966 midPointInd.push_back(edgeElements->getMidpoint(edgeNumbers[i]));
1967 taggedEdge.push_back(edgeNumbers[i]);
1968 }
1969 else
1970 untaggedEdge.push_back(edgeNumbers[i]);
1971 }
1972
1973 // We have to determine which edge is longer, as we use the opposite node of the longer edge for the element construction
1974 double length1, length2;
1975 int edgeIndexL=0; // index of the longer tagged edge in 'taggedEdge'
1976 int edgeIndexS=1; // index of the shorter tagged edge
1977 vec_dbl_Type P1(2),P2(2);
1978 LO p1ID =edgeElements->getElement(taggedEdge[0]).getNode(0);
1979 LO p2ID =edgeElements->getElement(taggedEdge[0]).getNode(1);
1980 P1 = this->pointsRep_->at(p1ID);
1981 P2 = this->pointsRep_->at(p2ID);
1982 length1 = std::sqrt(std::pow(P1[0]-P2[0],2)+std::pow(P1[1]-P2[1],2));
1983
1984 p1ID =edgeElements->getElement(taggedEdge[1]).getNode(0);
1985 p2ID =edgeElements->getElement(taggedEdge[1]).getNode(1);
1986 P1 = this->pointsRep_->at(p1ID);
1987 P2 = this->pointsRep_->at(p2ID);
1988 length2 = std::sqrt(std::pow(P1[0]-P2[0],2)+std::pow(P1[1]-P2[1],2));
1989
1990 if(length1 <= length2){
1991 edgeIndexL=1;
1992 edgeIndexS=0;
1993 }
1994
1995 // Determine opposite node of the longer Edge
1996 for(int i=0;i<3; i++){
1997 if(edgeNumbers[i] != taggedEdge[edgeIndexL]){
1998 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(taggedEdge[edgeIndexL]).getNode(0))
1999 oppositeNodeIndL = edgeElements->getElement(edgeNumbers[i]).getNode(1);
2000
2001 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(taggedEdge[edgeIndexL]).getNode(1))
2002 oppositeNodeIndL = edgeElements->getElement(edgeNumbers[i]).getNode(0);
2003
2004 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(taggedEdge[edgeIndexL]).getNode(1))
2005 oppositeNodeIndL = edgeElements->getElement(edgeNumbers[i]).getNode(1);
2006
2007 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(taggedEdge[edgeIndexL]).getNode(0))
2008 oppositeNodeIndL = edgeElements->getElement(edgeNumbers[i]).getNode(0);
2009
2010 i=2;
2011 }
2012 }
2013
2014 // Determine opposite node of the shorter Edge
2015 for(int i=0;i<3; i++){
2016 if(edgeNumbers[i] != taggedEdge[edgeIndexS]){
2017 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(taggedEdge[edgeIndexS]).getNode(0))
2018 oppositeNodeIndS = edgeElements->getElement(edgeNumbers[i]).getNode(1);
2019
2020 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(taggedEdge[edgeIndexS]).getNode(1))
2021 oppositeNodeIndS = edgeElements->getElement(edgeNumbers[i]).getNode(0);
2022
2023 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(taggedEdge[edgeIndexS]).getNode(1))
2024 oppositeNodeIndS = edgeElements->getElement(edgeNumbers[i]).getNode(1);
2025
2026 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(taggedEdge[edgeIndexS]).getNode(0))
2027 oppositeNodeIndS = edgeElements->getElement(edgeNumbers[i]).getNode(0);
2028
2029 i=2;
2030 }
2031 }
2032
2033 // Mutal Node of the two tagged edges
2034 int mutalNode;
2035 if(edgeElements->getElement(taggedEdge[0]).getNode(0) == edgeElements->getElement(taggedEdge[1]).getNode(0))
2036 mutalNode= edgeElements->getElement(taggedEdge[1]).getNode(0);
2037
2038 if(edgeElements->getElement(taggedEdge[0]).getNode(1) == edgeElements->getElement(taggedEdge[1]).getNode(1))
2039 mutalNode= edgeElements->getElement(taggedEdge[1]).getNode(1);
2040
2041 if(edgeElements->getElement(taggedEdge[0]).getNode(0) == edgeElements->getElement(taggedEdge[1]).getNode(1))
2042 mutalNode= edgeElements->getElement(taggedEdge[1]).getNode(1);
2043
2044 if(edgeElements->getElement(taggedEdge[0]).getNode(1) == edgeElements->getElement(taggedEdge[1]).getNode(0))
2045 mutalNode= edgeElements->getElement(taggedEdge[1]).getNode(0);
2046
2047
2048
2049 vec2D_int_Type newElements(3, vec_int_Type( 0 )); // vector for the new elements
2050 vec2D_int_Type newEdges(9,vec_int_Type(0)); // vector for the new edges
2051 vec_int_Type edgeFlags(9); // vector for the new flags
2052 vec2D_LO_Type markedPoints(0);
2053
2054 vec_bool_Type isInterfaceEdge(9);
2055 vec_GO_Type predecessorElement(9);;
2056 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
2057
2058 // Element 1
2059 (newElements)[0]={oppositeNodeIndL,midPointInd[edgeIndexL],midPointInd[edgeIndexS]};
2060
2061 (newEdges)[0] = {oppositeNodeIndL ,midPointInd[edgeIndexL]};
2062 (newEdges)[1] = {oppositeNodeIndL,midPointInd[edgeIndexS]};
2063 (newEdges)[2] = {midPointInd[edgeIndexL] ,midPointInd[edgeIndexS]};
2064
2065 edgeFlags[0]=this->volumeID_;
2066 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[edgeIndexS]);
2067 edgeFlags[2]=this->volumeID_;
2068
2069 isInterfaceEdge[0] = false;
2070 isInterfaceEdge[1] = edgeElements->getElement(taggedEdge[edgeIndexS]).isInterfaceElement();
2071 isInterfaceEdge[2] = false;
2072
2073 predecessorElement[0] = -1;
2074 predecessorElement[1] = this->edgeMap_->getGlobalElement(taggedEdge[edgeIndexS]);
2075 predecessorElement[2] = -1;
2076
2077
2078 // Element 2
2079 newElements[1]={oppositeNodeIndL,midPointInd[edgeIndexL],oppositeNodeIndS};
2080
2081 (newEdges)[3] = {oppositeNodeIndL ,midPointInd[edgeIndexL]};
2082 (newEdges)[4] = {oppositeNodeIndL ,oppositeNodeIndS};
2083 (newEdges)[5] = {midPointInd[edgeIndexL] ,oppositeNodeIndS};
2084
2085
2086 edgeFlags[3]=this->volumeID_;
2087 edgeFlags[4]=edgeElements->getElement(untaggedEdge[0]).getFlag();
2088 edgeFlags[5]=this->bcFlagRep_->at(midPointInd[edgeIndexL]);
2089
2090 isInterfaceEdge[3] = false;
2091 isInterfaceEdge[4] = edgeElements->getElement(untaggedEdge[0]).isInterfaceElement();
2092 isInterfaceEdge[5] = edgeElements->getElement(taggedEdge[edgeIndexL]).isInterfaceElement();;
2093
2094 predecessorElement[3] = -1;
2095 predecessorElement[4] = this->edgeMap_->getGlobalElement(untaggedEdge[0]);
2096 predecessorElement[5] = this->edgeMap_->getGlobalElement(taggedEdge[edgeIndexL]);
2097
2098
2099 // Element 3
2100 (newElements)[2]={midPointInd[edgeIndexL] , midPointInd[edgeIndexS] ,mutalNode};
2101
2102 (newEdges)[6] = {midPointInd[edgeIndexL] ,midPointInd[edgeIndexS]};
2103 (newEdges)[7] = {midPointInd[edgeIndexL] ,mutalNode};
2104 (newEdges)[8] = {midPointInd[edgeIndexS] ,mutalNode};
2105
2106 edgeFlags[6]=this->volumeID_;
2107 edgeFlags[7]=this->bcFlagRep_->at(midPointInd[edgeIndexL]);
2108 edgeFlags[8]=this->bcFlagRep_->at(midPointInd[edgeIndexS]);
2109
2110 isInterfaceEdge[6] = false;
2111 isInterfaceEdge[7] = edgeElements->getElement(taggedEdge[edgeIndexL]).isInterfaceElement();
2112 isInterfaceEdge[8] = edgeElements->getElement(taggedEdge[edgeIndexS]).isInterfaceElement();;
2113
2114 predecessorElement[6] = -1;
2115 predecessorElement[7] = this->edgeMap_->getGlobalElement(taggedEdge[edgeIndexL]);
2116 predecessorElement[8] = this->edgeMap_->getGlobalElement(taggedEdge[edgeIndexS]);
2117
2118
2119 int offsetElements = this->elementsC_->numberElements();
2120 int offsetEdges = this->edgeElements_->numberElements();
2121
2122 for( int i=0;i<3; i++){
2123 sort( newElements.at(i).begin(), newElements.at(i).end() );
2124 FiniteElement feNew(newElements.at(i),this->volumeID_);
2125 feNew.setFiniteElementRefinementType("blue");
2126 feNew.setPredecessorElement(indexElement);
2127 if(i<2)
2128 this->elementsC_->addElement(feNew);
2129 else
2130 this->elementsC_->switchElement(indexElement,feNew);
2131 }
2132
2133 // Kanten hinzufügen
2134 for( int i=0;i<9; i++){
2135 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
2136 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
2137 feNew.setInterfaceElement(isInterfaceEdge[i]);
2138 feNew.setPredecessorElement(predecessorElement[i]);
2139 if(i<6){
2140 this->edgeElements_->addEdge(feNew,i/3+offsetElements);
2141 if(edgeFlags[i]!=0 && edgeFlags[i]!=this->volumeID_){
2142 if ( !this->elementsC_->getElement(i/3+offsetElements).subElementsInitialized() )
2143 this->elementsC_->getElement(i/3+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
2144 this->elementsC_->getElement(i/3+offsetElements).addSubElement(feNew);
2145
2146 }
2147 }
2148 else{
2149 this->edgeElements_->addEdge(feNew,indexElement);
2150 if(edgeFlags[i]!=0 && edgeFlags[i]!=this->volumeID_){
2151 if ( !this->elementsC_->getElement(indexElement).subElementsInitialized() )
2152 this->elementsC_->getElement(indexElement).initializeSubElements( this->FEType_, this->dim_ -1) ;
2153 this->elementsC_->getElement(indexElement).addSubElement(feNew); }
2154
2155 }
2156 }
2157
2158 }
2159
2160 else if(this->dim_ == 3){
2161 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "3D Algorithm for irregular MeshRefinement is currently not available, please choose uniform Refinement");
2162 }
2163
2164
2165
2166}
2167
2176
2177template <class SC, class LO, class GO, class NO>
2178void RefinementFactory<SC,LO,GO,NO>::refineGreen(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement){
2179
2180 if(this->dim_ == 2){
2181 // The necessary Point was already added to the nodelist
2182 // now we have to figure out, which node it is -> check the tagged edge for midpoint
2183 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement);
2184
2185 // midpoint index
2186 int midPointInd;
2187 // Id of tagged Edge (id in edgenumbers)
2188 int taggedEdgeId;
2189 // Actual Id of edge (id in Edgelist)
2190 int taggedEdge;
2191 int oppositeNodeInd; // nodeInd of node opposite to tagged edge
2192 vec_int_Type sortedEdges(0); // Sorting the edges in edgeNumers as follows: {taggedEdge, untaggedEdge1, untaggedEdge2}
2193
2194 // Extracting midPoint Ind
2195 for(int i=0; i<3; i++) {
2196 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
2197 midPointInd = edgeElements->getMidpoint(edgeNumbers[i]);
2198 taggedEdgeId = i;
2199 taggedEdge = edgeNumbers[i];
2200 sortedEdges.push_back(edgeNumbers[i]); // tagged edge first to sortedEdges
2201 }
2202 }
2203
2204 // Determine opposite node of tagged edge
2205 for(int i=0;i<3; i++){
2206 if(edgeNumbers[i] != taggedEdge){
2207 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(taggedEdge).getNode(0))
2208 oppositeNodeInd = edgeElements->getElement(edgeNumbers[i]).getNode(1);
2209
2210 else if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(taggedEdge).getNode(1))
2211 oppositeNodeInd = edgeElements->getElement(edgeNumbers[i]).getNode(0);
2212
2213 else if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(taggedEdge).getNode(1))
2214 oppositeNodeInd = edgeElements->getElement(edgeNumbers[i]).getNode(1);
2215
2216 else if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(taggedEdge).getNode(0))
2217 oppositeNodeInd = edgeElements->getElement(edgeNumbers[i]).getNode(0);
2218
2219 i=2;
2220 }
2221 }
2222
2223 for(int i=0; i<3 ; i++){
2224 if(i != taggedEdgeId )
2225 sortedEdges.push_back(edgeNumbers[i]);
2226 }
2227
2228
2229 // adding Elements and Edges
2230 vec2D_int_Type newElements(2, vec_int_Type( 0 )); // vector for the new elements
2231 vec2D_int_Type newEdges(6,vec_int_Type(0)); // vector for the new edges
2232 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
2233 vec_int_Type edgeFlags(6); // vector for the new flags
2234 vec2D_LO_Type markedPoints(0);
2235
2236 vec_bool_Type isInterfaceEdge(6);
2237 vec_GO_Type predecessorElement(6);
2238
2239 // Element 1
2240 (newElements)[0]={midPointInd, edgeElements->getElement(sortedEdges[1]).getNode(0), edgeElements->getElement(sortedEdges[1]).getNode(1)};
2241
2242 (newEdges)[0] = {midPointInd, edgeElements->getElement(sortedEdges[1]).getNode(0)};
2243 (newEdges)[1] = {midPointInd, edgeElements->getElement(sortedEdges[1]).getNode(1)};
2244 (newEdges)[2] = {edgeElements->getElement(sortedEdges[1]).getNode(0) ,edgeElements->getElement(sortedEdges[1]).getNode(1) };
2245
2246 if(oppositeNodeInd == edgeElements->getElement(sortedEdges[1]).getNode(0)){
2247 edgeFlags[0]=this->volumeID_;
2248 isInterfaceEdge[0] = false;
2249 predecessorElement[0] = -1;
2250 }
2251 else {
2252 edgeFlags[0]=this->bcFlagRep_->at(midPointInd);
2253 isInterfaceEdge[0] = edgeElements->getElement(taggedEdge).isInterfaceElement();
2254 predecessorElement[0] = this->edgeMap_->getGlobalElement(taggedEdge);
2255 }
2256
2257 if(oppositeNodeInd == edgeElements->getElement(sortedEdges[1]).getNode(1)){
2258 edgeFlags[1]=this->volumeID_;
2259 isInterfaceEdge[1] = false;
2260 predecessorElement[1] = -1;
2261 }
2262 else {
2263 edgeFlags[1]=this->bcFlagRep_->at(midPointInd);
2264 isInterfaceEdge[1] = edgeElements->getElement(taggedEdge).isInterfaceElement();
2265 predecessorElement[1] = this->edgeMap_->getGlobalElement(taggedEdge);
2266 }
2267
2268 edgeFlags[2]=edgeElements->getElement(sortedEdges[1]).getFlag();
2269
2270 isInterfaceEdge[2] = edgeElements->getElement(sortedEdges[1]).isInterfaceElement();
2271
2272 predecessorElement[2] = this->edgeMap_->getGlobalElement(sortedEdges[1]);
2273
2274 // Element 2
2275 (newElements)[1]={midPointInd, edgeElements->getElement(sortedEdges[2]).getNode(0), edgeElements->getElement(sortedEdges[2]).getNode(1)};
2276
2277 (newEdges)[3] = {midPointInd, edgeElements->getElement(sortedEdges[2]).getNode(0)};
2278 (newEdges)[4] = {midPointInd, edgeElements->getElement(sortedEdges[2]).getNode(1)};
2279 (newEdges)[5] = {edgeElements->getElement(sortedEdges[2]).getNode(0) ,edgeElements->getElement(sortedEdges[2]).getNode(1) };
2280
2281 if(oppositeNodeInd == edgeElements->getElement(sortedEdges[2]).getNode(0)){
2282 edgeFlags[3]=this->volumeID_;
2283 isInterfaceEdge[3] = false;
2284 predecessorElement[3] = -1;
2285
2286 }
2287 else {
2288 edgeFlags[3]=this->bcFlagRep_->at(midPointInd);
2289 isInterfaceEdge[3] = edgeElements->getElement(taggedEdge).isInterfaceElement();
2290 predecessorElement[3] = this->edgeMap_->getGlobalElement(taggedEdge);
2291 }
2292
2293 if(oppositeNodeInd == edgeElements->getElement(sortedEdges[2]).getNode(1)){
2294 edgeFlags[4]=this->volumeID_;
2295 isInterfaceEdge[4] = false;
2296 predecessorElement[4] =-1;
2297 }
2298 else {
2299 edgeFlags[4]=this->bcFlagRep_->at(midPointInd);
2300 isInterfaceEdge[4] = edgeElements->getElement(taggedEdge).isInterfaceElement();
2301 predecessorElement[4] = this->edgeMap_->getGlobalElement(taggedEdge);
2302 }
2303
2304 edgeFlags[5]=edgeElements->getElement(sortedEdges[2]).getFlag();
2305
2306 isInterfaceEdge[5] = edgeElements->getElement(sortedEdges[2]).isInterfaceElement();
2307
2308 predecessorElement[5] = this->edgeMap_->getGlobalElement(sortedEdges[2]);
2309
2310 // We add one element and switch one element with the element 'indexElement'
2311 int offsetElements = this->elementsC_->numberElements(); // for determining which edge corresponds to which element
2312 int offsetEdges = this->edgeElements_->numberElements(); // just for printing
2313
2314 for( int i=0;i<2; i++){
2315 sort( newElements.at(i).begin(), newElements.at(i).end() );
2316 FiniteElement feNew(newElements.at(i),this->volumeID_);
2317 feNew.setFiniteElementRefinementType("green"); // setting green refinement type in order to check in following refinement stages
2318 feNew.setPredecessorElement(indexElement);
2319 if(i==0)
2320 this->elementsC_->addElement(feNew);
2321 else
2322 this->elementsC_->switchElement(indexElement,feNew);
2323 }
2324
2325 // add edges
2326 for( int i=0;i<6; i++){
2327 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
2328 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
2329 feNew.setInterfaceElement(isInterfaceEdge[i]);
2330 feNew.setPredecessorElement(predecessorElement[i]);
2331 if(i<3){
2332 this->edgeElements_->addEdge(feNew,offsetElements);
2333 if(edgeFlags[i]!=0 && edgeFlags[i]!=this->volumeID_){
2334 if ( !this->elementsC_->getElement(offsetElements).subElementsInitialized() )
2335 this->elementsC_->getElement(offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
2336 this->elementsC_->getElement(offsetElements).addSubElement(feNew);
2337 }
2338 }
2339 else{
2340 this->edgeElements_->addEdge(feNew,indexElement);
2341 if(edgeFlags[i]!=0 && edgeFlags[i]!=this->volumeID_){
2342 if ( !this->elementsC_->getElement(indexElement).subElementsInitialized() )
2343 this->elementsC_->getElement(indexElement).initializeSubElements( this->FEType_, this->dim_ -1) ;
2344 this->elementsC_->getElement(indexElement).addSubElement(feNew);
2345 }
2346 }
2347 }
2348 }
2349
2350 else if(this->dim_ == 3){
2351 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "3D Algorithm for irregular MeshRefinement is currently not available, please choose uniform Refinement");
2352 }
2353
2354
2355
2356}
2357
2366
2367template <class SC, class LO, class GO, class NO>
2368void RefinementFactory<SC,LO,GO,NO>::refineRed(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement){
2369
2370 if(this->dim_ == 2){
2371
2372 // The necessary Point was already added to the nodelist
2373 // now we have to figure out, which node it is -> check the tagged edge for midpoint
2374 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement);
2375
2376 // midpoint index
2377 vec_int_Type midPointInd(3);
2378
2379 for(int i=0; i<3; i++)
2380 midPointInd[i] = edgeElements->getMidpoint(edgeNumbers[i]);
2381
2382 // -> Edge 1: midPoint[0] - mutualNode[0] = mutualNode of Edge 1 and 2
2383 // -> Edge 2: midPoint[1] - mutualNode[1] = mutualNode of Edge 1 and 3
2384 // -> Edge 3: midpoint[3] - mutualNode[2] = mutualNode of Edge 2 and 3
2385 // Mutal Node of two edges
2386 vec_int_Type mutualNode(3);
2387 int ind=0;
2388 for(int i=0;i<2; i++){
2389 for(int j=1;j+i<3;j++){
2390 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(edgeNumbers[j+i]).getNode(0))
2391 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(0);
2392
2393 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(edgeNumbers[j+i]).getNode(1))
2394 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(1);
2395
2396 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(edgeNumbers[j+i]).getNode(1))
2397 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(1);
2398
2399 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(edgeNumbers[j+i]).getNode(0))
2400 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(0);
2401
2402 ind++;
2403 }
2404 }
2405
2406 // Adding Elements and the corresponding Edges
2407 vec2D_int_Type newElements(4, vec_int_Type( 0 )); // vector for the new elements
2408 vec2D_int_Type newEdges(12,vec_int_Type(0)); // vector for the new edges
2409 vec_int_Type edgeFlags(12); // vector for the new flags
2410 vec_bool_Type isInterfaceEdge(12); // bool vectot for interfaceEdges
2411 vec_GO_Type predecessorElement(12);
2412 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
2413
2414 // Element 1
2415 (newElements)[0]={mutualNode[0],midPointInd[0],midPointInd[1]};
2416
2417 (newEdges)[0] = {mutualNode[0] ,midPointInd[0]};
2418 (newEdges)[1] = {mutualNode[0] ,midPointInd[1]};
2419 (newEdges)[2] = {midPointInd[0] ,midPointInd[1]};
2420
2421 edgeFlags[0]=this->bcFlagRep_->at(midPointInd[0]);
2422 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[1]);
2423 edgeFlags[2]=this->volumeID_;
2424
2425 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
2426 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
2427 isInterfaceEdge[2] = false;
2428
2429 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
2430 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
2431 predecessorElement[2] = -1;
2432
2433 // Element 2
2434 newElements[1]={mutualNode[1],midPointInd[0],midPointInd[2]};
2435
2436 (newEdges)[3] = {mutualNode[1] ,midPointInd[0]};
2437 (newEdges)[4] = {mutualNode[1] ,midPointInd[2]};
2438 (newEdges)[5] = {midPointInd[0] ,midPointInd[2]};
2439
2440 edgeFlags[3]=this->bcFlagRep_->at(midPointInd[0]);
2441 edgeFlags[4]=this->bcFlagRep_->at(midPointInd[2]);
2442 edgeFlags[5]=this->volumeID_;
2443
2444 isInterfaceEdge[3] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
2445 isInterfaceEdge[4] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
2446 isInterfaceEdge[5] = false;
2447
2448 predecessorElement[3] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
2449 predecessorElement[4] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
2450 predecessorElement[5] = -1;
2451
2452 // Element 3
2453 (newElements)[2]={mutualNode[2] , midPointInd[1] ,midPointInd[2]};
2454
2455 (newEdges)[6] = {mutualNode[2] ,midPointInd[1]};
2456 (newEdges)[7] = {mutualNode[2] ,midPointInd[2]};
2457 (newEdges)[8] = {midPointInd[1] ,midPointInd[2]};
2458
2459 edgeFlags[6]=this->bcFlagRep_->at(midPointInd[1]);
2460 edgeFlags[7]=this->bcFlagRep_->at(midPointInd[2]);
2461 edgeFlags[8]=this->volumeID_;
2462
2463 isInterfaceEdge[6] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
2464 isInterfaceEdge[7] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
2465 isInterfaceEdge[8] = false;
2466
2467 predecessorElement[6] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
2468 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
2469 predecessorElement[8] = -1;
2470 // Element 4
2471 (newElements)[3]={midPointInd[0],midPointInd[1],midPointInd[2]};
2472
2473 (newEdges)[9] = {midPointInd[0] ,midPointInd[1]};
2474 (newEdges)[10] = {midPointInd[1] ,midPointInd[2]};
2475 (newEdges)[11] = {midPointInd[2] ,midPointInd[0]};
2476
2477 edgeFlags[9]=this->volumeID_;
2478 edgeFlags[10]=this->volumeID_;
2479 edgeFlags[11]=this->volumeID_;
2480
2481 isInterfaceEdge[9] = false;
2482 isInterfaceEdge[10] = false;
2483 isInterfaceEdge[11] = false;
2484
2485 predecessorElement[9] = -1;
2486 predecessorElement[10] = -1;
2487 predecessorElement[11] = -1;
2488
2489 int offsetElements = this->elementsC_->numberElements();
2490 int offsetEdges = this->edgeElements_->numberElements();
2491 for( int i=0;i<4; i++){
2492 sort( newElements.at(i).begin(), newElements.at(i).end() );
2493 FiniteElement feNew(newElements.at(i),0);
2494 feNew.setFiniteElementRefinementType("red");
2495 feNew.setPredecessorElement(indexElement);
2496 if(i<3)
2497 this->elementsC_->addElement(feNew);
2498 else
2499 this->elementsC_->switchElement(indexElement,feNew);
2500 }
2501
2502 for( int i=0;i<12; i++){
2503 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
2504 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
2505 feNew.setInterfaceElement(isInterfaceEdge[i]);
2506 feNew.setPredecessorElement(predecessorElement[i]);
2507 if(i<9){
2508 this->edgeElements_->addEdge(feNew,i/3+offsetElements);
2509 if(edgeFlags[i]!=0 && edgeFlags[i]!=this->volumeID_){
2510 if ( !this->elementsC_->getElement(i/3+offsetElements).subElementsInitialized() )
2511 this->elementsC_->getElement(i/3+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
2512 this->elementsC_->getElement(i/3+offsetElements).addSubElement(feNew);
2513 }
2514 }
2515 else
2516 this->edgeElements_->addEdge(feNew,indexElement);
2517
2518 }
2519 }
2520 else
2521 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The red irregular Refinement Method you requested is only applicable to a 2 dimensional Mesh.");
2522
2523}
2524
2535
2536template <class SC, class LO, class GO, class NO>
2537void RefinementFactory<SC,LO,GO,NO>::refineType4(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements){
2538
2539// Implementation of Type (4) Refinement Type
2540// We use this Refinement Type
2541 if(this->dim_ == 3){
2542
2543 // The way we refine the Tetrahedron is defined by how we order the nodes of the tetrahedron
2544 // (For the algorithm see "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refinement' in Computing, Springer Verlag 1955)
2545
2546 vec_int_Type midPointInd( 0 ); // indices of midpoints of edges of soon to be refined element
2547 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
2548 vec_int_Type edgeNumbersUntagged(0);
2549
2550 // We sort the node as follows:
2551 // In this refinement type both tagged edges don't share a common node thus we add the nodes of the first edge, then the second and order them per edge
2552 vec_int_Type nodeInd1(0);
2553 vec_int_Type nodeInd2(0);
2554 bool firstEdge = true;
2555 for(int i=0; i<6; i++){
2556
2557 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement() && firstEdge ==false){
2558 nodeInd2.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(0));
2559 nodeInd2.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(1));
2560 }
2561
2562 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement() && firstEdge == true){
2563 nodeInd1.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(0));
2564 nodeInd1.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(1));
2565 firstEdge=false;
2566 }
2567
2568 }
2569 sort( nodeInd1.begin(), nodeInd1.end() );
2570 sort( nodeInd2.begin(), nodeInd2.end() );
2571
2572 vec_int_Type nodeInd = {nodeInd1[0],nodeInd1[1],nodeInd2[0],nodeInd2[1]};
2573
2574 // We don't need to sort the nodes in any other way then we already did, as there is not more than one possibility to construct the subtetrahera in refinement type 3
2575
2576 // With our sorted Nodes we construct edges as follows
2577 // Edge_0 = [x_0,x_1]
2578 // Edge_1 = [x_0,x_2]
2579 // Edge_2 = [x_0,x_3]
2580 // Edge_3 = [x_1,x_2]
2581 // Edge_4 = [x_1,x_3]
2582 // Edge_5 = [x_2,x_3]
2583
2584 vec_int_Type edgeNumbersTmp = edgeNumbers;
2585 for(int i=0; i<6; i++){
2586 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[0] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[0]){
2587 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1])
2588 edgeNumbers[0] = edgeNumbersTmp[i];
2589 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
2590 edgeNumbers[1] = edgeNumbersTmp[i];
2591 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
2592 edgeNumbers[2] = edgeNumbersTmp[i];
2593 }
2594 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1]){
2595 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
2596 edgeNumbers[3] = edgeNumbersTmp[i];
2597 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
2598 edgeNumbers[4] = edgeNumbersTmp[i];
2599 }
2600 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2]){
2601 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
2602 edgeNumbers[5] = edgeNumbersTmp[i];
2603 }
2604 }
2605
2606 // We hace 4 Triangles in our Tetraedron
2607 // If one or more of those Triangles are Part of the domains' boundaries, they are added to the element in question as subelement
2608 // We extract them in follwing pattern:
2609
2610 // Tri_0 = [x_0,x_1,x_2]
2611 // Tri_1 = [x_0,x_1,x_3]
2612 // Tri_2 = [x_0,x_2,x_3]
2613 // Tri_3 = [x_1,x_2,x_3]
2614
2615
2616 // We check if one or more of these triangles are part of the boundary surface and determine there flag
2617 vec_int_Type surfaceElementsIDs = surfaceTriangleElements->getSurfacesOfElement(indexElement); // surfaces of Element k
2618 vec2D_int_Type originTriangles(4,vec_int_Type(3));
2619
2620 originTriangles[0] = {nodeInd[0], nodeInd[1], nodeInd[2] };
2621 originTriangles[1] = {nodeInd[0], nodeInd[1], nodeInd[3] };
2622 originTriangles[2] = {nodeInd[0], nodeInd[2], nodeInd[3] };
2623 originTriangles[3] = {nodeInd[1], nodeInd[2], nodeInd[3] };
2624
2625 vec_int_Type originFlag(4,this->volumeID_); // Triangle Flag
2626
2627 vec_bool_Type interfaceSurface(4);
2628 vec_LO_Type triTmp(3);
2629 vec_int_Type originTriangleTmp(3);
2630
2631 for(int i=0; i< 4 ; i++){
2632 originTriangleTmp = originTriangles[i];
2633 sort(originTriangleTmp.begin(),originTriangleTmp.end());
2634 for(int j=0; j<4 ; j++){
2635 FiniteElement surfaceTmp = surfaceTriangleElements->getElement(surfaceElementsIDs[j]);
2636 triTmp = surfaceTmp.getVectorNodeList();
2637 sort(triTmp.begin(),triTmp.end());
2638 if(triTmp[0] == originTriangleTmp[0] && triTmp[1] == originTriangleTmp[1] && triTmp[2] == originTriangleTmp[2] ) {
2639 originFlag[i] = surfaceTmp.getFlag();
2640 interfaceSurface[i] = surfaceTmp.isInterfaceElement();
2641 }
2642 }
2643 }
2644
2645 // Finally we need to determine or extract the indices of the edges midpoints. As in the describe algorithm the midpoints are set as follows:
2646 // Edge 0 = [x_0,x_1] -> x_01
2647 // Edge 1 = [x_0,x_2] -> x_02
2648 // Edge 2 = [x_0,x_3] -> x_03
2649 // Edge 3 = [x_1,x_2] -> x_12
2650 // Edge 4 = [x_1,x_3] -> x_13
2651 // Edge 5 = [x_2,x_3] -> x_23
2652
2653 for(int i=0; i<6; i++){
2654 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
2655 midPointInd.push_back(edgeElements->getMidpoint(edgeNumbers[i]));
2656 }
2657 }
2658
2659
2660
2661 // Now we construct the new Elements as proposed by Bey's Regular Refinement Algorithm
2662
2663 vec2D_int_Type newElements(4, vec_int_Type( 0 )); // new elements
2664 vec2D_int_Type newEdges(24,vec_int_Type(0)); // new edges
2665 vec2D_int_Type newTriangles(16,vec_int_Type(0)); // new Triangles
2666 vec_int_Type newTrianglesFlag(16) ; // new Triangle Flags
2667 vec_bool_Type isInterfaceSurface(16); // bool vector for interfaceSurface Information
2668 vec_int_Type edgeFlags(24); // new Edge flags
2669 vec_bool_Type isInterfaceEdge(24); // bool vector for interfaceEdge Information
2670 vec_GO_Type predecessorElement(24); // vector that stores the global IDs of the predecessor of each edge
2671
2672 vec2D_LO_Type newTriangleEdgeIDs(4,vec_LO_Type(12));
2673
2674 // How are Flags determined?
2675 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
2676 // If an edges emerges on a triangle, the flag is determined by the triangle flag. Opposite to the 2D case, edges that connect midpoints are not automatically interior edges, but are
2677 // determined by the triangle/surface they are on
2678
2679
2680 // Element 1: (x_0,x_2,x_01,x_23)
2681 (newElements)[0]={nodeInd[0],nodeInd[2], midPointInd[0],midPointInd[1]};
2682
2683 (newEdges)[0] = {nodeInd[0] ,nodeInd[2]};
2684 (newEdges)[1] = {nodeInd[0] ,midPointInd[0]};
2685 (newEdges)[2] = {nodeInd[0] ,midPointInd[1]};
2686 (newEdges)[3] = {nodeInd[2] ,midPointInd[0]};
2687 (newEdges)[4] = {nodeInd[2] ,midPointInd[1]};
2688 (newEdges)[5] = {midPointInd[0] ,midPointInd[1]};
2689
2690 edgeFlags[0]=edgeElements->getElement(edgeNumbers[1]).getFlag();
2691 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[0]);
2692 edgeFlags[2]=originFlag[2];
2693 edgeFlags[3]=originFlag[0];
2694 edgeFlags[4]=this->bcFlagRep_->at(midPointInd[1]);
2695 edgeFlags[5]=this->volumeID_;
2696
2697 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
2698 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
2699 isInterfaceEdge[2] = interfaceSurface[2];
2700 isInterfaceEdge[3] = interfaceSurface[0];
2701 isInterfaceEdge[4] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
2702 isInterfaceEdge[5] = false;
2703
2704 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
2705 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
2706 predecessorElement[2] = -1;
2707 predecessorElement[3] = -1;
2708 predecessorElement[4] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
2709 predecessorElement[5] = -1;
2710
2711 // Subelements of thetrahedron
2712 newTriangles[0]= {nodeInd[0],nodeInd[2],midPointInd[0]};
2713 newTriangles[1]= {nodeInd[0],nodeInd[2],midPointInd[1]};
2714 newTriangles[2]= {nodeInd[0],midPointInd[0],midPointInd[1]};
2715 newTriangles[3]= {nodeInd[2],midPointInd[0],midPointInd[1]};
2716
2717 newTrianglesFlag[0]= originFlag[0];
2718 newTrianglesFlag[1]= originFlag[2];
2719 newTrianglesFlag[2]= this->volumeID_;
2720 newTrianglesFlag[3]= this->volumeID_;
2721
2722 isInterfaceSurface[0]= interfaceSurface[0];
2723 isInterfaceSurface[1]= interfaceSurface[2];
2724 isInterfaceSurface[2]= false;
2725 isInterfaceSurface[3]= false;
2726
2727 newTriangleEdgeIDs[0]={0,1,3,0,2,4,1,2,5,3,4,5};
2728
2729 // Element 2: (x_1,x_2,x_01,x_23)
2730 (newElements)[1]={nodeInd[1],nodeInd[2],midPointInd[0],midPointInd[1]};
2731
2732 (newEdges)[6] = {nodeInd[1] ,nodeInd[2]};
2733 (newEdges)[7] = {nodeInd[1] ,midPointInd[0]};
2734 (newEdges)[8] = {nodeInd[1] ,midPointInd[1]};
2735 (newEdges)[9] = {nodeInd[2] ,midPointInd[0]};
2736 (newEdges)[10] = {nodeInd[2] ,midPointInd[1]};
2737 (newEdges)[11] = {midPointInd[0] ,midPointInd[1]};
2738
2739 edgeFlags[6]=edgeElements->getElement(edgeNumbers[3]).getFlag();
2740 edgeFlags[7]=edgeElements->getElement(edgeNumbers[0]).getFlag();
2741 edgeFlags[8]=originFlag[3];
2742 edgeFlags[9]=originFlag[0];
2743 edgeFlags[10]=this->bcFlagRep_->at(midPointInd[1]);
2744 edgeFlags[11]=this->volumeID_;
2745
2746 isInterfaceEdge[6] = edgeElements->getElement(edgeNumbers[3]).isInterfaceElement();
2747 isInterfaceEdge[7] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
2748 isInterfaceEdge[8] = interfaceSurface[3];
2749 isInterfaceEdge[9] = interfaceSurface[0];
2750 isInterfaceEdge[10] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
2751 isInterfaceEdge[11] = false;
2752
2753 predecessorElement[6] = this->edgeMap_->getGlobalElement(edgeNumbers[3]);
2754 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
2755 predecessorElement[8] = -1;
2756 predecessorElement[9] = -1;
2757 predecessorElement[10] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
2758 predecessorElement[11] = -1;
2759
2760 // Subelements of tetrahedron
2761 newTriangles[4]= {nodeInd[1],nodeInd[2],midPointInd[0]};
2762 newTriangles[5]= {nodeInd[1],nodeInd[2],midPointInd[1]};
2763 newTriangles[6]= {nodeInd[1],midPointInd[0],midPointInd[1]};
2764 newTriangles[7]= {nodeInd[2],midPointInd[0],midPointInd[1]};
2765
2766 newTrianglesFlag[4]= originFlag[0];
2767 newTrianglesFlag[5]= originFlag[3];
2768 newTrianglesFlag[6]= this->volumeID_;
2769 newTrianglesFlag[7]= this->volumeID_;
2770
2771 isInterfaceSurface[4]= interfaceSurface[0];
2772 isInterfaceSurface[5]= interfaceSurface[3];
2773 isInterfaceSurface[6]= false;
2774 isInterfaceSurface[7]= false;
2775
2776 newTriangleEdgeIDs[1]={6,7,9,6,8,10,7,8,11,9,10,11};
2777
2778 // Element 3: (x_0,x_3,x_01,x_23)
2779 (newElements)[2]={nodeInd[0],nodeInd[3],midPointInd[0],midPointInd[1]};
2780
2781 (newEdges)[12] = {nodeInd[0] ,nodeInd[3]};
2782 (newEdges)[13] = {nodeInd[0] ,midPointInd[0]};
2783 (newEdges)[14] = {nodeInd[0] ,midPointInd[1]};
2784 (newEdges)[15] = {nodeInd[3] ,midPointInd[0]};
2785 (newEdges)[16] = {nodeInd[3] ,midPointInd[1]};
2786 (newEdges)[17] = {midPointInd[0] ,midPointInd[1]};
2787
2788 edgeFlags[12]=edgeElements->getElement(edgeNumbers[2]).getFlag();
2789 edgeFlags[13]=edgeElements->getElement(edgeNumbers[0]).getFlag();
2790 edgeFlags[14]=originFlag[2];
2791 edgeFlags[15]=originFlag[1];
2792 edgeFlags[16]=edgeElements->getElement(edgeNumbers[5]).getFlag();;
2793 edgeFlags[17]=this->volumeID_;
2794
2795 isInterfaceEdge[12] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
2796 isInterfaceEdge[13] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
2797 isInterfaceEdge[14] = interfaceSurface[2];
2798 isInterfaceEdge[15] = interfaceSurface[1];
2799 isInterfaceEdge[16] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
2800 isInterfaceEdge[17] = false;
2801
2802 predecessorElement[12] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
2803 predecessorElement[13] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
2804 predecessorElement[14] = -1;
2805 predecessorElement[15] = -1;
2806 predecessorElement[16] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
2807 predecessorElement[17] = -1;
2808
2809 // Subelements of tetrahedron
2810 newTriangles[8]= {nodeInd[0],nodeInd[3],midPointInd[0]};
2811 newTriangles[9]= {nodeInd[0],nodeInd[3],midPointInd[1]};
2812 newTriangles[10]= {nodeInd[0],midPointInd[0],midPointInd[1]};
2813 newTriangles[11]= {nodeInd[3],midPointInd[0],midPointInd[1]};
2814
2815 newTrianglesFlag[8]= originFlag[1];
2816 newTrianglesFlag[9]= originFlag[2];
2817 newTrianglesFlag[10]= this->volumeID_;
2818 newTrianglesFlag[11]= this->volumeID_;
2819
2820 isInterfaceSurface[8]= interfaceSurface[1];
2821 isInterfaceSurface[9]= interfaceSurface[2];
2822 isInterfaceSurface[10]= false;
2823 isInterfaceSurface[11]= false;
2824
2825 newTriangleEdgeIDs[2]={8,9,11,8,10,12,9,10,13,11,12,13};
2826
2827
2828 // Element 4: (x_1,x_3,x_01,x_23)
2829 (newElements)[3]={nodeInd[1],nodeInd[3],midPointInd[0],midPointInd[1]};
2830
2831 (newEdges)[18] = {nodeInd[1] ,nodeInd[3]};
2832 (newEdges)[19] = {nodeInd[1] ,midPointInd[0]};
2833 (newEdges)[20] = {nodeInd[1] ,midPointInd[1]};
2834 (newEdges)[21] = {nodeInd[3] ,midPointInd[0]};
2835 (newEdges)[22] = {nodeInd[3] ,midPointInd[1]};
2836 (newEdges)[23] = {midPointInd[0] ,midPointInd[1]};
2837
2838 edgeFlags[18]=edgeElements->getElement(edgeNumbers[4]).getFlag();
2839 edgeFlags[19]=edgeElements->getElement(edgeNumbers[0]).getFlag();
2840 edgeFlags[20]=originFlag[3];
2841 edgeFlags[21]=originFlag[1];
2842 edgeFlags[22]=edgeElements->getElement(edgeNumbers[5]).getFlag();;
2843 edgeFlags[23]=this->volumeID_;
2844
2845 isInterfaceEdge[18] = edgeElements->getElement(edgeNumbers[4]).isInterfaceElement();
2846 isInterfaceEdge[19] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
2847 isInterfaceEdge[20] = interfaceSurface[3];
2848 isInterfaceEdge[21] = interfaceSurface[1];
2849 isInterfaceEdge[22] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
2850 isInterfaceEdge[23] = false;
2851
2852 predecessorElement[18] = this->edgeMap_->getGlobalElement(edgeNumbers[4]);
2853 predecessorElement[19] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
2854 predecessorElement[20] = -1;
2855 predecessorElement[21] = -1;
2856 predecessorElement[22] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
2857 predecessorElement[23] = -1;
2858
2859 // Subelements of tetrahedron
2860 newTriangles[12]= {nodeInd[1],nodeInd[3],midPointInd[0]};
2861 newTriangles[13]= {nodeInd[1],nodeInd[3],midPointInd[1]};
2862 newTriangles[14]= {nodeInd[1],midPointInd[0],midPointInd[1]};
2863 newTriangles[15]= {nodeInd[3],midPointInd[0],midPointInd[1]};
2864
2865 newTrianglesFlag[12]= originFlag[1];
2866 newTrianglesFlag[13]= originFlag[3];
2867 newTrianglesFlag[14]= this->volumeID_;
2868 newTrianglesFlag[15]= this->volumeID_;
2869
2870 isInterfaceSurface[12]= interfaceSurface[1];
2871 isInterfaceSurface[13]= interfaceSurface[3];
2872 isInterfaceSurface[14]= false;
2873 isInterfaceSurface[15]= false;
2874
2875 newTriangleEdgeIDs[3]={18,19,21,18,20,22,19,20,23,21,22,23};
2876
2877 // Now we add the elements, edges and triangles
2878
2879 // Adding Elements
2880 int offsetElements = this->elementsC_->numberElements();
2881 int offsetEdges = this->edgeElements_->numberElements();
2882 for( int i=0;i<4; i++){
2883 sort( newElements.at(i).begin(), newElements.at(i).end() );
2884 FiniteElement feNew(newElements.at(i),this->volumeID_);
2885 feNew.setFiniteElementRefinementType("irregular");
2886 feNew.setPredecessorElement(indexElement);
2887 if(i<3)
2888 this->elementsC_->addElement(feNew);
2889 else
2890 this->elementsC_->switchElement(indexElement,feNew);
2891 }
2892
2893 // Adding the edges (they also have to be added to triangles as subelements, but that is not implemented yet)
2894 for( int i=0;i<24; i++){
2895 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
2896 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
2897 feNew.setInterfaceElement(isInterfaceEdge[i]);
2898 feNew.setPredecessorElement(predecessorElement[i]);
2899 if(i<18){
2900 this->edgeElements_->addEdge(feNew,i/6+offsetElements);
2901 }
2902 else
2903 this->edgeElements_->addEdge(feNew,indexElement);
2904 }
2905
2906 // Adding triangles as subelements, if they arent interior triangles
2907 int offsetSurface=0;
2908 for( int i=0;i<16; i++){
2909 sort( newTriangles.at(i).begin(), newTriangles.at(i).end() );
2910 FiniteElement feNew(newTriangles[i],newTrianglesFlag[i]);
2911 feNew.setInterfaceElement(isInterfaceSurface[i]);
2912 if(i<12){
2913 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
2914 if ( !this->elementsC_->getElement(i/4+offsetElements).subElementsInitialized() )
2915 this->elementsC_->getElement(i/4+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
2916 this->elementsC_->getElement(i/4+offsetElements).addSubElement(feNew);
2917 }
2918 this->surfaceTriangleElements_->addSurface(feNew, i/4+offsetElements);
2919 }
2920 else{
2921 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
2922 if ( !this->elementsC_->getElement(indexElement).subElementsInitialized() )
2923 this->elementsC_->getElement(indexElement).initializeSubElements( this->FEType_, this->dim_ -1) ;
2924 this->elementsC_->getElement(indexElement).addSubElement(feNew);
2925 }
2926 this->surfaceTriangleElements_->addSurface(feNew, indexElement);
2927 }
2928 }
2929 FiniteElement element;
2930 FiniteElement feEdge;
2931 for( int i=0;i<4; i++){
2932 if(i<3)
2933 element = this->elementsC_->getElement(i+offsetElements);
2934 else
2935 element = this->elementsC_->getElement(indexElement);
2936 bool init=false;
2937 for(int j=0; j<24 ; j++){
2938 FiniteElement feEdge = this->edgeElements_->getElement(j+offsetEdges);
2939 if(feEdge.getFlag() != this->volumeID_){
2940 if(init == true)
2941 element.addSubElement( feEdge );
2942 else if ( !element.subElementsInitialized() ){
2943 element.initializeSubElements( "P1", 1 ); // only P1 for now
2944 element.addSubElement( feEdge );
2945 init= true;
2946 }
2947 else {
2948 ElementsPtr_Type surfaces = element.getSubElements();
2949 // We set the edge to the corresponding element(s)
2950 surfaces->setToCorrectElement( feEdge );
2951 }
2952 }
2953 }
2954 }
2955
2956 }
2957 else
2958 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The Type 4 irregular Refinement Method you requested is only applicable to a 3 dimensional Mesh. Please reconsider.");
2959
2960
2961}
2962
2972
2973template <class SC, class LO, class GO, class NO>
2974void RefinementFactory<SC,LO,GO,NO>::refineType3(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements){
2975
2976
2977// Implementation of Type (3) Refinement Type
2978// We use this Refinement Type
2979 if(this->dim_ == 3){
2980
2981 // The way we refine the Tetrahedron is defined by how we order the nodes of the tetrahedron
2982 // (For the algorithm see "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refinement' in Computing, Springer Verlag 1955)
2983
2984 vec_int_Type midPointInd(0); // indices of midpoints of edges of soon to be refined element
2985 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
2986 vec_int_Type edgeNumbersUntagged(0);
2987 // Extract the three points of tetraeder, that connect the tagged edges
2988 vec_int_Type nodeInd(0);
2989 for(int i=0; i<6; i++){
2990 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
2991 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(0));
2992 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(1));
2993 }
2994 else
2995 edgeNumbersUntagged.push_back(edgeNumbers[i]);
2996 }
2997 sort( nodeInd.begin(), nodeInd.end() );
2998 vec_int_Type nodeIndTmp = nodeInd;
2999 nodeInd.erase( unique( nodeInd.begin(), nodeInd.end() ), nodeInd.end() );
3000
3001 // We determine the common node index, this one will be placed at x_0
3002 int commonNode=-1;
3003 int entryCommonNode;
3004 vec_int_Type leftOverNodes(0);
3005 for(int i=0; i<3; i++){
3006 if(nodeIndTmp[i] == nodeIndTmp[i+1]){
3007 commonNode=nodeIndTmp[i];
3008 entryCommonNode=i;
3009 }
3010
3011 }
3012 for(int i=0; i<3; i++){
3013 if(nodeInd[i] != commonNode){
3014 leftOverNodes.push_back(nodeInd[i]);
3015 }
3016
3017 }
3018
3019 // Then we determine the longest of the tagged edges, of which the second node will be placed at x_1 and the leftover node at x_2
3020 vec_dbl_Type length(2);
3021 vec_dbl_Type P1(3),P2(3);
3022 double maxLength=0.0;
3023 int maxEntry=0;
3024 int minEntry=0;
3025 LO p1ID,p2ID;
3026 for(int i=0;i<2;i++){
3027 p1ID =commonNode;
3028 p2ID =leftOverNodes[i];
3029 P1 = this->pointsRep_->at(p1ID);
3030 P2 = this->pointsRep_->at(p2ID);
3031 length[i] = std::sqrt(std::pow(P1[0]-P2[0],2)+std::pow(P1[1]-P2[1],2)+std::pow(P1[2]-P2[2],2));
3032 if(length[i] > maxLength){
3033 maxLength = length[i];
3034 maxEntry= i;
3035 }
3036 else
3037 minEntry=i;
3038 }
3039 nodeInd[0] = commonNode;
3040 nodeInd[1] = leftOverNodes[minEntry];
3041 nodeInd[2] = leftOverNodes[maxEntry];
3042
3043 // We now have the two nodes that connect the tagged edge or rather make up the tagged edge
3044 // The left over nodes are the ones opposite to the tagged edge
3045 for(int i=0; i<4; i++){
3046 if(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(0) == nodeInd[0])
3047 nodeInd.push_back(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(1));
3048 else if(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(1) == nodeInd[0])
3049 nodeInd.push_back(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(0));
3050 }
3051
3052 // We don't need to sort the nodes in any other way then we already did, as there is not more than one possibility to construct the subtetrahera in refinement type 2
3053
3054 // With our sorted Nodes we construct edges as follows
3055 // Edge_0 = [x_0,x_1]
3056 // Edge_1 = [x_0,x_2]
3057 // Edge_2 = [x_0,x_3]
3058 // Edge_3 = [x_1,x_2]
3059 // Edge_4 = [x_1,x_3]
3060 // Edge_5 = [x_2,x_3]
3061
3062 vec_int_Type edgeNumbersTmp = edgeNumbers;
3063 for(int i=0; i<6; i++){
3064 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[0] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[0]){
3065 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1])
3066 edgeNumbers[0] = edgeNumbersTmp[i];
3067 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
3068 edgeNumbers[1] = edgeNumbersTmp[i];
3069 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3070 edgeNumbers[2] = edgeNumbersTmp[i];
3071 }
3072 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1]){
3073 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
3074 edgeNumbers[3] = edgeNumbersTmp[i];
3075 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3076 edgeNumbers[4] = edgeNumbersTmp[i];
3077 }
3078 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2]){
3079 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3080 edgeNumbers[5] = edgeNumbersTmp[i];
3081 }
3082 }
3083
3084 // We hace 4 Triangles in our Tetraedron
3085 // If one or more of those Triangles are Part of the domains' boundaries, they are added to the element in question as subelement
3086 // We extract them in follwing pattern:
3087
3088 // Tri_0 = [x_0,x_1,x_2]
3089 // Tri_1 = [x_0,x_1,x_3]
3090 // Tri_2 = [x_0,x_2,x_3]
3091 // Tri_3 = [x_1,x_2,x_3]
3092
3093
3094 // We check if one or more of these triangles are part of the boundary surface and determine there flag
3095 vec_int_Type surfaceElementsIDs = surfaceTriangleElements->getSurfacesOfElement(indexElement); // surfaces of Element k
3096 vec2D_int_Type originTriangles(4,vec_int_Type(3));
3097
3098 originTriangles[0] = {nodeInd[0], nodeInd[1], nodeInd[2] };
3099 originTriangles[1] = {nodeInd[0], nodeInd[1], nodeInd[3] };
3100 originTriangles[2] = {nodeInd[0], nodeInd[2], nodeInd[3] };
3101 originTriangles[3] = {nodeInd[1], nodeInd[2], nodeInd[3] };
3102
3103
3104
3105 vec_int_Type originFlag(4,this->volumeID_); // Triangle Flag
3106
3107 vec_bool_Type interfaceSurface(4);
3108 vec_LO_Type triTmp(3);
3109 vec_int_Type originTriangleTmp(3);
3110
3111 for(int i=0; i< 4 ; i++){
3112 originTriangleTmp = originTriangles[i];
3113 sort(originTriangleTmp.begin(),originTriangleTmp.end());
3114 for(int j=0; j<4 ; j++){
3115 FiniteElement surfaceTmp = surfaceTriangleElements->getElement(surfaceElementsIDs[j]);
3116 triTmp = surfaceTmp.getVectorNodeList();
3117 sort(triTmp.begin(),triTmp.end());
3118 if(triTmp[0] == originTriangleTmp[0] && triTmp[1] == originTriangleTmp[1] && triTmp[2] == originTriangleTmp[2] ) {
3119 originFlag[i] = surfaceTmp.getFlag();
3120 interfaceSurface[i] = surfaceTmp.isInterfaceElement();
3121 }
3122 }
3123 }
3124
3125 // Finally we need to determine or extract the indices of the edges midpoints. As in the describe algorithm the midpoints are set as follows:
3126 // Edge 0 = [x_0,x_1] -> x_01
3127 // Edge 1 = [x_0,x_2] -> x_02
3128 // Edge 2 = [x_0,x_3] -> x_03
3129 // Edge 3 = [x_1,x_2] -> x_12
3130 // Edge 4 = [x_1,x_3] -> x_13
3131 // Edge 5 = [x_2,x_3] -> x_23
3132
3133 for(int i=0; i<6; i++){
3134 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
3135 midPointInd.push_back(edgeElements->getMidpoint(edgeNumbers[i]));
3136 }
3137 }
3138
3139
3140 // Now we construct the new Elements as proposed by Bey's Regular Refinement Algorithm
3141
3142 vec2D_int_Type newElements(3, vec_int_Type( 0 )); // new elements
3143 vec2D_int_Type newEdges(18,vec_int_Type(0)); // new edges
3144 vec2D_int_Type newTriangles(12,vec_int_Type(0)); // new Triangles
3145 vec_int_Type newTrianglesFlag(12) ; // new Triangle Flags
3146 vec_int_Type isInterfaceSurface(12);
3147 vec_int_Type edgeFlags(18); // new Edge flags
3148 vec_bool_Type isInterfaceEdge(18); // bool vector for interfaceEdge Information
3149 vec_GO_Type predecessorElement(18); // vector that stores the global IDs of the predecessor of each edge
3150
3151 vec2D_LO_Type newTriangleEdgeIDs(3,vec_LO_Type(12));
3152
3153 // How are Flags determined?
3154 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
3155 // If an edges emerges on a triangle, the flag is determined by the triangle flag. Opposite to the 2D case, edges that connect midpoints are not automatically interior edges, but are
3156 // determined by the triangle/surface they are on
3157
3158
3159 // Element 1: (x_0,x_3,x_01,x_02)
3160 (newElements)[0]={nodeInd[0],nodeInd[3], midPointInd[0],midPointInd[1]};
3161
3162 (newEdges)[0] = {nodeInd[0] ,nodeInd[3]};
3163 (newEdges)[1] = {nodeInd[0] ,midPointInd[0]};
3164 (newEdges)[2] = {nodeInd[0] ,midPointInd[1]};
3165 (newEdges)[3] = {nodeInd[3] ,midPointInd[0]};
3166 (newEdges)[4] = {nodeInd[3] ,midPointInd[1]};
3167 (newEdges)[5] = {midPointInd[0] ,midPointInd[1]};
3168
3169 edgeFlags[0]=edgeElements->getElement(edgeNumbers[2]).getFlag();
3170 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[0]);
3171 edgeFlags[2]=this->bcFlagRep_->at(midPointInd[1]);
3172 edgeFlags[3]=originFlag[1];
3173 edgeFlags[4]=originFlag[2];
3174 edgeFlags[5]=originFlag[0];
3175
3176 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
3177 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
3178 isInterfaceEdge[2] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
3179 isInterfaceEdge[3] = interfaceSurface[1];
3180 isInterfaceEdge[4] = interfaceSurface[2];
3181 isInterfaceEdge[5] = interfaceSurface[0];
3182
3183 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
3184 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
3185 predecessorElement[2] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
3186 predecessorElement[3] = -1;
3187 predecessorElement[4] = -1;
3188 predecessorElement[5] = -1;
3189
3190 // Subelements of thetrahedron
3191 newTriangles[0]= {nodeInd[0],nodeInd[3],midPointInd[0]};
3192 newTriangles[1]= {nodeInd[0],nodeInd[3],midPointInd[1]};
3193 newTriangles[2]= {nodeInd[0],midPointInd[0],midPointInd[1]};
3194 newTriangles[3]= {nodeInd[3],midPointInd[0],midPointInd[1]};
3195
3196 newTrianglesFlag[0]= originFlag[1];
3197 newTrianglesFlag[1]= originFlag[2];
3198 newTrianglesFlag[2]= originFlag[0];
3199 newTrianglesFlag[3]= this->volumeID_;
3200
3201 isInterfaceSurface[0]= interfaceSurface[1];
3202 isInterfaceSurface[1]= interfaceSurface[2];
3203 isInterfaceSurface[2]= interfaceSurface[0];
3204 isInterfaceSurface[3]= false;
3205
3206 newTriangleEdgeIDs[0]={0,1,3,0,2,4,1,2,5,3,4,5};
3207
3208 // Element 2: (x_1,x_2,x_3,x_01)
3209 (newElements)[1]={nodeInd[1],nodeInd[2],nodeInd[3],midPointInd[0]};
3210
3211 (newEdges)[6] = {nodeInd[1] ,nodeInd[2]};
3212 (newEdges)[7] = {nodeInd[1] ,nodeInd[3]};
3213 (newEdges)[8] = {nodeInd[1] ,midPointInd[0]};
3214 (newEdges)[9] = {nodeInd[2] ,nodeInd[3]};
3215 (newEdges)[10] = {nodeInd[2] ,midPointInd[0]};
3216 (newEdges)[11] = {nodeInd[3] ,midPointInd[0]};
3217
3218 edgeFlags[6]=edgeElements->getElement(edgeNumbers[3]).getFlag();
3219 edgeFlags[7]=edgeElements->getElement(edgeNumbers[4]).getFlag();
3220 edgeFlags[8]=edgeElements->getElement(edgeNumbers[0]).getFlag();
3221 edgeFlags[9]=edgeElements->getElement(edgeNumbers[5]).getFlag();
3222 edgeFlags[10]=originFlag[0];
3223 edgeFlags[11]=originFlag[1];
3224
3225 isInterfaceEdge[6] = edgeElements->getElement(edgeNumbers[3]).isInterfaceElement();
3226 isInterfaceEdge[7] = edgeElements->getElement(edgeNumbers[4]).isInterfaceElement();
3227 isInterfaceEdge[8] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
3228 isInterfaceEdge[9] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
3229 isInterfaceEdge[10] = interfaceSurface[0];
3230 isInterfaceEdge[11] = interfaceSurface[1];
3231
3232 predecessorElement[6] = this->edgeMap_->getGlobalElement(edgeNumbers[3]);
3233 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[4]);
3234 predecessorElement[8] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
3235 predecessorElement[9] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
3236 predecessorElement[10] = -1;
3237 predecessorElement[11] = -1;
3238
3239 // Subelements of tetrahedron
3240 newTriangles[4]= {nodeInd[1],nodeInd[2],nodeInd[3]};
3241 newTriangles[5]= {nodeInd[1],nodeInd[2],midPointInd[0]};
3242 newTriangles[6]= {nodeInd[1],nodeInd[3],midPointInd[0]};
3243 newTriangles[7]= {nodeInd[2],nodeInd[3],midPointInd[0]};
3244
3245 newTrianglesFlag[4]= originFlag[3];
3246 newTrianglesFlag[5]= originFlag[0];
3247 newTrianglesFlag[6]= originFlag[1];
3248 newTrianglesFlag[7]= this->volumeID_;
3249
3250 isInterfaceSurface[4]= interfaceSurface[3];
3251 isInterfaceSurface[5]= interfaceSurface[0];
3252 isInterfaceSurface[6]= interfaceSurface[1];
3253 isInterfaceSurface[7]= false;
3254
3255 newTriangleEdgeIDs[1]={6,7,9,6,8,10,7,8,11,9,10,11};
3256 // Element 3: (x_2,x_3,x_01,x_02)
3257 (newElements)[2]={nodeInd[2],nodeInd[3],midPointInd[0],midPointInd[1]};
3258
3259 (newEdges)[12] = {nodeInd[2] ,nodeInd[3]};
3260 (newEdges)[13] = {nodeInd[2] ,midPointInd[0]};
3261 (newEdges)[14] = {nodeInd[2] ,midPointInd[1]};
3262 (newEdges)[15] = {nodeInd[3] ,midPointInd[0]};
3263 (newEdges)[16] = {nodeInd[3] ,midPointInd[1]};
3264 (newEdges)[17] = {midPointInd[0] ,midPointInd[1]};
3265
3266 edgeFlags[12]=edgeElements->getElement(edgeNumbers[5]).getFlag();
3267 edgeFlags[13]=originFlag[0];
3268 edgeFlags[14]=edgeElements->getElement(edgeNumbers[1]).getFlag();
3269 edgeFlags[15]=originFlag[1];
3270 edgeFlags[16]=originFlag[2];
3271 edgeFlags[17]=originFlag[0];
3272
3273 isInterfaceEdge[12] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
3274 isInterfaceEdge[13] = interfaceSurface[0];
3275 isInterfaceEdge[14] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
3276 isInterfaceEdge[15] = interfaceSurface[1];
3277 isInterfaceEdge[16] = interfaceSurface[2];
3278 isInterfaceEdge[17] = interfaceSurface[0];
3279
3280 predecessorElement[12] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
3281 predecessorElement[13] = -1;
3282 predecessorElement[14] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
3283 predecessorElement[15] = -1;
3284 predecessorElement[16] = -1;
3285 predecessorElement[17] = -1;
3286
3287 // Subelements of tetrahedron
3288 newTriangles[8]= {nodeInd[2],nodeInd[3],midPointInd[0]};
3289 newTriangles[9]= {nodeInd[2],nodeInd[3],midPointInd[1]};
3290 newTriangles[10]= {nodeInd[2],midPointInd[0],midPointInd[1]};
3291 newTriangles[11]= {nodeInd[3],midPointInd[0],midPointInd[1]};
3292
3293 newTrianglesFlag[8]=this->volumeID_;
3294 newTrianglesFlag[9]= originFlag[2];
3295 newTrianglesFlag[10]= originFlag[0];
3296 newTrianglesFlag[11]= this->volumeID_;
3297
3298 isInterfaceSurface[8]= false;
3299 isInterfaceSurface[9]= interfaceSurface[2];
3300 isInterfaceSurface[10]= interfaceSurface[0];
3301 isInterfaceSurface[11]= false;
3302
3303 newTriangleEdgeIDs[2]={8,9,11,8,10,12,9,10,13,11,12,13};
3304
3305
3306
3307 // Now we add the elements, edges and triangles
3308
3309 // Adding Elements
3310 int offsetElements = this->elementsC_->numberElements();
3311 int offsetEdges = this->edgeElements_->numberElements();
3312 for( int i=0;i<3; i++){
3313 sort( newElements.at(i).begin(), newElements.at(i).end() );
3314 FiniteElement feNew(newElements.at(i),this->volumeID_);
3315 feNew.setFiniteElementRefinementType("irregular");
3316 feNew.setPredecessorElement(indexElement);
3317 if(i<2)
3318 this->elementsC_->addElement(feNew);
3319 else
3320 this->elementsC_->switchElement(indexElement,feNew);
3321 }
3322
3323 // Adding the edges (they also have to be added to triangles as subelements, but that is not implemented yet)
3324 for( int i=0;i<18; i++){
3325 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
3326 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
3327 feNew.setInterfaceElement(isInterfaceEdge[i]);
3328 feNew.setPredecessorElement(predecessorElement[i]);
3329 if(i<12){
3330 this->edgeElements_->addEdge(feNew,i/6+offsetElements);
3331 }
3332 else
3333 this->edgeElements_->addEdge(feNew,indexElement);
3334 }
3335
3336 // Adding triangles as subelements, if they arent interior triangles
3337 int offsetSurface =0;
3338 for( int i=0;i<12; i++){
3339 sort( newTriangles.at(i).begin(), newTriangles.at(i).end() );
3340 FiniteElement feNew(newTriangles[i],newTrianglesFlag[i]);
3341 feNew.setInterfaceElement(isInterfaceSurface[i]);
3342 if(i<8){
3343 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
3344 if ( !this->elementsC_->getElement(i/4+offsetElements).subElementsInitialized() )
3345 this->elementsC_->getElement(i/4+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
3346 this->elementsC_->getElement(i/4+offsetElements).addSubElement(feNew);
3347 }
3348 this->surfaceTriangleElements_->addSurface(feNew, i/4+offsetElements);
3349 }
3350 else{
3351 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
3352 if ( !this->elementsC_->getElement(indexElement).subElementsInitialized() )
3353 this->elementsC_->getElement(indexElement).initializeSubElements( this->FEType_, this->dim_ -1) ;
3354 this->elementsC_->getElement(indexElement).addSubElement(feNew);
3355 }
3356 this->surfaceTriangleElements_->addSurface(feNew, indexElement);
3357 }
3358 }
3359 FiniteElement element;
3360 FiniteElement feEdge;
3361 for( int i=0;i<3; i++){
3362 if(i<2)
3363 element = this->elementsC_->getElement(i+offsetElements);
3364 else
3365 element = this->elementsC_->getElement(indexElement);
3366 bool init=false;
3367 for(int j=0; j<18 ; j++){
3368 FiniteElement feEdge = this->edgeElements_->getElement(j+offsetEdges);
3369 if(feEdge.getFlag() != this->volumeID_){
3370 if(init == true)
3371 element.addSubElement( feEdge );
3372 else if ( !element.subElementsInitialized() ){
3373 element.initializeSubElements( "P1", 1 ); // only P1 for now
3374 element.addSubElement( feEdge );
3375 init= true;
3376 }
3377 else {
3378 ElementsPtr_Type surfaces = element.getSubElements();
3379 // We set the edge to the corresponding element(s)
3380 surfaces->setToCorrectElement( feEdge );
3381 }
3382 }
3383 }
3384 }
3385
3386 }
3387 else
3388 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The Type 1 irregular Refinement Method you requested is only applicable to a 3 dimensional Mesh. Please reconsider.");
3389
3390
3391}
3392
3393
3404
3405template <class SC, class LO, class GO, class NO>
3406void RefinementFactory<SC,LO,GO,NO>::refineType2(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements){
3407
3408// Implementation of Type (2) Refinement Type
3409// We use this Refinement Type
3410 if(this->dim_ == 3){
3411
3412 // The way we refine the Tetrahedron is defined by how we order the nodes of the tetrahedron
3413 // (For the algorithm see "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refinement' in Computing, Springer Verlag 1955)
3414 // The Type 2 Refinement is similar to a green Refinement in two dimensions, as we connect the midpoint to the opposite points on the same surface
3415 // The procedure is similar to the regular refinement, we just add less elements
3416
3417 vec_int_Type midPointInd( 1 ); // indices of midpoints of edges of soon to be refined element
3418 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
3419 vec_int_Type edgeNumbersUntagged(0);
3420 // Extract the three points of tetraeder, that connect the tagged edges
3421 vec_int_Type nodeInd(0);
3422 for(int i=0; i<6; i++){
3423 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
3424 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(0));
3425 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(1));
3426 }
3427 else
3428 edgeNumbersUntagged.push_back(edgeNumbers[i]);
3429 }
3430 sort( nodeInd.begin(), nodeInd.end() );
3431 nodeInd.erase( unique( nodeInd.begin(), nodeInd.end() ), nodeInd.end() );
3432
3433 // We now have the two nodes that connect the tagged edge or rather make up the tagged edge
3434 // The left over nodes are the ones opposite to the tagged edge
3435 vec_int_Type nodeIndTmp(0);
3436 for(int i=0; i<5; i++){
3437 if(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(0) == nodeInd[0])
3438 nodeIndTmp.push_back(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(1));
3439 else if(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(1) == nodeInd[0])
3440 nodeIndTmp.push_back(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(0));
3441 else if(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(0) == nodeInd[1])
3442 nodeIndTmp.push_back(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(1));
3443 else if(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(1) == nodeInd[1])
3444 nodeIndTmp.push_back(edgeElements->getElement(edgeNumbersUntagged[i]).getNode(0));
3445 }
3446
3447 sort( nodeIndTmp.begin(), nodeIndTmp.end() );
3448 nodeIndTmp.erase( unique( nodeIndTmp.begin(), nodeIndTmp.end() ), nodeIndTmp.end() );
3449
3450 // Now we add the two remaining points, that dont belong to the tagged edge
3451 nodeInd.push_back(nodeIndTmp[0]);
3452 nodeInd.push_back(nodeIndTmp[1]);
3453
3454 // We don't need to sort the nodes in any other way then we already did, as there is not more than one possibility to construct the subtetrahera in refinement type 2
3455
3456 // With our sorted Nodes we construct edges as follows
3457 // Edge_0 = [x_0,x_1]
3458 // Edge_1 = [x_0,x_2]
3459 // Edge_2 = [x_0,x_3]
3460 // Edge_3 = [x_1,x_2]
3461 // Edge_4 = [x_1,x_3]
3462 // Edge_5 = [x_2,x_3]
3463
3464 vec_int_Type edgeNumbersTmp = edgeNumbers;
3465 for(int i=0; i<6; i++){
3466 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[0] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[0]){
3467 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1])
3468 edgeNumbers[0] = edgeNumbersTmp[i];
3469 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
3470 edgeNumbers[1] = edgeNumbersTmp[i];
3471 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3472 edgeNumbers[2] = edgeNumbersTmp[i];
3473 }
3474 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1]){
3475 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
3476 edgeNumbers[3] = edgeNumbersTmp[i];
3477 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3478 edgeNumbers[4] = edgeNumbersTmp[i];
3479 }
3480 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2]){
3481 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3482 edgeNumbers[5] = edgeNumbersTmp[i];
3483 }
3484 }
3485
3486 // We hace 4 Triangles in our Tetraedron
3487 // If one or more of those Triangles are Part of the domains' boundaries, they are added to the element in question as subelement
3488 // We extract them in follwing pattern:
3489
3490 // Tri_0 = [x_0,x_1,x_2]
3491 // Tri_1 = [x_0,x_1,x_3]
3492 // Tri_2 = [x_0,x_2,x_3]
3493 // Tri_3 = [x_1,x_2,x_3]
3494
3495
3496 // We check if one or more of these triangles are part of the boundary surface and determine there flag
3497 vec_int_Type surfaceElementsIDs = surfaceTriangleElements->getSurfacesOfElement(indexElement); // surfaces of Element k
3498 vec2D_int_Type originTriangles(4,vec_int_Type(3));
3499
3500 originTriangles[0] = {nodeInd[0], nodeInd[1], nodeInd[2] };
3501 originTriangles[1] = {nodeInd[0], nodeInd[1], nodeInd[3] };
3502 originTriangles[2] = {nodeInd[0], nodeInd[2], nodeInd[3] };
3503 originTriangles[3] = {nodeInd[1], nodeInd[2], nodeInd[3] };
3504
3505
3506
3507 vec_int_Type originFlag(4,this->volumeID_); // Triangle Flag
3508
3509 vec_bool_Type interfaceSurface(4);
3510 vec_LO_Type triTmp(3);
3511 vec_int_Type originTriangleTmp(3);
3512
3513 for(int i=0; i< 4 ; i++){
3514 originTriangleTmp = originTriangles[i];
3515 sort(originTriangleTmp.begin(),originTriangleTmp.end());
3516 for(int j=0; j<4 ; j++){
3517 FiniteElement surfaceTmp = surfaceTriangleElements->getElement(surfaceElementsIDs[j]);
3518 triTmp = surfaceTmp.getVectorNodeList();
3519 sort(triTmp.begin(),triTmp.end());
3520 if(triTmp[0] == originTriangleTmp[0] && triTmp[1] == originTriangleTmp[1] && triTmp[2] == originTriangleTmp[2] ) {
3521 originFlag[i] = surfaceTmp.getFlag();
3522 interfaceSurface[i] = surfaceTmp.isInterfaceElement();
3523 }
3524 }
3525 }
3526
3527 // Finally we need to determine or extract the indices of the edges midpoints. As in the describe algorithm the midpoints are set as follows:
3528 // Edge 0 = [x_0,x_1] -> x_01
3529 // Edge 1 = [x_0,x_2] -> x_02
3530 // Edge 2 = [x_0,x_3] -> x_03
3531 // Edge 3 = [x_1,x_2] -> x_12
3532 // Edge 4 = [x_1,x_3] -> x_13
3533 // Edge 5 = [x_2,x_3] -> x_23
3534
3535 for(int i=0; i<6; i++){
3536 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
3537 midPointInd[0] = edgeElements->getMidpoint(edgeNumbers[i]);
3538 }
3539 }
3540
3541
3542 // Now we construct the new Elements as proposed by Bey's Regular Refinement Algorithm
3543
3544 vec2D_int_Type newElements(2, vec_int_Type( 0 )); // new elements
3545 vec2D_int_Type newEdges(12,vec_int_Type(0)); // new edges
3546 vec2D_int_Type newTriangles(8,vec_int_Type(0)); // new Triangles
3547 vec_int_Type newTrianglesFlag(8) ; // new Triangle Flags
3548 vec_bool_Type isInterfaceSurface(8); // bool vector for interfaceSurface Information
3549 vec_int_Type edgeFlags(12); // new Edge flags
3550 vec_bool_Type isInterfaceEdge(12); // bool vector for interfaceEdge Information
3551 vec_GO_Type predecessorElement(12); // vector that stores the global IDs of the predecessor of each edge
3552
3553 vec2D_LO_Type newTriangleEdgeIDs(2,vec_LO_Type(12));
3554
3555 // How are Flags determined?
3556 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
3557 // If an edges emerges on a triangle, the flag is determined by the triangle flag. Opposite to the 2D case, edges that connect midpoints are not automatically interior edges, but are
3558 // determined by the triangle/surface they are on
3559
3560
3561 // Element 1: (x_0,x_2,x_3,x_01)
3562 (newElements)[0]={nodeInd[0],nodeInd[2],nodeInd[3],midPointInd[0]};
3563
3564 (newEdges)[0] = {nodeInd[0] ,nodeInd[2]};
3565 (newEdges)[1] = {nodeInd[0] ,nodeInd[3]};
3566 (newEdges)[2] = {nodeInd[0] ,midPointInd[0]};
3567 (newEdges)[3] = {nodeInd[2] ,nodeInd[3]};
3568 (newEdges)[4] = {nodeInd[2] ,midPointInd[0]};
3569 (newEdges)[5] = {nodeInd[3] ,midPointInd[0]};
3570
3571 edgeFlags[0]=edgeElements->getElement(edgeNumbers[1]).getFlag();
3572 edgeFlags[1]=edgeElements->getElement(edgeNumbers[2]).getFlag();
3573 edgeFlags[2]=this->bcFlagRep_->at(midPointInd[0]);
3574 edgeFlags[3]=edgeElements->getElement(edgeNumbers[5]).getFlag();
3575 edgeFlags[4]=originFlag[0];
3576 edgeFlags[5]=originFlag[1];
3577
3578 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
3579 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
3580 isInterfaceEdge[2] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
3581 isInterfaceEdge[3] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();;
3582 isInterfaceEdge[4] = interfaceSurface[0];
3583 isInterfaceEdge[5] = interfaceSurface[1];
3584
3585 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
3586 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
3587 predecessorElement[2] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
3588 predecessorElement[3] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
3589 predecessorElement[4] = -1;
3590 predecessorElement[5] = -1;
3591
3592 // Subelements of thetrahedron
3593 newTriangles[0]= {nodeInd[0],nodeInd[2],nodeInd[3]};
3594 newTriangles[1]= {nodeInd[0],nodeInd[2],midPointInd[0]};
3595 newTriangles[2]= {nodeInd[0],nodeInd[3],midPointInd[0]};
3596 newTriangles[3]= {nodeInd[2],nodeInd[3],midPointInd[0]};
3597
3598 newTrianglesFlag[0]= originFlag[2];
3599 newTrianglesFlag[1]= originFlag[0];
3600 newTrianglesFlag[2]= originFlag[1];
3601 newTrianglesFlag[3]= this->volumeID_;
3602
3603 isInterfaceSurface[0] = interfaceSurface[2];
3604 isInterfaceSurface[1] = interfaceSurface[0];
3605 isInterfaceSurface[2] = interfaceSurface[1];
3606 isInterfaceSurface[3] = false;
3607
3608 newTriangleEdgeIDs[0]={0,1,3,0,2,4,1,2,5,3,4,5};
3609
3610 // Element 2: (x_1,x_2,x_3,x_01)
3611 (newElements)[1]={nodeInd[1],nodeInd[2],nodeInd[3],midPointInd[0]};
3612
3613 (newEdges)[6] = {nodeInd[1] ,nodeInd[2]};
3614 (newEdges)[7] = {nodeInd[1] ,nodeInd[3]};
3615 (newEdges)[8] = {nodeInd[1] ,midPointInd[0]};
3616 (newEdges)[9] = {nodeInd[2] ,nodeInd[3]};
3617 (newEdges)[10] = {nodeInd[2] ,midPointInd[0]};
3618 (newEdges)[11] = {nodeInd[3] ,midPointInd[0]};
3619
3620 edgeFlags[6]=edgeElements->getElement(edgeNumbers[3]).getFlag();
3621 edgeFlags[7]=edgeElements->getElement(edgeNumbers[4]).getFlag();
3622 edgeFlags[8]=edgeElements->getElement(edgeNumbers[0]).getFlag();
3623 edgeFlags[9]=edgeElements->getElement(edgeNumbers[5]).getFlag();
3624 edgeFlags[10]=originFlag[0];
3625 edgeFlags[11]=originFlag[1];
3626
3627 isInterfaceEdge[6] = edgeElements->getElement(edgeNumbers[3]).isInterfaceElement();
3628 isInterfaceEdge[7] = edgeElements->getElement(edgeNumbers[4]).isInterfaceElement();
3629 isInterfaceEdge[8] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
3630 isInterfaceEdge[9] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
3631 isInterfaceEdge[10] = interfaceSurface[0];
3632 isInterfaceEdge[11] = interfaceSurface[1];
3633
3634 predecessorElement[6] = this->edgeMap_->getGlobalElement(edgeNumbers[3]);
3635 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[4]);
3636 predecessorElement[8] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
3637 predecessorElement[9] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
3638 predecessorElement[10] = -1;
3639 predecessorElement[11] = -1;
3640
3641 // Subelements of tetrahedron
3642 newTriangles[4]= {nodeInd[1],nodeInd[2],nodeInd[3]};
3643 newTriangles[5]= {nodeInd[1],nodeInd[2],midPointInd[0]};
3644 newTriangles[6]= {nodeInd[1],nodeInd[3],midPointInd[0]};
3645 newTriangles[7]= {nodeInd[2],nodeInd[3],midPointInd[0]};
3646
3647 newTrianglesFlag[4]= originFlag[3];
3648 newTrianglesFlag[5]= originFlag[0];
3649 newTrianglesFlag[6]= originFlag[1];
3650 newTrianglesFlag[7]= this->volumeID_;
3651
3652 isInterfaceSurface[4] = interfaceSurface[3];
3653 isInterfaceSurface[5] = interfaceSurface[0];
3654 isInterfaceSurface[6] = interfaceSurface[1];
3655 isInterfaceSurface[7] = false;
3656
3657 newTriangleEdgeIDs[1]={6,7,9,6,8,10,7,8,11,9,10,11};
3658
3659 // Now we add the elements, edges and triangles
3660
3661 // Adding Elements
3662 int offsetElements = this->elementsC_->numberElements();
3663 int offsetEdges = this->edgeElements_->numberElements();
3664 for( int i=0;i<2; i++){
3665 sort( newElements.at(i).begin(), newElements.at(i).end() );
3666 FiniteElement feNew(newElements.at(i),this->volumeID_);
3667 feNew.setFiniteElementRefinementType("irregular");
3668 if(refinementMode_ == "Bisection")
3669 feNew.setFiniteElementRefinementType("regular");
3670 feNew.setPredecessorElement(indexElement);
3671 if(i<1)
3672 this->elementsC_->addElement(feNew);
3673 else
3674 this->elementsC_->switchElement(indexElement,feNew);
3675 }
3676
3677 // Adding the edges (they also have to be added to triangles as subelements, but that is not implemented yet)
3678 for( int i=0;i<12; i++){
3679 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
3680 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
3681 feNew.setInterfaceElement(isInterfaceEdge[i]);
3682 feNew.setPredecessorElement(predecessorElement[i]);
3683 if(i<6){
3684 this->edgeElements_->addEdge(feNew,i/6+offsetElements);
3685 }
3686 else
3687 this->edgeElements_->addEdge(feNew,indexElement);
3688 }
3689
3690 // Adding triangles as subelements, if they arent interior triangles
3691 int offsetSurface =0;
3692 for( int i=0;i<8; i++){
3693 sort( newTriangles.at(i).begin(), newTriangles.at(i).end() );
3694 FiniteElement feNew(newTriangles[i],newTrianglesFlag[i]);
3695 feNew.setInterfaceElement(isInterfaceSurface[i]);
3696 if(i<4){
3697 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
3698 if ( !this->elementsC_->getElement(i/4+offsetElements).subElementsInitialized() )
3699 this->elementsC_->getElement(i/4+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
3700 this->elementsC_->getElement(i/4+offsetElements).addSubElement(feNew);
3701 }
3702 this->surfaceTriangleElements_->addSurface(feNew, i/4+offsetElements);
3703 }
3704 else{
3705 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
3706 if ( !this->elementsC_->getElement(indexElement).subElementsInitialized() )
3707 this->elementsC_->getElement(indexElement).initializeSubElements( this->FEType_, this->dim_ -1) ;
3708 this->elementsC_->getElement(indexElement).addSubElement(feNew);
3709 }
3710 this->surfaceTriangleElements_->addSurface(feNew, indexElement);
3711 }
3712
3713 }
3714 FiniteElement element;
3715 FiniteElement feEdge;
3716 for( int i=0;i<2; i++){
3717 if(i<1)
3718 element = this->elementsC_->getElement(i+offsetElements);
3719 else
3720 element = this->elementsC_->getElement(indexElement);
3721 bool init=false;
3722 for(int j=0; j<12 ; j++){
3723 FiniteElement feEdge = this->edgeElements_->getElement(j+offsetEdges);
3724 if(feEdge.getFlag() != this->volumeID_){
3725 if(init == true)
3726 element.addSubElement( feEdge );
3727 else if ( !element.subElementsInitialized() ){
3728 element.initializeSubElements( "P1", 1 ); // only P1 for now
3729 element.addSubElement( feEdge );
3730 init= true;
3731 }
3732 else {
3733 ElementsPtr_Type surfaces = element.getSubElements();
3734 // We set the edge to the corresponding element(s)
3735 surfaces->setToCorrectElement( feEdge );
3736 }
3737 }
3738 }
3739 }
3740 }
3741 else
3742 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The Type 1 irregular Refinement Method you requested is only applicable to a 3 dimensional Mesh. Please reconsider.");
3743
3744
3745}
3746
3757
3758template <class SC, class LO, class GO, class NO>
3759void RefinementFactory<SC,LO,GO,NO>::refineType1(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements){
3760
3761// Implementation of Type (1) Refinement Type
3762// We use this Refinement Type
3763 if(this->dim_ == 3){
3764
3765 // The way we refine the Tetrahedron is defined by how we order the nodes of the tetrahedron
3766 // (For the algorithm see "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refinement' in Computing, Springer Verlag 1955)
3767 // The Type 1 Refinement is similar to a red Refinement in two dimensions, as we connect the midpoints on one surface and connect them to the remaining point
3768 // The procedure is similar to the regular refinement, we just add less elements
3769
3770 vec_int_Type midPointInd(0); // indices of midpoints of edges of soon to be refined element
3771 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
3772 vec_int_Type edgeNumbersUntagged(0);
3773 // Extract the three points of tetraeder, that connect the tagged edges
3774 vec_int_Type nodeInd(0);
3775 int node4=0;
3776 for(int i=0; i<6; i++){
3777 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()){
3778 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(0));
3779 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(1));
3780 }
3781 else
3782 edgeNumbersUntagged.push_back(edgeNumbers[i]);
3783 }
3784 sort( nodeInd.begin(), nodeInd.end() );
3785 nodeInd.erase( unique( nodeInd.begin(), nodeInd.end() ), nodeInd.end() );
3786
3787 // We now have the three nodes that connect the tagged edges or rather make up the tagged triangle
3788 // The fourth node that is opposite to this tagged triangle we push back to the nodeInd list
3789 for(int i=0; i<3; i++){
3790 if(edgeElements->getElement(edgeNumbersUntagged[0]).getNode(0) == nodeInd[i])
3791 nodeInd.push_back(edgeElements->getElement(edgeNumbersUntagged[0]).getNode(1));
3792 if(edgeElements->getElement(edgeNumbersUntagged[0]).getNode(1) == nodeInd[i])
3793 nodeInd.push_back(edgeElements->getElement(edgeNumbersUntagged[0]).getNode(0));
3794 }
3795
3796 // We don't need to sort the nodes in any other way then we already did, as there is not more than one possibility to construct the subtetrahera in refinement type 1
3797
3798 // With our sorted Nodes we construct edges as follows
3799 // Edge_0 = [x_0,x_1]
3800 // Edge_1 = [x_0,x_2]
3801 // Edge_2 = [x_0,x_3]
3802 // Edge_3 = [x_1,x_2]
3803 // Edge_4 = [x_1,x_3]
3804 // Edge_5 = [x_2,x_3]
3805
3806 vec_int_Type edgeNumbersTmp = edgeNumbers;
3807 for(int i=0; i<6; i++){
3808 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[0] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[0]){
3809 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1])
3810 edgeNumbers[0] = edgeNumbersTmp[i];
3811 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
3812 edgeNumbers[1] = edgeNumbersTmp[i];
3813 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3814 edgeNumbers[2] = edgeNumbersTmp[i];
3815 }
3816 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1]){
3817 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
3818 edgeNumbers[3] = edgeNumbersTmp[i];
3819 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3820 edgeNumbers[4] = edgeNumbersTmp[i];
3821 }
3822 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2]){
3823 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
3824 edgeNumbers[5] = edgeNumbersTmp[i];
3825 }
3826 }
3827
3828 // We hace 4 Triangles in our Tetraedron
3829 // If one or more of those Triangles are Part of the domains' boundaries, they are added to the element in question as subelement
3830 // We extract them in follwing pattern:
3831
3832 // Tri_0 = [x_0,x_1,x_2]
3833 // Tri_1 = [x_0,x_1,x_3]
3834 // Tri_2 = [x_0,x_2,x_3]
3835 // Tri_3 = [x_1,x_2,x_3]
3836
3837
3838 // We check if one or more of these triangles are part of the boundary surface and determine there flag
3839
3840 vec_int_Type surfaceElementsIDs = surfaceTriangleElements->getSurfacesOfElement(indexElement); // surfaces of Element k
3841 vec2D_int_Type originTriangles(4,vec_int_Type(3));
3842
3843 originTriangles[0] = {nodeInd[0], nodeInd[1], nodeInd[2] };
3844 originTriangles[1] = {nodeInd[0], nodeInd[1], nodeInd[3] };
3845 originTriangles[2] = {nodeInd[0], nodeInd[2], nodeInd[3] };
3846 originTriangles[3] = {nodeInd[1], nodeInd[2], nodeInd[3] };
3847
3848 vec_int_Type originFlag(4,this->volumeID_); // Triangle Flag
3849
3850 vec_bool_Type interfaceSurface(4);
3851 vec_LO_Type triTmp(3);
3852 vec_int_Type originTriangleTmp(3);
3853
3854 for(int i=0; i< 4 ; i++){
3855 originTriangleTmp = originTriangles[i];
3856 sort(originTriangleTmp.begin(),originTriangleTmp.end());
3857 for(int j=0; j<4 ; j++){
3858 FiniteElement surfaceTmp = surfaceTriangleElements->getElement(surfaceElementsIDs[j]);
3859 triTmp = surfaceTmp.getVectorNodeList();
3860 sort(triTmp.begin(),triTmp.end());
3861 if(triTmp[0] == originTriangleTmp[0] && triTmp[1] == originTriangleTmp[1] && triTmp[2] == originTriangleTmp[2] ) {
3862 originFlag[i] = surfaceTmp.getFlag();
3863 interfaceSurface[i] = surfaceTmp.isInterfaceElement();
3864 }
3865 }
3866 }
3867 // Finally we need to determine or extract the indices of the edges midpoints. As in the describe algorithm the midpoints are set as follows:
3868 // Edge 0 = [x_0,x_1] -> x_01
3869 // Edge 1 = [x_0,x_2] -> x_02
3870 // Edge 2 = [x_0,x_3] -> x_03
3871 // Edge 3 = [x_1,x_2] -> x_12
3872 // Edge 4 = [x_1,x_3] -> x_13
3873 // Edge 5 = [x_2,x_3] -> x_23
3874
3875 for(int i=0; i<6; i++){
3876 if(edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement())
3877 midPointInd.push_back(edgeElements->getMidpoint(edgeNumbers[i]));
3878 }
3879
3880 // Now we construct the new Elements as proposed by Bey's Regular Refinement Algorithm
3881
3882 vec2D_int_Type newElements(4, vec_int_Type( 0 )); // new elements
3883 vec2D_int_Type newEdges(24,vec_int_Type(0)); // new edges
3884 vec2D_int_Type newTriangles(16,vec_int_Type(0)); // new Triangles
3885 vec_int_Type newTrianglesFlag(16) ; // new Triangle Flags
3886 vec_bool_Type isInterfaceSurface(16); // bool vector for interfaceSurface Information
3887 vec_int_Type edgeFlags(24); // new Edge flags
3888 vec_bool_Type isInterfaceEdge(24); // bool vector for interfaceEdge Information
3889 vec_GO_Type predecessorElement(24); // vector that stores the global IDs of the predecessor of each edge
3890
3891 vec2D_LO_Type newTriangleEdgeIDs(4,vec_LO_Type(12));
3892
3893 // How are Flags determined?
3894 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
3895 // If an edges emerges on a triangle, the flag is determined by the triangle flag. Opposite to the 2D case, edges that connect midpoints are not automatically interior edges, but are
3896 // determined by the triangle/surface they are on
3897
3898
3899 // Element 1: (x_0,x_01,x_02,x_03)
3900 (newElements)[0]={nodeInd[0],midPointInd[0],midPointInd[1],nodeInd[3]};
3901
3902 (newEdges)[0] = {nodeInd[0] ,midPointInd[0]};
3903 (newEdges)[1] = {nodeInd[0] ,midPointInd[1]};
3904 (newEdges)[2] = {nodeInd[0] ,nodeInd[3]};
3905 (newEdges)[3] = {midPointInd[0] ,midPointInd[1]};
3906 (newEdges)[4] = {midPointInd[0] ,nodeInd[3]};
3907 (newEdges)[5] = {midPointInd[1] ,nodeInd[3]};
3908
3909 edgeFlags[0]=this->bcFlagRep_->at(midPointInd[0]);
3910 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[1]);
3911 edgeFlags[2]=edgeElements->getElement(edgeNumbers[2]).getFlag();
3912 edgeFlags[3]=originFlag[0];
3913 edgeFlags[4]=originFlag[1];
3914 edgeFlags[5]=originFlag[2];
3915
3916 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
3917 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
3918 isInterfaceEdge[2] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
3919 isInterfaceEdge[3] = interfaceSurface[0];
3920 isInterfaceEdge[4] = interfaceSurface[1];
3921 isInterfaceEdge[5] = interfaceSurface[2];
3922
3923 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
3924 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
3925 predecessorElement[2] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
3926 predecessorElement[3] = -1;
3927 predecessorElement[4] = -1;
3928 predecessorElement[5] = -1;
3929
3930
3931 // Subelements of thetrahedron
3932 newTriangles[0]= {nodeInd[0],midPointInd[0],midPointInd[1]};
3933 newTriangles[1]= {nodeInd[0],midPointInd[0],nodeInd[3]};
3934 newTriangles[2]= {nodeInd[0],midPointInd[1],nodeInd[3]};
3935 newTriangles[3]= {midPointInd[0],midPointInd[1],nodeInd[3]};
3936
3937 newTrianglesFlag[0]= originFlag[0];
3938 newTrianglesFlag[1]= originFlag[1];
3939 newTrianglesFlag[2]= originFlag[2];
3940 newTrianglesFlag[3]= this->volumeID_;
3941
3942 isInterfaceSurface[0] = interfaceSurface[0];
3943 isInterfaceSurface[1] = interfaceSurface[1];
3944 isInterfaceSurface[2] = interfaceSurface[2];
3945 isInterfaceSurface[3] = false;
3946
3947 newTriangleEdgeIDs[0]={0,1,3,0,2,4,1,2,5,3,4,5};
3948
3949 // Element 2: (x_1,x_01,x_12,x_13)
3950 (newElements)[1]={nodeInd[1],midPointInd[0],midPointInd[2],nodeInd[3]};
3951
3952 (newEdges)[6] = {nodeInd[1] ,midPointInd[0]};
3953 (newEdges)[7] = {nodeInd[1] ,midPointInd[2]};
3954 (newEdges)[8] = {nodeInd[1] ,nodeInd[3]};
3955 (newEdges)[9] = {midPointInd[0] ,midPointInd[2]};
3956 (newEdges)[10] = {midPointInd[0] ,nodeInd[3]};
3957 (newEdges)[11] = {midPointInd[2] ,nodeInd[3]};
3958
3959 edgeFlags[6]=this->bcFlagRep_->at(midPointInd[0]);
3960 edgeFlags[7]=this->bcFlagRep_->at(midPointInd[2]);
3961 edgeFlags[8]=edgeElements->getElement(edgeNumbers[4]).getFlag();
3962 edgeFlags[9]=originFlag[0];
3963 edgeFlags[10]=originFlag[1];
3964 edgeFlags[11]=originFlag[3];
3965
3966 isInterfaceEdge[6] =edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
3967 isInterfaceEdge[7] =edgeElements->getElement(edgeNumbers[3]).isInterfaceElement();
3968 isInterfaceEdge[8] =edgeElements->getElement(edgeNumbers[4]).isInterfaceElement();
3969 isInterfaceEdge[9] = interfaceSurface[0];
3970 isInterfaceEdge[10] = interfaceSurface[1];
3971 isInterfaceEdge[11] = interfaceSurface[3];
3972
3973 predecessorElement[6] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
3974 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[3]);
3975 predecessorElement[8] = this->edgeMap_->getGlobalElement(edgeNumbers[4]);
3976 predecessorElement[9] = -1;
3977 predecessorElement[10] = -1;
3978 predecessorElement[11] = -1;
3979
3980 // Subelements of tetrahedron
3981 newTriangles[4]= {nodeInd[1],midPointInd[0],midPointInd[2]};
3982 newTriangles[5]= {nodeInd[1],midPointInd[0],nodeInd[3]};
3983 newTriangles[6]= {nodeInd[1],midPointInd[2],nodeInd[3]};
3984 newTriangles[7]= {midPointInd[0],midPointInd[2],nodeInd[3]};
3985
3986 newTrianglesFlag[4]= originFlag[0];
3987 newTrianglesFlag[5]= originFlag[1];
3988 newTrianglesFlag[6]= originFlag[3];
3989 newTrianglesFlag[7]= this->volumeID_;
3990
3991 isInterfaceSurface[4] = interfaceSurface[0];
3992 isInterfaceSurface[5] = interfaceSurface[1];
3993 isInterfaceSurface[6] = interfaceSurface[3];
3994 isInterfaceSurface[7] = false;
3995
3996 newTriangleEdgeIDs[1]={6,7,9,6,8,10,7,8,11,9,10,11};
3997
3998
3999 // Element 3: (x_2,x_02,x_12,x_23)
4000 (newElements)[2]={nodeInd[2],midPointInd[1],midPointInd[2],nodeInd[3]};
4001
4002 (newEdges)[12] = {nodeInd[2] ,midPointInd[1]};
4003 (newEdges)[13] = {nodeInd[2] ,midPointInd[2]};
4004 (newEdges)[14] = {nodeInd[2] ,nodeInd[3]};
4005 (newEdges)[15] = {midPointInd[1] ,midPointInd[2]};
4006 (newEdges)[16] = {midPointInd[1] ,nodeInd[3]};
4007 (newEdges)[17] = {midPointInd[2] ,nodeInd[3]};
4008
4009 edgeFlags[12]=this->bcFlagRep_->at(midPointInd[1]);
4010 edgeFlags[13]=this->bcFlagRep_->at(midPointInd[2]);
4011 edgeFlags[14]=edgeElements->getElement(edgeNumbers[5]).getFlag();
4012 edgeFlags[15]=originFlag[0];
4013 edgeFlags[16]=originFlag[2];
4014 edgeFlags[17]=originFlag[3];
4015
4016 isInterfaceEdge[12] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
4017 isInterfaceEdge[13] = edgeElements->getElement(edgeNumbers[3]).isInterfaceElement();
4018 isInterfaceEdge[14] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
4019 isInterfaceEdge[15] = interfaceSurface[0];
4020 isInterfaceEdge[16] = interfaceSurface[2];
4021 isInterfaceEdge[17] = interfaceSurface[3];
4022
4023 predecessorElement[12] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
4024 predecessorElement[13] = this->edgeMap_->getGlobalElement(edgeNumbers[3]);
4025 predecessorElement[14] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
4026 predecessorElement[15] = -1;
4027 predecessorElement[16] = -1;
4028 predecessorElement[17] = -1;
4029
4030 // Subelements of thetrahedron
4031 newTriangles[8]= {nodeInd[2],midPointInd[1],midPointInd[2]};
4032 newTriangles[9]= {nodeInd[2],midPointInd[1],nodeInd[3]};
4033 newTriangles[10]= {nodeInd[2],midPointInd[2],nodeInd[3]};
4034 newTriangles[11]= {midPointInd[1],midPointInd[2],nodeInd[3]};
4035
4036 newTrianglesFlag[8]= originFlag[0];
4037 newTrianglesFlag[9]= originFlag[2];
4038 newTrianglesFlag[10]= originFlag[3];
4039 newTrianglesFlag[11]= this->volumeID_;
4040
4041 isInterfaceSurface[8] = interfaceSurface[0];
4042 isInterfaceSurface[9] = interfaceSurface[2];
4043 isInterfaceSurface[10] = interfaceSurface[3];
4044 isInterfaceSurface[11] = false;
4045
4046 newTriangleEdgeIDs[2]={12,13,15,12,14,16,13,14,17,15,16,17};
4047
4048
4049 // Element 4: (x_3,x_03,x_13,x_23)
4050 (newElements)[3]={nodeInd[3],midPointInd[0],midPointInd[1],midPointInd[2]};
4051
4052 (newEdges)[18] = {nodeInd[3] ,midPointInd[0]};
4053 (newEdges)[19] = {nodeInd[3] ,midPointInd[1]};
4054 (newEdges)[20] = {nodeInd[3] ,midPointInd[2]};
4055 (newEdges)[21] = {midPointInd[0] ,midPointInd[1]};
4056 (newEdges)[22] = {midPointInd[0] ,midPointInd[2]};
4057 (newEdges)[23] = {midPointInd[1] ,midPointInd[2]};
4058
4059 edgeFlags[18]=originFlag[1];
4060 edgeFlags[19]=originFlag[2];
4061 edgeFlags[20]=originFlag[3];
4062 edgeFlags[21]=originFlag[0];
4063 edgeFlags[22]=originFlag[0];
4064 edgeFlags[23]=originFlag[0];
4065
4066 isInterfaceEdge[18] = interfaceSurface[1];
4067 isInterfaceEdge[19] = interfaceSurface[2];
4068 isInterfaceEdge[20] = interfaceSurface[3];
4069 isInterfaceEdge[21] = interfaceSurface[0];
4070 isInterfaceEdge[22] = interfaceSurface[0];
4071 isInterfaceEdge[23] = interfaceSurface[0];
4072
4073 predecessorElement[18] = -1;
4074 predecessorElement[19] = -1;
4075 predecessorElement[20] = -1;
4076 predecessorElement[21] = -1;
4077 predecessorElement[22] = -1;
4078 predecessorElement[23] = -1;
4079
4080
4081 // Subelements of thetrahedron
4082 newTriangles[12]= {nodeInd[3],midPointInd[0],midPointInd[1]};
4083 newTriangles[13]= {nodeInd[3],midPointInd[0],midPointInd[2]};
4084 newTriangles[14]= {nodeInd[3],midPointInd[1],midPointInd[2]};
4085 newTriangles[15]= {midPointInd[0],midPointInd[1],midPointInd[2]};
4086
4087 newTrianglesFlag[12]= this->volumeID_;
4088 newTrianglesFlag[13]= this->volumeID_;
4089 newTrianglesFlag[14]= this->volumeID_;
4090 newTrianglesFlag[15]= originFlag[0];
4091
4092 isInterfaceSurface[12] = false;
4093 isInterfaceSurface[13] = false;
4094 isInterfaceSurface[14] = false;
4095 isInterfaceSurface[15] = interfaceSurface[0];
4096
4097
4098 newTriangleEdgeIDs[3]={18,19,21,18,20,22,19,20,23,21,22,23};
4099 // Now we add the elements, edges and triangles
4100
4101 // Adding Elements
4102 int offsetElements = this->elementsC_->numberElements();
4103 int offsetEdges = this->edgeElements_->numberElements();
4104 for( int i=0;i<4; i++){
4105 sort( newElements.at(i).begin(), newElements.at(i).end() );
4106 FiniteElement feNew(newElements.at(i),this->volumeID_);
4107 feNew.setFiniteElementRefinementType("irregular");
4108 feNew.setPredecessorElement(indexElement);
4109 if(i<3)
4110 this->elementsC_->addElement(feNew);
4111 else
4112 this->elementsC_->switchElement(indexElement,feNew);
4113 }
4114
4115 // Adding the edges (they also have to be added to triangles as subelements, but that is not implemented yet)
4116 for( int i=0;i<24; i++){
4117 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
4118 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
4119 feNew.setInterfaceElement(isInterfaceEdge[i]);
4120 feNew.setPredecessorElement(predecessorElement[i]);
4121 if(i<18){
4122 this->edgeElements_->addEdge(feNew,i/6+offsetElements);
4123 }
4124 else
4125 this->edgeElements_->addEdge(feNew,indexElement);
4126 }
4127
4128 // Adding triangles as subelements, if they arent interior triangles
4129 int offsetSurface=0;
4130 for( int i=0;i<16; i++){
4131 sort( newTriangles.at(i).begin(), newTriangles.at(i).end() );
4132 FiniteElement feNew(newTriangles[i],newTrianglesFlag[i]);
4133 feNew.setInterfaceElement(isInterfaceSurface[i]);
4134 if(i<12){
4135 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
4136 if ( !this->elementsC_->getElement(i/4+offsetElements).subElementsInitialized() )
4137 this->elementsC_->getElement(i/4+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
4138 this->elementsC_->getElement(i/4+offsetElements).addSubElement(feNew);
4139 }
4140 this->surfaceTriangleElements_->addSurface(feNew, i/4+offsetElements);
4141 }
4142 else{
4143 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
4144 if ( !this->elementsC_->getElement(indexElement).subElementsInitialized() )
4145 this->elementsC_->getElement(indexElement).initializeSubElements( this->FEType_, this->dim_ -1) ;
4146 this->elementsC_->getElement(indexElement).addSubElement(feNew);
4147 }
4148 this->surfaceTriangleElements_->addSurface(feNew, indexElement);
4149
4150 }
4151 }
4152 FiniteElement element;
4153 FiniteElement feEdge;
4154 for( int i=0;i<4; i++){
4155 if(i<3)
4156 element = this->elementsC_->getElement(i+offsetElements);
4157 else
4158 element = this->elementsC_->getElement(indexElement);
4159 bool init=false;
4160 for(int j=0; j<24 ; j++){
4161 FiniteElement feEdge = this->edgeElements_->getElement(j+offsetEdges);
4162 if(feEdge.getFlag() != this->volumeID_){
4163 if(init == true)
4164 element.addSubElement( feEdge );
4165 else if ( !element.subElementsInitialized() ){
4166 element.initializeSubElements( "P1", 1 ); // only P1 for now
4167 element.addSubElement( feEdge );
4168 init= true;
4169 }
4170 else {
4171 ElementsPtr_Type surfaces = element.getSubElements();
4172 // We set the edge to the corresponding element(s)
4173 surfaces->setToCorrectElement( feEdge );
4174 }
4175 }
4176 }
4177 }
4178
4179 }
4180 else
4181 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The Type 1 irregular Refinement Method you requested is only applicable to a 3 dimensional Mesh. Please reconsider.");
4182
4183
4184}
4185
4197template <class SC, class LO, class GO, class NO>
4198void RefinementFactory<SC,LO,GO,NO>::refineRegular(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements){
4199
4200 if(this->dim_ == 2){
4201 vec_int_Type midPointInd( 3 ); // indices of midpoints of edges of soon to be refined element
4202
4203 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
4204 int k=0;
4205 for(int i=0; i<3; i++) {
4206 midPointInd[i] = edgeElements->getMidpoint(edgeNumbers[i]);
4207 }
4208
4209 // Mutal Node of two edges
4210 vec_int_Type mutualNode(3);
4211 int ind=0;
4212 for(int i=0;i<2; i++){
4213 for(int j=1;j+i<3;j++){
4214 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(edgeNumbers[j+i]).getNode(0))
4215 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(0);
4216
4217 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(edgeNumbers[j+i]).getNode(1))
4218 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(1);
4219
4220 if(edgeElements->getElement(edgeNumbers[i]).getNode(0) == edgeElements->getElement(edgeNumbers[j+i]).getNode(1))
4221 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(1);
4222
4223 if(edgeElements->getElement(edgeNumbers[i]).getNode(1) == edgeElements->getElement(edgeNumbers[j+i]).getNode(0))
4224 mutualNode[ind]= edgeElements->getElement(edgeNumbers[j+i]).getNode(0);
4225
4226 ind++;
4227
4228 }}
4229
4230 // Adding Elements and the corresponding Edges
4231 vec2D_int_Type newElements(4, vec_int_Type( 0 )); // vector for the new elements
4232 vec2D_int_Type newEdges(12,vec_int_Type(0)); // vector for the new edges
4233 vec_int_Type edgeFlags(12); // vector for the new flags
4234
4235 vec_bool_Type isInterfaceEdge(12); // bool vector for interfaceEdges
4236 vec_GO_Type predecessorElement(12);
4237 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
4238
4239 // Element 1
4240 (newElements)[0]={mutualNode[0],midPointInd[0],midPointInd[1]};
4241
4242 (newEdges)[0] = {mutualNode[0] ,midPointInd[0]};
4243 (newEdges)[1] = {mutualNode[0] ,midPointInd[1]};
4244 (newEdges)[2] = {midPointInd[0] ,midPointInd[1]};
4245
4246 edgeFlags[0]=this->bcFlagRep_->at(midPointInd[0]);
4247 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[1]);
4248 edgeFlags[2]=this->volumeID_;
4249
4250 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
4251 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
4252 isInterfaceEdge[2] = false;
4253
4254 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
4255 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
4256 predecessorElement[2] = -1;
4257
4258
4259 // Element 2
4260 newElements[1]={mutualNode[1],midPointInd[0],midPointInd[2]};
4261
4262 (newEdges)[3] = {mutualNode[1] ,midPointInd[0]};
4263 (newEdges)[4] = {mutualNode[1] ,midPointInd[2]};
4264 (newEdges)[5] = {midPointInd[0] ,midPointInd[2]};
4265
4266 edgeFlags[3]=this->bcFlagRep_->at(midPointInd[0]);
4267 edgeFlags[4]=this->bcFlagRep_->at(midPointInd[2]);
4268 edgeFlags[5]=this->volumeID_;
4269
4270 isInterfaceEdge[3] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
4271 isInterfaceEdge[4] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
4272 isInterfaceEdge[5] = false;
4273
4274 predecessorElement[3] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
4275 predecessorElement[4] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
4276 predecessorElement[5] = -1;
4277
4278 // Element 3
4279 (newElements)[2]={mutualNode[2] , midPointInd[1] ,midPointInd[2]};
4280
4281 (newEdges)[6] = {mutualNode[2] ,midPointInd[1]};
4282 (newEdges)[7] = {mutualNode[2] ,midPointInd[2]};
4283 (newEdges)[8] = {midPointInd[1] ,midPointInd[2]};
4284
4285 edgeFlags[6]=this->bcFlagRep_->at(midPointInd[1]);
4286 edgeFlags[7]=this->bcFlagRep_->at(midPointInd[2]);
4287 edgeFlags[8]=this->volumeID_;
4288
4289 isInterfaceEdge[6] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
4290 isInterfaceEdge[7] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
4291 isInterfaceEdge[8] = false;
4292
4293 predecessorElement[6] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
4294 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
4295 predecessorElement[8] = -1;
4296
4297
4298 // Element 4
4299 (newElements)[3]={midPointInd[0],midPointInd[1],midPointInd[2]};
4300
4301 (newEdges)[9] = {midPointInd[0] ,midPointInd[1]};
4302 (newEdges)[10] = {midPointInd[1] ,midPointInd[2]};
4303 (newEdges)[11] = {midPointInd[2] ,midPointInd[0]};
4304
4305 edgeFlags[9]=this->volumeID_;
4306 edgeFlags[10]=this->volumeID_;
4307 edgeFlags[11]=this->volumeID_;
4308
4309 isInterfaceEdge[9] = false;
4310 isInterfaceEdge[10] = false;
4311 isInterfaceEdge[11] = false;
4312
4313 predecessorElement[9] = -1;
4314 predecessorElement[10] = -1;
4315 predecessorElement[11] = -1;
4316
4317
4318 int offsetElements = this->elementsC_->numberElements();
4319 int offsetEdges = this->edgeElements_->numberElements();
4320 for( int i=0;i<4; i++){
4321 sort( newElements.at(i).begin(), newElements.at(i).end() );
4322 FiniteElement feNew(newElements.at(i),this->volumeID_);
4323 feNew.setFiniteElementRefinementType("regular");
4324 feNew.setPredecessorElement(indexElement);
4325 if(i<3)
4326 this->elementsC_->addElement(feNew);
4327 else
4328 this->elementsC_->switchElement(indexElement,feNew);
4329 }
4330
4331 for( int i=0;i<12; i++){
4332 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
4333 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
4334 feNew.setInterfaceElement(isInterfaceEdge[i]);
4335 feNew.setPredecessorElement(predecessorElement[i]);
4336 if(i<9){
4337 this->edgeElements_->addEdge(feNew,i/3+offsetElements);
4338 if(edgeFlags[i]!=0 && edgeFlags[i]!=this->volumeID_){
4339 if ( !this->elementsC_->getElement(i/3+offsetElements).subElementsInitialized() )
4340 this->elementsC_->getElement(i/3+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
4341 this->elementsC_->getElement(i/3+offsetElements).addSubElement(feNew);
4342
4343 }
4344 }
4345 else
4346 this->edgeElements_->addEdge(feNew,indexElement);
4347
4348 }
4349
4350 }
4351 // -------------------------------------------------------------------
4352 // 3D Regular Refinement Algorithm
4353 // -------------------------------------------------------------------
4354 else if(this->dim_ == 3){
4355
4356 // The way we refine the Tetrahedron is defined by how we order the nodes of the tetrahedron
4357 // (For the algorithm see "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refinement' in Computing, Springer Verlag 1955)
4358
4359
4360 vec_int_Type midPointInd( 6 ); // indices of midpoints of edges of soon to be refined element
4361 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
4362
4363 // Extract the four points of tetraeder
4364 /*vec_int_Type nodeInd(0);
4365 for(int i=0; i<6; i++){
4366 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(0));
4367 nodeInd.push_back(edgeElements->getElement(edgeNumbers[i]).getNode(1));
4368 }
4369 sort( nodeInd.begin(), nodeInd.end() );
4370 nodeInd.erase( unique( nodeInd.begin(), nodeInd.end() ), nodeInd.end() );
4371 */
4372 vec_int_Type nodeInd = elements->getElement(indexElement).getVectorNodeList();
4373
4374 vec2D_dbl_ptr_Type pointsRep = this->pointsRep_;
4375 // Right now the Nodes are ordered by the local Indices, which differ depending on the number of Processors. Hence the refinements are not
4376 // 100% equal when using a different number of processors.
4377 // If we sort the nodes by their values and not their local Indices, we can solve that problem, as these values don't change
4378 // This can also be done by using the global IDs of nodes
4379
4380 /*vec2D_dbl_Type points(4,vec_dbl_Type(4));
4381 points[0] = {pointsRep->at(nodeInd[0]).at(0),pointsRep->at(nodeInd[0]).at(1),pointsRep->at(nodeInd[0]).at(2), (double) nodeInd[0]};
4382 points[1] = {pointsRep->at(nodeInd[1]).at(0),pointsRep->at(nodeInd[1]).at(1),pointsRep->at(nodeInd[1]).at(2), (double) nodeInd[1]};
4383 points[2] = {pointsRep->at(nodeInd[2]).at(0),pointsRep->at(nodeInd[2]).at(1),pointsRep->at(nodeInd[2]).at(2), (double) nodeInd[2]};
4384 points[3] = {pointsRep->at(nodeInd[3]).at(0),pointsRep->at(nodeInd[3]).at(1),pointsRep->at(nodeInd[3]).at(2), (double) nodeInd[3]};
4385
4386 sort(points.begin(), points.end());
4387
4388 nodeInd[0] = (int) points[0][3];
4389 nodeInd[1] = (int) points[1][3];
4390 nodeInd[2] = (int) points[2][3];
4391 nodeInd[3] = (int) points[3][3];*/
4392
4393 // NOTE: The above described way of ensuring 100% equal refinement on a varing number of processors is disabled, as we want to keep natural element properties (Sorting such that determinant of element is always > 0)
4394
4395 // With our sorted Nodes we construct edges as follows
4396
4397 // Edge_0 = [x_0,x_1]
4398 // Edge_1 = [x_0,x_2]
4399 // Edge_2 = [x_0,x_3]
4400 // Edge_3 = [x_1,x_2]
4401 // Edge_4 = [x_1,x_3]
4402 // Edge_5 = [x_2,x_3]
4403
4404
4405 vec_int_Type edgeNumbersTmp = edgeNumbers;
4406 for(int i=0; i<6; i++){
4407 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[0] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[0]){
4408 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1])
4409 edgeNumbers[0] = edgeNumbersTmp[i];
4410 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
4411 edgeNumbers[1] = edgeNumbersTmp[i];
4412 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
4413 edgeNumbers[2] = edgeNumbersTmp[i];
4414 }
4415 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[1] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[1]){
4416 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2])
4417 edgeNumbers[3] = edgeNumbersTmp[i];
4418 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
4419 edgeNumbers[4] = edgeNumbersTmp[i];
4420 }
4421 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[2] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[2]){
4422 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == nodeInd[3] || edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == nodeInd[3])
4423 edgeNumbers[5] = edgeNumbersTmp[i];
4424 }
4425 }
4426
4427 // We have 4 Triangles in our Tetraedron
4428 // If one or more of those Triangles are Part of the domains' boundaries, they are added to the element in question as subelement
4429 // We extract them in follwing pattern:
4430
4431 // Tri_0 = [x_0,x_1,x_2]
4432 // Tri_1 = [x_0,x_1,x_3]
4433 // Tri_2 = [x_0,x_2,x_3]
4434 // Tri_3 = [x_1,x_2,x_3]
4435
4436 // We check if one or more of these triangles are part of the boundary surface and determine their flag
4437 vec_int_Type surfaceElementsIDs = surfaceTriangleElements->getSurfacesOfElement(indexElement); // surfaces of Element k
4438 vec2D_int_Type originTriangles(4,vec_int_Type(3));
4439
4440 originTriangles[0] = {nodeInd[0], nodeInd[1], nodeInd[2] };
4441 originTriangles[1] = {nodeInd[0], nodeInd[1], nodeInd[3] };
4442 originTriangles[2] = {nodeInd[0], nodeInd[2], nodeInd[3] };
4443 originTriangles[3] = {nodeInd[1], nodeInd[2], nodeInd[3] };
4444
4445
4446
4447 vec_int_Type originFlag(4,this->volumeID_); // Triangle Flag
4448
4449 vec_bool_Type interfaceSurface(4);
4450 vec_LO_Type triTmp(3);
4451 vec_int_Type originTriangleTmp(3);
4452
4453 for(int i=0; i< 4 ; i++){
4454 originTriangleTmp = originTriangles[i];
4455 sort(originTriangleTmp.begin(),originTriangleTmp.end());
4456 for(int j=0; j<4 ; j++){
4457 FiniteElement surfaceTmp = surfaceTriangleElements->getElement(surfaceElementsIDs[j]);
4458 triTmp = surfaceTmp.getVectorNodeList();
4459 sort(triTmp.begin(),triTmp.end());
4460 if(triTmp[0] == originTriangleTmp[0] && triTmp[1] == originTriangleTmp[1] && triTmp[2] == originTriangleTmp[2] ) {
4461 originFlag[i] = surfaceTmp.getFlag();
4462 interfaceSurface[i] = surfaceTmp.isInterfaceElement();
4463 }
4464 }
4465 }
4466
4467
4468 // Furthermore we have to determine whether the triangles are part of the interface between processors, as we need this information to determine if edges
4469 // that emerge on the triangles are part of the interface
4470 // A triangle is part of the interface if all of its edges are part of the interface (the information if edges are part of the interface was determined
4471 // at the beginning of the Mesh Refinement by 'determineInterfaceEdges')
4472
4473
4474
4475 // Finally we need to determine or extract the indices of the edges midpoints. As in the describe algorithm the midpoints are set as follows:
4476 // Edge 0 = [x_0,x_1] -> x_01
4477 // Edge 1 = [x_0,x_2] -> x_02
4478 // Edge 2 = [x_0,x_3] -> x_03
4479 // Edge 3 = [x_1,x_2] -> x_12
4480 // Edge 4 = [x_1,x_3] -> x_13
4481 // Edge 5 = [x_2,x_3] -> x_23
4482
4483
4484
4485 for(int i=0; i<6; i++){
4486 if(!edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()) // we tag every edge, after we refine an element -> no tag - no refinement on that edge so far
4487 {
4488 this->addMidpoint(edgeElements,edgeNumbers[i]);
4489 midPointInd[i] = edgeElements->getMidpoint(edgeNumbers[i]);
4490 }
4491 else{
4492 midPointInd[i] = edgeElements->getMidpoint(edgeNumbers[i]);
4493
4494 }
4495
4496 }
4497
4498
4499 // Now we construct the new Elements as proposed by Bey's Regular Refinement Algorithm
4500
4501 vec2D_int_Type newElements(8, vec_int_Type( 0 )); // new elements
4502 vec2D_int_Type newEdges(48,vec_int_Type(0)); // new edges
4503 vec2D_int_Type newTriangles(32,vec_int_Type(0)); // new Triangles
4504 vec_int_Type newTrianglesFlag(32) ; // new Triangle Flags
4505 vec_int_Type isInterfaceSurface(32);
4506 vec_int_Type edgeFlags(48); // new Edge flags
4507 vec_bool_Type isInterfaceEdge(48); // bool vector for interfaceEdge Information
4508 vec_GO_Type predecessorElement(48); // vector that stores the global IDs of the predecessor of each edge
4509
4510 vec2D_LO_Type newTriangleEdgeIDs(8,vec_LO_Type(12));
4511
4512 // How are Flags determined?
4513 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
4514 // If an edges emerges on a triangle, the flag is determined by the triangle flag. Opposite to the 2D case, edges that connect midpoints are not automatically interior edges, but are
4515 // determined by the triangle/surface they are on
4516
4517
4518 // Element 1: (x_0,x_01,x_02,x_03)
4519 (newElements)[0]={nodeInd[0],midPointInd[0],midPointInd[1],midPointInd[2]};
4520
4521 (newEdges)[0] = {nodeInd[0] ,midPointInd[0]};
4522 (newEdges)[1] = {nodeInd[0] ,midPointInd[1]};
4523 (newEdges)[2] = {nodeInd[0] ,midPointInd[2]};
4524 (newEdges)[3] = {midPointInd[0] ,midPointInd[1]};
4525 (newEdges)[4] = {midPointInd[0] ,midPointInd[2]};
4526 (newEdges)[5] = {midPointInd[1] ,midPointInd[2]};
4527
4528 edgeFlags[0]=this->bcFlagRep_->at(midPointInd[0]);
4529 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[1]);
4530 edgeFlags[2]=this->bcFlagRep_->at(midPointInd[2]);
4531 edgeFlags[3]=originFlag[0];
4532 edgeFlags[4]=originFlag[1];
4533 edgeFlags[5]=originFlag[2];
4534
4535 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
4536 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
4537 isInterfaceEdge[2] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
4538 isInterfaceEdge[3] = interfaceSurface[0];
4539 isInterfaceEdge[4] = interfaceSurface[1];
4540 isInterfaceEdge[5] = interfaceSurface[2];
4541
4542 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
4543 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
4544 predecessorElement[2] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
4545 predecessorElement[3] = -1;
4546 predecessorElement[4] = -1;
4547 predecessorElement[5] = -1;
4548
4549 // Subelements of thetrahedron
4550 newTriangles[0]= {nodeInd[0],midPointInd[1],midPointInd[0]};
4551 newTriangles[1]= {nodeInd[0],midPointInd[0],midPointInd[2]};
4552 newTriangles[2]= {nodeInd[0],midPointInd[2],midPointInd[1]};
4553 newTriangles[3]= {midPointInd[0],midPointInd[1],midPointInd[2]};
4554
4555 newTrianglesFlag[0]= originFlag[0];
4556 newTrianglesFlag[1]= originFlag[1];
4557 newTrianglesFlag[2]= originFlag[2];
4558 newTrianglesFlag[3]= this->volumeID_;
4559
4560 isInterfaceSurface[0] = interfaceSurface[0];
4561 isInterfaceSurface[1] = interfaceSurface[1];
4562 isInterfaceSurface[2] = interfaceSurface[2];
4563 isInterfaceSurface[3] = false;
4564
4565 newTriangleEdgeIDs[0]={0,1,3,0,2,4,1,2,5,3,4,5};
4566 // Element 2: (x_01,x_1,x_12,x_13)
4567 (newElements)[1]={midPointInd[0],nodeInd[1],midPointInd[3],midPointInd[4]};
4568
4569 (newEdges)[6] = {nodeInd[1] ,midPointInd[0]};
4570 (newEdges)[7] = {nodeInd[1] ,midPointInd[3]};
4571 (newEdges)[8] = {nodeInd[1] ,midPointInd[4]};
4572 (newEdges)[9] = {midPointInd[0] ,midPointInd[3]};
4573 (newEdges)[10] = {midPointInd[0] ,midPointInd[4]};
4574 (newEdges)[11] = {midPointInd[3] ,midPointInd[4]};
4575
4576 edgeFlags[6]=this->bcFlagRep_->at(midPointInd[0]);
4577 edgeFlags[7]=this->bcFlagRep_->at(midPointInd[3]);
4578 edgeFlags[8]=this->bcFlagRep_->at(midPointInd[4]);
4579 edgeFlags[9]=originFlag[0];
4580 edgeFlags[10]=originFlag[1];
4581 edgeFlags[11]=originFlag[3];
4582
4583 isInterfaceEdge[6] =edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
4584 isInterfaceEdge[7] =edgeElements->getElement(edgeNumbers[3]).isInterfaceElement();
4585 isInterfaceEdge[8] =edgeElements->getElement(edgeNumbers[4]).isInterfaceElement();
4586 isInterfaceEdge[9] = interfaceSurface[0];
4587 isInterfaceEdge[10] = interfaceSurface[1];
4588 isInterfaceEdge[11] = interfaceSurface[3];
4589
4590 predecessorElement[6] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
4591 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[3]);
4592 predecessorElement[8] = this->edgeMap_->getGlobalElement(edgeNumbers[4]);
4593 predecessorElement[9] = -1;
4594 predecessorElement[10] = -1;
4595 predecessorElement[11] = -1;
4596
4597 // Subelements of tetrahedron
4598 newTriangles[4]= {nodeInd[1],midPointInd[0],midPointInd[3]};
4599 newTriangles[5]= {nodeInd[1],midPointInd[4],midPointInd[0]};
4600 newTriangles[6]= {nodeInd[1],midPointInd[3],midPointInd[4]};
4601 newTriangles[7]= {midPointInd[0],midPointInd[3],midPointInd[4]};
4602
4603 newTrianglesFlag[4]= originFlag[0];
4604 newTrianglesFlag[5]= originFlag[1];
4605 newTrianglesFlag[6]= originFlag[3];
4606 newTrianglesFlag[7]= this->volumeID_;
4607
4608 isInterfaceSurface[4] = interfaceSurface[0];
4609 isInterfaceSurface[5] = interfaceSurface[1];
4610 isInterfaceSurface[6] = interfaceSurface[3];
4611 isInterfaceSurface[7] = false;
4612
4613 newTriangleEdgeIDs[1]={6,7,9,6,8,10,7,8,11,9,10,11};
4614 // Element 3: (x_2,x_02,x_12,x_23)
4615 (newElements)[2]={nodeInd[2],midPointInd[1],midPointInd[3],midPointInd[5]};
4616
4617 (newEdges)[12] = {nodeInd[2] ,midPointInd[1]};
4618 (newEdges)[13] = {nodeInd[2] ,midPointInd[3]};
4619 (newEdges)[14] = {nodeInd[2] ,midPointInd[5]};
4620 (newEdges)[15] = {midPointInd[1] ,midPointInd[3]};
4621 (newEdges)[16] = {midPointInd[1] ,midPointInd[5]};
4622 (newEdges)[17] = {midPointInd[3] ,midPointInd[5]};
4623
4624 edgeFlags[12]=this->bcFlagRep_->at(midPointInd[1]);
4625 edgeFlags[13]=this->bcFlagRep_->at(midPointInd[3]);
4626 edgeFlags[14]=this->bcFlagRep_->at(midPointInd[5]);
4627 edgeFlags[15]=originFlag[0];
4628 edgeFlags[16]=originFlag[2];
4629 edgeFlags[17]=originFlag[3];
4630
4631 isInterfaceEdge[12] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
4632 isInterfaceEdge[13] = edgeElements->getElement(edgeNumbers[3]).isInterfaceElement();
4633 isInterfaceEdge[14] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
4634 isInterfaceEdge[15] = interfaceSurface[0];
4635 isInterfaceEdge[16] = interfaceSurface[2];
4636 isInterfaceEdge[17] = interfaceSurface[3];
4637
4638 predecessorElement[12] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
4639 predecessorElement[13] = this->edgeMap_->getGlobalElement(edgeNumbers[3]);
4640 predecessorElement[14] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
4641 predecessorElement[15] = -1;
4642 predecessorElement[16] = -1;
4643 predecessorElement[17] = -1;
4644
4645 // Subelements of thetrahedron
4646 newTriangles[8]= {nodeInd[2],midPointInd[3],midPointInd[1]};
4647 newTriangles[9]= {nodeInd[2],midPointInd[1],midPointInd[5]};
4648 newTriangles[10]= {nodeInd[2],midPointInd[5],midPointInd[3]};
4649 newTriangles[11]= {midPointInd[1],midPointInd[3],midPointInd[5]};
4650
4651 newTrianglesFlag[8]= originFlag[0];
4652 newTrianglesFlag[9]= originFlag[2];
4653 newTrianglesFlag[10]= originFlag[3];
4654 newTrianglesFlag[11]= this->volumeID_;
4655
4656 isInterfaceSurface[8] = interfaceSurface[0];
4657 isInterfaceSurface[9] = interfaceSurface[2];
4658 isInterfaceSurface[10] = interfaceSurface[3];
4659 isInterfaceSurface[11] = false;
4660
4661 newTriangleEdgeIDs[2]={12,13,15,12,14,16,13,14,17,15,16,17};
4662
4663 // Element 4: (x_3,x_03,x_13,x_23)
4664 (newElements)[3]={midPointInd[2],midPointInd[4],midPointInd[5],nodeInd[3]};
4665
4666 (newEdges)[18] = {nodeInd[3] ,midPointInd[2]};
4667 (newEdges)[19] = {nodeInd[3] ,midPointInd[4]};
4668 (newEdges)[20] = {nodeInd[3] ,midPointInd[5]};
4669 (newEdges)[21] = {midPointInd[2] ,midPointInd[4]};
4670 (newEdges)[22] = {midPointInd[2] ,midPointInd[5]};
4671 (newEdges)[23] = {midPointInd[4] ,midPointInd[5]};
4672
4673 edgeFlags[18]=this->bcFlagRep_->at(midPointInd[2]);
4674 edgeFlags[19]=this->bcFlagRep_->at(midPointInd[4]);
4675 edgeFlags[20]=this->bcFlagRep_->at(midPointInd[5]);
4676 edgeFlags[21]=originFlag[1];
4677 edgeFlags[22]=originFlag[2];
4678 edgeFlags[23]=originFlag[3];
4679
4680 isInterfaceEdge[18] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
4681 isInterfaceEdge[19] = edgeElements->getElement(edgeNumbers[4]).isInterfaceElement();
4682 isInterfaceEdge[20] = edgeElements->getElement(edgeNumbers[5]).isInterfaceElement();
4683 isInterfaceEdge[21] = interfaceSurface[1];
4684 isInterfaceEdge[22] = interfaceSurface[2];
4685 isInterfaceEdge[23] = interfaceSurface[3];
4686
4687 predecessorElement[18] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
4688 predecessorElement[19] = this->edgeMap_->getGlobalElement(edgeNumbers[4]);
4689 predecessorElement[20] = this->edgeMap_->getGlobalElement(edgeNumbers[5]);
4690 predecessorElement[21] = -1;
4691 predecessorElement[22] = -1;
4692 predecessorElement[23] = -1;
4693
4694
4695 // Subelements of thetrahedron
4696 newTriangles[12]= {nodeInd[3],midPointInd[2],midPointInd[4]};
4697 newTriangles[13]= {nodeInd[3],midPointInd[5],midPointInd[2]};
4698 newTriangles[14]= {nodeInd[3],midPointInd[4],midPointInd[5]};
4699 newTriangles[15]= {midPointInd[2],midPointInd[4],midPointInd[5]};
4700
4701 newTrianglesFlag[12]= originFlag[1];
4702 newTrianglesFlag[13]= originFlag[2];
4703 newTrianglesFlag[14]= originFlag[3];
4704 newTrianglesFlag[15]= this->volumeID_;
4705
4706 isInterfaceSurface[12] = interfaceSurface[1];
4707 isInterfaceSurface[13] = interfaceSurface[2];
4708 isInterfaceSurface[14] = interfaceSurface[3];
4709 isInterfaceSurface[15] = false;
4710
4711
4712 newTriangleEdgeIDs[3]={18,19,20,18,20,22,19,21,23,21,22,23};
4713
4714 // The following elements are constructed only with the edges midpoints, hence they have the surface flag and interface characteristic
4715 // In order to control a certain mesh quality the diagonal cut, which is usually between midpoint[1] and midPoint[4]
4716 vec_dbl_Type lengthDia(3);
4717
4718 int diaInd=0;
4719
4720 lengthDia[0] = std::sqrt(std::pow(pointsRep->at(midPointInd[1]).at(0) - pointsRep->at(midPointInd[4]).at(0),2) + std::pow(pointsRep->at(midPointInd[1]).at(1) - pointsRep->at(midPointInd[4]).at(1),2) +std::pow(pointsRep->at(midPointInd[1]).at(2) - pointsRep->at(midPointInd[4]).at(2),2) );
4721
4722 lengthDia[1] = std::sqrt(std::pow(pointsRep->at(midPointInd[0]).at(0) - pointsRep->at(midPointInd[5]).at(0),2) + std::pow(pointsRep->at(midPointInd[0]).at(1) - pointsRep->at(midPointInd[5]).at(1),2) +std::pow(pointsRep->at(midPointInd[0]).at(2) - pointsRep->at(midPointInd[5]).at(2),2) );
4723
4724 lengthDia[2] = std::sqrt(std::pow(pointsRep->at(midPointInd[2]).at(0) - pointsRep->at(midPointInd[3]).at(0),2) + std::pow(pointsRep->at(midPointInd[2]).at(1) - pointsRep->at(midPointInd[3]).at(1),2) +std::pow(pointsRep->at(midPointInd[2]).at(2) - pointsRep->at(midPointInd[3]).at(2),2) );
4725
4726
4727 vec2D_dbl_Type dia(3,vec_dbl_Type(2));
4728 dia[0] = { lengthDia[0],0.};
4729 dia[1] = { lengthDia[1],1.};
4730 dia[2] = { lengthDia[2],2.};
4731 sort(dia.begin(),dia.end());
4732
4733 // Diagonal 0 represents the shortest
4734 // Diagonal 1 represents the second shortest
4735 // Diagonal 2 represents the longest
4736
4737 // If the Diagonal is not within that range we allways use diaInd =0. Same Diagonal with consistent indexing of elements
4738 if(refinement3DDiagonal_>2 || refinement3DDiagonal_ == 0)
4739 diaInd =0;
4740 else {
4741 diaInd = (int) dia[refinement3DDiagonal_][1];
4742 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The Refinement feature to pick a specific internal Diagonal in regular refinement is not yet orientation preserving!");
4743
4744 }
4745
4746
4747 // Element 5: (x_01,x_02,x_03,x_12)
4748 if(diaInd ==0){
4749 (newElements)[4]={midPointInd[0],midPointInd[1],midPointInd[2],midPointInd[4]};
4750
4751 (newEdges)[24] = {midPointInd[0] ,midPointInd[1]};
4752 (newEdges)[25] = {midPointInd[0] ,midPointInd[2]};
4753 (newEdges)[26] = {midPointInd[0] ,midPointInd[4]};
4754 (newEdges)[27] = {midPointInd[1] ,midPointInd[2]};
4755 (newEdges)[28] = {midPointInd[1] ,midPointInd[4]};
4756 (newEdges)[29] = {midPointInd[2] ,midPointInd[4]};
4757
4758 edgeFlags[24]=originFlag[0];
4759 edgeFlags[25]=originFlag[1];
4760 edgeFlags[26]=originFlag[1];
4761 edgeFlags[27]=originFlag[2];
4762 edgeFlags[28]=this->volumeID_;
4763 edgeFlags[29]=originFlag[1];
4764
4765 isInterfaceEdge[24] = interfaceSurface[0];
4766 isInterfaceEdge[25] = interfaceSurface[1];
4767 isInterfaceEdge[26] = interfaceSurface[1];
4768 isInterfaceEdge[27] = interfaceSurface[2];
4769 isInterfaceEdge[28] = false;
4770 isInterfaceEdge[29] = interfaceSurface[1];
4771
4772
4773 predecessorElement[24] = -1;
4774 predecessorElement[25] = -1;
4775 predecessorElement[26] = -1;
4776 predecessorElement[27] = -1;
4777 predecessorElement[28] = -1;
4778 predecessorElement[29] = -1;
4779
4780 // Subelements of thetrahedron
4781 newTriangles[16]= {midPointInd[0],midPointInd[1],midPointInd[2]};
4782 newTriangles[17]= {midPointInd[0],midPointInd[1],midPointInd[4]};
4783 newTriangles[18]= {midPointInd[0],midPointInd[4],midPointInd[2]};
4784 newTriangles[19]= {midPointInd[1],midPointInd[2],midPointInd[4]};
4785
4786
4787 newTrianglesFlag[16]= this->volumeID_;
4788 newTrianglesFlag[17]= this->volumeID_;
4789 newTrianglesFlag[18]= originFlag[1];
4790 newTrianglesFlag[19]= this->volumeID_;
4791
4792 isInterfaceSurface[16] = false;
4793 isInterfaceSurface[17] = false;
4794 isInterfaceSurface[18] = interfaceSurface[1];
4795 isInterfaceSurface[19] = false;
4796
4797 newTriangleEdgeIDs[4]={24,25,27,24,26,28,25,26,29,27,28,29};
4798
4799 // Element 6: (x_01,x_02,x_12,x_13)
4800 (newElements)[5]={midPointInd[0],midPointInd[3],midPointInd[1],midPointInd[4]};
4801
4802 (newEdges)[30] = {midPointInd[0],midPointInd[1]};
4803 (newEdges)[31] = {midPointInd[0] ,midPointInd[3]};
4804 (newEdges)[32] = {midPointInd[0],midPointInd[4]};
4805 (newEdges)[33] = {midPointInd[1] ,midPointInd[3]};
4806 (newEdges)[34] = {midPointInd[1] ,midPointInd[4]};
4807 (newEdges)[35] = {midPointInd[3] ,midPointInd[4]};
4808
4809 edgeFlags[30]=originFlag[0];
4810 edgeFlags[31]=originFlag[0];
4811 edgeFlags[32]=originFlag[1];
4812 edgeFlags[33]=originFlag[0];
4813 edgeFlags[34]=this->volumeID_;
4814 edgeFlags[35]=originFlag[3];
4815
4816 isInterfaceEdge[30] = interfaceSurface[0];
4817 isInterfaceEdge[31] = interfaceSurface[0];
4818 isInterfaceEdge[32] = interfaceSurface[1];
4819 isInterfaceEdge[33] = interfaceSurface[0];
4820 isInterfaceEdge[34] = false;
4821 isInterfaceEdge[35] = interfaceSurface[3];
4822
4823 predecessorElement[30] = -1;
4824 predecessorElement[31] = -1;
4825 predecessorElement[32] = -1;
4826 predecessorElement[33] = -1;
4827 predecessorElement[34] = -1;
4828 predecessorElement[35] = -1;
4829
4830
4831 // Subelements of thetrahedron
4832 newTriangles[20]= {midPointInd[0],midPointInd[1],midPointInd[3]};
4833 newTriangles[21]= {midPointInd[0],midPointInd[1],midPointInd[4]};
4834 newTriangles[22]= {midPointInd[0],midPointInd[3],midPointInd[4]};
4835 newTriangles[23]= {midPointInd[1],midPointInd[3],midPointInd[4]};
4836
4837 newTrianglesFlag[20]= originFlag[0];
4838 newTrianglesFlag[21]= this->volumeID_;
4839 newTrianglesFlag[22]= this->volumeID_;
4840 newTrianglesFlag[23]= this->volumeID_;
4841
4842 isInterfaceSurface[20] = interfaceSurface[0];
4843 isInterfaceSurface[21] = false;
4844 isInterfaceSurface[22] = false;
4845 isInterfaceSurface[23] = false;
4846
4847 newTriangleEdgeIDs[5]={30,31,33,30,32,34,31,32,35,33,34,35};
4848 // Element 7: (x_02,x_03,x_13,x_23)
4849 (newElements)[6]={midPointInd[1],midPointInd[2],midPointInd[4],midPointInd[5]};
4850
4851 (newEdges)[36] = {midPointInd[1] ,midPointInd[2]};
4852 (newEdges)[37] = {midPointInd[1] ,midPointInd[4]};
4853 (newEdges)[38] = {midPointInd[1] ,midPointInd[5]};
4854 (newEdges)[39] = {midPointInd[2] ,midPointInd[4]};
4855 (newEdges)[40] = {midPointInd[2] ,midPointInd[5]};
4856 (newEdges)[41] = {midPointInd[4] ,midPointInd[5]};
4857
4858 edgeFlags[36]=originFlag[2];
4859 edgeFlags[37]=this->volumeID_;
4860 edgeFlags[38]=originFlag[2];
4861 edgeFlags[39]=originFlag[1];
4862 edgeFlags[40]=originFlag[2];
4863 edgeFlags[41]=originFlag[3];
4864
4865 isInterfaceEdge[36] = interfaceSurface[2];
4866 isInterfaceEdge[37] = false;
4867 isInterfaceEdge[38] = interfaceSurface[2];
4868 isInterfaceEdge[39] = interfaceSurface[1];
4869 isInterfaceEdge[40] = interfaceSurface[2];
4870 isInterfaceEdge[41] = interfaceSurface[3];
4871
4872 predecessorElement[36] = -1;
4873 predecessorElement[37] = -1;
4874 predecessorElement[38] = -1;
4875 predecessorElement[39] = -1;
4876 predecessorElement[40] = -1;
4877 predecessorElement[41] = -1;
4878
4879 // Subelements of thetrahedron
4880 newTriangles[24]= {midPointInd[1],midPointInd[2],midPointInd[4]};
4881 newTriangles[25]= {midPointInd[1],midPointInd[2],midPointInd[5]};
4882 newTriangles[26]= {midPointInd[1],midPointInd[4],midPointInd[5]};
4883 newTriangles[27]= {midPointInd[2],midPointInd[4],midPointInd[5]};
4884
4885 newTrianglesFlag[24]= this->volumeID_;
4886 newTrianglesFlag[25]= originFlag[2];
4887 newTrianglesFlag[26]= this->volumeID_;
4888 newTrianglesFlag[27]= this->volumeID_;
4889
4890 isInterfaceSurface[24] = false;
4891 isInterfaceSurface[25] = interfaceSurface[2];
4892 isInterfaceSurface[26] = false;
4893 isInterfaceSurface[27] = false;
4894
4895 newTriangleEdgeIDs[6]={36,37,39,36,38,40,37,38,41,39,40,41};
4896
4897 // Element 8: (x_02,x_12,x_13,x_23)
4898 (newElements)[7]={midPointInd[1],midPointInd[3],midPointInd[5],midPointInd[4]};
4899
4900 (newEdges)[42] = {midPointInd[1] ,midPointInd[3]};
4901 (newEdges)[43] = {midPointInd[1] ,midPointInd[4]};
4902 (newEdges)[44] = {midPointInd[1] ,midPointInd[5]};
4903 (newEdges)[45] = {midPointInd[3] ,midPointInd[4]};
4904 (newEdges)[46] = {midPointInd[3] ,midPointInd[5]};
4905 (newEdges)[47] = {midPointInd[4] ,midPointInd[5]};
4906
4907 edgeFlags[42]=originFlag[0];
4908 edgeFlags[43]=this->volumeID_;
4909 edgeFlags[44]=originFlag[2];
4910 edgeFlags[45]=originFlag[3];
4911 edgeFlags[46]=originFlag[3];
4912 edgeFlags[47]=originFlag[3];
4913
4914 isInterfaceEdge[42] = interfaceSurface[0];
4915 isInterfaceEdge[43] = false;
4916 isInterfaceEdge[44] = interfaceSurface[2];
4917 isInterfaceEdge[45] = interfaceSurface[3];
4918 isInterfaceEdge[46] = interfaceSurface[3];
4919 isInterfaceEdge[47] = interfaceSurface[3];
4920
4921 predecessorElement[42] = -1;
4922 predecessorElement[43] = -1;
4923 predecessorElement[44] = -1;
4924 predecessorElement[45] = -1;
4925 predecessorElement[46] = -1;
4926 predecessorElement[47] = -1;
4927
4928 // Subelements of thetrahedron
4929 newTriangles[28]= {midPointInd[1],midPointInd[3],midPointInd[4]};
4930 newTriangles[29]= {midPointInd[1],midPointInd[3],midPointInd[5]};
4931 newTriangles[30]= {midPointInd[1],midPointInd[4],midPointInd[5]};
4932 newTriangles[31]= {midPointInd[3],midPointInd[5],midPointInd[4]};
4933
4934 newTrianglesFlag[28]= this->volumeID_;
4935 newTrianglesFlag[29]= this->volumeID_;
4936 newTrianglesFlag[30]= this->volumeID_;
4937 newTrianglesFlag[31]= originFlag[3];
4938
4939 isInterfaceSurface[28] = false;
4940 isInterfaceSurface[29] = false;
4941 isInterfaceSurface[30] = false;
4942 isInterfaceSurface[31] = interfaceSurface[3];
4943
4944 newTriangleEdgeIDs[7]={42,43,45,42,44,46,43,44,47,45,46,47};
4945 }
4946
4947 else if(diaInd ==1){
4948 // Element 5:
4949 (newElements)[4]={midPointInd[0],midPointInd[1],midPointInd[2],midPointInd[5]};
4950
4951 (newEdges)[24] = {midPointInd[0] ,midPointInd[1]};
4952 (newEdges)[25] = {midPointInd[0] ,midPointInd[2]};
4953 (newEdges)[26] = {midPointInd[0] ,midPointInd[5]};
4954 (newEdges)[27] = {midPointInd[1] ,midPointInd[2]};
4955 (newEdges)[28] = {midPointInd[1] ,midPointInd[5]};
4956 (newEdges)[29] = {midPointInd[2] ,midPointInd[5]};
4957
4958 edgeFlags[24]=originFlag[0];
4959 edgeFlags[25]=originFlag[1];
4960 edgeFlags[26]=this->volumeID_;
4961 edgeFlags[27]=originFlag[2];
4962 edgeFlags[28]=originFlag[2];
4963 edgeFlags[29]=originFlag[2];
4964
4965 isInterfaceEdge[24] = interfaceSurface[0];
4966 isInterfaceEdge[25] = interfaceSurface[1];
4967 isInterfaceEdge[26] = false;
4968 isInterfaceEdge[27] = interfaceSurface[2];
4969 isInterfaceEdge[28] = interfaceSurface[2];
4970 isInterfaceEdge[29] = interfaceSurface[2];
4971
4972
4973 predecessorElement[24] = -1;
4974 predecessorElement[25] = -1;
4975 predecessorElement[26] = -1;
4976 predecessorElement[27] = -1;
4977 predecessorElement[28] = -1;
4978 predecessorElement[29] = -1;
4979
4980 // Subelements of thetrahedron
4981 newTriangles[16]= {midPointInd[0],midPointInd[1],midPointInd[2]};
4982 newTriangles[17]= {midPointInd[0],midPointInd[1],midPointInd[5]};
4983 newTriangles[18]= {midPointInd[0],midPointInd[2],midPointInd[5]};
4984 newTriangles[19]= {midPointInd[1],midPointInd[2],midPointInd[5]};
4985
4986
4987 newTrianglesFlag[16]= this->volumeID_;
4988 newTrianglesFlag[17]= this->volumeID_;
4989 newTrianglesFlag[18]= this->volumeID_;
4990 newTrianglesFlag[19]= originFlag[2];
4991
4992 isInterfaceSurface[16] = false;
4993 isInterfaceSurface[17] = false;
4994 isInterfaceSurface[18] = false;
4995 isInterfaceSurface[19] = interfaceSurface[2];;
4996
4997 newTriangleEdgeIDs[4]={24,25,27,24,26,28,25,26,29,27,28,29};
4998
4999 // Element 6: (x_01,x_02,x_12,x_13)
5000 (newElements)[5]={midPointInd[0],midPointInd[3],midPointInd[4],midPointInd[5]};
5001
5002 (newEdges)[30] = {midPointInd[0],midPointInd[3]};
5003 (newEdges)[31] = {midPointInd[0] ,midPointInd[4]};
5004 (newEdges)[32] = {midPointInd[0],midPointInd[5]};
5005 (newEdges)[33] = {midPointInd[3] ,midPointInd[4]};
5006 (newEdges)[34] = {midPointInd[3] ,midPointInd[5]};
5007 (newEdges)[35] = {midPointInd[4] ,midPointInd[5]};
5008
5009 edgeFlags[30]=originFlag[0];
5010 edgeFlags[31]=originFlag[1];
5011 edgeFlags[32]=this->volumeID_;
5012 edgeFlags[33]=originFlag[3];
5013 edgeFlags[34]=originFlag[3];
5014 edgeFlags[35]=originFlag[3];
5015
5016 isInterfaceEdge[30] = interfaceSurface[0];
5017 isInterfaceEdge[31] = interfaceSurface[1];
5018 isInterfaceEdge[32] = false;
5019 isInterfaceEdge[33] = interfaceSurface[3];
5020 isInterfaceEdge[34] = interfaceSurface[3];
5021 isInterfaceEdge[35] = interfaceSurface[3];
5022
5023 predecessorElement[30] = -1;
5024 predecessorElement[31] = -1;
5025 predecessorElement[32] = -1;
5026 predecessorElement[33] = -1;
5027 predecessorElement[34] = -1;
5028 predecessorElement[35] = -1;
5029
5030
5031 // Subelements of thetrahedron
5032 newTriangles[20]= {midPointInd[0],midPointInd[3],midPointInd[4]};
5033 newTriangles[21]= {midPointInd[0],midPointInd[3],midPointInd[5]};
5034 newTriangles[22]= {midPointInd[0],midPointInd[4],midPointInd[5]};
5035 newTriangles[23]= {midPointInd[3],midPointInd[4],midPointInd[5]};
5036
5037 newTrianglesFlag[20]= this->volumeID_;
5038 newTrianglesFlag[21]= this->volumeID_;
5039 newTrianglesFlag[22]= this->volumeID_;
5040 newTrianglesFlag[23]= originFlag[3];
5041
5042 isInterfaceSurface[20] = false;
5043 isInterfaceSurface[21] = false;
5044 isInterfaceSurface[22] = false;
5045 isInterfaceSurface[23] = interfaceSurface[3];
5046
5047 newTriangleEdgeIDs[5]={30,31,33,30,32,34,31,32,35,33,34,35};
5048
5049 // Element 7: (x_02,x_03,x_13,x_23)
5050 (newElements)[6]={midPointInd[0],midPointInd[1],midPointInd[3],midPointInd[5]};
5051
5052 (newEdges)[36] = {midPointInd[0] ,midPointInd[1]};
5053 (newEdges)[37] = {midPointInd[0] ,midPointInd[3]};
5054 (newEdges)[38] = {midPointInd[0] ,midPointInd[5]};
5055 (newEdges)[39] = {midPointInd[1] ,midPointInd[3]};
5056 (newEdges)[40] = {midPointInd[1] ,midPointInd[5]};
5057 (newEdges)[41] = {midPointInd[3] ,midPointInd[5]};
5058
5059 edgeFlags[36]=originFlag[0];
5060 edgeFlags[37]=originFlag[0];
5061 edgeFlags[38]=this->volumeID_;
5062 edgeFlags[39]=originFlag[0];
5063 edgeFlags[40]=originFlag[2];
5064 edgeFlags[41]=originFlag[3];
5065
5066 isInterfaceEdge[36] = interfaceSurface[0];
5067 isInterfaceEdge[37] = interfaceSurface[0];
5068 isInterfaceEdge[38] = false;
5069 isInterfaceEdge[39] = interfaceSurface[0];
5070 isInterfaceEdge[40] = interfaceSurface[2];
5071 isInterfaceEdge[41] = interfaceSurface[3];
5072
5073 predecessorElement[36] = -1;
5074 predecessorElement[37] = -1;
5075 predecessorElement[38] = -1;
5076 predecessorElement[39] = -1;
5077 predecessorElement[40] = -1;
5078 predecessorElement[41] = -1;
5079
5080 // Subelements of thetrahedron
5081 newTriangles[24]= {midPointInd[0],midPointInd[1],midPointInd[3]};
5082 newTriangles[25]= {midPointInd[0],midPointInd[1],midPointInd[5]};
5083 newTriangles[26]= {midPointInd[0],midPointInd[3],midPointInd[5]};
5084 newTriangles[27]= {midPointInd[1],midPointInd[3],midPointInd[5]};
5085
5086 newTrianglesFlag[24]= originFlag[0];
5087 newTrianglesFlag[25]= this->volumeID_;
5088 newTrianglesFlag[26]= this->volumeID_;
5089 newTrianglesFlag[27]= this->volumeID_;
5090
5091 isInterfaceSurface[24] = interfaceSurface[0];
5092 isInterfaceSurface[25] = false;
5093 isInterfaceSurface[26] = false;
5094 isInterfaceSurface[27] = false;
5095
5096 newTriangleEdgeIDs[6]={36,37,39,36,38,40,37,38,41,39,40,41};
5097
5098 // Element 8: (x_02,x_12,x_13,x_23)
5099 (newElements)[7]={midPointInd[0],midPointInd[4],midPointInd[2],midPointInd[5]};
5100
5101 (newEdges)[42] = {midPointInd[0] ,midPointInd[2]};
5102 (newEdges)[43] = {midPointInd[0] ,midPointInd[4]};
5103 (newEdges)[44] = {midPointInd[0] ,midPointInd[5]};
5104 (newEdges)[45] = {midPointInd[2] ,midPointInd[4]};
5105 (newEdges)[46] = {midPointInd[2] ,midPointInd[5]};
5106 (newEdges)[47] = {midPointInd[4] ,midPointInd[5]};
5107
5108 edgeFlags[42]=originFlag[1];
5109 edgeFlags[43]=originFlag[1];
5110 edgeFlags[44]=this->volumeID_;
5111 edgeFlags[45]=originFlag[1];
5112 edgeFlags[46]=originFlag[2];
5113 edgeFlags[47]=originFlag[3];
5114
5115 isInterfaceEdge[42] = interfaceSurface[1];
5116 isInterfaceEdge[43] = interfaceSurface[1];
5117 isInterfaceEdge[44] = false;
5118 isInterfaceEdge[45] = interfaceSurface[1];
5119 isInterfaceEdge[46] = interfaceSurface[2];
5120 isInterfaceEdge[47] = interfaceSurface[3];
5121
5122 predecessorElement[42] = -1;
5123 predecessorElement[43] = -1;
5124 predecessorElement[44] = -1;
5125 predecessorElement[45] = -1;
5126 predecessorElement[46] = -1;
5127 predecessorElement[47] = -1;
5128
5129 // Subelements of thetrahedron
5130 newTriangles[28]= {midPointInd[0],midPointInd[2],midPointInd[4]};
5131 newTriangles[29]= {midPointInd[0],midPointInd[2],midPointInd[5]};
5132 newTriangles[30]= {midPointInd[0],midPointInd[4],midPointInd[5]};
5133 newTriangles[31]= {midPointInd[2],midPointInd[4],midPointInd[5]};
5134
5135 newTrianglesFlag[28]= originFlag[1];
5136 newTrianglesFlag[29]= this->volumeID_;
5137 newTrianglesFlag[30]= this->volumeID_;
5138 newTrianglesFlag[31]= this->volumeID_;
5139
5140 isInterfaceSurface[28] = interfaceSurface[1];
5141 isInterfaceSurface[29] = false;
5142 isInterfaceSurface[30] = false;
5143 isInterfaceSurface[31] = false;
5144
5145 newTriangleEdgeIDs[7]={42,43,45,42,44,46,43,44,47,45,46,47};
5146 }
5147 else if(diaInd ==2){
5148 // Element 5:
5149 (newElements)[4]={midPointInd[0],midPointInd[1],midPointInd[2],midPointInd[3]};
5150
5151 (newEdges)[24] = {midPointInd[0] ,midPointInd[1]};
5152 (newEdges)[25] = {midPointInd[0] ,midPointInd[2]};
5153 (newEdges)[26] = {midPointInd[0] ,midPointInd[3]};
5154 (newEdges)[27] = {midPointInd[1] ,midPointInd[2]};
5155 (newEdges)[28] = {midPointInd[1] ,midPointInd[3]};
5156 (newEdges)[29] = {midPointInd[2] ,midPointInd[3]};
5157
5158 edgeFlags[24]=originFlag[0];
5159 edgeFlags[25]=originFlag[1];
5160 edgeFlags[26]=originFlag[0];
5161 edgeFlags[27]=originFlag[2];
5162 edgeFlags[28]=originFlag[0];
5163 edgeFlags[29]=this->volumeID_;
5164
5165 isInterfaceEdge[24] = interfaceSurface[0];
5166 isInterfaceEdge[25] = interfaceSurface[1];
5167 isInterfaceEdge[26] = interfaceSurface[0];
5168 isInterfaceEdge[27] = interfaceSurface[2];
5169 isInterfaceEdge[28] = interfaceSurface[0];
5170 isInterfaceEdge[29] = false;
5171
5172
5173 predecessorElement[24] = -1;
5174 predecessorElement[25] = -1;
5175 predecessorElement[26] = -1;
5176 predecessorElement[27] = -1;
5177 predecessorElement[28] = -1;
5178 predecessorElement[29] = -1;
5179
5180 // Subelements of thetrahedron
5181 newTriangles[16]= {midPointInd[0],midPointInd[1],midPointInd[2]};
5182 newTriangles[17]= {midPointInd[0],midPointInd[1],midPointInd[3]};
5183 newTriangles[18]= {midPointInd[0],midPointInd[2],midPointInd[3]};
5184 newTriangles[19]= {midPointInd[1],midPointInd[2],midPointInd[3]};
5185
5186
5187 newTrianglesFlag[16]= this->volumeID_;
5188 newTrianglesFlag[17]= originFlag[0];
5189 newTrianglesFlag[18]= this->volumeID_;
5190 newTrianglesFlag[19]= this->volumeID_;
5191
5192 isInterfaceSurface[16] = false;
5193 isInterfaceSurface[17] = interfaceSurface[0];
5194 isInterfaceSurface[18] = false;
5195 isInterfaceSurface[19] = false;
5196
5197 newTriangleEdgeIDs[4]={24,25,27,24,26,28,25,26,29,27,28,29};
5198
5199 // Element 6: (x_01,x_02,x_12,x_13)
5200 (newElements)[5]={midPointInd[0],midPointInd[2],midPointInd[3],midPointInd[4]};
5201
5202 (newEdges)[30] = {midPointInd[0],midPointInd[2]};
5203 (newEdges)[31] = {midPointInd[0] ,midPointInd[3]};
5204 (newEdges)[32] = {midPointInd[0],midPointInd[4]};
5205 (newEdges)[33] = {midPointInd[2] ,midPointInd[3]};
5206 (newEdges)[34] = {midPointInd[2] ,midPointInd[4]};
5207 (newEdges)[35] = {midPointInd[3] ,midPointInd[4]};
5208
5209 edgeFlags[30]=originFlag[1];
5210 edgeFlags[31]=originFlag[0];
5211 edgeFlags[32]=originFlag[1];
5212 edgeFlags[33]=this->volumeID_;
5213 edgeFlags[34]=originFlag[1];
5214 edgeFlags[35]=originFlag[3];
5215
5216 isInterfaceEdge[30] = interfaceSurface[1];
5217 isInterfaceEdge[31] = interfaceSurface[0];
5218 isInterfaceEdge[32] = interfaceSurface[1];
5219 isInterfaceEdge[33] = false;
5220 isInterfaceEdge[34] = interfaceSurface[1];
5221 isInterfaceEdge[35] = interfaceSurface[3];
5222
5223 predecessorElement[30] = -1;
5224 predecessorElement[31] = -1;
5225 predecessorElement[32] = -1;
5226 predecessorElement[33] = -1;
5227 predecessorElement[34] = -1;
5228 predecessorElement[35] = -1;
5229
5230
5231 // Subelements of thetrahedron
5232 newTriangles[20]= {midPointInd[0],midPointInd[2],midPointInd[3]};
5233 newTriangles[21]= {midPointInd[0],midPointInd[2],midPointInd[4]};
5234 newTriangles[22]= {midPointInd[0],midPointInd[3],midPointInd[4]};
5235 newTriangles[23]= {midPointInd[2],midPointInd[3],midPointInd[4]};
5236
5237 newTrianglesFlag[20]= this->volumeID_;
5238 newTrianglesFlag[21]= originFlag[1];
5239 newTrianglesFlag[22]= this->volumeID_;
5240 newTrianglesFlag[23]= this->volumeID_;
5241
5242 isInterfaceSurface[20] = false;
5243 isInterfaceSurface[21] = interfaceSurface[1];
5244 isInterfaceSurface[22] = false;
5245 isInterfaceSurface[23] = false;
5246
5247 newTriangleEdgeIDs[5]={30,31,33,30,32,34,31,32,35,33,34,35};
5248 // Element 7: (x_02,x_03,x_13,x_23)
5249 (newElements)[6]={midPointInd[1],midPointInd[2],midPointInd[3],midPointInd[5]};
5250
5251 (newEdges)[36] = {midPointInd[1] ,midPointInd[2]};
5252 (newEdges)[37] = {midPointInd[1] ,midPointInd[3]};
5253 (newEdges)[38] = {midPointInd[1] ,midPointInd[5]};
5254 (newEdges)[39] = {midPointInd[2] ,midPointInd[3]};
5255 (newEdges)[40] = {midPointInd[2] ,midPointInd[5]};
5256 (newEdges)[41] = {midPointInd[3] ,midPointInd[5]};
5257
5258 edgeFlags[36]=originFlag[2];
5259 edgeFlags[37]=originFlag[0];
5260 edgeFlags[38]=originFlag[2];
5261 edgeFlags[39]=this->volumeID_;
5262 edgeFlags[40]=originFlag[2];
5263 edgeFlags[41]=originFlag[3];
5264
5265 isInterfaceEdge[36] = interfaceSurface[2];
5266 isInterfaceEdge[37] = interfaceSurface[0];
5267 isInterfaceEdge[38] = interfaceSurface[2];
5268 isInterfaceEdge[39] = false;
5269 isInterfaceEdge[40] = interfaceSurface[2];
5270 isInterfaceEdge[41] = interfaceSurface[3];
5271
5272 predecessorElement[36] = -1;
5273 predecessorElement[37] = -1;
5274 predecessorElement[38] = -1;
5275 predecessorElement[39] = -1;
5276 predecessorElement[40] = -1;
5277 predecessorElement[41] = -1;
5278
5279 // Subelements of thetrahedron
5280 newTriangles[24]= {midPointInd[1],midPointInd[2],midPointInd[3]};
5281 newTriangles[25]= {midPointInd[1],midPointInd[2],midPointInd[5]};
5282 newTriangles[26]= {midPointInd[1],midPointInd[3],midPointInd[5]};
5283 newTriangles[27]= {midPointInd[2],midPointInd[3],midPointInd[5]};
5284
5285 newTrianglesFlag[24]= this->volumeID_;
5286 newTrianglesFlag[25]= originFlag[2];
5287 newTrianglesFlag[26]= this->volumeID_;
5288 newTrianglesFlag[27]= this->volumeID_;
5289
5290 isInterfaceSurface[24] = false;
5291 isInterfaceSurface[25] = interfaceSurface[2];
5292 isInterfaceSurface[26] = false;
5293 isInterfaceSurface[27] = false;
5294
5295 newTriangleEdgeIDs[6]={36,37,39,36,38,40,37,38,41,39,40,41};
5296
5297 // Element 8: (x_02,x_12,x_13,x_23)
5298 (newElements)[7]={midPointInd[2],midPointInd[3],midPointInd[4],midPointInd[5]};
5299
5300 (newEdges)[42] = {midPointInd[2] ,midPointInd[3]};
5301 (newEdges)[43] = {midPointInd[2] ,midPointInd[4]};
5302 (newEdges)[44] = {midPointInd[2] ,midPointInd[5]};
5303 (newEdges)[45] = {midPointInd[3] ,midPointInd[4]};
5304 (newEdges)[46] = {midPointInd[3] ,midPointInd[5]};
5305 (newEdges)[47] = {midPointInd[4] ,midPointInd[5]};
5306
5307 edgeFlags[42]=this->volumeID_;
5308 edgeFlags[43]=originFlag[1];
5309 edgeFlags[44]=originFlag[2];
5310 edgeFlags[45]=originFlag[3];
5311 edgeFlags[46]=originFlag[3];
5312 edgeFlags[47]=originFlag[3];
5313
5314 isInterfaceEdge[42] = false;
5315 isInterfaceEdge[43] = interfaceSurface[1];
5316 isInterfaceEdge[44] = interfaceSurface[2];
5317 isInterfaceEdge[45] = interfaceSurface[3];
5318 isInterfaceEdge[46] = interfaceSurface[3];
5319 isInterfaceEdge[47] = interfaceSurface[3];
5320
5321 predecessorElement[42] = -1;
5322 predecessorElement[43] = -1;
5323 predecessorElement[44] = -1;
5324 predecessorElement[45] = -1;
5325 predecessorElement[46] = -1;
5326 predecessorElement[47] = -1;
5327
5328 // Subelements of thetrahedron
5329 newTriangles[28]= {midPointInd[2],midPointInd[3],midPointInd[4]};
5330 newTriangles[29]= {midPointInd[2],midPointInd[3],midPointInd[5]};
5331 newTriangles[30]= {midPointInd[2],midPointInd[4],midPointInd[5]};
5332 newTriangles[31]= {midPointInd[3],midPointInd[4],midPointInd[5]};
5333
5334 newTrianglesFlag[28]= this->volumeID_;
5335 newTrianglesFlag[29]= this->volumeID_;
5336 newTrianglesFlag[30]= this->volumeID_;
5337 newTrianglesFlag[31]= originFlag[3];
5338
5339 isInterfaceSurface[28] = false;
5340 isInterfaceSurface[29] = false;
5341 isInterfaceSurface[30] = false;
5342 isInterfaceSurface[31] = interfaceSurface[3];
5343
5344 newTriangleEdgeIDs[7]={42,43,45,42,44,46,43,44,47,45,46,47};
5345 }
5346
5347
5348
5349 // Now we add the elements, edges and triangles
5350
5351 // Adding Elements
5352 int offsetElements = this->elementsC_->numberElements();
5353 int offsetEdges = this->edgeElements_->numberElements();
5354 for( int i=0;i<8; i++){
5355 //sort( newElements.at(i).begin(), newElements.at(i).end() );
5356 FiniteElement feNew(newElements.at(i),this->volumeID_);
5357 feNew.setFiniteElementRefinementType("regular");
5358 feNew.setPredecessorElement(indexElement);
5359 if(elements->getElement(indexElement).getFiniteElementRefinementType() == "irregular" || elements->getElement(indexElement).getFiniteElementRefinementType() == "irregularRegular" )
5360 feNew.setFiniteElementRefinementType("irregularRegular");
5361 if(i<7)
5362 this->elementsC_->addElement(feNew);
5363 else
5364 this->elementsC_->switchElement(indexElement,feNew);
5365 }
5366
5367 // Adding the edges (they also have to be added to triangles as subelements, but that is not implemented yet)
5368 for( int i=0;i<48; i++){
5369 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
5370 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
5371 feNew.setInterfaceElement(isInterfaceEdge[i]);
5372 feNew.setPredecessorElement(predecessorElement[i]);
5373 if(i<42){
5374 this->edgeElements_->addEdge(feNew,i/6+offsetElements);
5375 }
5376 else
5377 this->edgeElements_->addEdge(feNew,indexElement);
5378
5379 }
5380
5381 // Adding triangles as subelements, if they arent interior triangles
5382 int offsetSurfaces =this->surfaceTriangleElements_->numberElements();
5383 int offsetSurface =0;
5384 for( int i=0;i<32; i++){
5385 //sort( newTriangles.at(i).begin(), newTriangles.at(i).end() );
5386 FiniteElement feNew(newTriangles[i],newTrianglesFlag[i]);
5387 feNew.setInterfaceElement(isInterfaceSurface[i]);
5388 if(i<28){
5389 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
5390 if ( !this->elementsC_->getElement(i/4+offsetElements).subElementsInitialized() )
5391 this->elementsC_->getElement(i/4+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
5392 this->elementsC_->getElement(i/4+offsetElements).addSubElement(feNew);
5393 }
5394 this->surfaceTriangleElements_->addSurface(feNew, i/4+offsetElements);
5395
5396 }
5397 else{
5398 if(newTrianglesFlag[i]!=0 && newTrianglesFlag[i]!=this->volumeID_){
5399 if ( !this->elementsC_->getElement(indexElement).subElementsInitialized() )
5400 this->elementsC_->getElement(indexElement).initializeSubElements( this->FEType_, this->dim_ -1) ;
5401 this->elementsC_->getElement(indexElement).addSubElement(feNew);
5402 }
5403 this->surfaceTriangleElements_->addSurface(feNew, indexElement);
5404 }
5405
5406 /*this->surfaceTriangleElements_->getElement(i+offsetSurfaces).initializeSubElements( this->FEType_, this->dim_ -2) ;
5407 for(int j=0; j< 3 ; j++){
5408 this->surfaceTriangleElements_->getElement(i+offsetSurfaces).addSubElement(this->edgeElements_->getElement(offsetEdges + newTriangleEdgeIDs[i/4][j+offsetSurface]));
5409 }
5410 offsetSurface += 3;
5411 if((i % 4) == 0)
5412 offsetSurface =0;*/
5413 }
5414 FiniteElement element;
5415 FiniteElement feEdge;
5416 for( int i=0;i<8; i++){
5417 if(i<7) {
5418 element = this->elementsC_->getElement(i+offsetElements);
5419 }
5420 else{
5421 element = this->elementsC_->getElement(indexElement);
5422 }
5423 bool init=false;
5424 for(int j=0; j<48 ; j++){
5425 FiniteElement feEdge = this->edgeElements_->getElement(j+offsetEdges);
5426 if(feEdge.getFlag() != this->volumeID_){
5427 if(init == true)
5428 element.addSubElement( feEdge );
5429 else if ( !element.subElementsInitialized() ){
5430 element.initializeSubElements( "P1", 1 ); // only P1 for now
5431 element.addSubElement( feEdge );
5432 init= true;
5433 }
5434 else {
5435 ElementsPtr_Type surfaces = element.getSubElements();
5436 // We set the edge to the corresponding element(s)
5437 surfaces->setToCorrectElement( feEdge );
5438 }
5439 }
5440 }
5441 }
5442 // tagging the Edges for refinement
5443 for (int d=0; d<6; d++){
5444 // now we tag the edge as 'refined'
5445 edgeElements->getElement(edgeNumbers[d]).tagForRefinement();
5446 }
5447
5448 }
5449 else
5450 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The Refinement Algorithm for the Dimension at hand is not available");
5451 }
5452
5464template <class SC, class LO, class GO, class NO>
5465void RefinementFactory<SC,LO,GO,NO>::bisectEdges(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements, std::string mode){
5466
5467 if(refinementMode_ == "Bisection"){
5468
5469 if(this->dim_ == 2){
5470 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
5471
5472 int entry = this->determineLongestEdge(edgeElements,edgeNumbers,this->pointsRep_); // we determine the edge, we would choose for blue Refinement
5473
5474 if(!edgeElements->getElement(entry).isTaggedForRefinement()) // we tag every edge, after we refine an element -> no tag - no refinement on that edge so far
5475 {
5476 this->addMidpoint(edgeElements,entry);
5477 edgeElements->getElement(entry).tagForRefinement();
5478 }
5479
5480 }
5481 else if(this->dim_==3)
5482 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "Explicit refinement by bisections is only implemented in 2d.");
5483 }
5484 else{
5485 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
5486
5487 for(int i=0; i<edgeNumbers.size(); i++){
5488 if(!edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()) // we tag every edge, after we refine an element -> no tag - no refinement on that edge so far
5489 {
5490 this->addMidpoint(edgeElements,edgeNumbers[i]);
5491 edgeElements->getElement(edgeNumbers[i]).tagForRefinement();
5492 }
5493 }
5494 }
5495 if(mode == "all"){
5496 vec_int_Type edgeNumbers = edgeElements->getEdgesOfElement(indexElement); // indeces of edges belonging to element
5497
5498 for(int i=0; i<edgeNumbers.size(); i++){
5499 if(!edgeElements->getElement(edgeNumbers[i]).isTaggedForRefinement()) // we tag every edge, after we refine an element -> no tag - no refinement on that edge so far
5500 {
5501 this->addMidpoint(edgeElements,edgeNumbers[i]);
5502 edgeElements->getElement(edgeNumbers[i]).tagForRefinement();
5503 }
5504 }
5505 }
5506
5507}
5508
5518template <class SC, class LO, class GO, class NO>
5519void RefinementFactory<SC,LO,GO,NO>::bisectElement3(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement){
5520
5521 if(this->dim_ == 2){
5522
5523 // The necessary Point was already added to the nodelist
5524 // now we have to figure out, which node it is -> check the tagged edge for midpoint
5525 vec_int_Type edgeNumbersTmp = edgeElements->getEdgesOfElement(indexElement);
5526
5527
5528 int entry = this->determineLongestEdge(edgeElements,edgeNumbersTmp,this->pointsRep_); // we determine the edge, we would choose for blue Refinement
5529
5530 int midPointEntry=0;
5531 // midpoint index
5532 vec_int_Type midPointInd(3);
5533 vec_int_Type edgeNumbers(3);
5534 vec_int_Type mutualNode(3);
5535
5536
5537 // -> longest Edge: Edge 1: midPoint[0] - mutualNode[0] = mutualNode of Edge 1 and 2
5538 // -> Edge 2: midPoint[1] - mutualNode[1] = mutualNode of Edge 1 and 3
5539 // -> Edge 3: midpoint[2] - mutualNode[2] = mutualNode of Edge 2 and 3
5540
5541 for(int i=0; i<3; i++){
5542 if(edgeNumbersTmp[i] == entry) {
5543 midPointInd[0] = edgeElements->getMidpoint(edgeNumbersTmp[i]);
5544 edgeNumbers[0] = edgeNumbersTmp[i];
5545 mutualNode[0] = edgeElements->getElement(entry).getNode(0);
5546 mutualNode[2] = edgeElements->getElement(entry).getNode(1);
5547 }
5548 }
5549 int tmp=1;
5550 for(int i=0; i<3; i++){
5551 if(edgeNumbersTmp[i] != entry) {
5552 midPointInd[tmp] = edgeElements->getMidpoint(edgeNumbersTmp[i]);
5553 edgeNumbers[tmp] = edgeNumbersTmp[i];
5554 tmp++;
5555 if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(0) == mutualNode[0])
5556 mutualNode[1] = edgeElements->getElement(edgeNumbersTmp[i]).getNode(1);
5557 else if(edgeElements->getElement(edgeNumbersTmp[i]).getNode(1) == mutualNode[0])
5558 mutualNode[1] = edgeElements->getElement(edgeNumbersTmp[i]).getNode(0);
5559 }
5560 }
5561
5562
5563 // Adding Elements and the corresponding Edges
5564 vec2D_int_Type newElements(4, vec_int_Type( 0 )); // vector for the new elements
5565 vec2D_int_Type newEdges(12,vec_int_Type(0)); // vector for the new edges
5566 vec_int_Type edgeFlags(12); // vector for the new flags
5567 vec_bool_Type isInterfaceEdge(12); // bool vectot for interfaceEdges
5568 vec_GO_Type predecessorElement(12);
5569 // Edgeflags are determined by the midpoints flag or by the fact, that they are inside a triangle, which consequently makes them interior edges (flag =this->volumeID_)
5570
5571 // Element 1
5572 (newElements)[0]={mutualNode[0],midPointInd[0],midPointInd[1]};
5573
5574 (newEdges)[0] = {mutualNode[0] ,midPointInd[0]};
5575 (newEdges)[1] = {mutualNode[0] ,midPointInd[1]};
5576 (newEdges)[2] = {midPointInd[0] ,midPointInd[1]};
5577
5578 edgeFlags[0]=this->bcFlagRep_->at(midPointInd[0]);
5579 edgeFlags[1]=this->bcFlagRep_->at(midPointInd[1]);
5580 edgeFlags[2]=this->volumeID_;
5581
5582 isInterfaceEdge[0] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
5583 isInterfaceEdge[1] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
5584 isInterfaceEdge[2] = false;
5585
5586 predecessorElement[0] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);
5587 predecessorElement[1] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
5588 predecessorElement[2] = -1;
5589
5590 // Element 2
5591 newElements[1]={mutualNode[1],midPointInd[0],midPointInd[1]};
5592
5593 (newEdges)[3] = {mutualNode[1] ,midPointInd[0]};
5594 (newEdges)[4] = {mutualNode[1] ,midPointInd[1]};
5595 (newEdges)[5] = {midPointInd[0] ,midPointInd[1]};
5596
5597 edgeFlags[3]=this->volumeID_;
5598 edgeFlags[4]=this->bcFlagRep_->at(midPointInd[1]);
5599 edgeFlags[5]=this->volumeID_;
5600
5601 isInterfaceEdge[3] = false;
5602 isInterfaceEdge[4] = edgeElements->getElement(edgeNumbers[1]).isInterfaceElement();
5603 isInterfaceEdge[5] = false;
5604
5605 predecessorElement[3] = -1;
5606 predecessorElement[4] = this->edgeMap_->getGlobalElement(edgeNumbers[1]);
5607 predecessorElement[5] = -1;
5608
5609 // Element 3
5610 (newElements)[2]={mutualNode[1] , midPointInd[0] ,midPointInd[2]};
5611
5612 (newEdges)[6] = {mutualNode[1] ,midPointInd[0]};
5613 (newEdges)[7] = {mutualNode[1] ,midPointInd[2]};
5614 (newEdges)[8] = {midPointInd[0] ,midPointInd[2]};
5615
5616 edgeFlags[6]=this->volumeID_;
5617 edgeFlags[7]=this->bcFlagRep_->at(midPointInd[2]);
5618 edgeFlags[8]=this->volumeID_;
5619
5620 isInterfaceEdge[6] = false;
5621 isInterfaceEdge[7] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
5622 isInterfaceEdge[8] = false;
5623
5624 predecessorElement[6] = -1;
5625 predecessorElement[7] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);
5626 predecessorElement[8] = -1;
5627
5628 // Element 4
5629 (newElements)[3]={midPointInd[0],midPointInd[2],mutualNode[2]};
5630
5631 (newEdges)[9] = {midPointInd[0] ,midPointInd[2]};
5632 (newEdges)[10] = {midPointInd[0] ,mutualNode[2]};
5633 (newEdges)[11] = {midPointInd[2] ,mutualNode[2]};
5634
5635 edgeFlags[9]=this->volumeID_;
5636 edgeFlags[10]=this->bcFlagRep_->at(midPointInd[0]);;
5637 edgeFlags[11]=this->bcFlagRep_->at(midPointInd[2]);;
5638
5639 isInterfaceEdge[9] = false;
5640 isInterfaceEdge[10] = edgeElements->getElement(edgeNumbers[0]).isInterfaceElement();
5641 isInterfaceEdge[11] = edgeElements->getElement(edgeNumbers[2]).isInterfaceElement();
5642
5643 predecessorElement[9] = -1;
5644 predecessorElement[10] = this->edgeMap_->getGlobalElement(edgeNumbers[0]);;
5645 predecessorElement[11] = this->edgeMap_->getGlobalElement(edgeNumbers[2]);;
5646
5647 int offsetElements = this->elementsC_->numberElements();
5648 int offsetEdges = this->edgeElements_->numberElements();
5649 for( int i=0;i<4; i++){
5650 sort( newElements.at(i).begin(), newElements.at(i).end() );
5651 FiniteElement feNew(newElements.at(i),this->volumeID_);
5652 feNew.setFiniteElementRefinementType("regular");
5653 feNew.setPredecessorElement(indexElement);
5654 if(i<3)
5655 this->elementsC_->addElement(feNew);
5656 else
5657 this->elementsC_->switchElement(indexElement,feNew);
5658 }
5659
5660 for( int i=0;i<12; i++){
5661 sort( newEdges.at(i).begin(), newEdges.at(i).end() );
5662 FiniteElement feNew(newEdges.at(i),edgeFlags[i]);
5663 feNew.setInterfaceElement(isInterfaceEdge[i]);
5664 feNew.setPredecessorElement(predecessorElement[i]);
5665 if(i<9){
5666 this->edgeElements_->addEdge(feNew,i/3+offsetElements);
5667 if(edgeFlags[i]!=0 && edgeFlags[i]!=this->volumeID_){
5668 if ( !this->elementsC_->getElement(i/3+offsetElements).subElementsInitialized() )
5669 this->elementsC_->getElement(i/3+offsetElements).initializeSubElements( this->FEType_, this->dim_ -1) ;
5670 this->elementsC_->getElement(i/3+offsetElements).addSubElement(feNew);
5671 }
5672 }
5673 else
5674 this->edgeElements_->addEdge(feNew,indexElement);
5675
5676 }
5677 }
5678 else
5679 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, "The Refinement by Bisection Method you requested is only applicable to a 2 dimensional Mesh.");
5680
5681 }
5682
5683}
5684
5685#endif
Definition EdgeElements.hpp:17
Definition Elements.hpp:23
Definition FiniteElement.hpp:17
Definition Map_decl.hpp:30
Definition MeshUnstructured_decl.hpp:33
void buildEdgeMap()
Definition MeshUnstructured_def.hpp:1099
MapConstPtr_Type getEdgeMap()
Definition Mesh_def.hpp:118
MapConstPtr_Type getMapRepeated() const
Definition Mesh_def.hpp:105
void buildSurfaceTriangleElements(ElementsPtr_Type elements, EdgeElementsPtr_Type edgeElements, SurfaceElementsPtr_Type surfaceTriangleElements, MapConstPtr_Type edgeMap, MapConstPtr_Type elementMap)
Building surface triangle elements, as they are not originally part of the mesh information provided ...
Definition RefinementFactory_def.hpp:824
void bisectElement3(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElementp)
2D refinement by bisection of tagged Elements with three tagged Edges.
Definition RefinementFactory_def.hpp:5519
void refineType3(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements)
3D Type(3) refinement as defined in "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refine...
Definition RefinementFactory_def.hpp:2974
void refineGreen(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int i)
2D green refinement: refining the element according to green scheme - connecting node on refined edge...
Definition RefinementFactory_def.hpp:2178
void refineRegular(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int i, SurfaceElementsPtr_Type surfaceTriangleElements)
2D and 3D regular refinement. Chosen by error estimator or otherwise elements are refined regular by ...
Definition RefinementFactory_def.hpp:4198
void updateElementsOfEdgesLocalAndGlobal(int maxRank, MapConstPtr_Type edgeMap)
Updating ElementsOfEdgesLocal and ElementsOfEdgesGlobal.
Definition RefinementFactory_def.hpp:1636
void refineMeshRegIreg(ElementsPtr_Type elements, EdgeElementsPtr_Type edgeElements, int &newElements, MapConstPtr_Type edgeMap, SurfaceElementsPtr_Type surfaceTriangleElements)
Refinement performed according to the set of rules determined by Bey or Verfürth.
Definition RefinementFactory_def.hpp:1496
int determineLongestEdge(EdgeElementsPtr_Type edgeElements, vec_int_Type edgeVec, vec2D_dbl_ptr_Type points)
Eetermine longest edge in triangle.
Definition RefinementFactory_def.hpp:1894
void buildEdgeMap(MapConstPtr_Type mapGlobalProc, MapConstPtr_Type mapProc)
Building edgeMap after refinement.
Definition RefinementFactory_def.hpp:952
void bisectEdges(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements, std::string mode="default")
2D and 3D that bisects the edges of tagged Elements. Chosen by error estimator or otherwise elements ...
Definition RefinementFactory_def.hpp:5465
void refineType2(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements)
3D Type(2) refinement as defined in "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refine...
Definition RefinementFactory_def.hpp:3406
void refinementRestrictions(MeshUnstrPtr_Type meshP1, ElementsPtr_Type elements, EdgeElementsPtr_Type edgeElements, SurfaceElementsPtr_Type surfaceTriangleElements, int &newPoints, int &newPointsCommon, vec_GO_Type &globalInterfaceIDsTagged, MapConstPtr_Type mapInterfaceEdges, int &newElements)
Refinement Restrictions.
Definition RefinementFactory_def.hpp:1176
vec_bool_Type checkInterfaceSurface(EdgeElementsPtr_Type edgeElements, vec_int_Type originFlag, vec_int_Type edgeNumbers, int indexElement)
Checking if surfaces are part of the interface. Done by checking if all edges of a triangle are part ...
Definition RefinementFactory_def.hpp:538
void refineType1(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements)
3D Type(1) refinement as defined in "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refine...
Definition RefinementFactory_def.hpp:3759
void buildNodeMap(EdgeElementsPtr_Type edgeElements, MapConstPtr_Type mapGlobalProc, MapConstPtr_Type mapProc, int newPoints, int newPointsRepeated)
Building nodemap after refinement.
Definition RefinementFactory_def.hpp:607
void refineRed(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int i)
2D red refinement: refining the element red by connecting all tagged edges midpoints....
Definition RefinementFactory_def.hpp:2368
void refineType4(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int indexElement, SurfaceElementsPtr_Type surfaceTriangleElements)
3D Type(4) refinement as defined in "Tetrahedral Grid Refinement" by J. Bey 'Algorithm Regular Refine...
Definition RefinementFactory_def.hpp:2537
void refineMesh(MeshUnstrPtr_Type meshP1, int iteration, MeshUnstrPtr_Type outputMesh, std::string refinementMode)
Main function of RefinementFactory, performs one complete mesh refinement, according to red-green ref...
Definition RefinementFactory_def.hpp:99
void refineBlue(EdgeElementsPtr_Type edgeElements, ElementsPtr_Type elements, int i)
2D blue refinement: refining element according to blue refinement scheme - connecting nodes of shorte...
Definition RefinementFactory_def.hpp:1952
void addMidpoint(EdgeElementsPtr_Type edgeElements, int i)
Adding a Midpoint on an edge.
Definition RefinementFactory_def.hpp:1851
Definition TriangleElements.hpp:18
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement_decl.hpp:36