/[escript]/trunk/finley/src/Mesh.cpp
ViewVC logotype

Contents of /trunk/finley/src/Mesh.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4496 - (show annotations)
Mon Jul 15 06:53:44 2013 UTC (6 years ago) by caltinay
File size: 23720 byte(s)
finley (WIP):
-moved all of finley into its namespace
-introduced some shared pointers
-Mesh is now a class
-other bits and pieces...

1 /*****************************************************************************
2 *
3 * Copyright (c) 2003-2013 by University of Queensland
4 * http://www.uq.edu.au
5 *
6 * Primary Business: Queensland, Australia
7 * Licensed under the Open Software License version 3.0
8 * http://www.opensource.org/licenses/osl-3.0.php
9 *
10 * Development until 2012 by Earth Systems Science Computational Center (ESSCC)
11 * Development since 2012 by School of Earth Sciences
12 *
13 *****************************************************************************/
14
15
16 /****************************************************************************
17
18 Finley: Mesh
19
20 *****************************************************************************/
21
22 #include "Mesh.h"
23 #include "IndexList.h"
24
25 namespace finley {
26
27 /// Constructor.
28 /// Allocates a Mesh with given name and dimensionality
29 Mesh::Mesh(const std::string name, int numDim, Esys_MPIInfo *mpi_info) :
30 m_name(name),
31 approximationOrder(-1),
32 reducedApproximationOrder(-1),
33 integrationOrder(-1),
34 reducedIntegrationOrder(-1),
35 Elements(NULL),
36 FaceElements(NULL),
37 ContactElements(NULL),
38 Points(NULL),
39 FullFullPattern(NULL),
40 FullReducedPattern(NULL),
41 ReducedFullPattern(NULL),
42 ReducedReducedPattern(NULL)
43 {
44 MPIInfo = Esys_MPIInfo_getReference(mpi_info);
45
46 // allocate node table
47 Nodes = new NodeFile(numDim, mpi_info);
48 }
49
50 /// destructor
51 Mesh::~Mesh()
52 {
53 delete Nodes;
54 delete FaceElements;
55 delete Elements;
56 delete ContactElements;
57 delete Points;
58 tagMap.clear();
59 Paso_SystemMatrixPattern_free(FullFullPattern);
60 Paso_SystemMatrixPattern_free(FullReducedPattern);
61 Paso_SystemMatrixPattern_free(ReducedFullPattern);
62 Paso_SystemMatrixPattern_free(ReducedReducedPattern);
63 Esys_MPIInfo_free(MPIInfo);
64 }
65
66 void Mesh::setElements(ElementFile *elements)
67 {
68 delete Elements;
69 Elements=elements;
70 }
71
72 void Mesh::setFaceElements(ElementFile *elements)
73 {
74 delete FaceElements;
75 FaceElements=elements;
76 }
77
78 void Mesh::setContactElements(ElementFile *elements)
79 {
80 delete ContactElements;
81 ContactElements=elements;
82 }
83
84 void Mesh::setPoints(ElementFile *elements)
85 {
86 delete Points;
87 Points=elements;
88 }
89
90 void Mesh::setOrders()
91 {
92 const int ORDER_MAX=9999999;
93 int locals[4] = { ORDER_MAX, ORDER_MAX, ORDER_MAX, ORDER_MAX };
94
95 if (Elements != NULL && Elements->numElements > 0) {
96 locals[0]=std::min(locals[0], Elements->referenceElementSet->referenceElement->BasisFunctions->Type->numOrder);
97 locals[1]=std::min(locals[1], Elements->referenceElementSet->referenceElement->LinearBasisFunctions->Type->numOrder);
98 locals[2]=std::min(locals[2], Elements->referenceElementSet->referenceElement->integrationOrder);
99 locals[3]=std::min(locals[3], Elements->referenceElementSet->referenceElementReducedQuadrature->integrationOrder);
100 }
101 if (FaceElements != NULL && FaceElements->numElements > 0) {
102 locals[0]=std::min(locals[0], FaceElements->referenceElementSet->referenceElement->BasisFunctions->Type->numOrder);
103 locals[1]=std::min(locals[1], FaceElements->referenceElementSet->referenceElement->LinearBasisFunctions->Type->numOrder);
104 locals[2]=std::min(locals[2], FaceElements->referenceElementSet->referenceElement->integrationOrder);
105 locals[3]=std::min(locals[3], FaceElements->referenceElementSet->referenceElementReducedQuadrature->integrationOrder);
106 }
107 if (ContactElements != NULL && ContactElements->numElements > 0) {
108 locals[0]=std::min(locals[0], ContactElements->referenceElementSet->referenceElement->BasisFunctions->Type->numOrder);
109 locals[1]=std::min(locals[1], ContactElements->referenceElementSet->referenceElement->LinearBasisFunctions->Type->numOrder);
110 locals[2]=std::min(locals[2], ContactElements->referenceElementSet->referenceElement->integrationOrder);
111 locals[3]=std::min(locals[3], ContactElements->referenceElementSet->referenceElementReducedQuadrature->integrationOrder);
112 }
113
114 #ifdef ESYS_MPI
115 int globals[4];
116 MPI_Allreduce(locals, globals, 4, MPI_INT, MPI_MIN, MPIInfo->comm);
117 approximationOrder=(globals[0] < ORDER_MAX ? globals[0] : -1);
118 reducedApproximationOrder=(globals[1] < ORDER_MAX ? globals[1] : -1);
119 integrationOrder=(globals[2] < ORDER_MAX ? globals[2] : -1);
120 reducedIntegrationOrder=(globals[3] < ORDER_MAX ? globals[3] : -1);
121 #else
122 approximationOrder=(locals[0] < ORDER_MAX ? locals[0] : -1);
123 reducedApproximationOrder=(locals[1] < ORDER_MAX ? locals[1] : -1);
124 integrationOrder=(locals[2] < ORDER_MAX ? locals[2] : -1);
125 reducedIntegrationOrder=(locals[3] < ORDER_MAX ? locals[3] : -1);
126 #endif
127 }
128
129 /// creates node mappings without (re-)distributing anything
130 void Mesh::createMappings(const std::vector<int>& dofDistribution,
131 const std::vector<int>& nodeDistribution)
132 {
133 std::vector<short> maskReducedNodes(Nodes->numNodes, -1);
134 markNodes(maskReducedNodes, 0, true);
135 std::vector<int> indexReducedNodes = util::packMask(maskReducedNodes);
136 if (noError())
137 Nodes->createNodeMappings(indexReducedNodes, dofDistribution,
138 nodeDistribution);
139 }
140
141 /// redistributes the Nodes and Elements including overlap
142 /// according to the DOF distribution. It will create an element colouring
143 /// but will not create any mappings.
144 void Mesh::distributeByRankOfDOF(const std::vector<int>& dof_distribution)
145 {
146 std::vector<int> mpiRankOfDOF(Nodes->numNodes);
147 Nodes->assignMPIRankToDOFs(mpiRankOfDOF, dof_distribution);
148
149 // first, the elements are redistributed according to mpiRankOfDOF
150 // at the input the Node tables refer to the local labeling of the nodes
151 // while at the output they refer to the global labeling which is rectified
152 // in the next step
153 if (noError())
154 Elements->distributeByRankOfDOF(mpiRankOfDOF, Nodes->Id);
155 if (noError())
156 FaceElements->distributeByRankOfDOF(mpiRankOfDOF, Nodes->Id);
157 if (noError())
158 ContactElements->distributeByRankOfDOF(mpiRankOfDOF, Nodes->Id);
159 if (noError())
160 Points->distributeByRankOfDOF(mpiRankOfDOF, Nodes->Id);
161
162 // resolve the node ids
163 if (noError())
164 resolveNodeIds();
165
166 // create a local labeling of the DOFs
167 const std::pair<int,int> dof_range(Nodes->getDOFRange());
168 const int len=dof_range.second-dof_range.first+1;
169 // local mask for used nodes
170 std::vector<int> localDOF_mask(len, -1);
171 std::vector<int> localDOF_map(Nodes->numNodes, -1);
172
173 #pragma omp parallel for
174 for (int n=0; n<Nodes->numNodes; n++) {
175 #ifdef BOUNDS_CHECK
176 if ((Nodes->globalDegreesOfFreedom[n]-dof_range.first) >= len ||
177 (Nodes->globalDegreesOfFreedom[n]-dof_range.first) < 0) {
178 printf("BOUNDS_CHECK %s %d\n", __FILE__, __LINE__);
179 exit(1);
180 }
181 #endif
182 localDOF_mask[Nodes->globalDegreesOfFreedom[n]-dof_range.first]=n;
183 }
184
185 int numDOFs=0;
186 for (int n=0; n<len; n++) {
187 const int k=localDOF_mask[n];
188 if (k>=0) {
189 localDOF_mask[n]=numDOFs;
190 numDOFs++;
191 }
192 }
193 #pragma omp parallel for
194 for (int n=0; n<Nodes->numNodes; n++) {
195 const int k=localDOF_mask[Nodes->globalDegreesOfFreedom[n]-dof_range.first];
196 localDOF_map[n]=k;
197 }
198 // create element coloring
199 if (noError())
200 createColoring(localDOF_map);
201 }
202
203 /// prints the mesh details to standard output
204 void Mesh::print()
205 {
206 // write header
207 printf("Mesh name: %s\n", m_name.c_str());
208
209 // write nodes
210 Nodes->print();
211
212 // write elements
213 if (Elements) {
214 printf("=== %s:\nnumber of elements=%d\ncolor range=[%d,%d]\n",
215 Elements->referenceElementSet->referenceElement->Type->Name,
216 Elements->numElements, Elements->minColor, Elements->maxColor);
217 if (Elements->numElements > 0) {
218 const int NN=Elements->referenceElementSet->referenceElement->Type->numNodes;
219 const int NN2=Elements->numNodes;
220 printf("Id,Tag,Owner,Color,Nodes\n");
221 for (int i=0; i<Elements->numElements; i++) {
222 printf("%d,%d,%d,%d,", Elements->Id[i], Elements->Tag[i],
223 Elements->Owner[i], Elements->Color[i]);
224 for (int j=0; j<NN; j++)
225 printf(" %d", Nodes->Id[Elements->Nodes[INDEX2(j,i,NN2)]]);
226 printf("\n");
227 }
228 }
229 }
230
231 // write face elements
232 if (FaceElements) {
233 printf("=== %s:\nnumber of elements=%d\ncolor range=[%d,%d]\n",
234 FaceElements->referenceElementSet->referenceElement->Type->Name,
235 FaceElements->numElements, FaceElements->minColor,
236 FaceElements->maxColor);
237 if (FaceElements->numElements > 0) {
238 const int NN=FaceElements->referenceElementSet->referenceElement->Type->numNodes;
239 const int NN2=FaceElements->numNodes;
240 printf("Id,Tag,Owner,Color,Nodes\n");
241 for (int i=0; i<FaceElements->numElements; i++) {
242 printf("%d,%d,%d,%d,", FaceElements->Id[i],
243 FaceElements->Tag[i], FaceElements->Owner[i],
244 FaceElements->Color[i]);
245 for (int j=0; j<NN; j++)
246 printf(" %d", Nodes->Id[FaceElements->Nodes[INDEX2(j,i,NN2)]]);
247 printf("\n");
248 }
249 }
250 }
251
252 // write Contact elements
253 if (ContactElements) {
254 printf("=== %s:\nnumber of elements=%d\ncolor range=[%d,%d]\n",
255 ContactElements->referenceElementSet->referenceElement->Type->Name,
256 ContactElements->numElements, ContactElements->minColor,
257 ContactElements->maxColor);
258 if (ContactElements->numElements > 0) {
259 const int NN=ContactElements->referenceElementSet->referenceElement->Type->numNodes;
260 const int NN2=ContactElements->numNodes;
261 printf("Id,Tag,Owner,Color,Nodes\n");
262 for (int i=0; i<ContactElements->numElements; i++) {
263 printf("%d,%d,%d,%d,", ContactElements->Id[i],
264 ContactElements->Tag[i], ContactElements->Owner[i],
265 ContactElements->Color[i]);
266 for (int j=0; j<NN; j++)
267 printf(" %d", Nodes->Id[ContactElements->Nodes[INDEX2(j,i,NN2)]]);
268 printf("\n");
269 }
270 }
271 }
272
273 // write points
274 if (Points) {
275 printf("=== %s:\nnumber of elements=%d\ncolor range=[%d,%d]\n",
276 Points->referenceElementSet->referenceElement->Type->Name,
277 Points->numElements, Points->minColor, Points->maxColor);
278 if (Points->numElements > 0) {
279 const int NN=Points->referenceElementSet->referenceElement->Type->numNodes;
280 const int NN2=Points->numNodes;
281 printf("Id,Tag,Owner,Color,Nodes\n");
282 for (int i=0; i<Points->numElements; i++) {
283 printf("%d,%d,%d,%d,", Points->Id[i], Points->Tag[i],
284 Points->Owner[i], Points->Color[i]);
285 for (int j=0; j<NN; j++)
286 printf(" %d", Nodes->Id[Points->Nodes[INDEX2(j,i,NN2)]]);
287 printf("\n");
288 }
289 }
290 }
291 }
292
293 void Mesh::markNodes(std::vector<short>& mask, int offset, bool useLinear)
294 {
295 Elements->markNodes(mask, offset, useLinear);
296 FaceElements->markNodes(mask, offset, useLinear);
297 ContactElements->markNodes(mask, offset, useLinear);
298 Points->markNodes(mask, offset, useLinear);
299 }
300
301 void Mesh::markDOFsConnectedToRange(int* mask, int offset, int marker,
302 int firstDOF, int lastDOF, bool useLinear)
303 {
304 const int *dofIndex = (useLinear ? Nodes->globalReducedDOFIndex
305 : Nodes->globalDegreesOfFreedom);
306 Elements->markDOFsConnectedToRange(mask, offset, marker, firstDOF, lastDOF,
307 dofIndex, useLinear);
308 FaceElements->markDOFsConnectedToRange(mask, offset, marker, firstDOF,
309 lastDOF, dofIndex, useLinear);
310 ContactElements->markDOFsConnectedToRange(mask, offset, marker, firstDOF,
311 lastDOF, dofIndex, useLinear);
312 Points->markDOFsConnectedToRange(mask, offset, marker, firstDOF, lastDOF,
313 dofIndex, useLinear);
314 }
315
316 /// optimizes the labeling of the DOFs on each processor
317 void Mesh::optimizeDOFLabeling(const std::vector<int>& distribution)
318 {
319 const int myRank=MPIInfo->rank;
320 const int mpiSize=MPIInfo->size;
321 const int myFirstVertex=distribution[myRank];
322 const int myLastVertex=distribution[myRank+1];
323 const int myNumVertices=myLastVertex-myFirstVertex;
324 int len=0;
325 for (int p=0; p<mpiSize; ++p)
326 len=std::max(len, distribution[p+1]-distribution[p]);
327
328 IndexList* index_list=new IndexList[myNumVertices];
329 std::vector<int> newGlobalDOFID(len);
330 // create the adjacency structure xadj and adjncy
331 #pragma omp parallel
332 {
333 // insert contributions from element matrices into columns index
334 IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list,
335 myFirstVertex, myLastVertex, Elements,
336 Nodes->globalDegreesOfFreedom,
337 Nodes->globalDegreesOfFreedom);
338 IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list,
339 myFirstVertex, myLastVertex, FaceElements,
340 Nodes->globalDegreesOfFreedom,
341 Nodes->globalDegreesOfFreedom);
342 IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list,
343 myFirstVertex, myLastVertex, ContactElements,
344 Nodes->globalDegreesOfFreedom,
345 Nodes->globalDegreesOfFreedom);
346 IndexList_insertElementsWithRowRangeNoMainDiagonal(index_list,
347 myFirstVertex, myLastVertex, Points,
348 Nodes->globalDegreesOfFreedom,
349 Nodes->globalDegreesOfFreedom);
350 }
351 // create the local matrix pattern
352 Paso_Pattern *pattern=IndexList_createPattern(0, myNumVertices,
353 index_list, myFirstVertex, myLastVertex, -myFirstVertex);
354
355 if (noError())
356 Paso_Pattern_reduceBandwidth(pattern, &newGlobalDOFID[0]);
357
358 Paso_Pattern_free(pattern);
359 delete[] index_list;
360 Esys_MPIInfo_noError(MPIInfo);
361
362 if (noError()) {
363 // shift new labeling to create a global id
364 #pragma omp parallel for
365 for (int i=0; i<myNumVertices; ++i)
366 newGlobalDOFID[i]+=myFirstVertex;
367
368 // distribute new labeling to other processors
369 #ifdef ESYS_MPI
370 const int dest=Esys_MPIInfo_mod(mpiSize, myRank + 1);
371 const int source=Esys_MPIInfo_mod(mpiSize, myRank - 1);
372 #endif
373 int current_rank=myRank;
374 for (int p=0; p<mpiSize; ++p) {
375 const int firstVertex=distribution[current_rank];
376 const int lastVertex=distribution[current_rank+1];
377 #pragma omp parallel for
378 for (int i=0; i<Nodes->numNodes; ++i) {
379 const int k=Nodes->globalDegreesOfFreedom[i];
380 if (firstVertex<=k && k<lastVertex) {
381 Nodes->globalDegreesOfFreedom[i]=newGlobalDOFID[k-firstVertex];
382 }
383 }
384
385 if (p<mpiSize-1) { // the final send can be skipped
386 #ifdef ESYS_MPI
387 MPI_Status status;
388 MPI_Sendrecv_replace(&newGlobalDOFID[0], len, MPI_INT,
389 dest, MPIInfo->msg_tag_counter,
390 source, MPIInfo->msg_tag_counter,
391 MPIInfo->comm, &status);
392 #endif
393 MPIInfo->msg_tag_counter++;
394 current_rank=Esys_MPIInfo_mod(mpiSize, current_rank-1);
395 }
396 }
397 }
398 }
399
400 /// prepares the mesh for further use
401 void Mesh::prepare(bool optimize)
402 {
403 setOrders();
404
405 // first step is to distribute the elements according to a global
406 // distribution of DOF
407 std::vector<int> distribution(MPIInfo->size+1);
408
409 // first we create dense labeling for the DOFs
410 int newGlobalNumDOFs=Nodes->createDenseDOFLabeling();
411
412 // create a distribution of the global DOFs and determine the MPI rank
413 // controlling the DOFs on this processor
414 Esys_MPIInfo_setDistribution(MPIInfo, 0, newGlobalNumDOFs-1, &distribution[0]);
415
416 // now the mesh is re-distributed according to the distribution vector
417 // this will redistribute the Nodes and Elements including overlap and
418 // will create an element coloring but will not create any mappings
419 // (see later in this function)
420 if (noError())
421 distributeByRankOfDOF(distribution);
422
423 // at this stage we are able to start an optimization of the DOF
424 // distribution using ParMetis. On return distribution is altered and
425 // new DOF IDs have been assigned
426 if (noError() && optimize && MPIInfo->size>1) {
427 optimizeDOFDistribution(distribution);
428 if (noError())
429 distributeByRankOfDOF(distribution);
430 }
431 // the local labelling of the degrees of freedom is optimized
432 if (noError() && optimize) {
433 optimizeDOFLabeling(distribution);
434 }
435 // rearrange elements with the aim of bringing elements closer to memory
436 // locations of the nodes (distributed shared memory!):
437 optimizeElementOrdering();
438
439 // create the global indices
440 if (noError()) {
441 std::vector<short> maskReducedNodes(Nodes->numNodes, -1);
442 std::vector<int> nodeDistribution(MPIInfo->size+1);
443 markNodes(maskReducedNodes, 0, true);
444 std::vector<int> indexReducedNodes = util::packMask(maskReducedNodes);
445
446 Nodes->createDenseNodeLabeling(nodeDistribution, distribution);
447 // created reduced DOF labeling
448 Nodes->createDenseReducedLabeling(maskReducedNodes, false);
449 // created reduced node labeling
450 Nodes->createDenseReducedLabeling(maskReducedNodes, true);
451
452 // create the missing mappings
453 if (noError())
454 Nodes->createNodeMappings(indexReducedNodes, distribution, nodeDistribution);
455 }
456
457 updateTagList();
458 }
459
460 /// tries to reduce the number of colours for all element files
461 void Mesh::createColoring(const std::vector<int>& dofMap)
462 {
463 if (noError())
464 Elements->createColoring(dofMap);
465 if (noError())
466 FaceElements->createColoring(dofMap);
467 if (noError())
468 Points->createColoring(dofMap);
469 if (noError())
470 ContactElements->createColoring(dofMap);
471 }
472
473 /// redistributes elements to minimize communication during assemblage
474 void Mesh::optimizeElementOrdering()
475 {
476 if (noError())
477 Elements->optimizeOrdering();
478 if (noError())
479 FaceElements->optimizeOrdering();
480 if (noError())
481 Points->optimizeOrdering();
482 if (noError())
483 ContactElements->optimizeOrdering();
484 }
485
486 /// regenerates list of tags in use for node file and element files
487 void Mesh::updateTagList()
488 {
489 if (noError()) Nodes->updateTagList();
490 if (noError()) Elements->updateTagList();
491 if (noError()) FaceElements->updateTagList();
492 if (noError()) Points->updateTagList();
493 if (noError()) ContactElements->updateTagList();
494 }
495
496 /// assigns new node reference numbers to all element files
497 void Mesh::relabelElementNodes(const std::vector<int>& newNode, int offset)
498 {
499 Elements->relabelNodes(newNode, offset);
500 FaceElements->relabelNodes(newNode, offset);
501 ContactElements->relabelNodes(newNode, offset);
502 Points->relabelNodes(newNode, offset);
503 }
504
505 void Mesh::resolveNodeIds()
506 {
507 // Initially the element nodes refer to the numbering defined by the global
508 // id assigned to the nodes in the NodeFile. It is also not ensured that
509 // all nodes referred by an element are actually available on the process.
510 // At the output, a local node labeling is used and all nodes are
511 // available. In particular the numbering of the element nodes is between
512 // 0 and NodeFile->numNodes.
513 // The function does not create a distribution of the degrees of freedom.
514
515 // find the minimum and maximum id used by elements
516 int min_id=std::numeric_limits<int>::max();
517 int max_id=std::numeric_limits<int>::min();
518 std::pair<int,int> range(Elements->getNodeRange());
519 max_id=std::max(max_id,range.second);
520 min_id=std::min(min_id,range.first);
521 range=FaceElements->getNodeRange();
522 max_id=std::max(max_id,range.second);
523 min_id=std::min(min_id,range.first);
524 range=ContactElements->getNodeRange();
525 max_id=std::max(max_id,range.second);
526 min_id=std::min(min_id,range.first);
527 range=Points->getNodeRange();
528 max_id=std::max(max_id,range.second);
529 min_id=std::min(min_id,range.first);
530 #ifdef Finley_TRACE
531 int global_min_id, global_max_id;
532 #ifdef ESYS_MPI
533 int id_range[2], global_id_range[2];
534 id_range[0]=-min_id;
535 id_range[1]=max_id;
536 MPI_Allreduce(id_range, global_id_range, 2, MPI_INT, MPI_MAX, MPIInfo->comm);
537 global_min_id=-global_id_range[0];
538 global_max_id=global_id_range[1];
539 #else
540 global_min_id=min_id;
541 global_max_id=max_id;
542 #endif
543 printf("Node id range used by elements is %d:%d\n",global_min_id,global_max_id);
544 #endif
545 if (min_id>max_id) {
546 max_id=-1;
547 min_id=0;
548 }
549
550 // allocate mappings for new local node labeling to global node labeling
551 // (newLocalToGlobalNodeLabels) and global node labeling to the new local
552 // node labeling (globalToNewLocalNodeLabels[i-min_id] is the new local id
553 // of global node i)
554 int len=(max_id>=min_id) ? max_id-min_id+1 : 0;
555
556 // mark the nodes referred by elements in usedMask
557 std::vector<short> usedMask(len, -1);
558 markNodes(usedMask, min_id, false);
559
560 // create a local labeling newLocalToGlobalNodeLabels of the local nodes
561 // by packing the mask usedMask
562 std::vector<int> newLocalToGlobalNodeLabels=util::packMask(usedMask);
563 const int newNumNodes=newLocalToGlobalNodeLabels.size();
564 usedMask.clear();
565
566 // invert the new labeling and shift the index newLocalToGlobalNodeLabels
567 // to global node ids
568 std::vector<int> globalToNewLocalNodeLabels(len, -1);
569
570 #pragma omp parallel for
571 for (int n=0; n<newNumNodes; n++) {
572 #ifdef BOUNDS_CHECK
573 if (newLocalToGlobalNodeLabels[n] >= len || newLocalToGlobalNodeLabels[n] < 0) {
574 printf("BOUNDS_CHECK %s %d n=%d\n", __FILE__, __LINE__, n);
575 exit(1);
576 }
577 #endif
578 globalToNewLocalNodeLabels[newLocalToGlobalNodeLabels[n]]=n;
579 newLocalToGlobalNodeLabels[n]+=min_id;
580 }
581
582 // create a new table
583 NodeFile *newNodeFile=new NodeFile(getDim(), MPIInfo);
584 if (noError()) {
585 newNodeFile->allocTable(newNumNodes);
586 }
587 if (noError()) {
588 newNodeFile->gather_global(newLocalToGlobalNodeLabels, Nodes);
589 }
590 if (noError()) {
591 delete Nodes;
592 Nodes=newNodeFile;
593 // relabel nodes of the elements
594 relabelElementNodes(globalToNewLocalNodeLabels, min_id);
595 }
596 }
597
598 /// sets new coordinates for the nodes
599 void Mesh::setCoordinates(const escript::Data& newX)
600 {
601 Nodes->setCoordinates(newX);
602 }
603
604 void Mesh::addTagMap(const char* name, int tag_key)
605 {
606 tagMap[std::string(name)]=tag_key;
607 }
608
609 int Mesh::getTag(const char* name) const
610 {
611 TagMap::const_iterator it = tagMap.find(name);
612 if (it == tagMap.end()) {
613 std::stringstream ss;
614 ss << "getTag: unknown tag name " << name << ".";
615 const std::string errorMsg(ss.str());
616 setError(VALUE_ERROR, errorMsg.c_str());
617 return -1;
618 }
619 return it->second;
620 }
621
622 bool Mesh::isValidTagName(const char* name) const
623 {
624 return (tagMap.count(std::string(name)) > 0);
625 }
626
627 } // namespace finley
628

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision
svn:mergeinfo /branches/lapack2681/finley/src/Mesh.cpp:2682-2741 /branches/pasowrap/finley/src/Mesh.cpp:3661-3674 /branches/py3_attempt2/finley/src/Mesh.cpp:3871-3891 /branches/restext/finley/src/Mesh.cpp:2610-2624 /branches/ripleygmg_from_3668/finley/src/Mesh.cpp:3669-3791 /branches/stage3.0/finley/src/Mesh.cpp:2569-2590 /branches/symbolic_from_3470/finley/src/Mesh.cpp:3471-3974 /release/3.0/finley/src/Mesh.cpp:2591-2601 /trunk/finley/src/Mesh.cpp:4257-4344

  ViewVC Help
Powered by ViewVC 1.1.26