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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5148 - (show annotations)
Mon Sep 15 01:25:23 2014 UTC (4 years, 11 months ago) by caltinay
File size: 23440 byte(s)
Merging ripley diagonal storage + CUDA support into trunk.
Options file version has been incremented due to new options
'cuda' and 'nvccflags'.

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision
svn:mergeinfo /branches/diaplayground/finley/src/Mesh.cpp:4940-5147 /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