1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
5 * \file MULTIPR_Elements.cxx
7 * \brief see MULTIPR_Elements.hxx
9 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
14 //*****************************************************************************
16 //*****************************************************************************
18 #include "MULTIPR_Elements.hxx"
19 #include "MULTIPR_Nodes.hxx"
20 #include "MULTIPR_Exceptions.hxx"
33 //*****************************************************************************
34 // Class Elements implementation
35 //*****************************************************************************
43 mFlagPrintAll = false;
47 Elements::Elements(med_geometrie_element pGeomType)
55 mNumNodesByElt = mGeom % 100;
58 mFlagPrintAll = false;
67 void Elements::reset()
75 if (mId != NULL) { delete[] mId; mId = NULL; }
76 if (mFamIdent != NULL) { delete[] mFamIdent; mFamIdent = NULL; }
77 if (mNames != NULL) { delete[] mNames; mNames = NULL; }
78 if (mCon != NULL) { delete[] mCon; mCon = NULL; }
82 mFlagPrintAll = false;
86 med_int Elements::getFamilyIdentifier(med_int pIndex) const
88 if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
90 return mFamIdent[pIndex];
94 const med_int* Elements::getConnectivity(int pIndex) const
96 if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
98 return mCon + mNumNodesByElt * pIndex;
102 void Elements::getCoordinates(med_int pIndexElt, const Nodes* pNodes, med_float* pCoo, int pFirst) const
104 if ((pIndexElt < 0) || (pIndexElt >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
105 if (pNodes == NULL) throw NullArgumentException("", __FILE__, __LINE__);
106 if (pCoo == NULL) throw NullArgumentException("", __FILE__, __LINE__);
108 // get the list of nodes of the element
109 const med_int* con = getConnectivity(pIndexElt);
111 med_float* destCoo = pCoo;
112 int size = sizeof(med_float) * mDim;
114 // for each node of the element
115 int n = (mNumNodesByElt < pFirst) ? mNumNodesByElt : pFirst;
116 for (int i = 0 ; i < n ; i++)
118 // get index of node (MED index start at 1)
119 med_int indexNode = con[i] - 1;
121 // get coordinates of this node
122 const med_float* srcCoo = pNodes->getCoordinates(indexNode);
124 // copy coordinates to destCoo
125 memcpy(destCoo, srcCoo, size);
127 // prepare next point
133 Elements* Elements::extractSubSet(const set<med_int>& pSetIndices) const
135 Elements* subset = new Elements();
137 //---------------------------------------------------------------------
139 //---------------------------------------------------------------------
140 subset->mNum = pSetIndices.size();
141 subset->mEntity = mEntity;
142 subset->mGeom = mGeom; // e.g. 310 for a TETRA10
143 subset->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
144 subset->mDim = mDim; // e.g. 3 for a TETRA10
146 //---------------------------------------------------------------------
148 //---------------------------------------------------------------------
149 subset->mFamIdent = new med_int[subset->mNum];
150 subset->mCon = new med_int[mNumNodesByElt * subset->mNum];
152 //---------------------------------------------------------------------
153 // Copy subset of familys id and connectivity.
154 //---------------------------------------------------------------------
155 med_int* destCon = subset->mCon;
156 set<med_int>::iterator itSet = pSetIndices.begin();
157 for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
159 med_int srcIndex = (*itSet) - 1; // MED index start at 1
160 subset->mFamIdent[itElt] = mFamIdent[srcIndex];
162 med_int* srcCon = mCon + srcIndex * mNumNodesByElt;
163 memcpy(destCon, srcCon, sizeof(med_int) * mNumNodesByElt);
165 destCon += mNumNodesByElt;
168 //---------------------------------------------------------------------
169 // Copy subset of identifiers if necessary
170 //---------------------------------------------------------------------
173 itSet = pSetIndices.begin();
174 subset->mId = new med_int[subset->mNum];
175 for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
177 med_int srcIndex = (*itSet) - 1; // MED index start at 1
178 subset->mId[itElt] = mId[srcIndex];
184 //---------------------------------------------------------------------
185 // Copy subset of names if necessary
186 //---------------------------------------------------------------------
189 itSet = pSetIndices.begin();
190 subset->mNames = new char[MED_TAILLE_PNOM * subset->mNum + 1];
191 char* destPtr = subset->mNames;
192 for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
194 med_int srcIndex = (*itSet) - 1; // MED index start at 1
195 char* srcPtr = mNames + srcIndex * MED_TAILLE_PNOM;
196 memcpy(destPtr, srcPtr, MED_TAILLE_PNOM);
198 destPtr += MED_TAILLE_PNOM;
201 subset->mNames[MED_TAILLE_PNOM * subset->mNum] = '\0';
207 void Elements::extractSubSetFromNodes(const std::set<med_int>& pSetOfNodes,
208 std::set<med_int>& pSubSetOfElements) const
210 if (&pSetOfNodes == &pSubSetOfElements) throw IllegalStateException("pSetOfNodes and pSubSetOfElements must be different !", __FILE__, __LINE__);
212 int numOfNodes = pSetOfNodes.size();
213 bool keepElt = false;
214 for (int itElt = 0; itElt < mNum; ++itElt)
217 for (std::set<med_int>::iterator itNode = pSetOfNodes.begin();
218 itNode != pSetOfNodes.end() && keepElt == false; ++itNode)
220 for (int itCon = 0; itCon < mNumNodesByElt && keepElt == false; ++itCon)
222 if ((*itNode) == mCon[itElt * mNumNodesByElt + itCon])
230 pSubSetOfElements.insert(itElt + 1);
235 const set<med_int>& Elements::getSetOfNodes()
237 // lazy get: test if mSetOfNodes has already been built
238 if (mSetOfNodes.size() == 0)
247 set<med_int> Elements::getSetOfFamilies() const
249 // set of families is empty at the beginning
250 set<med_int> setOfFamilies;
252 // for each element, add its family to the set
253 for (int itElt = 0 ; itElt < mNum ; itElt++)
255 setOfFamilies.insert(mFamIdent[itElt]);
258 return setOfFamilies;
262 void Elements::remap()
265 // build set of nodes if necessary
266 if (mSetOfNodes.size() == 0)
271 // build the map for indices convertion
272 map<med_int, med_int> mapOldIndexToNewIndex;
273 med_int newIndex = 1; // MED index start at 1
274 for (set<med_int>::iterator itSet = mSetOfNodes.begin(); itSet != mSetOfNodes.end() ; itSet++)
276 med_int oldIndex = (*itSet);
277 mapOldIndexToNewIndex.insert(make_pair(oldIndex, newIndex));
281 // for each node referenced by this set of elements
282 for (itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
284 // convert old index to new index (remap)
285 mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]];
291 void Elements::remap(std::set<med_int>& pSetOfNodes)
295 // build the map for indices convertion
296 map<med_int, med_int> mapOldIndexToNewIndex;
297 med_int newIndex = 1; // MED index start at 1
299 for (std::set<med_int>::iterator it = pSetOfNodes.begin(); it != pSetOfNodes.end(); ++it)
301 med_int oldIndex = *it;
302 mapOldIndexToNewIndex.insert(make_pair(oldIndex, itNode));
305 // for each node referenced by this set of elements
306 for (itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
308 // convert old index to new index (remap).
309 mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]];;
315 Elements* Elements::mergePartial(Elements* pElements, int pOffset)
317 Elements* elements = new Elements();
319 //---------------------------------------------------------------------
321 //---------------------------------------------------------------------
322 elements->mNum = mNum + pElements->mNum;
324 if (mEntity != pElements->mEntity) throw IllegalStateException("entity should be the same", __FILE__, __LINE__);
325 elements->mEntity = mEntity;
327 elements->mGeom = mGeom; // e.g. 310 for a TETRA10
328 elements->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
329 if (mDim != pElements->mDim) throw IllegalStateException("dimension should be the same", __FILE__, __LINE__);
330 elements->mDim = mDim; // e.g. 3 for a TETRA10
332 elements->mId = NULL;
333 elements->mNames = NULL;
335 //---------------------------------------------------------------------
337 //---------------------------------------------------------------------
338 elements->mFamIdent = new med_int[elements->mNum];
339 elements->mCon = new med_int[mNumNodesByElt * elements->mNum];
341 //---------------------------------------------------------------------
342 // Copy familys id and connectivity.
343 //---------------------------------------------------------------------
344 memcpy(elements->mFamIdent, mFamIdent, mNum * sizeof(med_int));
345 memcpy(elements->mFamIdent + mNum, pElements->mFamIdent, pElements->mNum * sizeof(med_int));
347 memcpy(elements->mCon, mCon, mNum * mNumNodesByElt * sizeof(med_int));
349 med_int* dst = elements->mCon + mNum * mNumNodesByElt;
350 for (int i = 0, n = pElements->mNum * mNumNodesByElt ; i < n ; i++)
352 dst[i] = pElements->mCon[i] + pOffset;
355 //cout << "WARNING: do no build set of nodes" << endl;
356 //elements->buildSetOfNodes();
362 Elements* Elements::mergePartial(vector<Elements*> pElements, vector<int>& pOffsets)
364 if (pElements.size() == 0) throw IllegalArgumentException("pElements should contain at least 1 element", __FILE__, __LINE__);
366 Elements* elements = new Elements();
368 //---------------------------------------------------------------------
370 //---------------------------------------------------------------------
371 elements->mNum = mNum;
372 for (unsigned i = 0 ; i < pElements.size() ; i++)
374 elements->mNum += pElements[i]->mNum;
376 if (mEntity != pElements[i]->mEntity) throw IllegalStateException("entity should be the same", __FILE__, __LINE__);
377 if (mDim != pElements[i]->mDim) throw IllegalStateException("dimension should be the same", __FILE__, __LINE__);
380 elements->mEntity = mEntity;
381 elements->mGeom = mGeom; // e.g. 310 for a TETRA10
382 elements->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
383 elements->mDim = mDim; // e.g. 3 for a TETRA10
385 elements->mId = NULL;
386 elements->mNames = NULL;
388 //---------------------------------------------------------------------
390 //---------------------------------------------------------------------
391 elements->mFamIdent = new med_int[elements->mNum];
392 elements->mCon = new med_int[mNumNodesByElt * elements->mNum];
394 //---------------------------------------------------------------------
395 // Copy familys id and connectivity.
396 //---------------------------------------------------------------------
397 memcpy(elements->mFamIdent, mFamIdent, mNum * sizeof(med_int));
398 memcpy(elements->mCon, mCon, mNum * mNumNodesByElt * sizeof(med_int));
400 int offsetFamIdent = mNum;
401 int offsetCon = mNum;
402 for (unsigned j = 0 ; j < pElements.size() ; j++)
404 memcpy(elements->mFamIdent + offsetFamIdent, pElements[j]->mFamIdent, pElements[j]->mNum * sizeof(med_int)); offsetFamIdent += pElements[j]->mNum;
406 med_int* dst = elements->mCon + offsetCon * mNumNodesByElt;
407 for (int i = 0, n = pElements[j]->mNum * mNumNodesByElt ; i < n ; i++)
409 dst[i] = pElements[j]->mCon[i] + pOffsets[j];
411 offsetCon += pElements[j]->mNum;
414 //cout << "WARNING: do no build set of nodes" << endl;
415 //elements->buildSetOfNodes();
421 void Elements::buildSetOfNodes()
423 if (mSetOfNodes.size() != 0)
428 // for each node referenced by this set of elements
429 for (int itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
431 // add the node to the set
432 mSetOfNodes.insert(mCon[itNode]);
437 void Elements::readMED(
441 med_entite_maillage pEntity,
442 med_geometrie_element pGeom)
444 if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
445 if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
446 if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
452 mNumNodesByElt = mGeom % 100;
458 MED_CONN, // type of information requested = CONNECTIVITY
461 MED_NOD); // nodal connectivity
463 if (mNum < 0) throw IOException("i/o error while reading information about elements in MED file", __FILE__, __LINE__);
471 mCon = new med_int[mNumNodesByElt * mNum];
472 mNames = new char[MED_TAILLE_PNOM * mNum + 1];
473 mId = new med_int[mNum];
474 mFamIdent = new med_int[mNum];
476 med_booleen isIdentifiers;
478 med_err ret = MEDelementsLire(
492 MED_NOD); // NODAL CONNECTIVITY
494 if (ret != 0) throw IOException("i/o error while reading elements in MED file", __FILE__, __LINE__);
510 void Elements::writeMED(med_idt pMEDfile, char* pMeshName, med_int pMeshDim)
512 if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
513 if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
514 if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__);
515 if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
517 // special case: if no elements => do nothing
518 if (mNum == 0) return;
520 med_err ret = MEDelementsEcr(
527 isNames()?MED_VRAI:MED_FAUX,
529 isIdentifiers()?MED_VRAI:MED_FAUX,
534 MED_NOD); // NODAL CONNECTIVITY
536 if (ret != 0) throw IOException("i/o error while writing elements in MED file", __FILE__, __LINE__);
540 ostream& operator<<(ostream& pOs, Elements& pE)
545 case MED_MAILLE: strcpy(strEntity, "MED_MAILLE"); break;
546 case MED_FACE: strcpy(strEntity, "MED_FACE"); break;
547 case MED_ARETE: strcpy(strEntity, "MED_ARETE"); break;
548 case MED_NOEUD: strcpy(strEntity, "MED_NOEUD"); break;
549 default: strcpy(strEntity, "UNKNOWN"); break;
552 pOs << "Elements: " << endl;
553 pOs << " #number =" << pE.mNum << endl;
554 pOs << " Entity =" << strEntity << endl;
555 pOs << " Geom =" << pE.mGeom << endl;
556 pOs << " Has names?" << (pE.isNames()?"yes":"no") << endl;
557 pOs << " Has id ?" << (pE.isIdentifiers()?"yes":"no") << endl;
560 set<med_int> setOfFam = pE.getSetOfFamilies();
561 if (setOfFam.size() == 0)
563 pOs << " Families: #fam=0" << endl;
567 set<med_int>::iterator itFam = setOfFam.end();
569 pOs << " Families: #fam=" << setOfFam.size() << " id_min=" << (*(setOfFam.begin())) << " id_max=" << (*itFam) << endl;
571 if (pE.mFlagPrintAll)
573 for (int i = 0 ; i < pE.mNum; i++)
575 pOs << " Elt " << (i + 1) << ": " << pE.mFamIdent[i] << endl;
582 set<med_int> setOfNodes = pE.getSetOfNodes();
583 if (setOfNodes.size() == 0)
585 pOs << " Connectivity: #nodes=0" << endl;
589 set<med_int>::iterator itNode = setOfNodes.end();
591 pOs << " Connectivity: #nodes=" << setOfNodes.size() << " id_min=" << (*(setOfNodes.begin())) << " id_max=" << (*itNode) << endl;
593 if (pE.mFlagPrintAll)
595 for (int i = 0 ; i < pE.mNum ; i++)
597 pOs << " Elt " << (i + 1) << ": ";
598 for (int j = 0 ; j < pE.mNumNodesByElt ; j++)
600 pOs << pE.mCon[i * pE.mNumNodesByElt + j] << " ";
608 if (pE.mFlagPrintAll)
611 if (pE.isIdentifiers())
613 pOs << " Num (identifier): " << endl;
614 for (int i = 0 ; i < pE.mNum; i++)
616 pOs << " Elt " << (i + 1) << ": " << pE.mId[i] << " " << endl;
622 pE.mNames[MED_TAILLE_PNOM * pE.mNum] = '\0';
623 pOs << " Names: |" << pE.mNames << "|" << endl;
632 } // namespace multipr