1 // Project MULTIPR, IOLS WP1.2.1 - EDF/CS
2 // Partitioning/decimation module for the SALOME v3.2 platform
5 * \file MULTIPR_MeshDis.cxx
7 * \brief see MULTIPR_MeshDis.hxx
9 * \author Olivier LE ROUX - CS, Virtual Reality Dpt
14 //*****************************************************************************
16 //*****************************************************************************
18 #include "MULTIPR_MeshDis.hxx"
19 #include "MULTIPR_Mesh.hxx"
20 #include "MULTIPR_DecimationFilter.hxx"
21 #include "MULTIPR_Utils.hxx"
22 #include "MULTIPR_Globals.hxx"
23 #include "MULTIPR_API.hxx"
24 #include "MULTIPR_Exceptions.hxx"
25 #include "MULTIPR_ProgressCallback.hxx"
27 #include "MEDSPLITTER_API.hxx"
39 //*****************************************************************************
40 // Global variables (exported)
41 //*****************************************************************************
43 // callback used to report progress about a long task (e.g. save to disk)
44 MULTIPR_ProgressCallback* gProgressCallback = NULL;
46 // callback used to report empty meshes
47 MULTIPR_EmptyMeshCallback* gEmptyMeshCallback = NULL;
50 //*****************************************************************************
51 // Class MeshDisEntry implementation
52 //*****************************************************************************
54 MeshDisPart::MeshDisPart()
58 mOldCollection = NULL;
64 MeshDisPart::~MeshDisPart()
70 void MeshDisPart::reset()
72 mToDoOnNextWrite = MULTIPR_UNDEFINED;
78 mMEDFileName[0] = '\0';
88 if (mCollection != NULL)
94 if (mOldCollection != NULL)
96 delete mOldCollection;
97 mOldCollection = NULL;
102 const char* MeshDisPart::getMEDFileNameSuffix() const
105 // "agregat100grains_12pas_grain97.med" -> "grain97"
106 // "agregat100grains_12pas_grain100_part2.med" -> "grain100_part2"
107 // "aagregat100grains_12pas_grain98_gradmoy-low-25.0-0.3.med" -> "grain98_gradmoy-low-25-0.3"
109 string prefix = removeExtension(mMEDFileName, ".med");
110 prefix.erase(0, prefix.rfind("grain"));
111 return prefix.c_str();
115 void MeshDisPart::create(
116 OnNextWrite pToDoOnNextWrite,
117 const char* pMeshName,
119 const char* pPartName,
121 const char* pMEDFileName,
124 if (pToDoOnNextWrite == MULTIPR_UNDEFINED) throw IllegalArgumentException("", __FILE__, __LINE__);
125 if (pMeshName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
126 if (pId < 1) throw IllegalArgumentException("", __FILE__, __LINE__);
127 if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
128 if (pPath == NULL) throw NullArgumentException("", __FILE__, __LINE__);
129 if (pMEDFileName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
133 mToDoOnNextWrite = pToDoOnNextWrite;
134 strcpy(mMeshName, pMeshName);
136 strcpy(mPartName, pPartName);
137 strcpy(mPath, pPath);
138 strcpy(mMEDFileName, pMEDFileName);
144 void MeshDisPart::readMED()
146 if (mMesh != NULL) throw IllegalStateException("", __FILE__, __LINE__);
147 if (mCollection != NULL) throw IllegalStateException("", __FILE__, __LINE__);
148 if (mOldCollection != NULL) throw IllegalStateException("", __FILE__, __LINE__);
151 mMesh->readSequentialMED(mMEDFileName, mMeshName);
155 ostream& operator<<(ostream& pOs, MeshDisPart& pM)
157 switch (pM.mToDoOnNextWrite)
159 case MeshDisPart::MULTIPR_UNDEFINED:
163 case MeshDisPart::MULTIPR_KEEP_AS_IT:
164 pOs << pM.mMeshName << " " << pM.mId << " " << pM.mPartName << " " << pM.mPath << " " << pM.mMEDFileName;
167 case MeshDisPart::MULTIPR_WRITE_MESH:
168 pOs << pM.mMeshName << " " << pM.mId << " " << pM.mPartName << " " << pM.mPath << " " << pM.mMEDFileName;
171 case MeshDisPart::MULTIPR_WRITE_PARTS:
172 pOs << pM.mMeshName << " " << pM.mId << " " << pM.mPartName << " " << pM.mPath << " " << pM.mMEDFileName << " SPLIT " << pM.mSplit;
175 default: throw IllegalStateException("", __FILE__, __LINE__);
182 //*****************************************************************************
183 // Class MeshDis implementation
184 //*****************************************************************************
198 void MeshDis::reset()
200 mSequentialMEDFilename[0] = '\0';
201 mDistributedMEDFilename[0] = '\0';
203 for (unsigned itPart = 0 ; itPart != mParts.size() ; itPart++)
205 MeshDisPart* part = mParts[itPart];
210 //mProgressCallback = NULL;
214 void MeshDis::setSequentialMEDFilename(const char* pFilename)
216 strcpy(mSequentialMEDFilename, pFilename);
220 void MeshDis::addMesh(
221 MeshDisPart::OnNextWrite pToDoOnNextWrite,
222 const char* pMeshName,
224 const char* pPartName,
226 const char* pMEDFileName,
229 MeshDisPart* part = new MeshDisPart();
240 mParts.push_back(part);
244 void MeshDis::insertMesh(
245 MeshDisPart::OnNextWrite pToDoOnNextWrite,
246 const char* pMeshName,
248 const char* pPartName,
250 const char* pMEDFileName,
254 MeshDisPart* part = new MeshDisPart();
265 mParts.insert(mParts.begin() + pPosition, part);
267 // rename id of following parts
268 for (unsigned i = pPosition + 1 ; i < mParts.size() ; i++)
275 void MeshDis::removeParts(const char* pPrefixPartName)
277 if (pPrefixPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
280 sprintf(strPrefix, "%s_", pPrefixPartName);
282 for (vector<MeshDisPart*>::iterator itPart = mParts.begin() ; itPart != mParts.end() ; itPart++)
284 MeshDisPart* currentPart = (*itPart);
286 // remove part which have the same name and all sub_parts
287 // e.g. if pPrefixPartName="PART_4" => remove "PART_4" and "PART_4_*", but not "PART41"
288 if ((strcmp(currentPart->getPartName(), pPrefixPartName) == 0) ||
289 startsWith(currentPart->getPartName(), strPrefix))
291 mParts.erase(itPart);
293 // decrement id of following parts
294 for (vector<MeshDisPart*>::iterator itPart2 = itPart ; itPart2 != mParts.end() ; itPart2++)
300 if (currentPart->mMEDFileName != NULL)
302 remove(currentPart->mMEDFileName);
311 MeshDisPart* MeshDis::findPart(const char* pPartName)
313 if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
315 MeshDisPart* part = NULL;
317 for (unsigned itPart = 0 ; itPart < mParts.size() ; itPart++)
319 MeshDisPart* currentPart = mParts[itPart];
321 if (strcmp(currentPart->getPartName(), pPartName) == 0)
333 vector<string> MeshDis::getMeshes() const
337 if (mParts.size() > 0)
339 MeshDisPart* part = mParts[0];
340 const char* meshName = part->getMeshName();
341 res.push_back(meshName);
348 vector<string> MeshDis::getFields() const
352 if (mParts.size() == 0)
357 // all the parts of the distributed MED file should have the same fields
358 // => just return the name of fields of the first part
359 switch (mParts[0]->mToDoOnNextWrite)
361 case MeshDisPart::MULTIPR_KEEP_AS_IT:
362 case MeshDisPart::MULTIPR_WRITE_PARTS:
364 vector<pair<string, int> > tmp = multipr::getListScalarFields(mParts[0]->getMEDFileName());
366 for (unsigned i = 0 ; i < tmp.size() ; i++)
368 res.push_back(tmp[i].first);
373 case MeshDisPart::MULTIPR_WRITE_MESH:
374 return mParts[0]->mMesh->getNameScalarFields();
377 throw IllegalStateException("", __FILE__, __LINE__);
382 int MeshDis::getTimeStamps(const char* pFieldName) const
384 if (mParts.size() == 0)
386 // no parts in this distributed MED file => no fields => #iteration = 0
390 // all the parts of the distributed MED file should have the same fields
391 // => just return the number of iteration found in the field of the first part
392 switch (mParts[0]->mToDoOnNextWrite)
394 case MeshDisPart::MULTIPR_KEEP_AS_IT:
395 case MeshDisPart::MULTIPR_WRITE_PARTS:
397 vector<pair<string, int> > tmp = multipr::getListScalarFields(mParts[0]->getMEDFileName());
399 for (int i = 0 ; i < tmp.size() ; i++)
401 if (strcmp(tmp[i].first.c_str(), pFieldName) == 0)
403 return tmp[i].second;
407 // pFieldName not found in the list of fields
411 case MeshDisPart::MULTIPR_WRITE_MESH:
412 return mParts[0]->mMesh->getTimeStamps(pFieldName);
415 throw IllegalStateException("", __FILE__, __LINE__);
420 string MeshDis::getPartInfo(const char* pPartName)
422 MeshDisPart* part = findPart(pPartName);
427 sprintf(num, "%d", part->mId);
430 string(part->mMeshName) +
434 string(part->mPartName) +
436 string(part->mPath) +
438 string(part->mMEDFileName);
444 // part not found => return empty string
450 void MeshDis::splitPart(const char* pPartName, int pNbParts, int pPartitionner)
452 cout << "MULTIPR: MeshDis::splitPart()" << endl;
453 if (pPartName == NULL) throw NullArgumentException("", __FILE__, __LINE__);
454 if (pNbParts < 2) throw IllegalArgumentException("", __FILE__, __LINE__);
455 if ((pPartitionner != MULTIPR_METIS) && (pPartitionner != MULTIPR_SCOTCH)) throw IllegalArgumentException("should be 0=METIS or 1=SCOTCH", __FILE__, __LINE__);
457 cout << "MULTIPR: file=" << __FILE__ << " line=" << __LINE__ << " args OK" << endl;
459 //---------------------------------------------------------------------
460 // Find the MED file corresponding to the given part
461 //---------------------------------------------------------------------
462 MeshDisPart* part = findPart(pPartName);
466 throw IllegalArgumentException("part not found in this distributed MED file", __FILE__, __LINE__);
469 cout << "MULTIPR: file=" << __FILE__ << " line=" << __LINE__ << " find part OK" << endl;
471 //---------------------------------------------------------------------
472 // Load the sequential MED file
473 //---------------------------------------------------------------------
474 MEDSPLITTER::MESHCollection* collection;
475 collection = new MEDSPLITTER::MESHCollection(part->getMEDFileName(), part->getMeshName());
477 cout << "MULTIPR: file=" << __FILE__ << " line=" << __LINE__ << " MEDSPLITTER collection OK" << endl;
478 //---------------------------------------------------------------------
479 // Partition the group
480 //---------------------------------------------------------------------
481 MEDSPLITTER::Topology* topology;
482 if (pPartitionner == MULTIPR_METIS)
486 topology = collection->createPartition(pNbParts, MEDSPLITTER::Graph::METIS);
490 throw RuntimeException("MEDSPLITTER error: createPartition(), using METIS", __FILE__, __LINE__);
493 else if (pPartitionner == MULTIPR_SCOTCH)
497 cout << "MULTIPR: file=" << __FILE__ << " line=" << __LINE__ << " try to create partition using SCOTCH: #parts=" << pNbParts << endl;
498 topology = collection->createPartition(pNbParts, MEDSPLITTER::Graph::SCOTCH);
499 cout << "MULTIPR: file=" << __FILE__ << " line=" << __LINE__ << " assigned SCOTCH" << endl;
503 throw RuntimeException("MEDSPLITTER error: createPartition(), using SCOTCH", __FILE__, __LINE__);
508 throw IllegalStateException("unknown partitionner", __FILE__, __LINE__);
513 MEDSPLITTER::MESHCollection* newCollection = new MEDSPLITTER::MESHCollection(*collection, topology);
515 part->mToDoOnNextWrite = MeshDisPart::MULTIPR_WRITE_PARTS;
516 part->mSplit = pNbParts;
517 part->mOldCollection = collection;
518 part->mCollection = newCollection;
522 cout << "MEDSPLITTER error: new MESHCollection()" << endl;
523 throw RuntimeException("MEDSPLITTER error: new MESHCollection()", __FILE__, __LINE__);
528 void MeshDis::decimatePart(
529 const char* pPartName,
530 const char* pFieldName,
532 const char* pFilterName,
538 //---------------------------------------------------------------------
540 //---------------------------------------------------------------------
541 if (pPartName == NULL) throw NullArgumentException("partname should not be NULL", __FILE__, __LINE__);
542 if (pFieldName == NULL) throw NullArgumentException("fieldname should not be NULL", __FILE__, __LINE__);
543 if (pFieldIt < med_int(1)) throw IllegalArgumentException("invalid field iteration; should be >= 1", __FILE__, __LINE__);
544 if (pTMed < 0.0) throw IllegalArgumentException("med res.: threshold must be > 0", __FILE__, __LINE__);
545 if (pTMed >= pTLow) throw IllegalArgumentException("threshold for med res. must be < threshold for low res.", __FILE__, __LINE__);
546 if (pRadius <= med_float(0.0)) throw IllegalArgumentException("radius should be > 0", __FILE__, __LINE__);
547 if ((pBoxing < 1) || (pBoxing > 200)) throw IllegalArgumentException("boxing should be in [1..200]", __FILE__, __LINE__);
549 //---------------------------------------------------------------------
550 // Find the MED file corresponding to the given part
551 //---------------------------------------------------------------------
552 MeshDisPart* part = findPart(pPartName);
555 throw IllegalArgumentException("part not found in the given distributed MED file", __FILE__, __LINE__);
558 //---------------------------------------------------------------------
559 // Load the associated sequential MED file
560 //---------------------------------------------------------------------
561 if (part->mMesh == NULL)
566 Mesh* meshFull = part->mMesh;
567 cout << (*meshFull) << endl;
569 const char* originalFilename = part->getMEDFileName();
570 string strPrefix = removeExtension(originalFilename, ".med");
573 //cout << (*this) << endl;
575 //---------------------------------------------------------------------
576 // Decimates the given mesh
577 //---------------------------------------------------------------------
578 // arguments for decimation are passed as a string for genericity
580 char newPartName[MED_TAILLE_NOM + 1];
581 char newMEDFileName[256];
583 // *** create a new mesh = MEDIUM resolution ***
584 sprintf(argv, "%s %d %lf %lf %d", pFieldName, pFieldIt, pTMed, pRadius, pBoxing);
585 sprintf(newPartName, "%s_MED", pPartName);
586 sprintf(newMEDFileName, "%s_gradmoy-med-%s-%s.med",
588 realToString(pTMed).c_str(),
589 realToString(pRadius).c_str());
592 Mesh* meshMedium = meshFull->decimate(pFilterName, argv, part->getMeshName());
593 cout << (*meshMedium) << endl;
596 MeshDisPart::MULTIPR_WRITE_MESH,
605 if ((meshMedium->getNumberOfElements() == 0) && (gEmptyMeshCallback != NULL))
607 gEmptyMeshCallback->reportEmptyMesh(newPartName);
611 // *** create a new mesh = LOW resolution ***
612 sprintf(argv, "%s %d %lf %lf %d", pFieldName, pFieldIt, pTLow, pRadius, pBoxing);
613 sprintf(newPartName, "%s_LOW", pPartName);
614 sprintf(newMEDFileName, "%s_gradmoy-low-%s-%s.med",
616 realToString(pTLow).c_str(),
617 realToString(pRadius).c_str());
620 Mesh* meshLow = meshFull->decimate(pFilterName, argv, part->getMeshName());
621 cout << (*meshLow) << endl;
624 MeshDisPart::MULTIPR_WRITE_MESH,
633 if ((meshLow->getNumberOfElements() == 0) && (gEmptyMeshCallback != NULL))
635 gEmptyMeshCallback->reportEmptyMesh(newPartName);
640 //cout << (*this) << endl;
644 string MeshDis::evalDecimationParams(
645 const char* pPartName,
646 const char* pFieldName,
648 const char* pFilterName,
649 const char* pFilterParams)
651 MeshDisPart* part = findPart(pPartName);
659 if (part->mMesh == NULL)
664 multipr::DecimationFilter* filter = multipr::DecimationFilter::create(pFilterName);
670 multipr::DecimationFilterGradAvg* filterGrad = dynamic_cast<multipr::DecimationFilterGradAvg*>(filter);
672 if (filterGrad != NULL)
676 int ret = sscanf(pFilterParams, "%d", &mode);
678 // mode 2 = GET RADIUS
679 if ((ret == 1) && (mode == 2))
681 double radius = part->mMesh->evalDefaultRadius(8);
683 sprintf(res, "%f", radius);
690 ret = sscanf(pFilterParams, "%d %f %d", &mode, &radius, &boxing);
692 // mode 1 = GET GRADIENT MIN, MAX and AVG
693 if ((ret == 3) && (mode == 1))
695 double gradMin = 0.1, gradAvg = 0.15, gradMax = 0.2;
697 filterGrad->getGradientInfo(
708 sprintf(res, "%f %f %f", gradMin, gradAvg, gradMax);
723 int MeshDis::computeNumParts()
727 for (unsigned itPart = 0 ; itPart < mParts.size() ; itPart++)
729 switch (mParts[itPart]->mToDoOnNextWrite)
731 case MeshDisPart::MULTIPR_KEEP_AS_IT:
732 case MeshDisPart::MULTIPR_WRITE_MESH:
736 case MeshDisPart::MULTIPR_WRITE_PARTS:
737 numParts += mParts[itPart]->mSplit;
740 default: throw IllegalStateException("", __FILE__, __LINE__);
748 void MeshDis::readDistributedMED(const char* pMEDfilename)
750 if (pMEDfilename == NULL) throw NullArgumentException("filename should not be NULL", __FILE__, __LINE__);
752 const int MAX_SIZEOF_LINE = 1024;
755 strcpy(mDistributedMEDFilename, pMEDfilename);
757 //---------------------------------------------------------------------
758 // Open master file (ASCII file)
759 //---------------------------------------------------------------------
760 ifstream fileMaster(mDistributedMEDFilename);
761 if (fileMaster.fail()) throw IOException("i/o error while opening MED master file", __FILE__, __LINE__);
763 //---------------------------------------------------------------------
765 //---------------------------------------------------------------------
766 char charbuffer[MAX_SIZEOF_LINE];
767 fileMaster.getline(charbuffer, MAX_SIZEOF_LINE);
768 if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__);
771 if ((charbuffer[0] != '#') ||
772 (charbuffer[1] != ' ') ||
773 (charbuffer[2] != 'M') ||
774 (charbuffer[3] != 'E') ||
775 (charbuffer[4] != 'D'))
776 throw IOException("not a valid distributed MED file", __FILE__, __LINE__);
778 while ((charbuffer[0] == '#') || (strlen(charbuffer) == 0))
781 if ((charbuffer[0] == '#') && ((strTag = strstr(charbuffer, "[SOURCE]=")) != NULL))
783 char strSequentialMEDFilename[256];
784 int ret = sscanf(strTag, "[SOURCE]=%s", strSequentialMEDFilename);
787 setSequentialMEDFilename(strSequentialMEDFilename);
790 fileMaster.getline(charbuffer, MAX_SIZEOF_LINE);
791 if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__);
794 // read number of parts
795 int nbParts = atoi(charbuffer);
797 //---------------------------------------------------------------------
798 // Read infos about sub-parts
799 //---------------------------------------------------------------------
800 char lMeshName[MED_TAILLE_NOM + 1];
802 char lPartName[MED_TAILLE_NOM + 1];
804 char lMEDFileName[256];
806 for (int i = 0 ; i < nbParts ; i++)
808 fileMaster.getline(charbuffer, MAX_SIZEOF_LINE);
809 if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__);
811 while ((charbuffer[0] == '#') || (strlen(charbuffer) == 0))
813 fileMaster.getline(charbuffer, MAX_SIZEOF_LINE);
814 if (fileMaster.fail()) throw IOException("i/o error while reading MED master file", __FILE__, __LINE__);
821 lMEDFileName[0] = '\0';
823 int ret = sscanf(charbuffer, "%s %d %s %s %s",
830 if (ret != 5) throw IOException("i/o error while reading MED master file; bad format", __FILE__, __LINE__);
832 //cout << "DBG: read: " << lMeshName << " " << lId << " " << lPartName << endl;
834 MeshDisPart::MULTIPR_KEEP_AS_IT,
843 //---------------------------------------------------------------------
845 //---------------------------------------------------------------------
847 if (fileMaster.fail()) throw IOException("i/o error while closing MED master file", __FILE__, __LINE__);
852 * Retrieves the output of MEDSPLITTER and convert it for MULTIPR.
854 int convertMedsplitterToMultipr(ofstream& pFileMaster, const char* pTmpFilename, int pId, MeshDisPart* pPart, string pDestPath)
856 MULTIPR_LOG("convert" << endl);
858 const int MAX_SIZEOF_LINE = 1024;
859 char charbuffer[MAX_SIZEOF_LINE];
861 // Open medsplitter master file (ASCII file)
862 ifstream fileMasterMedsplitter(pTmpFilename);
863 if (fileMasterMedsplitter.fail()) throw IOException("i/o error while opening MEDSPLITTER master file", __FILE__, __LINE__);
865 fileMasterMedsplitter.getline(charbuffer, MAX_SIZEOF_LINE);
866 if (fileMasterMedsplitter.fail()) throw IOException("i/o error while reading MEDSPLITTER master file", __FILE__, __LINE__);
868 while ((charbuffer[0] == '#') || (strlen(charbuffer) == 0))
870 fileMasterMedsplitter.getline(charbuffer, MAX_SIZEOF_LINE);
871 if (fileMasterMedsplitter.fail()) throw IOException("i/o error while reading MEDSPLITTER master file", __FILE__, __LINE__);
874 // read number of parts
875 int nbParts = atoi(charbuffer);
876 //cout << "nb parts=" << nbParts << endl;
878 char lMeshName[MED_TAILLE_NOM + 1];
880 char lPartName[MED_TAILLE_NOM + 1];
882 char lMEDFileName[256];
884 for (int i = 0 ; i < nbParts ; i++)
886 fileMasterMedsplitter.getline(charbuffer, MAX_SIZEOF_LINE);
887 if (fileMasterMedsplitter.fail()) throw IOException("", __FILE__, __LINE__);
889 // parses the current line
894 lMEDFileName[0] = '\0';
896 int ret = sscanf(charbuffer, "%s %d %s %s %s",
903 if (ret != 5) throw IOException("i/o error while reading MEDSPLITTER master file; bad format", __FILE__, __LINE__);
905 string strDestFilename = pDestPath + multipr::getFilenameWithoutPath(lMEDFileName);
906 if (strcmp(lMEDFileName, strDestFilename.c_str()) != 0)
908 multipr::copyFile(lMEDFileName, pDestPath.c_str());
909 strcpy(lMEDFileName, strDestFilename.c_str());
912 pFileMaster << lMeshName << " " << (pId + i) << " " << pPart->getPartName() << "_" << (i + 1) << " " << lPath << " " << lMEDFileName << endl;
915 fileMasterMedsplitter.close();
916 if (fileMasterMedsplitter.fail()) throw IOException("i/o error while closing MEDSPLITTER master file", __FILE__, __LINE__);
918 // remove master file generated by MEDSPLITTER
919 remove(pTmpFilename);
925 void MeshDis::writeDistributedMED(const char* pMEDfilenamePrefix)
927 if (pMEDfilenamePrefix == NULL) throw NullArgumentException("", __FILE__, __LINE__);
929 //---------------------------------------------------------------------
930 // Build master filename
931 //---------------------------------------------------------------------
932 string strPrefix = string(pMEDfilenamePrefix);
933 const char* strExtension = ".med";
934 string strMasterFilename;
936 // add suffix "_grains_maitre" iff it is not yet in the filename
937 if (strstr(pMEDfilenamePrefix, "_grains_maitre") == 0)
939 strMasterFilename= strPrefix + "_grains_maitre" + strExtension;
943 strMasterFilename = strPrefix + strExtension;
946 string strDestPath = multipr::getPath(strMasterFilename.c_str());
948 MULTIPR_LOG("Create master: " << strMasterFilename << endl);
949 strcpy(mDistributedMEDFilename, strMasterFilename.c_str());
951 //---------------------------------------------------------------------
952 // Create an ASCII master file for the resulting distributed mesh and write header
953 //---------------------------------------------------------------------
954 remove(strMasterFilename.c_str());
955 ofstream fileMaster(strMasterFilename.c_str());
957 if (fileMaster == 0) throw IOException("i/o error while creating MED master file", __FILE__, __LINE__);
959 fileMaster << "# MED file v2.3 - Master file created by MULTIPR v" << getVersion() << endl;
960 fileMaster << "#" << " " << endl;
961 fileMaster << "# [SOURCE]=" << mSequentialMEDFilename << endl;
962 fileMaster << "#" << " " << endl;
964 fileMaster << computeNumParts() << endl;
965 if (fileMaster.fail()) throw IOException("i/o error while writing MED master file", __FILE__, __LINE__);
967 //---------------------------------------------------------------------
968 // Create a new MED file (v2.3)
969 //---------------------------------------------------------------------
972 if (gProgressCallback != NULL) gProgressCallback->start("Save mesh", mParts.size());
977 // for each sub-meshes
978 for (unsigned itPart = 0 ; itPart < mParts.size() ; itPart++)
980 switch (mParts[itPart]->mToDoOnNextWrite)
982 case MeshDisPart::MULTIPR_KEEP_AS_IT:
984 mParts[itPart]->mId = id;
987 // copy file in another directory?
988 string strSrcPath = multipr::getPath(mParts[itPart]->getMEDFileName());
989 if (strSrcPath != strDestPath)
991 cout << "Write: KEEP_AS_IT: copy file" << endl;
992 string strDestFilename = strDestPath + multipr::getFilenameWithoutPath(mParts[itPart]->getMEDFileName());
993 multipr::copyFile(mParts[itPart]->getMEDFileName(), strDestPath.c_str());
994 strcpy(mParts[itPart]->mMEDFileName, strDestFilename.c_str());
997 fileMaster << (*mParts[itPart]) << endl;
998 cout << (*mParts[itPart]) << endl;
1002 case MeshDisPart::MULTIPR_WRITE_MESH:
1004 if (strlen(mParts[itPart]->getMEDFileName()) == 0) throw IOException("MED filename is empty", __FILE__, __LINE__);
1005 if (mParts[itPart]->mMesh == NULL) throw IllegalStateException("invalid mesh (shoult not be NULL)", __FILE__, __LINE__);
1007 string strDestFilename = strDestPath + multipr::getFilenameWithoutPath(mParts[itPart]->getMEDFileName());
1008 strcpy(mParts[itPart]->mMEDFileName, strDestFilename.c_str());
1010 mParts[itPart]->mMesh->writeMED(mParts[itPart]->getMEDFileName());
1011 mParts[itPart]->mId = id;
1013 fileMaster << (*mParts[itPart]) << endl;
1014 cout << (*mParts[itPart]) << endl;
1018 case MeshDisPart::MULTIPR_WRITE_PARTS:
1020 // split this part using medsplitter
1021 if (mParts[itPart]->mOldCollection == NULL) throw IllegalStateException("", __FILE__, __LINE__);
1022 string strPrefix = removeExtension(mParts[itPart]->getMEDFileName(), ".med");
1023 char tmpFilename[256];
1024 sprintf(tmpFilename, "%s_part", strPrefix.c_str());
1025 mParts[itPart]->mCollection->write(tmpFilename);
1026 mParts[itPart]->mCollection->castAllFields(*(mParts[itPart]->mOldCollection));
1027 int ret = convertMedsplitterToMultipr(fileMaster, tmpFilename, id, mParts[itPart], strDestPath);
1029 remove(mParts[itPart]->getMEDFileName());
1033 default: throw IllegalStateException("should not be there", __FILE__, __LINE__);
1036 if (gProgressCallback != NULL) gProgressCallback->moveOn();
1040 catch (RuntimeException& e)
1042 if (gProgressCallback != NULL) gProgressCallback->done();
1046 if (gProgressCallback != NULL) gProgressCallback->done();
1048 //---------------------------------------------------------------------
1049 // Close master file
1050 //---------------------------------------------------------------------
1052 if (fileMaster.fail()) throw IOException("i/o error while closing MED master file", __FILE__, __LINE__);
1056 ostream& operator<<(ostream& pOs, MeshDis& pM)
1058 pOs << "Mesh Dis.:" << endl;
1059 pOs << " Sequential filename (source) =|" << pM.mSequentialMEDFilename << "|" << endl;
1060 pOs << " Distributed filename (master)=|" << pM.mDistributedMEDFilename << "|" << endl;
1061 pOs << " #Sub-meshes =" << pM.mParts.size() << endl;
1063 for (unsigned itPart = 0 ; itPart < pM.mParts.size() ; itPart++)
1065 cout << " " << (itPart + 1) << ": " << (*(pM.mParts[itPart])) << endl;
1072 } // namespace multipr