1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Partitioning/decimation module for the SALOME v3.2 platform
22 * \file MULTIPR_Elements.cxx
24 * \brief see MULTIPR_Elements.hxx
26 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
31 //*****************************************************************************
33 //*****************************************************************************
35 #include "MULTIPR_Elements.hxx"
36 #include "MULTIPR_Nodes.hxx"
37 #include "MULTIPR_Exceptions.hxx"
50 //*****************************************************************************
51 // Class Elements implementation
52 //*****************************************************************************
60 mFlagPrintAll = false;
64 Elements::Elements(med_geometrie_element pGeomType)
72 mNumNodesByElt = mGeom % 100;
75 mFlagPrintAll = false;
84 void Elements::reset()
92 if (mId != NULL) { delete[] mId; mId = NULL; }
93 if (mFamIdent != NULL) { delete[] mFamIdent; mFamIdent = NULL; }
94 if (mNames != NULL) { delete[] mNames; mNames = NULL; }
95 if (mCon != NULL) { delete[] mCon; mCon = NULL; }
99 mFlagPrintAll = false;
103 med_int Elements::getFamilyIdentifier(med_int pIndex) const
105 if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
107 return mFamIdent[pIndex];
111 const med_int* Elements::getConnectivity(int pIndex) const
113 if ((pIndex < 0) || (pIndex >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
115 return mCon + mNumNodesByElt * pIndex;
119 void Elements::getCoordinates(med_int pIndexElt, const Nodes* pNodes, med_float* pCoo, int pFirst) const
121 if ((pIndexElt < 0) || (pIndexElt >= mNum)) throw IndexOutOfBoundsException("", __FILE__, __LINE__);
122 if (pNodes == NULL) throw NullArgumentException("", __FILE__, __LINE__);
123 if (pCoo == NULL) throw NullArgumentException("", __FILE__, __LINE__);
125 // get the list of nodes of the element
126 const med_int* con = getConnectivity(pIndexElt);
128 med_float* destCoo = pCoo;
129 int size = sizeof(med_float) * mDim;
131 // for each node of the element
132 int n = (mNumNodesByElt < pFirst) ? mNumNodesByElt : pFirst;
133 for (int i = 0 ; i < n ; i++)
135 // get index of node (MED index start at 1)
136 med_int indexNode = con[i] - 1;
138 // get coordinates of this node
139 const med_float* srcCoo = pNodes->getCoordinates(indexNode);
141 // copy coordinates to destCoo
142 memcpy(destCoo, srcCoo, size);
144 // prepare next point
150 Elements* Elements::extractSubSet(const set<med_int>& pSetIndices) const
152 Elements* subset = new Elements();
154 //---------------------------------------------------------------------
156 //---------------------------------------------------------------------
157 subset->mNum = pSetIndices.size();
158 subset->mEntity = mEntity;
159 subset->mGeom = mGeom; // e.g. 310 for a TETRA10
160 subset->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
161 subset->mDim = mDim; // e.g. 3 for a TETRA10
163 //---------------------------------------------------------------------
165 //---------------------------------------------------------------------
166 subset->mFamIdent = new med_int[subset->mNum];
167 subset->mCon = new med_int[mNumNodesByElt * subset->mNum];
169 //---------------------------------------------------------------------
170 // Copy subset of familys id and connectivity.
171 //---------------------------------------------------------------------
172 med_int* destCon = subset->mCon;
173 set<med_int>::iterator itSet = pSetIndices.begin();
174 for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
176 med_int srcIndex = (*itSet) - 1; // MED index start at 1
177 subset->mFamIdent[itElt] = mFamIdent[srcIndex];
179 med_int* srcCon = mCon + srcIndex * mNumNodesByElt;
180 memcpy(destCon, srcCon, sizeof(med_int) * mNumNodesByElt);
182 destCon += mNumNodesByElt;
185 //---------------------------------------------------------------------
186 // Copy subset of identifiers if necessary
187 //---------------------------------------------------------------------
190 itSet = pSetIndices.begin();
191 subset->mId = new med_int[subset->mNum];
192 for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
194 med_int srcIndex = (*itSet) - 1; // MED index start at 1
195 subset->mId[itElt] = mId[srcIndex];
201 //---------------------------------------------------------------------
202 // Copy subset of names if necessary
203 //---------------------------------------------------------------------
206 itSet = pSetIndices.begin();
207 subset->mNames = new char[MED_TAILLE_PNOM * subset->mNum + 1];
208 char* destPtr = subset->mNames;
209 for (int itElt = 0 ; itElt < subset->mNum && itSet != pSetIndices.end(); itElt++)
211 med_int srcIndex = (*itSet) - 1; // MED index start at 1
212 char* srcPtr = mNames + srcIndex * MED_TAILLE_PNOM;
213 memcpy(destPtr, srcPtr, MED_TAILLE_PNOM);
215 destPtr += MED_TAILLE_PNOM;
218 subset->mNames[MED_TAILLE_PNOM * subset->mNum] = '\0';
224 void Elements::extractSubSetFromNodes(const std::set<med_int>& pSetOfNodes,
225 std::set<med_int>& pSubSetOfElements) const
227 if (&pSetOfNodes == &pSubSetOfElements) throw IllegalStateException("pSetOfNodes and pSubSetOfElements must be different !", __FILE__, __LINE__);
229 int numOfNodes = pSetOfNodes.size();
230 bool keepElt = false;
231 for (int itElt = 0; itElt < mNum; ++itElt)
234 for (std::set<med_int>::iterator itNode = pSetOfNodes.begin();
235 itNode != pSetOfNodes.end() && keepElt == false; ++itNode)
237 for (int itCon = 0; itCon < mNumNodesByElt && keepElt == false; ++itCon)
239 if ((*itNode) == mCon[itElt * mNumNodesByElt + itCon])
247 pSubSetOfElements.insert(itElt + 1);
252 const set<med_int>& Elements::getSetOfNodes()
254 // lazy get: test if mSetOfNodes has already been built
255 if (mSetOfNodes.size() == 0)
264 set<med_int> Elements::getSetOfFamilies() const
266 // set of families is empty at the beginning
267 set<med_int> setOfFamilies;
269 // for each element, add its family to the set
270 for (int itElt = 0 ; itElt < mNum ; itElt++)
272 setOfFamilies.insert(mFamIdent[itElt]);
275 return setOfFamilies;
279 void Elements::remap()
282 // build set of nodes if necessary
283 if (mSetOfNodes.size() == 0)
288 // build the map for indices convertion
289 map<med_int, med_int> mapOldIndexToNewIndex;
290 med_int newIndex = 1; // MED index start at 1
291 for (set<med_int>::iterator itSet = mSetOfNodes.begin(); itSet != mSetOfNodes.end() ; itSet++)
293 med_int oldIndex = (*itSet);
294 mapOldIndexToNewIndex.insert(make_pair(oldIndex, newIndex));
298 // for each node referenced by this set of elements
299 for (itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
301 // convert old index to new index (remap)
302 mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]];
308 void Elements::remap(std::set<med_int>& pSetOfNodes)
312 // build the map for indices convertion
313 map<med_int, med_int> mapOldIndexToNewIndex;
314 med_int newIndex = 1; // MED index start at 1
316 for (std::set<med_int>::iterator it = pSetOfNodes.begin(); it != pSetOfNodes.end(); ++it)
318 med_int oldIndex = *it;
319 mapOldIndexToNewIndex.insert(make_pair(oldIndex, itNode));
322 // for each node referenced by this set of elements
323 for (itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
325 // convert old index to new index (remap).
326 mCon[itNode] = mapOldIndexToNewIndex[mCon[itNode]];;
332 Elements* Elements::mergePartial(Elements* pElements, int pOffset)
334 Elements* elements = new Elements();
336 //---------------------------------------------------------------------
338 //---------------------------------------------------------------------
339 elements->mNum = mNum + pElements->mNum;
341 if (mEntity != pElements->mEntity) throw IllegalStateException("entity should be the same", __FILE__, __LINE__);
342 elements->mEntity = mEntity;
344 elements->mGeom = mGeom; // e.g. 310 for a TETRA10
345 elements->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
346 if (mDim != pElements->mDim) throw IllegalStateException("dimension should be the same", __FILE__, __LINE__);
347 elements->mDim = mDim; // e.g. 3 for a TETRA10
349 elements->mId = NULL;
350 elements->mNames = NULL;
352 //---------------------------------------------------------------------
354 //---------------------------------------------------------------------
355 elements->mFamIdent = new med_int[elements->mNum];
356 elements->mCon = new med_int[mNumNodesByElt * elements->mNum];
358 //---------------------------------------------------------------------
359 // Copy familys id and connectivity.
360 //---------------------------------------------------------------------
361 memcpy(elements->mFamIdent, mFamIdent, mNum * sizeof(med_int));
362 memcpy(elements->mFamIdent + mNum, pElements->mFamIdent, pElements->mNum * sizeof(med_int));
364 memcpy(elements->mCon, mCon, mNum * mNumNodesByElt * sizeof(med_int));
366 med_int* dst = elements->mCon + mNum * mNumNodesByElt;
367 for (int i = 0, n = pElements->mNum * mNumNodesByElt ; i < n ; i++)
369 dst[i] = pElements->mCon[i] + pOffset;
372 //cout << "WARNING: do no build set of nodes" << endl;
373 //elements->buildSetOfNodes();
379 Elements* Elements::mergePartial(vector<Elements*> pElements, vector<int>& pOffsets)
381 if (pElements.size() == 0) throw IllegalArgumentException("pElements should contain at least 1 element", __FILE__, __LINE__);
383 Elements* elements = new Elements();
385 //---------------------------------------------------------------------
387 //---------------------------------------------------------------------
388 elements->mNum = mNum;
389 for (unsigned i = 0 ; i < pElements.size() ; i++)
391 elements->mNum += pElements[i]->mNum;
393 if (mEntity != pElements[i]->mEntity) throw IllegalStateException("entity should be the same", __FILE__, __LINE__);
394 if (mDim != pElements[i]->mDim) throw IllegalStateException("dimension should be the same", __FILE__, __LINE__);
397 elements->mEntity = mEntity;
398 elements->mGeom = mGeom; // e.g. 310 for a TETRA10
399 elements->mNumNodesByElt = mNumNodesByElt; // e.g. 10 for a TETRA10
400 elements->mDim = mDim; // e.g. 3 for a TETRA10
402 elements->mId = NULL;
403 elements->mNames = NULL;
405 //---------------------------------------------------------------------
407 //---------------------------------------------------------------------
408 elements->mFamIdent = new med_int[elements->mNum];
409 elements->mCon = new med_int[mNumNodesByElt * elements->mNum];
411 //---------------------------------------------------------------------
412 // Copy familys id and connectivity.
413 //---------------------------------------------------------------------
414 memcpy(elements->mFamIdent, mFamIdent, mNum * sizeof(med_int));
415 memcpy(elements->mCon, mCon, mNum * mNumNodesByElt * sizeof(med_int));
417 int offsetFamIdent = mNum;
418 int offsetCon = mNum;
419 for (unsigned j = 0 ; j < pElements.size() ; j++)
421 memcpy(elements->mFamIdent + offsetFamIdent, pElements[j]->mFamIdent, pElements[j]->mNum * sizeof(med_int)); offsetFamIdent += pElements[j]->mNum;
423 med_int* dst = elements->mCon + offsetCon * mNumNodesByElt;
424 for (int i = 0, n = pElements[j]->mNum * mNumNodesByElt ; i < n ; i++)
426 dst[i] = pElements[j]->mCon[i] + pOffsets[j];
428 offsetCon += pElements[j]->mNum;
431 //cout << "WARNING: do no build set of nodes" << endl;
432 //elements->buildSetOfNodes();
438 void Elements::buildSetOfNodes()
440 if (mSetOfNodes.size() != 0)
445 // for each node referenced by this set of elements
446 for (int itNode = 0, size = mNum * mNumNodesByElt ; itNode < size ; itNode++)
448 // add the node to the set
449 mSetOfNodes.insert(mCon[itNode]);
454 void Elements::readMED(
458 med_entite_maillage pEntity,
459 med_geometrie_element pGeom)
461 if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
462 if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
463 if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
469 mNumNodesByElt = mGeom % 100;
475 MED_CONN, // type of information requested = CONNECTIVITY
478 MED_NOD); // nodal connectivity
480 if (mNum < 0) throw IOException("i/o error while reading information about elements in MED file", __FILE__, __LINE__);
488 mCon = new med_int[mNumNodesByElt * mNum];
489 mNames = new char[MED_TAILLE_PNOM * mNum + 1];
490 mId = new med_int[mNum];
491 mFamIdent = new med_int[mNum];
493 med_booleen isIdentifiers;
495 med_err ret = MEDelementsLire(
509 MED_NOD); // NODAL CONNECTIVITY
511 if (ret != 0) throw IOException("i/o error while reading elements in MED file", __FILE__, __LINE__);
527 void Elements::writeMED(med_idt pMEDfile, char* pMeshName, med_int pMeshDim)
529 if (pMEDfile == 0) throw IOException("", __FILE__, __LINE__);
530 if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
531 if (strlen(pMeshName) > MED_TAILLE_NOM) throw IllegalArgumentException("", __FILE__, __LINE__);
532 if ((pMeshDim < 1) || (pMeshDim > 3)) throw IllegalArgumentException("", __FILE__, __LINE__);
534 // special case: if no elements => do nothing
535 if (mNum == 0) return;
537 med_err ret = MEDelementsEcr(
544 isNames()?MED_VRAI:MED_FAUX,
546 isIdentifiers()?MED_VRAI:MED_FAUX,
551 MED_NOD); // NODAL CONNECTIVITY
553 if (ret != 0) throw IOException("i/o error while writing elements in MED file", __FILE__, __LINE__);
557 ostream& operator<<(ostream& pOs, Elements& pE)
562 case MED_MAILLE: strcpy(strEntity, "MED_MAILLE"); break;
563 case MED_FACE: strcpy(strEntity, "MED_FACE"); break;
564 case MED_ARETE: strcpy(strEntity, "MED_ARETE"); break;
565 case MED_NOEUD: strcpy(strEntity, "MED_NOEUD"); break;
566 default: strcpy(strEntity, "UNKNOWN"); break;
569 pOs << "Elements: " << endl;
570 pOs << " #number =" << pE.mNum << endl;
571 pOs << " Entity =" << strEntity << endl;
572 pOs << " Geom =" << pE.mGeom << endl;
573 pOs << " Has names?" << (pE.isNames()?"yes":"no") << endl;
574 pOs << " Has id ?" << (pE.isIdentifiers()?"yes":"no") << endl;
577 set<med_int> setOfFam = pE.getSetOfFamilies();
578 if (setOfFam.size() == 0)
580 pOs << " Families: #fam=0" << endl;
584 set<med_int>::iterator itFam = setOfFam.end();
586 pOs << " Families: #fam=" << setOfFam.size() << " id_min=" << (*(setOfFam.begin())) << " id_max=" << (*itFam) << endl;
588 if (pE.mFlagPrintAll)
590 for (int i = 0 ; i < pE.mNum; i++)
592 pOs << " Elt " << (i + 1) << ": " << pE.mFamIdent[i] << endl;
599 set<med_int> setOfNodes = pE.getSetOfNodes();
600 if (setOfNodes.size() == 0)
602 pOs << " Connectivity: #nodes=0" << endl;
606 set<med_int>::iterator itNode = setOfNodes.end();
608 pOs << " Connectivity: #nodes=" << setOfNodes.size() << " id_min=" << (*(setOfNodes.begin())) << " id_max=" << (*itNode) << endl;
610 if (pE.mFlagPrintAll)
612 for (int i = 0 ; i < pE.mNum ; i++)
614 pOs << " Elt " << (i + 1) << ": ";
615 for (int j = 0 ; j < pE.mNumNodesByElt ; j++)
617 pOs << pE.mCon[i * pE.mNumNodesByElt + j] << " ";
625 if (pE.mFlagPrintAll)
628 if (pE.isIdentifiers())
630 pOs << " Num (identifier): " << endl;
631 for (int i = 0 ; i < pE.mNum; i++)
633 pOs << " Elt " << (i + 1) << ": " << pE.mId[i] << " " << endl;
639 pE.mNames[MED_TAILLE_PNOM * pE.mNum] = '\0';
640 pOs << " Names: |" << pE.mNames << "|" << endl;
649 } // namespace multipr