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