X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDLoader%2FMEDFileMesh.cxx;h=b2a610fbbee11fef798cf3fcaff0931ae75d57da;hb=3f78fd9a0ef0296eee2e9df7ca43cf77dbd1dd45;hp=be85b93ba2744cf855d708b81046d46f5ae96960;hpb=c0d1b91cfe164d84c1f549e48578a66662e90034;p=modules%2Fmed.git diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index be85b93ba..b2a610fbb 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D +// Copyright (C) 2007-2015 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,7 +20,10 @@ #include "MEDFileMesh.hxx" #include "MEDFileUtilities.hxx" +#include "MEDFileFieldOverView.hxx" +#include "MEDFileField.hxx" #include "MEDLoader.hxx" +#include "MEDFileSafeCaller.txx" #include "MEDLoaderBase.hxx" #include "MEDCouplingUMesh.hxx" @@ -30,17 +33,19 @@ #include #include +extern med_geometry_type typmai3[34]; + using namespace ParaMEDMEM; const char MEDFileMesh::DFT_FAM_NAME[]="FAMILLE_ZERO"; -MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.) +MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.),_univ_wr_status(true) { } -std::size_t MEDFileMesh::getHeapMemorySize() const +std::size_t MEDFileMesh::getHeapMemorySizeWithoutChildren() const { - std::size_t ret=_dt_unit.capacity()+_name.capacity()+_univ_name.capacity()+_desc_name.capacity(); + std::size_t ret(_dt_unit.capacity()+_name.capacity()+_univ_name.capacity()+_desc_name.capacity()); for(std::map >::const_iterator it=_groups.begin();it!=_groups.end();it++) { ret+=(*it).first.capacity()+(*it).second.capacity()*sizeof(std::string); @@ -52,7 +57,22 @@ std::size_t MEDFileMesh::getHeapMemorySize() const return ret; } -MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +std::vector MEDFileMesh::getDirectChildrenWithNull() const +{ + return std::vector(); +} + +/*! + * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED + * file. The first mesh in the file is loaded. + * \param [in] fileName - the name of MED file to read. + * \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + * \throw If the file is not readable. + * \throw If there is no meshes in the file. + * \throw If the mesh in the file is of a not supported type. + */ +MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs) { std::vector ms=MEDLoader::GetMeshNames(fileName); if(ms.empty()) @@ -62,69 +82,105 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Excepti } MEDFileUtilities::CheckFileForRead(fileName); ParaMEDMEM::MEDCouplingMeshType meshType; - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); int dt,it; std::string dummy2; - MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2); + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2); switch(meshType) - { + { case UNSTRUCTURED: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileUMesh::New(); - ret->loadUMeshFromFile(fid,ms.front().c_str(),dt,it); + ret->loadUMeshFromFile(fid,ms.front(),dt,it,mrs); + ret->loadJointsFromFile(fid); return (MEDFileUMesh *)ret.retn(); } case CARTESIAN: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCMesh::New(); - ret->loadCMeshFromFile(fid,ms.front().c_str(),dt,it); + ret->loadCMeshFromFile(fid,ms.front(),dt,it,mrs); + ret->loadJointsFromFile(fid); return (MEDFileCMesh *)ret.retn(); } case CURVE_LINEAR: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCurveLinearMesh::New(); - ret->loadCLMeshFromFile(fid,ms.front().c_str(),dt,it); - return (MEDFileCMesh *)ret.retn(); + ret->loadCLMeshFromFile(fid,ms.front(),dt,it,mrs); + ret->loadJointsFromFile(fid); + return (MEDFileCurveLinearMesh *)ret.retn(); } default: { std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << ms.front() << "' exists but unsupported type yet !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - } + } } -MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED + * file. The mesh to load is specified by its name and numbers of a time step and an + * iteration. + * \param [in] fileName - the name of MED file to read. + * \param [in] mName - the name of the mesh to read. + * \param [in] dt - the number of a time step. + * \param [in] it - the number of an iteration. + * \param [in] joints - the sub-domain joints to use instead of those that can be read + * from the MED file. Usually this joints are those just read by another iteration + * of mName mesh, when this method is called by MEDFileMeshMultiTS::New() + * \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + * \throw If the file is not readable. + * \throw If there is no mesh with given attributes in the file. + * \throw If the mesh in the file is of a not supported type. + */ +MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs, MEDFileJoints* joints) { MEDFileUtilities::CheckFileForRead(fileName); ParaMEDMEM::MEDCouplingMeshType meshType; - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); int dummy0,dummy1; std::string dummy2; MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2); switch(meshType) - { + { case UNSTRUCTURED: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileUMesh::New(); - ret->loadUMeshFromFile(fid,mName,dt,it); + ret->loadUMeshFromFile(fid,mName,dt,it,mrs); + ret->loadJointsFromFile(fid,joints); return (MEDFileUMesh *)ret.retn(); } case CARTESIAN: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCMesh::New(); - ret->loadCMeshFromFile(fid,mName,dt,it); + ret->loadCMeshFromFile(fid,mName,dt,it,mrs); + ret->loadJointsFromFile(fid,joints); return (MEDFileCMesh *)ret.retn(); } + case CURVE_LINEAR: + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileCurveLinearMesh::New(); + ret->loadCLMeshFromFile(fid,mName,dt,it,mrs); + ret->loadJointsFromFile(fid,joints); + return (MEDFileCurveLinearMesh *)ret.retn(); + } default: { std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << mName << "' exists but unsupported type yet !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - } + } } -void MEDFileMesh::write(med_idt fid) const throw(INTERP_KERNEL::Exception) +/*! + * Writes \a this mesh into an open MED file specified by its descriptor. + * \param [in] fid - the MED file descriptor. + * \throw If the mesh name is not set. + * \throw If the file is open for reading only. + * \throw If the writing mode == 1 and the same data is present in an existing file. + */ +void MEDFileMesh::write(med_idt fid) const { if(!existsFamily(0)) const_cast(this)->addFamily(DFT_FAM_NAME,0); @@ -133,15 +189,32 @@ void MEDFileMesh::write(med_idt fid) const throw(INTERP_KERNEL::Exception) writeLL(fid); } -void MEDFileMesh::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception) +/*! + * Writes \a this mesh into a MED file specified by its name. + * \param [in] fileName - the MED file name. + * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. + * - 2 - erase; an existing file is removed. + * - 1 - append; same data should not be present in an existing file. + * - 0 - overwrite; same data present in an existing file is overwritten. + * \throw If the mesh name is not set. + * \throw If \a mode == 1 and the same data is present in an existing file. + */ +void MEDFileMesh::write(const std::string& fileName, int mode) const { med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod); std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; - MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str()); + MEDFileUtilities::CheckMEDCode(fid,fid,oss.str()); write(fid); } +/*! + * Checks if \a this and another mesh are equal. + * \param [in] other - the mesh to compare with. + * \param [in] eps - a precision used to compare real values. + * \param [in,out] what - the string returning description of unequal data. + * \return bool - \c true if the meshes are equal, \c false, else. + */ bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const { if(_order!=other->_order) @@ -169,11 +242,7 @@ bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wha what="Names differ !"; return false; } - if(_univ_name!=other->_univ_name) - { - what="Univ names differ !"; - return false; - } + //univ_name has been ignored -> not a bug because it is a mutable attribute if(_desc_name!=other->_desc_name) { what="Description names differ !"; @@ -186,12 +255,20 @@ bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wha return true; } +void MEDFileMesh::setName(const std::string& name) +{ + _name=name; +} + +/*! + * Clears redundant attributes of incorporated data arrays. + */ void MEDFileMesh::clearNonDiscrAttributes() const { - + } -bool MEDFileMesh::changeNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +bool MEDFileMesh::changeNames(const std::vector< std::pair >& modifTab) { for(std::vector< std::pair >::const_iterator it=modifTab.begin();it!=modifTab.end();it++) { @@ -204,13 +281,62 @@ bool MEDFileMesh::changeNames(const std::vector< std::pair MEDFileMesh::getFamiliesOnGroup(const char *name) const throw(INTERP_KERNEL::Exception) + +/*! + * This method clear all the groups in the map. + * So this method does not operate at all on arrays. + * So this method can lead to orphan families. + * + * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps + */ +void MEDFileMesh::clearGrpMap() +{ + _groups.clear(); +} + +/*! + * This method clear all the families in the map. + * So this method does not operate at all on arrays. + * WARNING ! if there are some groups lying on cleared families, those groups will be impacted ! + * + * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps + */ +void MEDFileMesh::clearFamMap() +{ + _families.clear(); +} + +/*! + * This method clear all the families and groups in the map. + * So this method does not operate at all on arrays. + * As all groups and families entry will be removed after + * the call of MEDFileMesh::setFamilyFieldArr method with 0 or None (python) in the 2nd parameter can be useful to reduce the size of the object. + * + * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamMap + */ +void MEDFileMesh::clearFamGrpMaps() +{ + clearGrpMap(); + clearFamMap(); +} + +/*! + * Returns names of families constituting a group. + * \param [in] name - the name of the group of interest. + * \return std::vector - a sequence of names of the families. + * \throw If the name of a nonexistent group is specified. + */ +std::vector MEDFileMesh::getFamiliesOnGroup(const std::string& name) const { std::string oname(name); std::map >::const_iterator it=_groups.find(oname); @@ -224,7 +350,13 @@ std::vector MEDFileMesh::getFamiliesOnGroup(const char *name) const return (*it).second; } -std::vector MEDFileMesh::getFamiliesOnGroups(const std::vector& grps) const throw(INTERP_KERNEL::Exception) +/*! + * Returns names of families constituting some groups. + * \param [in] grps - a sequence of names of groups of interest. + * \return std::vector - a sequence of names of the families. + * \throw If a name of a nonexistent group is present in \a grps. + */ +std::vector MEDFileMesh::getFamiliesOnGroups(const std::vector& grps) const { std::set fams; for(std::vector::const_iterator it=grps.begin();it!=grps.end();it++) @@ -243,7 +375,13 @@ std::vector MEDFileMesh::getFamiliesOnGroups(const std::vector MEDFileMesh::getFamiliesIdsOnGroup(const char *name) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of families constituting a group. + * \param [in] name - the name of the group of interest. + * \return std::vector - sequence of ids of the families. + * \throw If the name of a nonexistent group is specified. + */ +std::vector MEDFileMesh::getFamiliesIdsOnGroup(const std::string& name) const { std::string oname(name); std::map >::const_iterator it=_groups.find(oname); @@ -258,10 +396,13 @@ std::vector MEDFileMesh::getFamiliesIdsOnGroup(const char *name) const thro } /*! - * This method sets families at a corresponding groups existing or not. If it existed, it is replaced by new 'fams'. - * Each entry in 'fams' is checked if it is not still existing default id 0 is set. + * Sets names of families constituting a group. If data on families of this group is + * already present, it is overwritten. Every family in \a fams is checked, and if a + family is not yet in \a this mesh, the default group id \c 0 is assigned to it. + * \param [in] name - the name of the group of interest. + * \param [in] fams - a sequence of names of families constituting the group. */ -void MEDFileMesh::setFamiliesOnGroup(const char *name, const std::vector& fams) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::setFamiliesOnGroup(const std::string& name, const std::vector& fams) { std::string oname(name); _groups[oname]=fams; @@ -274,10 +415,14 @@ void MEDFileMesh::setFamiliesOnGroup(const char *name, const std::vector& famIds) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::setFamiliesIdsOnGroup(const std::string& name, const std::vector& famIds) { std::string oname(name); std::vector fams(famIds.size()); @@ -290,7 +435,12 @@ void MEDFileMesh::setFamiliesIdsOnGroup(const char *name, const std::vector _groups[oname]=fams; } -std::vector MEDFileMesh::getGroupsOnFamily(const char *name) const throw(INTERP_KERNEL::Exception) +/*! + * Returns names of groups including a given family. + * \param [in] name - the name of the family of interest. + * \return std::vector - a sequence of names of groups including the family. + */ +std::vector MEDFileMesh::getGroupsOnFamily(const std::string& name) const { std::vector ret; for(std::map >::const_iterator it1=_groups.begin();it1!=_groups.end();it1++) @@ -306,9 +456,12 @@ std::vector MEDFileMesh::getGroupsOnFamily(const char *name) const } /*! - * This method expects that family 'famName' is already existing. If not an exception will be thrown. + * Adds an existing family to groups. + * \param [in] famName - a name of family to add to \a grps. + * \param [in] grps - a sequence of group names to add the family in. + * \throw If a family named \a famName not yet exists. */ -void MEDFileMesh::setGroupsOnFamily(const char *famName, const std::vector& grps) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::setGroupsOnFamily(const std::string& famName, const std::vector& grps) { std::string fName(famName); const std::map::const_iterator it=_families.find(fName); @@ -332,6 +485,10 @@ void MEDFileMesh::setGroupsOnFamily(const char *famName, const std::vector - a sequence of group names. + */ std::vector MEDFileMesh::getGroupsNames() const { std::vector ret(_groups.size()); @@ -341,6 +498,10 @@ std::vector MEDFileMesh::getGroupsNames() const return ret; } +/*! + * Returns names of all families of \a this mesh. + * \return std::vector - a sequence of family names. + */ std::vector MEDFileMesh::getFamiliesNames() const { std::vector ret(_families.size()); @@ -351,15 +512,16 @@ std::vector MEDFileMesh::getFamiliesNames() const } /*! - * This method scans every families and for each families shared by only one group, the corresponding family takes the same name than the group. + * Changes a name of every family, included in one group only, to be same as the group name. + * \throw If there are families with equal names in \a this mesh. */ -void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception) +void MEDFileMesh::assignFamilyNameWithGroupName() { std::map > groups(_groups); std::map newFams; for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) { - std::vector grps=getGroupsOnFamily((*it).first.c_str()); + std::vector grps=getGroupsOnFamily((*it).first); if(grps.size()==1 && groups[grps[0]].size()==1) { if(newFams.find(grps[0])!=newFams.end()) @@ -386,7 +548,33 @@ void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception _groups=groups; } -void MEDFileMesh::removeGroup(const char *name) throw(INTERP_KERNEL::Exception) +/*! + * Removes all groups lying on no family. If there is no empty groups, \a this is let untouched. + * + * \return the removed groups. + */ +std::vector MEDFileMesh::removeEmptyGroups() +{ + std::vector ret; + std::map > newGrps; + for(std::map >::const_iterator it=_groups.begin();it!=_groups.end();it++) + { + if((*it).second.empty()) + ret.push_back((*it).first); + else + newGrps[(*it).first]=(*it).second; + } + if(!ret.empty()) + _groups=newGrps; + return ret; +} + +/*! + * Removes a group from \a this mesh. + * \param [in] name - the name of the group to remove. + * \throw If no group with such a \a name exists. + */ +void MEDFileMesh::removeGroup(const std::string& name) { std::string oname(name); std::map >::iterator it=_groups.find(oname); @@ -400,7 +588,12 @@ void MEDFileMesh::removeGroup(const char *name) throw(INTERP_KERNEL::Exception) _groups.erase(it); } -void MEDFileMesh::removeFamily(const char *name) throw(INTERP_KERNEL::Exception) +/*! + * Removes a family from \a this mesh. + * \param [in] name - the name of the family to remove. + * \throw If no family with such a \a name exists. + */ +void MEDFileMesh::removeFamily(const std::string& name) { std::string oname(name); std::map::iterator it=_families.find(oname); @@ -421,7 +614,145 @@ void MEDFileMesh::removeFamily(const char *name) throw(INTERP_KERNEL::Exception) } } -void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception) +/*! + * Removes all groups in \a this that are orphan. A group is orphan if this group lies on + * a set of families, themselves orphan. A family is said orphan if its id appears nowhere in + * family field whatever its level. This method also suppresses the orphan families. + * + * \return - The list of removed groups names. + * + * \sa MEDFileMesh::removeOrphanFamilies. + */ +std::vector MEDFileMesh::removeOrphanGroups() +{ + removeOrphanFamilies(); + return removeEmptyGroups(); +} + +/*! + * Removes all families in \a this that are orphan. A family is said orphan if its id appears nowhere in + * family field whatever its level. Groups are updated in consequence, that is to say all groups lying on orphan family, will see their families list modified. + * + * \return - The list of removed families names. + * \sa MEDFileMesh::removeOrphanGroups. + */ +std::vector MEDFileMesh::removeOrphanFamilies() +{ + MEDCouplingAutoRefCountObjectPtr allFamIdsInUse=computeAllFamilyIdsInUse(); + std::vector ret; + if(!((DataArrayInt*)allFamIdsInUse)) + { + ret=getFamiliesNames(); + _families.clear(); _groups.clear(); + return ret; + } + std::map famMap; + std::map > grps(_groups); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + { + if(allFamIdsInUse->presenceOfValue((*it).second)) + famMap[(*it).first]=(*it).second; + else + { + ret.push_back((*it).first); + std::vector grpsOnEraseFam=getGroupsOnFamily((*it).first); + for(std::vector::const_iterator it2=grpsOnEraseFam.begin();it2!=grpsOnEraseFam.end();it2++) + { + std::map >::iterator it3=grps.find(*it2);//it3!=grps.empty() thanks to copy + std::vector& famv=(*it3).second; + std::vector::iterator it4=std::find(famv.begin(),famv.end(),(*it).first);//it4!=famv.end() thanks to copy + famv.erase(it4); + } + } + } + if(!ret.empty()) + { _families=famMap; _groups=grps; } + return ret; +} + +/*! + * This method operates only on maps in \a this. The arrays are not considered here. So this method will remove a family (except "FAMILLE_ZERO" family) if no group lies on it whatever + * this family is orphan or not. + * + * \warning this method is different from removeOrphanFamilies that scans family field array to find orphan families. + */ +void MEDFileMesh::removeFamiliesReferedByNoGroups() +{ + std::map fams; + std::set sfams; + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + sfams.insert((*it).first); + for(std::map >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++) + for(std::vector::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++) + sfams.erase(*it1); + for(std::set::const_iterator it=sfams.begin();it!=sfams.end();it++) + if(*it!=DFT_FAM_NAME) + _families.erase(*it); +} + +/*! + * This method has no impact on groups. This method only works on families. This method firstly removes families not refered by any groups in \a this, then all unused entities + * are put as belonging to family 0 ("FAMILLE_ZERO"). Finally, all orphanFamilies are killed. + * This method raises an exception if "FAMILLE_ZERO" is already belonging to a group. + * + * \sa MEDFileMesh::removeOrphanFamilies + */ +void MEDFileMesh::rearrangeFamilies() +{ + checkOrphanFamilyZero(); + removeFamiliesReferedByNoGroups(); + // + std::vector levels(getNonEmptyLevelsExt()); + std::set idsRefed; + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + idsRefed.insert((*it).second); + for(std::vector::const_iterator it=levels.begin();it!=levels.end();it++) + { + const DataArrayInt *fams(0); + try + { + fams=getFamilyFieldAtLevel(*it); + } + catch(INTERP_KERNEL::Exception& e) { } + if(!fams) + continue; + std::vector v(fams->getNumberOfTuples(),false); + for(std::set::const_iterator pt=idsRefed.begin();pt!=idsRefed.end();pt++) + fams->switchOnTupleEqualTo(*pt,v); + MEDCouplingAutoRefCountObjectPtr unfetchedIds(DataArrayInt::BuildListOfSwitchedOff(v)); + if(!unfetchedIds->empty()) + { + MEDCouplingAutoRefCountObjectPtr newFams(fams->deepCpy()); + newFams->setPartOfValuesSimple3(0,unfetchedIds->begin(),unfetchedIds->end(),0,1,1); + setFamilyFieldArr(*it,newFams); + } + } + removeOrphanFamilies(); +} + +/*! + * This method only checks that "FAMILLE_ZERO" is orphan (not belonging to a group). + */ +void MEDFileMesh::checkOrphanFamilyZero() const +{ + for(std::map >::const_iterator it=_groups.begin();it!=_groups.end();it++) + { + if(std::find((*it).second.begin(),(*it).second.end(),DFT_FAM_NAME)!=(*it).second.end()) + { + std::ostringstream oss; oss << "MEDFileMesh::rearrangeFamilies : Groups \"" << (*it).first << "\" is lying on family \"" << DFT_FAM_NAME << "\" !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } +} + +/*! + * Renames a group in \a this mesh. + * \param [in] oldName - a current name of the group to rename. + * \param [in] newName - a new group name. + * \throw If no group named \a oldName exists in \a this mesh. + * \throw If a group named \a newName already exists. + */ +void MEDFileMesh::changeGroupName(const std::string& oldName, const std::string& newName) { std::string oname(oldName); std::map >::iterator it=_groups.find(oname); @@ -433,8 +764,8 @@ void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) thro throw INTERP_KERNEL::Exception(oss.str().c_str()); } std::string nname(newName); - it=_groups.find(nname); - if(it!=_groups.end()) + std::map >::iterator it2=_groups.find(nname); + if(it2!=_groups.end()) { std::ostringstream oss; oss << "Such groupname \"" << newName << "\" already exists ! Kill it before !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); @@ -445,10 +776,12 @@ void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) thro } /*! - * This method changes the family ids in 'this'. It leads to a modification into '_families' attributes \b and in - * ids stored in arrays. This method calls MEDFileMesh::changeFamilyIdArr method. + * Changes an id of a family in \a this mesh. + * This method calls changeFamilyIdArr(). + * \param [in] oldId - a current id of the family. + * \param [in] newId - a new family id. */ -void MEDFileMesh::changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::changeFamilyId(int oldId, int newId) { changeFamilyIdArr(oldId,newId); std::map fam2; @@ -462,7 +795,14 @@ void MEDFileMesh::changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exce _families=fam2; } -void MEDFileMesh::changeFamilyName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception) +/*! + * Renames a family in \a this mesh. + * \param [in] oldName - a current name of the family to rename. + * \param [in] newName - a new family name. + * \throw If no family named \a oldName exists in \a this mesh. + * \throw If a family named \a newName already exists. + */ +void MEDFileMesh::changeFamilyName(const std::string& oldName, const std::string& newName) { std::string oname(oldName); std::map::iterator it=_families.find(oname); @@ -492,6 +832,13 @@ void MEDFileMesh::changeFamilyName(const char *oldName, const char *newName) thr } } +/*! + * Checks if \a this and another mesh contains the same families. + * \param [in] other - the mesh to compare with \a this one. + * \param [in,out] what - an unused parameter. + * \return bool - \c true if number of families and their ids are the same in the two + * meshes. Families with the id == \c 0 are not considered. + */ bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) const { if(_families==other->_families) @@ -507,6 +854,14 @@ bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) cons return fam0==fam1; } +/*! + * Checks if \a this and another mesh contains the same groups. + * \param [in] other - the mesh to compare with \a this one. + * \param [in,out] what - a string describing a difference of groups of the two meshes + * in case if this method returns \c false. + * \return bool - \c true if number of groups and families constituting them are the + * same in the two meshes. + */ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) const { if(_groups==other->_groups) @@ -545,7 +900,7 @@ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) cons { oss << " Group \"" << (*it).first << "\" on following families :\n"; for(std::vector::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++) - oss << " \"" << *it2 << "\n"; + oss << " \"" << *it2 << "\n"; } oss << "Second group description :\n"; for(std::map >::const_iterator it=other->_groups.begin();it!=other->_groups.end();it++) @@ -559,12 +914,22 @@ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) cons return ret; } -bool MEDFileMesh::existsGroup(const char *groupName) const +/*! + * Checks if a group with a given name exists in \a this mesh. + * \param [in] groupName - the group name. + * \return bool - \c true the group \a groupName exists in \a this mesh. + */ +bool MEDFileMesh::existsGroup(const std::string& groupName) const { std::string grpName(groupName); return _groups.find(grpName)!=_groups.end(); } +/*! + * Checks if a family with a given id exists in \a this mesh. + * \param [in] famId - the family id. + * \return bool - \c true the family with the id \a famId exists in \a this mesh. + */ bool MEDFileMesh::existsFamily(int famId) const { for(std::map::const_iterator it2=_families.begin();it2!=_families.end();it2++) @@ -573,19 +938,29 @@ bool MEDFileMesh::existsFamily(int famId) const return false; } -bool MEDFileMesh::existsFamily(const char *familyName) const +/*! + * Checks if a family with a given name exists in \a this mesh. + * \param [in] familyName - the family name. + * \return bool - \c true the family \a familyName exists in \a this mesh. + */ +bool MEDFileMesh::existsFamily(const std::string& familyName) const { std::string fname(familyName); return _families.find(fname)!=_families.end(); } -void MEDFileMesh::setFamilyId(const char *familyName, int id) +/*! + * Sets an id of a family. + * \param [in] familyName - the family name. + * \param [in] id - a new id of the family. + */ +void MEDFileMesh::setFamilyId(const std::string& familyName, int id) { std::string fname(familyName); _families[fname]=id; } -void MEDFileMesh::setFamilyIdUnique(const char *familyName, int id) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::setFamilyIdUnique(const std::string& familyName, int id) { std::string fname(familyName); for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) @@ -601,23 +976,25 @@ void MEDFileMesh::setFamilyIdUnique(const char *familyName, int id) throw(INTERP } /*! - * This method appends a new entry in _families attribute. An exception is thrown if either the famId is already - * kept by an another familyName. An exception is thrown if name 'familyName' is alreadyset with a different 'famId'. + * Adds a family to \a this mesh. + * \param [in] familyName - a name of the family. + * \param [in] famId - an id of the family. + * \throw If a family with the same name or id already exists in \a this mesh. */ -void MEDFileMesh::addFamily(const char *familyName, int famId) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::addFamily(const std::string& familyName, int famId) { std::string fname(familyName); std::map::const_iterator it=_families.find(fname); if(it==_families.end()) { - for(std::map::const_iterator it2=_families.begin();it2!=_families.end();it2++) - if((*it2).second==famId) - { - std::ostringstream oss; - oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } - _families[fname]=famId; + for(std::map::const_iterator it2=_families.begin();it2!=_families.end();it2++) + if((*it2).second==famId) + { + std::ostringstream oss; + oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + _families[fname]=famId; } else { @@ -631,14 +1008,19 @@ void MEDFileMesh::addFamily(const char *familyName, int famId) throw(INTERP_KERN } /*! - * This method creates a new group called 'groupName' in 'this'. If it exists a group with the same name an INTERP_KERNEL::Exception will be thrown. - * If the 'meshDimRelToMaxExt' is not existing an INTERP_KERNEL::Exception will be thrown too. - * \b WARNING : This method does \b not garantee that 'groupName' lies only on a single level specified by 'meshDimRelToMaxExt'. - * in the case of a presence of one or more family id in family field at 'meshDimRelToMaxExt' level that appears in another level. - * If there is a risk of such case call MEDFileMesh::keepFamIdsOnlyOnLevs method \b before calling this method. - * (call to MEDFileMesh::keepFamIdsOnlyOnLevs should be done with MEDFileMesh::getFamiliesIdsOnGroup('groupName' as first input ). + * Creates a group including all mesh entities of given dimension. + * \warning This method does \b not guarantee that the created group includes mesh + * entities of only \a meshDimRelToMaxExt dimension in the case if some family id is + * present in family fields of different dimensions. To assure this, call + * ensureDifferentFamIdsPerLevel() \b before calling this method. + * \param [in] meshDimRelToMaxExt - a relative dimension of mesh entities to include to + * the group. + * \param [in] groupName - a name of the new group. + * \throw If a group named \a groupName already exists. + * \throw If no mesh entities of dimension \a meshDimRelToMaxExt exist in \a this mesh. + * \throw If no family field of dimension \a meshDimRelToMaxExt is present in \a this mesh. */ -void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const std::string& groupName) { std::string grpName(groupName); std::vector levs=getNonEmptyLevelsExt(); @@ -671,12 +1053,15 @@ void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName } /*! - * This method checks that family Ids in 'famIds' are not present in levels \b not in 'vMeshDimRelToMaxExt'. - * If it is the case true is returned and 'this' is not modified. - * If there is some levels not in 'vMeshDimRelToMaxExt' where one or more family ids in 'famIds' appear - * new families are created and groups are updated in consequence. + * Ensures that given family ids do not present in family fields of dimensions different + * than given ones. If a family id is present in the family fields of dimensions different + * than the given ones, a new family is created and the whole data is updated accordingly. + * \param [in] famIds - a sequence of family ids to check. + * \param [in] vMeshDimRelToMaxExt - a sequence of relative dimensions to which the \a + * famIds should exclusively belong. + * \return bool - \c true if no modification is done in \a this mesh by this method. */ -bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector& famIds, const std::vector& vMeshDimRelToMaxExt) throw(INTERP_KERNEL::Exception) +bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector& famIds, const std::vector& vMeshDimRelToMaxExt) { std::set levsInput(vMeshDimRelToMaxExt.begin(),vMeshDimRelToMaxExt.end()); std::vector levs=getNonEmptyLevelsExt(); @@ -703,7 +1088,7 @@ bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector& famIds, const std std::string famName=getFamilyNameGivenId(*it2); std::ostringstream oss; oss << "Family_" << maxFamId; std::string zeName=CreateNameNotIn(oss.str(),allFams); - addFamilyOnAllGroupsHaving(famName.c_str(),zeName.c_str()); + addFamilyOnAllGroupsHaving(famName,zeName); _families[zeName]=maxFamId; (const_cast(fieldFamIds))->changeValue(*it2,maxFamId); maxFamId++; @@ -714,12 +1099,14 @@ bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector& famIds, const std } /*! - * This method add into the family list of a group 'grpName' the family with name 'famName'. - * If the group 'grpName' does not exist it is created and 'famName' is added to the list. - * If the group 'grpName' already exists, 'famName' will be added into family list of the existing group. - * This method throws an INTERP_KERNEL::Exception if 'famName' does not exit. + * Adds a family to a given group in \a this mesh. If the group with a given name does + * not exist, it is created. + * \param [in] grpName - the name of the group to add the family in. + * \param [in] famName - the name of the family to add to the group named \a grpName. + * \throw If \a grpName or \a famName is an empty string. + * \throw If no family named \a famName is present in \a this mesh. */ -void MEDFileMesh::addFamilyOnGrp(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::addFamilyOnGrp(const std::string& grpName, const std::string& famName) { std::string grpn(grpName); std::string famn(famName); @@ -751,7 +1138,7 @@ void MEDFileMesh::addFamilyOnGrp(const char *grpName, const char *famName) throw * This method is quite underground because it can lead to unconsistency because family 'otherFamName' is \b not added into _families. * This method is used by MEDFileMesh::keepFamIdsOnlyOnLevs method. */ -void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *otherFamName) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::addFamilyOnAllGroupsHaving(const std::string& famName, const std::string& otherFamName) { std::string famNameCpp(famName); std::string otherCpp(otherFamName); @@ -765,12 +1152,91 @@ void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *ot } } -void MEDFileMesh::changeAllGroupsContainingFamily(const char *familyNameToChange, const std::vector& newFamiliesNames) throw(INTERP_KERNEL::Exception) +/*! + * \param [in] ids ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm). + * \parma [in,out] famArr family array on level of interest to be renumbered. The input pointer should be not \c NULL (no check of that will be performed) + */ +void MEDFileMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr) +{ + if(!ids) + throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !"); + std::string grpName(ids->getName()); + if(grpName.empty()) + throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !"); + ids->checkStrictlyMonotonic(true); + famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr famArrTmp(famArr); + std::vector grpsNames=getGroupsNames(); + if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end()) + { + std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + std::list< MEDCouplingAutoRefCountObjectPtr > allFamIds(getAllNonNullFamilyIds()); + allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp)); + MEDCouplingAutoRefCountObjectPtr famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end()); + MEDCouplingAutoRefCountObjectPtr diffFamIds=famIds->getDifferentValues(); + std::vector familyIds; + std::vector< MEDCouplingAutoRefCountObjectPtr > idsPerfamiliyIds; + int maxVal=getTheMaxAbsFamilyId()+1; + std::map families(_families); + std::map > groups(_groups); + std::vector fams; + bool created(false); + for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++) + { + MEDCouplingAutoRefCountObjectPtr ids2Tmp=famIds->getIdsEqual(*famId); + MEDCouplingAutoRefCountObjectPtr ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end()); + MEDCouplingAutoRefCountObjectPtr ids1=famArr->getIdsEqual(*famId); + MEDCouplingAutoRefCountObjectPtr ret0(ids1->buildSubstractionOptimized(ids2)); + if(ret0->empty()) + { + bool isFamPresent=false; + for(std::list< MEDCouplingAutoRefCountObjectPtr >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++) + isFamPresent=(*itl)->presenceOfValue(*famId); + if(!isFamPresent) + { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp + else + { + familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2); + std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created); + fams.push_back(locFamName); + if(existsFamily(*famId)) + { + std::string locFamName2=getFamilyNameGivenId(*famId); std::vector v(2); v[0]=locFamName2; v[1]=locFamName; + ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v); + } + maxVal++; + } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal + } + else + { + familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1 + familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1 + std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2); + if(existsFamily(*famId)) + { + std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector v(2); v[0]=n1; v[1]=n2; + ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v); + } + maxVal+=2; + } + } + for(std::size_t i=0;isetPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1); + } + _families=families; + _groups=groups; + _groups[grpName]=fams; +} + +void MEDFileMesh::changeAllGroupsContainingFamily(const std::string& familyNameToChange, const std::vector& newFamiliesNames) { ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames); } -void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map >& groups, const char *familyNameToChange, const std::vector& newFamiliesNames) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map >& groups, const std::string& familyNameToChange, const std::vector& newFamiliesNames) { std::string fam(familyNameToChange); for(std::map >::iterator it=groups.begin();it!=groups.end();it++) @@ -786,14 +1252,14 @@ void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map& families, int id, bool& created) throw(INTERP_KERNEL::Exception) +std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map& families, int id, bool& created) { std::vector famAlreadyExisting(families.size()); int ii=0; @@ -829,17 +1295,32 @@ std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map& info) { _families=info; } +/*! + * Sets names of all groups and families constituting them in \a this mesh. + * \param [in] info - a map of a group name to a vector of names of families + * constituting the group. + */ void MEDFileMesh::setGroupInfo(const std::map >&info) { _groups=info; } -int MEDFileMesh::getFamilyId(const char *name) const throw(INTERP_KERNEL::Exception) +/*! + * Returns an id of the family having a given name. + * \param [in] name - the name of the family of interest. + * \return int - the id of the family of interest. + * \throw If no family with such a \a name exists. + */ +int MEDFileMesh::getFamilyId(const std::string& name) const { std::string oname(name); std::map::const_iterator it=_families.find(oname); @@ -853,7 +1334,13 @@ int MEDFileMesh::getFamilyId(const char *name) const throw(INTERP_KERNEL::Except return (*it).second; } -std::vector MEDFileMesh::getFamiliesIds(const std::vector& fams) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of the families having given names. + * \param [in] fams - a sequence of the names of families of interest. + * \return std::vector - a sequence of the ids of families of interest. + * \throw If \a fams contains a name of an inexistent family. + */ +std::vector MEDFileMesh::getFamiliesIds(const std::vector& fams) const { std::vector ret(fams.size()); int i=0; @@ -872,40 +1359,91 @@ std::vector MEDFileMesh::getFamiliesIds(const std::vector& fam return ret; } -int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception) +/*! + * Returns a maximal abs(id) of families in \a this mesh. + * \return int - the maximal norm of family id. + * \throw If there are no families in \a this mesh. + */ +int MEDFileMesh::getMaxAbsFamilyId() const { if(_families.empty()) - throw INTERP_KERNEL::Exception("MEDFileUMesh::getMaxFamilyId : no families set !"); + throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !"); int ret=-std::numeric_limits::max(); for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) { - ret=std::max((*it).second,ret); + ret=std::max(std::abs((*it).second),ret); } return ret; } -int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception) +/*! + * Returns a maximal id of families in \a this mesh. + * \return int - the maximal family id. + * \throw If there are no families in \a this mesh. + */ +int MEDFileMesh::getMaxFamilyId() const { if(_families.empty()) - throw INTERP_KERNEL::Exception("MEDFileUMesh::getMinFamilyId : no families set !"); - int ret=std::numeric_limits::max(); + throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !"); + int ret=-std::numeric_limits::max(); for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) { - ret=std::min((*it).second,ret); + ret=std::max((*it).second,ret); } return ret; } -int MEDFileMesh::getTheMaxFamilyId() const throw(INTERP_KERNEL::Exception) +/*! + * Returns a minimal id of families in \a this mesh. + * \return int - the minimal family id. + * \throw If there are no families in \a this mesh. + */ +int MEDFileMesh::getMinFamilyId() const { - int m1=-std::numeric_limits::max(); + if(_families.empty()) + throw INTERP_KERNEL::Exception("MEDFileMesh::getMinFamilyId : no families set !"); + int ret=std::numeric_limits::max(); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + { + ret=std::min((*it).second,ret); + } + return ret; +} + +/*! + * Returns a maximal id of families in \a this mesh. Not only named families are + * considered but all family fields as well. + * \return int - the maximal family id. + */ +int MEDFileMesh::getTheMaxAbsFamilyId() const +{ + int m1=-std::numeric_limits::max(); + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + m1=std::max(std::abs((*it).second),m1); + int m2=getMaxAbsFamilyIdInArrays(); + return std::max(m1,m2); +} + +/*! + * Returns a maximal id of families in \a this mesh. Not only named families are + * considered but all family fields as well. + * \return int - the maximal family id. + */ +int MEDFileMesh::getTheMaxFamilyId() const +{ + int m1=-std::numeric_limits::max(); for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) m1=std::max((*it).second,m1); int m2=getMaxFamilyIdInArrays(); return std::max(m1,m2); } -int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception) +/*! + * Returns a minimal id of families in \a this mesh. Not only named families are + * considered but all family fields as well. + * \return int - the minimal family id. + */ +int MEDFileMesh::getTheMinFamilyId() const { int m1=std::numeric_limits::max(); for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) @@ -914,7 +1452,12 @@ int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception) return std::min(m1,m2); } -DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception) +/*! + * This method only considers the maps. The contain of family array is ignored here. + * + * \sa MEDFileMesh::computeAllFamilyIdsInUse + */ +DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const { MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); std::set v; @@ -925,11 +1468,32 @@ DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERN return ret.retn(); } +/*! + * This method does not consider map of family name, family id. Only family field array on different levels is considered. + * + * \sa MEDFileMesh::getAllFamiliesIdsReferenced + */ +DataArrayInt *MEDFileMesh::computeAllFamilyIdsInUse() const +{ + std::vector famLevs=getFamArrNonEmptyLevelsExt(); + MEDCouplingAutoRefCountObjectPtr ret; + for(std::vector::const_iterator it=famLevs.begin();it!=famLevs.end();it++) + { + const DataArrayInt *arr=getFamilyFieldAtLevel(*it);//arr not null due to spec of getFamArrNonEmptyLevelsExt + MEDCouplingAutoRefCountObjectPtr dv=arr->getDifferentValues(); + if((DataArrayInt *) ret) + ret=dv->buildUnion(ret); + else + ret=dv; + } + return ret.retn(); +} + /*! * true is returned if no modification has been needed. false if family * renumbering has been needed. */ -bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception) +bool MEDFileMesh::ensureDifferentFamIdsPerLevel() { std::vector levs=getNonEmptyLevelsExt(); std::set allFamIds; @@ -962,12 +1526,12 @@ bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception if(allIds->presenceOfValue(*it3)) { std::string famName=getFamilyNameGivenId(*it3); - std::vector grps=getGroupsOnFamily(famName.c_str()); + std::vector grps=getGroupsOnFamily(famName); ren[*it3]=maxId; bool dummy; std::string newFam=findOrCreateAndGiveFamilyWithId(maxId,dummy); for(std::vector::const_iterator it4=grps.begin();it4!=grps.end();it4++) - addFamilyOnGrp((*it4).c_str(),newFam.c_str()); + addFamilyOnGrp((*it4),newFam); } } MEDCouplingAutoRefCountObjectPtr ids=fam->getIdsEqualList(&(*it2).second[0],&(*it2).second[0]+(*it2).second.size()); @@ -984,7 +1548,7 @@ bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception * This method will throw an exception if a same family id is detected in different level. * \warning This policy is the opposite of those in MED file documentation ... */ -void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception) +void MEDFileMesh::normalizeFamIdsTrio() { ensureDifferentFamIdsPerLevel(); MEDCouplingAutoRefCountObjectPtr allIds=getAllFamiliesIdsReferenced(); @@ -1076,7 +1640,7 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception) * This policy is those defined in the MED file format but is the opposite of those implemented in SMESH and Trio. * This method will throw an exception if a same family id is detected in different level. */ -void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception) +void MEDFileMesh::normalizeFamIdsMEDFile() { ensureDifferentFamIdsPerLevel(); MEDCouplingAutoRefCountObjectPtr allIds=getAllFamiliesIdsReferenced(); @@ -1113,7 +1677,7 @@ void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception) refId=-1; for(std::set::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++) { - const DataArrayInt *fam=getFamilyFieldAtLevel(1); + const DataArrayInt *fam=getFamilyFieldAtLevel(*it2); if(fam) { MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); @@ -1146,9 +1710,13 @@ void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception) } /*! - * Returns the first (in lexical order) family name having family id equal to 'id'. + * Returns a name of the family by its id. If there are several families having the given + * id, the name first in lexical order is returned. + * \param [in] id - the id of the family whose name is required. + * \return std::string - the name of the found family. + * \throw If no family with the given \a id exists. */ -std::string MEDFileMesh::getFamilyNameGivenId(int id) const throw(INTERP_KERNEL::Exception) +std::string MEDFileMesh::getFamilyNameGivenId(int id) const { for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) if((*it).second==id) @@ -1157,6 +1725,11 @@ std::string MEDFileMesh::getFamilyNameGivenId(int id) const throw(INTERP_KERNEL: throw INTERP_KERNEL::Exception(oss.str().c_str()); } +/*! + * Returns a string describing \a this mesh. This description includes the mesh name and + * the mesh description string. + * \return std::string - the mesh information string. + */ std::string MEDFileMesh::simpleRepr() const { std::ostringstream oss; @@ -1166,7 +1739,36 @@ std::string MEDFileMesh::simpleRepr() const return oss.str(); } -DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * This method is nearly like getFamilyFieldAtLevel method. Except that if the array does not exist at the specified level \a meshDimRelToMaxExt + * an empty one is created. + */ +DataArrayInt *MEDFileMesh::getOrCreateAndGetFamilyFieldAtLevel(int meshDimRelToMaxExt) +{ + DataArrayInt *ret(getFamilyFieldAtLevel(meshDimRelToMaxExt)); + if(ret) + return ret; + MEDCouplingAutoRefCountObjectPtr arr(DataArrayInt::New()); + arr->alloc(getSizeAtLevel(meshDimRelToMaxExt),1); + arr->fillWithZero(); + setFamilyFieldArr(meshDimRelToMaxExt,arr); + return getFamilyFieldAtLevel(meshDimRelToMaxExt); +} + +/*! + * Returns ids of mesh entities contained in a given group of a given dimension. + * \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids + * are required. + * \param [in] grp - the name of the group of interest. + * \param [in] renum - if \c true, the optional numbers of entities, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of mesh entities of the group. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the name of a nonexistent group is specified. + * \throw If the family field is missing for \a meshDimRelToMaxExt. + */ +DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const std::string& grp, bool renum) const { std::vector tmp(1); tmp[0]=grp; @@ -1175,13 +1777,38 @@ DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const char *grp, return ret; } -DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector& grps, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of mesh entities contained in given groups of a given dimension. + * \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids + * are required. + * \param [in] grps - the names of the groups of interest. + * \param [in] renum - if \c true, the optional numbers of entities, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of mesh entities of the groups. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the name of a nonexistent group is present in \a grps. + * \throw If the family field is missing for \a meshDimRelToMaxExt. + */ +DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector& grps, bool renum) const { std::vector fams2=getFamiliesOnGroups(grps); return getFamiliesArr(meshDimRelToMaxExt,fams2,renum); } -DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of mesh entities contained in a given family of a given dimension. + * \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids + * are required. + * \param [in] fam - the name of the family of interest. + * \param [in] renum - if \c true, the optional numbers of entities, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of mesh entities of the family. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the family field is missing for \a meshDimRelToMaxExt. + */ +DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const std::string& fam, bool renum) const { std::vector tmp(1); tmp[0]=fam; @@ -1190,7 +1817,18 @@ DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const char *fam, return ret; } -DataArrayInt *MEDFileMesh::getNodeGroupArr(const char *grp, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of nodes contained in a given group. + * \param [in] grp - the name of the group of interest. + * \param [in] renum - if \c true, the optional numbers of nodes, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of nodes of the group. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the name of a nonexistent group is specified. + * \throw If the family field is missing for nodes. + */ +DataArrayInt *MEDFileMesh::getNodeGroupArr(const std::string& grp, bool renum) const { std::vector tmp(1); tmp[0]=grp; @@ -1199,12 +1837,34 @@ DataArrayInt *MEDFileMesh::getNodeGroupArr(const char *grp, bool renum) const th return ret; } -DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector& grps, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of nodes contained in given groups. + * \param [in] grps - the names of the groups of interest. + * \param [in] renum - if \c true, the optional numbers of nodes, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of nodes of the groups. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the name of a nonexistent group is present in \a grps. + * \throw If the family field is missing for nodes. + */ +DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector& grps, bool renum) const { return getGroupsArr(1,grps,renum); } -DataArrayInt *MEDFileMesh::getNodeFamilyArr(const char *fam, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of nodes contained in a given group. + * \param [in] grp - the name of the group of interest. + * \param [in] renum - if \c true, the optional numbers of nodes, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of nodes of the group. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the name of a nonexistent group is specified. + * \throw If the family field is missing for nodes. + */ +DataArrayInt *MEDFileMesh::getNodeFamilyArr(const std::string& fam, bool renum) const { std::vector tmp(1); tmp[0]=fam; @@ -1213,12 +1873,34 @@ DataArrayInt *MEDFileMesh::getNodeFamilyArr(const char *fam, bool renum) const t return ret; } -DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector& fams, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of nodes contained in given families. + * \param [in] fams - the names of the families of interest. + * \param [in] renum - if \c true, the optional numbers of nodes, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of nodes of the families. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the family field is missing for nodes. + */ +DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector& fams, bool renum) const { return getFamiliesArr(1,fams,renum); } -void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector& grps, bool renum) throw(INTERP_KERNEL::Exception) +/*! + * Adds groups of given dimension and creates corresponding families and family fields + * given ids of mesh entities of each group. + * \param [in] meshDimRelToMaxExt - the relative mesh dimension of given mesh entities. + * \param [in] grps - a sequence of arrays of ids each describing a group. + * \param [in] renum - \c true means that \a grps contains not ids but optional numbers + * of mesh entities. + * \throw If names of some groups in \a grps are equal. + * \throw If \a grps includes a group with an empty name. + * \throw If \a grps includes invalid ids (or numbers if \a renum == \c true ). + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector& grps, bool renum) { if(grps.empty()) return ; @@ -1248,15 +1930,15 @@ void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vectorsetName(grps[ii]->getName().c_str()); + grps2[ii]->setName(grps[ii]->getName()); } std::vector grps3(grps2.begin(),grps2.end()); fam=DataArrayInt::MakePartition(grps3,sz,fidsOfGroups); } int offset=1; if(!_families.empty()) - offset=getMaxFamilyId()+1; - TranslateFamilyIds(offset,fam,fidsOfGroups); + offset=getMaxAbsFamilyId()+1; + TranslateFamilyIds(meshDimRelToMaxExt==1?offset:-offset,fam,fidsOfGroups); MEDCouplingAutoRefCountObjectPtr ids=fam->getDifferentValues(); appendFamilyEntries(ids,fidsOfGroups,grpsName2); setFamilyFieldArr(meshDimRelToMaxExt,fam); @@ -1287,11 +1969,33 @@ void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vec } } +std::vector MEDFileMesh::getAllGeoTypes() const +{ + std::vector levs(getNonEmptyLevels()); + std::vector ret; + for(std::vector::const_iterator it=levs.begin();it!=levs.end();it++) + { + std::vector elts(getGeoTypesAtLevel(*it)); + ret.insert(ret.end(),elts.begin(),elts.end()); + } + return ret; +} + +std::vector MEDFileMesh::getDistributionOfTypes(int meshDimRelToMax) const +{ + MEDCouplingAutoRefCountObjectPtr mLev(getGenMeshAtLevel(meshDimRelToMax)); + return mLev->getDistributionOfTypes(); +} + void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector >& famIdsPerGrp) { - famArr->applyLin(1,offset,0); + famArr->applyLin(offset>0?1:-1,offset,0); for(std::vector< std::vector >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++) - std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus(),offset)); + { + if(offset<0) + std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::negate()); + std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus(),offset)); + } } /*! @@ -1299,7 +2003,7 @@ void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vect * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'. * If this method fails to find such a name it will throw an exception. */ -std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector& namesToAvoid) throw(INTERP_KERNEL::Exception) +std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector& namesToAvoid) { //attempt #0 if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end()) @@ -1332,7 +2036,7 @@ std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std:: throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !"); } -int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector& code, int strt) throw(INTERP_KERNEL::Exception) +int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector& code, int strt) { std::size_t nbOfChunks=code.size()/3; if(code.size()%3!=0) @@ -1352,8 +2056,10 @@ int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector& code, int str * If _name is not empty and that 'm' has the same name nothing is done. * If _name is not emplt and that 'm' has \b NOT the same name an exception is thrown. */ -void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m) throw(INTERP_KERNEL::Exception) +void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m) { + if(!m) + throw INTERP_KERNEL::Exception("MEDFileMesh::dealWithTinyInfo : input mesh in NULL !"); if(_name.empty()) _name=m->getName(); else @@ -1393,20 +2099,44 @@ void MEDFileMesh::getFamilyRepr(std::ostream& oss) const { oss << "- Family with name \"" << (*it).first << "\" with number " << (*it).second << std::endl; oss << " - Groups lying on this family : "; - std::vector grps=getGroupsOnFamily((*it).first.c_str()); + std::vector grps=getGroupsOnFamily((*it).first); std::copy(grps.begin(),grps.end(),std::ostream_iterator(oss," ")); oss << std::endl << std::endl; } } -MEDFileUMesh *MEDFileUMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED + * file. The mesh to load is specified by its name and numbers of a time step and an + * iteration. + * \param [in] fileName - the name of MED file to read. + * \param [in] mName - the name of the mesh to read. + * \param [in] dt - the number of a time step. + * \param [in] it - the number of an iteration. + * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + * \throw If the file is not readable. + * \throw If there is no mesh with given attributes in the file. + * \throw If the mesh in the file is not an unstructured one. + */ +MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - return new MEDFileUMesh(fid,mName,dt,it); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); + return new MEDFileUMesh(fid,mName,dt,it,mrs); } -MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED + * file. The first mesh in the file is loaded. + * \param [in] fileName - the name of MED file to read. + * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + * \throw If the file is not readable. + * \throw If there is no meshes in the file. + * \throw If the mesh in the file is not an unstructured one. + */ +MEDFileUMesh *MEDFileUMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs) { std::vector ms=MEDLoader::GetMeshNames(fileName); if(ms.empty()) @@ -1415,46 +2145,91 @@ MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep throw INTERP_KERNEL::Exception(oss.str().c_str()); } MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); int dt,it; ParaMEDMEM::MEDCouplingMeshType meshType; std::string dummy2; - MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2); - return new MEDFileUMesh(fid,ms.front().c_str(),dt,it); + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2); + return new MEDFileUMesh(fid,ms.front(),dt,it,mrs); } +/*! + * Returns an empty instance of MEDFileUMesh. + * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + */ MEDFileUMesh *MEDFileUMesh::New() { return new MEDFileUMesh; } -std::size_t MEDFileUMesh::getHeapMemorySize() const +/*! + * This method loads from file with name \a fileName the mesh called \a mName as New does. The difference is that + * here only a part of cells contained in the file will be loaded. The selection of cell is specified using the two consecutive parameters + * \a types and \a slicPerTyp. This method allows to load from a mesh (typically huge) in a MED file a part of cells of that mesh. + * The part of cells is specified using triplet (start,stop,step) for each geometric type. Only nodes lying on selected cells will be loaded to reduce + * at most the memory consumtion. + * + * \param [in] fileName - the name of the file. + * \param [in] mName - the name of the mesh to be read. + * \param [in] types - the list of the geo types of which some part will be taken. A geometric type in \a types must appear only once at most. + * \param [in] slicPerType - an array of size 3 times larger than \a types that specifies for each type in \a types (in the same order) resp the start, the stop and the step. + * \param [in] dt - the iteration, that is to say the first element of the pair that locates the asked time step. + * \param [in] it - the order, that is to say the second element of the pair that locates the asked time step. + * \param [in] mrs - the request for what to be loaded. + * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this mesh using decrRef() as it is no more needed. + */ +MEDFileUMesh *MEDFileUMesh::LoadPartOf(const std::string& fileName, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid(MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY)); + return MEDFileUMesh::LoadPartOf(fid,mName,types,slicPerTyp,dt,it,mrs); +} + +/*! + * Please refer to the other MEDFileUMesh::LoadPartOf method that has the same semantic and the same parameter (excepted the first). + * This method is \b NOT wrapped into python. + */ +MEDFileUMesh *MEDFileUMesh::LoadPartOf(med_idt fid, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + MEDCouplingAutoRefCountObjectPtr ret(MEDFileUMesh::New()); + ret->loadPartUMeshFromFile(fid,mName,types,slicPerTyp,dt,it,mrs); + return ret.retn(); +} + +std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const { - std::size_t ret=MEDFileMesh::getHeapMemorySize(); - if((const DataArrayDouble*)_coords) - ret+=_coords->getHeapMemorySize(); - if((const DataArrayInt *)_fam_coords) - ret+=_fam_coords->getHeapMemorySize(); - if((const DataArrayInt *)_num_coords) - ret+=_num_coords->getHeapMemorySize(); - if((const DataArrayInt *)_rev_num_coords) - ret+=_rev_num_coords->getHeapMemorySize(); - if((const DataArrayAsciiChar *)_name_coords) - ret+=_name_coords->getHeapMemorySize(); + std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren()); ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); + return ret; +} + +std::vector MEDFileUMesh::getDirectChildrenWithNull() const +{ + std::vector ret(MEDFileMesh::getDirectChildrenWithNull()); + ret.push_back((const DataArrayDouble*)_coords); + ret.push_back((const DataArrayInt *)_fam_coords); + ret.push_back((const DataArrayInt *)_num_coords); + ret.push_back((const DataArrayInt *)_rev_num_coords); + ret.push_back((const DataArrayAsciiChar *)_name_coords); + ret.push_back((const PartDefinition *)_part_coords); for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) - if((const MEDFileUMeshSplitL1*) *it) - ret+=(*it)->getHeapMemorySize(); + ret.push_back((const MEDFileUMeshSplitL1*) *it); return ret; } -MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileUMesh::shallowCpy() const { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileUMesh(*this); return ret.retn(); } -MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileUMesh::createNewEmpty() const +{ + return new MEDFileUMesh; +} + +MEDFileMesh *MEDFileUMesh::deepCpy() const { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileUMesh(*this); if((const DataArrayDouble*)_coords) @@ -1471,11 +2246,20 @@ MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception) for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++) { if((const MEDFileUMeshSplitL1 *)(*it)) - ret->_ms[i]=(*it)->deepCpy(); + ret->_ms[i]=(*it)->deepCpy(ret->_coords); } + if((const PartDefinition*)_part_coords) + ret->_part_coords=_part_coords->deepCpy(); return ret.retn(); } +/*! + * Checks if \a this and another mesh are equal. + * \param [in] other - the mesh to compare with. + * \param [in] eps - a precision used to compare real values. + * \param [in,out] what - the string returning description of unequal data. + * \return bool - \c true if the meshes are equal, \c false, else. + */ bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const { if(!MEDFileMesh::isEqual(other,eps,what)) @@ -1574,9 +2358,20 @@ bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh return false; } } - return true; + const PartDefinition *pd0(_part_coords),*pd1(otherC->_part_coords); + if(!pd0 && !pd1) + return true; + if((!pd0 && pd1) || (pd0 && !pd1)) + { + what=std::string("node part def is defined only for one among this or other !"); + return false; + } + return pd0->isEqual(pd1,what); } +/*! + * Clears redundant attributes of incorporated data arrays. + */ void MEDFileUMesh::clearNonDiscrAttributes() const { MEDFileMesh::clearNonDiscrAttributes(); @@ -1600,33 +2395,130 @@ void MEDFileUMesh::clearNonDiscrAttributes() const } } +void MEDFileUMesh::setName(const std::string& name) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_ms.begin();it!=_ms.end();it++) + if((MEDFileUMeshSplitL1 *)(*it)!=0) + (*it)->setName(name); + MEDFileMesh::setName(name); +} + MEDFileUMesh::MEDFileUMesh() { } -MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) try - { - loadUMeshFromFile(fid,mName,dt,it); +{ + loadUMeshFromFile(fid,mName,dt,it,mrs); + loadJointsFromFile(fid); } catch(INTERP_KERNEL::Exception& e) - { +{ throw e; - } +} + +/*! + * This method loads only a part of specified cells (given by range of cell ID per geometric type) + * See MEDFileUMesh::LoadPartOf for detailed description. + * + * \sa loadUMeshFromFile + */ +void MEDFileUMesh::loadPartUMeshFromFile(med_idt fid, const std::string& mName, const std::vector& types, const std::vector& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + MEDFileUMeshL2 loaderl2; + ParaMEDMEM::MEDCouplingMeshType meshType; + int dummy0,dummy1; + std::string dummy2; + int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2)); + if(meshType!=UNSTRUCTURED) + { + std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs); + dispatchLoadedPart(fid,loaderl2,mName,mrs); +} + +/*! + * \brief Write joints in a file + */ +void MEDFileMesh::writeJoints(med_idt fid) const +{ + if ( (const MEDFileJoints*) _joints ) + _joints->write(fid); +} + +/*! + * \brief Load joints in a file or use provided ones + */ +//================================================================================ +/*! + * \brief Load joints in a file or use provided ones + * \param [in] fid - MED file descriptor + * \param [in] toUseInstedOfReading - optional joints to use instead of reading, + * Usually this joints are those just read by another iteration + * of namesake mesh, when this method is called by MEDFileMeshMultiTS::New() + */ +//================================================================================ + +void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading) +{ + if ( toUseInstedOfReading ) + setJoints( toUseInstedOfReading ); + else + _joints = MEDFileJoints::New( fid, _name ); +} + +/*! + * \brief Return number of joints, which is equal to number of adjacent mesh domains + */ +int MEDFileMesh::getNumberOfJoints() +{ + return ( (MEDFileJoints*) _joints ) ? _joints->getNumberOfJoints() : 0; +} + +/*! + * \brief Return joints with all adjacent mesh domains + */ +MEDFileJoints * MEDFileMesh::getJoints() const +{ + return const_cast(& (*_joints)); +} + +void MEDFileMesh::setJoints( MEDFileJoints* joints ) +{ + if ( joints != _joints ) + { + _joints = joints; + if ( joints ) + joints->incrRef(); + } +} -void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +/*! + * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor. + * + * \sa loadPartUMeshFromFile + */ +void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { MEDFileUMeshL2 loaderl2; ParaMEDMEM::MEDCouplingMeshType meshType; int dummy0,dummy1; std::string dummy2; - int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2); + int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2)); if(meshType!=UNSTRUCTURED) { std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - loaderl2.loadAll(fid,mid,mName,dt,it); + loaderl2.loadAll(fid,mid,mName,dt,it,mrs); + dispatchLoadedPart(fid,loaderl2,mName,mrs); +} + +void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs) +{ int lev=loaderl2.getNumberOfLevels(); _ms.resize(lev); for(int i=0;iisNodeFamilyFieldReading()) + _fam_coords=loaderl2.getCoordsFamily(); + if(!mrs || mrs->isNodeNumFieldReading()) + _num_coords=loaderl2.getCoordsNum(); + if(!mrs || mrs->isNodeNameFieldReading()) + _name_coords=loaderl2.getCoordsName(); + _part_coords=loaderl2.getPartDefOfCoo(); computeRevNum(); } @@ -1655,7 +2552,7 @@ MEDFileUMesh::~MEDFileUMesh() { } -void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::writeLL(med_idt fid) const { const DataArrayDouble *coo=_coords; INTERP_KERNEL::AutoPtr maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); @@ -1663,7 +2560,9 @@ void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str); MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str); int spaceDim=coo?coo->getNumberOfComponents():0; - int mdim=getMeshDimension(); + int mdim(0); + if(!_ms.empty()) + mdim=getMeshDimension(); INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE); INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE); for(int i=0;i >::const_iterator it=_ms.begin();it!=_ms.end();it++) if((const MEDFileUMeshSplitL1 *)(*it)!=0) - (*it)->write(fid,maa,mdim); - MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str); + (*it)->write(fid,meshName,mdim); + MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str); + + writeJoints(fid); } +/*! + * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh. + * \return std::vector - a sequence of the relative dimensions. + */ std::vector MEDFileUMesh::getNonEmptyLevels() const { std::vector ret; @@ -1693,6 +2600,10 @@ std::vector MEDFileUMesh::getNonEmptyLevels() const return ret; } +/*! + * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh. + * \return std::vector - a sequence of the relative dimensions. + */ std::vector MEDFileUMesh::getNonEmptyLevelsExt() const { std::vector ret0=getNonEmptyLevels(); @@ -1706,68 +2617,133 @@ std::vector MEDFileUMesh::getNonEmptyLevelsExt() const return ret0; } +std::vector MEDFileUMesh::getFamArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *famCoo(_fam_coords); + if(famCoo) + ret.push_back(1); + int lev=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--) + { + const MEDFileUMeshSplitL1 *cur(*it); + if(cur) + if(cur->getFamilyField()) + ret.push_back(lev); + } + return ret; +} + +std::vector MEDFileUMesh::getNumArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *numCoo(_num_coords); + if(numCoo) + ret.push_back(1); + int lev=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--) + { + const MEDFileUMeshSplitL1 *cur(*it); + if(cur) + if(cur->getNumberField()) + ret.push_back(lev); + } + return ret; +} + +std::vector MEDFileUMesh::getNameArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayAsciiChar *nameCoo(_name_coords); + if(nameCoo) + ret.push_back(1); + int lev=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--) + { + const MEDFileUMeshSplitL1 *cur(*it); + if(cur) + if(cur->getNameField()) + ret.push_back(lev); + } + return ret; +} + /*! - * This methods returns all relative mesh levels where group 'grp' is defined \b excluded \b nodes. - * To include nodes call MEDFileUMesh::getGrpNonEmptyLevelsExt method. + * Returns all relative mesh levels (**excluding nodes**) where a given group is defined. + * To include nodes, call getGrpNonEmptyLevelsExt() method. + * \param [in] grp - the name of the group of interest. + * \return std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getGrpNonEmptyLevels(const char *grp) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getGrpNonEmptyLevels(const std::string& grp) const { std::vector fams=getFamiliesOnGroup(grp); return getFamsNonEmptyLevels(fams); } /*! - * This method is a generalization of MEDFileUMesh::getGrpNonEmptyLevelsExt. It looks at the node level to state if the group 'grp' has a part lying on node. + * Returns all relative mesh levels (including nodes) where a given group is defined. + * \param [in] grp - the name of the group of interest. + * \return std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getGrpNonEmptyLevelsExt(const char *grp) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getGrpNonEmptyLevelsExt(const std::string& grp) const { std::vector fams=getFamiliesOnGroup(grp); return getFamsNonEmptyLevelsExt(fams); } /*! - * This methods returns all relative mesh levels where family 'fam' is defined \b excluded \b nodes. - * To include nodes call MEDFileUMesh::getFamNonEmptyLevelsExt method. + * Returns all relative mesh levels (**excluding nodes**) where a given family is defined. + * To include nodes, call getFamNonEmptyLevelsExt() method. + * \param [in] fam - the name of the family of interest. + * \return std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getFamNonEmptyLevels(const char *fam) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getFamNonEmptyLevels(const std::string& fam) const { std::vector fams(1,std::string(fam)); return getFamsNonEmptyLevels(fams); } /*! - * This method is a generalization of MEDFileUMesh::getFamNonEmptyLevels. It looks at the node level to state if the family 'fam' has a part lying on node. + * Returns all relative mesh levels (including nodes) where a given family is defined. + * \param [in] fam - the name of the family of interest. + * \return std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getFamNonEmptyLevelsExt(const char *fam) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getFamNonEmptyLevelsExt(const std::string& fam) const { std::vector fams(1,std::string(fam)); return getFamsNonEmptyLevelsExt(fams); } /*! - * This methods returns all relative mesh levels where groups 'grps' are defined \b excluded \b nodes. - * To include nodes call MEDFileUMesh::getGrpsNonEmptyLevelsExt method. + * Returns all relative mesh levels (**excluding nodes**) where given groups are defined. + * To include nodes, call getGrpsNonEmptyLevelsExt() method. + * \param [in] grps - a sequence of names of the groups of interest. + * \return std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector& grps) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector& grps) const { std::vector fams=getFamiliesOnGroups(grps); return getFamsNonEmptyLevels(fams); } /*! - * This method is a generalization of MEDFileUMesh::getGrpsNonEmptyLevels. It looks at the node level to state if the families 'fams' has a part lying on node. + * Returns all relative mesh levels (including nodes) where given groups are defined. + * \param [in] grps - a sequence of names of the groups of interest. + * \return std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector& grps) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector& grps) const { std::vector fams=getFamiliesOnGroups(grps); return getFamsNonEmptyLevelsExt(fams); } /*! - * This methods returns all relative mesh levels where families 'fams' are defined \b excluded \b nodes. - * To include nodes call MEDFileUMesh::getFamsNonEmptyLevelsExt method. + * Returns all relative mesh levels (**excluding nodes**) where given families are defined. + * To include nodes, call getFamsNonEmptyLevelsExt() method. + * \param [in] fams - the name of the family of interest. + * \return std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getFamsNonEmptyLevels(const std::vector& fams) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getFamsNonEmptyLevels(const std::vector& fams) const { std::vector ret; std::vector levs=getNonEmptyLevels(); @@ -1779,9 +2755,11 @@ std::vector MEDFileUMesh::getFamsNonEmptyLevels(const std::vector - a sequence of the relative dimensions. */ -std::vector MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector& fams) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector& fams) const { std::vector ret0=getFamsNonEmptyLevels(fams); const DataArrayInt *famCoords=_fam_coords; @@ -1800,22 +2778,48 @@ std::vector MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector - a sequence of group names at \a meshDimRelToMaxExt + * level. */ -std::vector MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const { std::vector ret; std::vector allGrps=getGroupsNames(); for(std::vector::const_iterator it=allGrps.begin();it!=allGrps.end();it++) { - std::vector levs=getGrpNonEmptyLevelsExt((*it).c_str()); + std::vector levs=getGrpNonEmptyLevelsExt((*it)); if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end()) ret.push_back(*it); } return ret; } -int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) +int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const +{ + int ret=-std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_coords) + { + int val=_fam_coords->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) + { + if((const MEDFileUMeshSplitL1 *)(*it)) + { + const DataArrayInt *da=(*it)->getFamilyField(); + if(da) + { + int val=da->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + } + } + return ret; +} + +int MEDFileUMesh::getMaxFamilyIdInArrays() const { int ret=-std::numeric_limits::max(),tmp=-1; if((const DataArrayInt *)_fam_coords) @@ -1830,7 +2834,7 @@ int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) const DataArrayInt *da=(*it)->getFamilyField(); if(da) { - int val=_fam_coords->getMaxValue(tmp); + int val=da->getMaxValue(tmp); ret=std::max(ret,val); } } @@ -1838,7 +2842,7 @@ int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) return ret; } -int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) +int MEDFileUMesh::getMinFamilyIdInArrays() const { int ret=std::numeric_limits::max(),tmp=-1; if((const DataArrayInt *)_fam_coords) @@ -1853,7 +2857,7 @@ int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) const DataArrayInt *da=(*it)->getFamilyField(); if(da) { - int val=_fam_coords->getMinValue(tmp); + int val=da->getMinValue(tmp); ret=std::min(ret,val); } } @@ -1861,7 +2865,12 @@ int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) return ret; } -int MEDFileUMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) +/*! + * Returns the dimension on cells in \a this mesh. + * \return int - the mesh dimension. + * \throw If there are no cells in this mesh. + */ +int MEDFileUMesh::getMeshDimension() const { int lev=0; for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++) @@ -1870,7 +2879,13 @@ int MEDFileUMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !"); } -int MEDFileUMesh::getSpaceDimension() const throw(INTERP_KERNEL::Exception) +/*! + * Returns the space dimension of \a this mesh that is equal to number of components in + * the node coordinates array. + * \return int - the space dimension of \a this mesh. + * \throw If the node coordinates array is not available. + */ +int MEDFileUMesh::getSpaceDimension() const { const DataArrayDouble *coo=_coords; if(!coo) @@ -1878,6 +2893,10 @@ int MEDFileUMesh::getSpaceDimension() const throw(INTERP_KERNEL::Exception) return coo->getNumberOfComponents(); } +/*! + * Returns a string describing \a this mesh. + * \return std::string - the mesh information string. + */ std::string MEDFileUMesh::simpleRepr() const { std::ostringstream oss; @@ -1926,12 +2945,22 @@ std::string MEDFileUMesh::simpleRepr() const return oss.str(); } +/*! + * Returns a full textual description of \a this mesh. + * \return std::string - the string holding the mesh description. + */ std::string MEDFileUMesh::advancedRepr() const { return simpleRepr(); } -int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * Returns number of mesh entities of a given relative dimension in \a this mesh. + * \param [in] meshDimRelToMaxExt - the relative dimension of interest. + * \return int - the number of entities. + * \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh. + */ +int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt==1) { @@ -1942,15 +2971,35 @@ int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERN return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize(); } -const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * Returns the family field for mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the family field. It is an array of ids of families + * each mesh entity belongs to. It can be \c NULL. + */ +const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt==1) return _fam_coords; - const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt); + const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt)); return l1->getFamilyField(); } -const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) +{ + if(meshDimRelToMaxExt==1) + return _fam_coords; + MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt)); + return l1->getFamilyField(); +} + +/*! + * Returns the optional numbers of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the array of the entity numbers. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt==1) return _num_coords; @@ -1958,7 +3007,7 @@ const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) return l1->getNumberField(); } -const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt==1) return _name_coords; @@ -1966,15 +3015,76 @@ const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxE return l1->getNameField(); } -int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) +/*! + * This method returns for a specified relative level \a meshDimRelToMaxExt the part effectively read (if the instance is the result of the read of a file). + * + * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested. + * \param [in] gt - The input geometric type for which the part definition is requested. + * \return the part definition owned by \a this. So no need to deallocate the returned instance. + */ +const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const { - const DataArrayDouble *coo=_coords; + if(meshDimRelToMaxExt==1) + return _part_coords; + const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt)); + return l1->getPartDef(gt); +} + +int MEDFileUMesh::getNumberOfNodes() const +{ + const DataArrayDouble *coo(_coords); if(!coo) throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !"); return coo->getNumberOfTuples(); } -const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +int MEDFileUMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const +{ + const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt)); + return l1->getNumberOfCells(); +} + +bool MEDFileUMesh::hasImplicitPart() const +{ + return false; +} + +int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const +{ + throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !"); +} + +void MEDFileUMesh::releaseImplicitPartIfAny() const +{ +} + +void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector& nodesFetched) const +{ + std::size_t sz(st.getNumberOfItems()); + for(std::size_t i=0;icomputeNodeIdsAlg(nodesFetched); + else + { + const DataArrayInt *arr(globs->getProfile(st[i].getPflName())); + MEDCouplingAutoRefCountObjectPtr m2(dynamic_cast(m->buildPartOfMySelf(arr->begin(),arr->end(),true))); + m2->computeNodeIdsAlg(nodesFetched); + } + } +} + +/*! + * Returns the optional numbers of mesh entities of a given dimension transformed using + * DataArrayInt::invertArrayN2O2O2N(). + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the array of the entity numbers transformed using + * DataArrayInt::invertArrayN2O2O2N(). + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt==1) { @@ -1987,7 +3097,8 @@ const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxEx } /*! - * This method returns coordinates in 'this'. The returned array reference counter is \b not incremented by this method (as MEDCouplingPointSet::getCoords does). + * Returns a pointer to the node coordinates array of \a this mesh \b without + * incrementing its reference counter, thus there is no need to decrRef() it by the caller. */ DataArrayDouble *MEDFileUMesh::getCoords() const { @@ -1999,34 +3110,89 @@ DataArrayDouble *MEDFileUMesh::getCoords() const return 0; } -MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given + * group of \a this mesh. Only mesh entities of a given dimension are included in the + * new mesh. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest. + * \param [in] grp - the name of the group whose mesh entities are included in the + * new mesh. + * \param [in] renum - if \c true, cells and nodes of the result mesh are permuted + * according to the optional numbers of entities, if available. + * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + * \throw If the name of a nonexistent group is specified. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const { synchronizeTinyInfoOnLeaves(); std::vector tmp(1); tmp[0]=grp; - MEDCouplingUMesh *ret=getGroups(meshDimRelToMaxExt,tmp,renum); - ret->setName(grp); - return ret; + return getGroups(meshDimRelToMaxExt,tmp,renum); } -MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector& grps, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given + * groups of \a this mesh. Only mesh entities of a given dimension are included in the + * new mesh. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest. + * \param [in] grps - a sequence of group names whose mesh entities are included in the + * new mesh. + * \param [in] renum - if \c true, cells and nodes of the result mesh are permuted + * according to the optional numbers of entities, if available. + * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + * \throw If a name of a nonexistent group is present in \a grps. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector& grps, bool renum) const { synchronizeTinyInfoOnLeaves(); std::vector fams2=getFamiliesOnGroups(grps); - return getFamilies(meshDimRelToMaxExt,fams2,renum); + MEDCouplingAutoRefCountObjectPtr zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum); + if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet)) + zeRet->setName(grps[0]); + return zeRet.retn(); } -MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given + * family of \a this mesh. Only mesh entities of a given dimension are included in the + * new mesh. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest. + * \param [in] fam - the name of the family whose mesh entities are included in the + * new mesh. + * \param [in] renum - if \c true, cells and nodes of the result mesh are permuted + * according to the optional numbers of entities, if available. + * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + * \throw If a name of a nonexistent family is present in \a grps. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const { synchronizeTinyInfoOnLeaves(); std::vector tmp(1); tmp[0]=fam; - MEDCouplingUMesh *ret=getFamilies(meshDimRelToMaxExt,tmp,renum); - ret->setName(fam); - return ret; + return getFamilies(meshDimRelToMaxExt,tmp,renum); } -MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given + * families of \a this mesh. Only mesh entities of a given dimension are included in the + * new mesh. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest. + * \param [in] fams - a sequence of family names whose mesh entities are included in the + * new mesh. + * \param [in] renum - if \c true, cells and nodes of the result mesh are permuted + * according to the optional numbers of entities, if available. + * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to + * delete this mesh using decrRef() as it is no more needed. + * \throw If a name of a nonexistent family is present in \a fams. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const { synchronizeTinyInfoOnLeaves(); if(meshDimRelToMaxExt==1) @@ -2039,13 +3205,29 @@ MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::v } std::vector famIds=getFamiliesIds(fams); const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt); + MEDCouplingAutoRefCountObjectPtr zeRet; if(!famIds.empty()) - return l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum); + zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum); else - return l1->getFamilyPart(0,0,renum); + zeRet=l1->getFamilyPart(0,0,renum); + if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet)) + zeRet->setName(fams[0]); + return zeRet.retn(); } -DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of mesh entities contained in given families of a given dimension. + * \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids + * are required. + * \param [in] fams - the names of the families of interest. + * \param [in] renum - if \c true, the optional numbers of entities, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of mesh entities of the families. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the family field is missing for \a meshDimRelToMaxExt. + */ +DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const { std::vector famIds=getFamiliesIds(fams); if(meshDimRelToMaxExt==1) @@ -2073,16 +3255,20 @@ DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::ve } /*! - * Returns a pointer to mesh at the specified level. ** WARNING **, if the input \a meshDimRelToMaxExt is set to one (nodes), - * The returned mesh ** will be not valid **. It is a feature, because MEDLoader do not creates cells that do not exist ! - * To build a valid MEDCouplingUMesh instance from the returned value when \a meshDimRelToMaxExt is equal to one, simply - * call MEDCouplingUMesh::Build0DMeshFromCoords. - * - * \return a pointer to unstructured mesh that need to be managed by the caller. - * \warning the returned pointer has to be managed by the caller. - * \sa MEDFileUMesh::getGenMeshAtLevel + * Returns a MEDCouplingUMesh of a given relative dimension. + * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not + * valid**. This is a feature, because MEDLoader does not create cells that do not exist! + * To build a valid MEDCouplingUMesh from the returned one in this case, + * call MEDCouplingUMesh::Build0DMeshFromCoords(). + * \param [in] meshDimRelToMax - the relative dimension of interest. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \sa getGenMeshAtLevel() */ -MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception) +MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const { synchronizeTinyInfoOnLeaves(); if(meshDimRelToMaxExt==1) @@ -2102,38 +3288,176 @@ MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renu } /*! - * Returns a pointer to mesh at the specified level. - * - * \return a pointer to unstructured mesh that need to be managed by the caller. - * \warning the returned pointer has to be managed by the caller. - * \sa MEDFileUMesh::getMeshAtLevel + * Returns a MEDCouplingUMesh of a given relative dimension. + * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not + * valid**. This is a feature, because MEDLoader does not create cells that do not exist! + * To build a valid MEDCouplingUMesh from the returned one in this case, + * call MEDCouplingUMesh::Build0DMeshFromCoords(). + * \param [in] meshDimRelToMax - the relative dimension of interest. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh. + * \sa getMeshAtLevel() */ -MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception) +MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const { return getMeshAtLevel(meshDimRelToMax,renum); } -MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const +{ + const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax)); + return l1->getDistributionOfTypes(); +} + +/*! + * Returns a MEDCouplingUMesh of a relative dimension == 0. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const { return getMeshAtLevel(0,renum); } -MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a MEDCouplingUMesh of a relative dimension == -1. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const { return getMeshAtLevel(-1,renum); } -MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a MEDCouplingUMesh of a relative dimension == -2. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const { return getMeshAtLevel(-2,renum); } -MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns a MEDCouplingUMesh of a relative dimension == -3. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh. + */ +MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const { return getMeshAtLevel(-3,renum); } -const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * This method is for advanced users. There is two storing strategy of mesh in \a this. + * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances. + * When assignement is done the first one is done, which is not optimal in write mode for MED file. + * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode. + */ +void MEDFileUMesh::forceComputationOfParts() const +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) + { + const MEDFileUMeshSplitL1 *elt(*it); + if(elt) + elt->forceComputationOfParts(); + } +} + +/*! + * This method returns a vector of mesh parts containing each exactly one geometric type. + * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown). + * This method is only for memory aware users. + * The returned pointers are **NOT** new object pointer. No need to mange them. + */ +std::vector MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const +{ + const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax)); + return sp->getDirectUndergroundSingleGeoTypeMeshes(); +} + +/*! + * This method returns the part of \a this having the geometric type \a gt. + * If such part is not existing an exception will be thrown. + * The returned pointer is **NOT** new object pointer. No need to mange it. + */ +MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const +{ + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt); + int lev=(int)cm.getDimension()-getMeshDimension(); + const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev)); + return sp->getDirectUndergroundSingleGeoTypeMesh(gt); +} + +/*! + * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this. + * \throw if the reqsuested \a meshDimRelToMax does not exist. + */ +std::vector MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const +{ + const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax)); + return sp->getGeoTypes(); +} + +/*! + * This method extracts from whole family field ids the part relative to the input parameter \a gt. + * \param [in] gt - the geometric type for which the family field is asked. + * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to + * delete using decrRef() as it is no more needed. + * \sa MEDFileUMesh::extractNumberFieldOnGeoType + */ +DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const +{ + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt); + int lev=(int)cm.getDimension()-getMeshDimension(); + const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev)); + return sp->extractFamilyFieldOnGeoType(gt); +} + +/*! + * This method extracts from whole number field ids the part relative to the input parameter \a gt. + * \param [in] gt - the geometric type for which the number field is asked. + * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to + * delete using decrRef() as it is no more needed. + * \sa MEDFileUMesh::extractFamilyFieldOnGeoType + */ +DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const +{ + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt); + int lev=(int)cm.getDimension()-getMeshDimension(); + const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev)); + return sp->extractNumberFieldOnGeoType(gt); +} + +/*! + * This method returns for specified geometric type \a gt the relative level to \a this. + * If the relative level is empty an exception will be thrown. + */ +int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const +{ + const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt); + int ret((int)cm.getDimension()-getMeshDimension()); + getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level. + return ret; +} + +const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt==1) throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !"); @@ -2141,27 +3465,27 @@ const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !"); int tracucedRk=-meshDimRelToMaxExt; if(tracucedRk>=(int)_ms.size()) - throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !"); + throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !"); if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0) throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !"); return _ms[tracucedRk]; } -MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception) +MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) { - if(meshDimRelToMaxExt==1) + if(meshDimRelToMaxExt==1) throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !"); if(meshDimRelToMaxExt>1) throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !"); int tracucedRk=-meshDimRelToMaxExt; if(tracucedRk>=(int)_ms.size()) - throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !"); + throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !"); if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0) throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !"); return _ms[tracucedRk]; } -void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const { if(-meshDimRelToMax>=(int)_ms.size()) throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !"); @@ -2177,7 +3501,12 @@ void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const } } -void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception) +/*! + * Sets the node coordinates array of \a this mesh. + * \param [in] coords - the new node coordinates array. + * \throw If \a coords == \c NULL. + */ +void MEDFileUMesh::setCoords(DataArrayDouble *coords) { if(!coords) throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !"); @@ -2188,9 +3517,17 @@ void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Excep _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfTuples,1); _fam_coords->fillWithZero(); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_ms.begin();it!=_ms.end();it++) + if((MEDFileUMeshSplitL1 *)(*it)) + (*it)->setCoords(coords); } -void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception) +/*! + * Removes all groups of a given dimension in \a this mesh. + * \param [in] meshDimRelToMaxExt - the relative dimension of interest. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) { if(meshDimRelToMaxExt==1) { @@ -2203,7 +3540,10 @@ void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNE optimizeFamilies(); } -void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception) +/*! + * Removes all families with ids not present in the family fields of \a this mesh. + */ +void MEDFileUMesh::optimizeFamilies() { std::vector levs=getNonEmptyLevelsExt(); std::set allFamsIds; @@ -2241,7 +3581,7 @@ void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception) _groups.erase(*it); } -void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified) throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::duplicateNodesOnM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified) { std::vector levs=getNonEmptyLevels(); if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end()) @@ -2314,8 +3654,8 @@ void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt * setMeshAtLevel(-1,newm1); setFamilyFieldArr(-1,newFam); std::string grpName2(grpNameM1); grpName2+="_dup"; - addFamily(grpName2.c_str(),idd); - addFamilyOnGrp(grpName2.c_str(),grpName2.c_str()); + addFamily(grpName2,idd); + addFamilyOnGrp(grpName2,grpName2); // fam=_fam_coords; if(fam) @@ -2339,7 +3679,7 @@ void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt * * \return false if no modification has been performed linked to the unpolyzation. Neither cell type, not cell numbers. When false is returned no need of field on cells or on gauss renumbering. * Inversely, if true is returned, it means that distribution of cell by geometric type has changed and field on cell and field on gauss point must be renumbered. */ -bool MEDFileUMesh::unPolyze(std::vector& oldCode, std::vector& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception) +bool MEDFileUMesh::unPolyze(std::vector& oldCode, std::vector& newCode, DataArrayInt *& o2nRenumCell) { o2nRenumCell=0; oldCode.clear(); newCode.clear(); std::vector levs=getNonEmptyLevels(); @@ -2357,7 +3697,7 @@ bool MEDFileUMesh::unPolyze(std::vector& oldCode, std::vector& newCode bool hasChanged=m->unPolyze(); DataArrayInt *fake=0; MEDCouplingAutoRefCountObjectPtr o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER, - MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake); + MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake); fake->decrRef(); renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart); if(hasChanged) @@ -2414,31 +3754,42 @@ struct MEDLoaderAccVisit1 * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes. * -1 values in returned array means that the corresponding old node is no more used. * - * \return newly allocated array containing correspondance in \b old \b to \b new format. If all nodes in \a this are fetched NULL pointer is returned and nothing + * \return newly allocated array containing correspondance in \b old \b to \b new format. If all nodes in \a this are fetched \c NULL pointer is returned and nothing * is modified in \a this. * \throw If no coordinates are set in \a this or if there is in any available mesh in \a this a cell having a nodal connectivity containing a node id not in the range of * set coordinates. */ -DataArrayInt *MEDFileUMesh::zipCoords() throw(INTERP_KERNEL::Exception) +DataArrayInt *MEDFileUMesh::zipCoords() { - const DataArrayDouble *coo=getCoords(); + const DataArrayDouble *coo(getCoords()); if(!coo) throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !"); - int nbOfNodes=coo->getNumberOfTuples(); + int nbOfNodes(coo->getNumberOfTuples()); std::vector nodeIdsInUse(nbOfNodes,false); - std::vector neLevs=getNonEmptyLevels(); + std::vector neLevs(getNonEmptyLevels()); for(std::vector::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++) { - MEDCouplingAutoRefCountObjectPtr m=getMeshAtLevel(*lev); - m->computeNodeIdsAlg(nodeIdsInUse); + const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev)); + if(zeLev->isMeshStoredSplitByType()) + { + std::vector ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes()); + for(std::vector::const_iterator it=ms.begin();it!=ms.end();it++) + if(*it) + (*it)->computeNodeIdsAlg(nodeIdsInUse); + } + else + { + MEDCouplingAutoRefCountObjectPtr mesh(zeLev->getWholeMesh(false)); + mesh->computeNodeIdsAlg(nodeIdsInUse); + } } - int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true); + int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true)); if(nbrOfNodesInUse==nbOfNodes) - return 0; - MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1); + return 0;//no need to update _part_coords + MEDCouplingAutoRefCountObjectPtr ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1); std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1()); - MEDCouplingAutoRefCountObjectPtr ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse); - MEDCouplingAutoRefCountObjectPtr newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end()); + MEDCouplingAutoRefCountObjectPtr ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse)); + MEDCouplingAutoRefCountObjectPtr newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end())); MEDCouplingAutoRefCountObjectPtr newFamCoords; MEDCouplingAutoRefCountObjectPtr newNameCoords; if((const DataArrayInt *)_fam_coords) @@ -2452,155 +3803,566 @@ DataArrayInt *MEDFileUMesh::zipCoords() throw(INTERP_KERNEL::Exception) for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_ms.begin();it!=_ms.end();it++) { if((MEDFileUMeshSplitL1*)*it) - (*it)->renumberNodesInConn(ret->begin()); + { + (*it)->renumberNodesInConn(ret->begin()); + (*it)->setCoords(_coords); + } + } + // updates _part_coords + const PartDefinition *pc(_part_coords); + if(pc) + { + MEDCouplingAutoRefCountObjectPtr tmpPD(DataArrayPartDefinition::New(ret2)); + _part_coords=tmpPD->composeWith(pc); } return ret.retn(); } /*! - * This method is here only to add a group on node. - * MEDFileUMesh::setGroupsAtLevel with 1 in the first parameter. + * This method performs an extrusion along a path defined by \a m1D. + * \a this is expected to be a mesh with max mesh dimension equal to 2. + * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1. + * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this. + * This method scans all levels in \a this + * and put them in the returned mesh. All groups in \a this are also put in the returned mesh. * - * \param [in] ids node ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm). + * \param [in] m1D - the mesh defining the extrusion path. + * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details) + * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this. + * + * \sa MEDCouplingUMesh::buildExtrudedMesh */ -void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Exception) -{ - const DataArrayDouble *coords=_coords; - if(!coords) - throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !"); - int nbOfNodes=coords->getNumberOfTuples(); - if(!((DataArrayInt *)_fam_coords)) - { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); } - // - addGroupUnderground(ids,_fam_coords); -} - -void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception) -{ - std::vector levs=getNonEmptyLevelsExt(); - if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end()) - { - std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in "; - std::copy(levs.begin(),levs.end(),std::ostream_iterator(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); +MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const +{ + if(getMeshDimension()!=2) + throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !"); + MEDCouplingAutoRefCountObjectPtr ret(MEDFileUMesh::New()); + m1D->checkCoherency(); + if(m1D->getMeshDimension()!=1) + throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !"); + int nbRep(m1D->getNumberOfCells()); + std::vector levs(getNonEmptyLevels()); + std::vector grps(getGroupsNames()); + std::vector< MEDCouplingAutoRefCountObjectPtr > zeList; + DataArrayDouble *coords(0); + std::size_t nbOfLevsOut(levs.size()+1); + std::vector< MEDCouplingAutoRefCountObjectPtr > o2ns(nbOfLevsOut); + for(std::vector::const_iterator lev=levs.begin();lev!=levs.end();lev++) + { + MEDCouplingAutoRefCountObjectPtr item(getMeshAtLevel(*lev)); + item=item->clone(false); + item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data + MEDCouplingAutoRefCountObjectPtr tmp(static_cast(m1D->deepCpy())); + tmp->changeSpaceDimension(3+(*lev),0.); + MEDCouplingAutoRefCountObjectPtr elt(item->buildExtrudedMesh(tmp,policy)); + zeList.push_back(elt); + if(*lev==0) + coords=elt->getCoords(); } - if(meshDimRelToMaxExt==1) - { addNodeGroup(ids); return ; } - MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt); - DataArrayInt *fam=lev->getOrCreateAndGetFamilyField(); - addGroupUnderground(ids,fam); -} - -/*! - * \param [in] ids ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm). - * \parma [in,out] famArr family array on level of interest to be renumbered. The input pointer should be not NULL (no check of that will be performed) - */ -void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception) -{ - if(!ids) - throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !"); - std::string grpName(ids->getName()); - if(grpName.empty()) - throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !"); - ids->checkStrictlyMonotonic(true); - famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr famArrTmp(famArr); - std::vector grpsNames=getGroupsNames(); - if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end()) + if(!coords) + throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !"); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=zeList.begin();it!=zeList.end();it++) { - std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); + (*it)->setName(getName()); + (*it)->setCoords(coords); } - std::list< MEDCouplingAutoRefCountObjectPtr > allFamIds=getAllNonNullFamilyIds(); - allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp)); - MEDCouplingAutoRefCountObjectPtr famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end()); - MEDCouplingAutoRefCountObjectPtr diffFamIds=famIds->getDifferentValues(); - std::vector familyIds; - std::vector< MEDCouplingAutoRefCountObjectPtr > idsPerfamiliyIds; - int maxVal=getTheMaxFamilyId()+1; - std::map families(_families); - std::map > groups(_groups); - std::vector fams; - bool created(false); - for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++) + for(std::size_t ii=0;ii!=zeList.size();ii++) { - MEDCouplingAutoRefCountObjectPtr ids2Tmp=famIds->getIdsEqual(*famId); - MEDCouplingAutoRefCountObjectPtr ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end()); - MEDCouplingAutoRefCountObjectPtr ids1=famArr->getIdsEqual(*famId); - MEDCouplingAutoRefCountObjectPtr ret0(ids1->buildSubstractionOptimized(ids2)); - if(ret0->empty()) + int lev(levs[ii]); + MEDCouplingAutoRefCountObjectPtr elt(zeList[ii]); + if(lev<=-1) { - bool isFamPresent=false; - for(std::list< MEDCouplingAutoRefCountObjectPtr >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++) - isFamPresent=(*itl)->presenceOfValue(*famId); - if(!isFamPresent) - { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp - else + MEDCouplingAutoRefCountObjectPtr elt1(getMeshAtLevel(lev+1)); + MEDCouplingAutoRefCountObjectPtr elt2(elt1->clone(false)); + MEDCouplingAutoRefCountObjectPtr tmp(elt2->getNodalConnectivity()->deepCpy()); + elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex()); + elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes()); + elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords()); + std::vector elts(3); + elts[0]=elt; elts[1]=elt1; elts[2]=elt2; + elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts); + elt->setName(getName()); + } + // + o2ns[ii]=elt->sortCellsInMEDFileFrmt(); + ret->setMeshAtLevel(lev,elt); + } + MEDCouplingAutoRefCountObjectPtr endLev(getMeshAtLevel(levs.back())),endLev2; + endLev=endLev->clone(false); endLev->setCoords(coords); + MEDCouplingAutoRefCountObjectPtr tmp(endLev->getNodalConnectivity()->deepCpy()); + endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex()); + endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes()); + endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2); + o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt(); + endLev->setName(getName()); + ret->setMeshAtLevel(levs.back()-1,endLev); + // + for(std::size_t ii=0;ii!=zeList.size();ii++) + { + int lev(levs[ii]); + std::vector< MEDCouplingAutoRefCountObjectPtr > outGrps; + std::vector< const DataArrayInt * > outGrps2; + if(lev<=-1) + { + for(std::vector::const_iterator grp=grps.begin();grp!=grps.end();grp++) { - familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ids2); std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,maxVal,created); - fams.push_back(locFamName); - if(existsFamily(*famId)) + MEDCouplingAutoRefCountObjectPtr grpArr(getGroupArr(lev+1,*grp)); + if(!grpArr->empty()) { - std::string locFamName2=getFamilyNameGivenId(*famId); std::vector v(2); v[0]=locFamName2; v[1]=locFamName; - ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v); + MEDCouplingAutoRefCountObjectPtr grpArr1(grpArr->deepCpy()),grpArr2(grpArr->deepCpy()); + int offset0(zeList[ii]->getNumberOfCells()); + int offset1(offset0+getNumberOfCellsAtLevel(lev+1)); + grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1); + std::ostringstream oss; oss << grpArr2->getName() << "_top"; + grpArr2->setName(oss.str()); + grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end()); + grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end()); + outGrps.push_back(grpArr1); outGrps.push_back(grpArr2); + outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2); } - maxVal++; - } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal + } } - else + // + for(std::vector::const_iterator grp=grps.begin();grp!=grps.end();grp++) { - familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1 - familyIds.push_back(maxVal+1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1 - std::string n2(FindOrCreateAndGiveFamilyWithId(families,maxVal+1,created)); fams.push_back(n2); - if(existsFamily(*famId)) + MEDCouplingAutoRefCountObjectPtr grpArr(getGroupArr(lev,*grp)); + if(!grpArr->empty()) { - std::string n1(FindOrCreateAndGiveFamilyWithId(families,maxVal,created)); std::vector v(2); v[0]=n1; v[1]=n2; - ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v); + int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev)); + std::vector< MEDCouplingAutoRefCountObjectPtr > grpArrs(nbRep); + std::vector< const DataArrayInt *> grpArrs2(nbRep); + for(int iii=0;iiideepCpy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion); + grpArrs2[iii]=grpArrs[iii]; + } + MEDCouplingAutoRefCountObjectPtr grpArrExt(DataArrayInt::Aggregate(grpArrs2)); + grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end()); + std::ostringstream grpName; grpName << *grp << "_extruded"; + grpArrExt->setName(grpName.str()); + outGrps.push_back(grpArrExt); + outGrps2.push_back(grpArrExt); } - maxVal+=2; } - } - for(std::size_t i=0;isetPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1); - } - _families=families; - _groups=groups; - _groups[grpName]=fams; + ret->setGroupsAtLevel(lev,outGrps2); + } + std::vector< MEDCouplingAutoRefCountObjectPtr > outGrps; + std::vector< const DataArrayInt * > outGrps2; + for(std::vector::const_iterator grp=grps.begin();grp!=grps.end();grp++) + { + MEDCouplingAutoRefCountObjectPtr grpArr1(getGroupArr(levs.back(),*grp)); + if(grpArr1->empty()) + continue; + MEDCouplingAutoRefCountObjectPtr grpArr2(grpArr1->deepCpy()); + std::ostringstream grpName; grpName << *grp << "_top"; + grpArr2->setName(grpName.str()); + grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back())); + outGrps.push_back(grpArr1); outGrps.push_back(grpArr2); + outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2); + } + ret->setGroupsAtLevel(levs.back()-1,outGrps2); + return ret.retn(); } -void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception) +/*! + * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy). + * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance. + * Groups on nodes and families on nodes are copied directly to the returned instance without transformation. + * + * \param [in] conversionType - conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple + * corresponding quadratic cells. 1 is those creating the 'most' complex. + * \param [in] eps - detection threshold for coordinates. + * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance. + * + * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear + */ +MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const { - std::string oldName=getFamilyNameGivenId(id); - _families.erase(oldName); - _families[newFamName]=id; + MEDCouplingAutoRefCountObjectPtr ret(MEDFileUMesh::New()); + int initialNbNodes(getNumberOfNodes()); + MEDCouplingAutoRefCountObjectPtr m0Tmp(getMeshAtLevel(0)); + MEDCouplingAutoRefCountObjectPtr m0(dynamic_cast(m0Tmp->deepCpy())); + { + MEDCouplingAutoRefCountObjectPtr notUsed(m0->convertLinearCellsToQuadratic(conversionType)); + } + DataArrayDouble *zeCoords(m0->getCoords()); + ret->setMeshAtLevel(0,m0); + std::vector levs(getNonEmptyLevels()); + const DataArrayInt *famField(getFamilyFieldAtLevel(0)); + if(famField) + { + MEDCouplingAutoRefCountObjectPtr famFieldCpy(famField->deepCpy()); + ret->setFamilyFieldArr(0,famFieldCpy); + } + famField=getFamilyFieldAtLevel(1); + if(famField) + { + MEDCouplingAutoRefCountObjectPtr fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1); + fam->fillWithZero(); + fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1); + ret->setFamilyFieldArr(1,fam); + } + ret->copyFamGrpMapsFrom(*this); + MEDCouplingAutoRefCountObjectPtr partZeCoords(zeCoords->selectByTupleId2(initialNbNodes,zeCoords->getNumberOfTuples(),1)); + for(std::vector::const_iterator lev=levs.begin();lev!=levs.end();lev++) + { + if(*lev==0) + continue; + MEDCouplingAutoRefCountObjectPtr m1Tmp(getMeshAtLevel(*lev)); + MEDCouplingAutoRefCountObjectPtr m1(dynamic_cast(m1Tmp->deepCpy())); + { + MEDCouplingAutoRefCountObjectPtr notUsed(m1->convertLinearCellsToQuadratic(conversionType)); + } + MEDCouplingAutoRefCountObjectPtr m1Coords(m1->getCoords()->selectByTupleId2(initialNbNodes,m1->getNumberOfNodes(),1)); + DataArrayInt *b(0); + bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b)); + MEDCouplingAutoRefCountObjectPtr bSafe(b); + if(!a) + { + std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + b->applyLin(1,initialNbNodes); + MEDCouplingAutoRefCountObjectPtr l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota(); + std::vector v(2); v[0]=l0; v[1]=b; + MEDCouplingAutoRefCountObjectPtr renum(DataArrayInt::Aggregate(v)); + m1->renumberNodesInConn(renum->begin()); + m1->setCoords(zeCoords); + ret->setMeshAtLevel(*lev,m1); + famField=getFamilyFieldAtLevel(*lev); + if(famField) + { + MEDCouplingAutoRefCountObjectPtr famFieldCpy(famField->deepCpy()); + ret->setFamilyFieldArr(*lev,famFieldCpy); + } + } + return ret.retn(); } -void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception) -{ - std::vector levSet=getNonEmptyLevels(); - std::vector::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax); - if(it==levSet.end()) - throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !"); - int pos=(-meshDimRelToMax); - _ms[pos]=0; +/*! + * This method converts all quadratic cells in \a this into linear cells. + * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance. + * Groups on nodes and families on nodes are copied directly to the returned instance without transformation. + * + * \param [in] eps - detection threshold for coordinates. + * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance. + * + * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic + */ +MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const +{ + MEDCouplingAutoRefCountObjectPtr ret(MEDFileUMesh::New()); + MEDCouplingAutoRefCountObjectPtr m0Tmp(getMeshAtLevel(0)); + MEDCouplingAutoRefCountObjectPtr m0(dynamic_cast(m0Tmp->deepCpy())); + m0->convertQuadraticCellsToLinear(); + m0->zipCoords(); + DataArrayDouble *zeCoords(m0->getCoords()); + ret->setMeshAtLevel(0,m0); + std::vector levs(getNonEmptyLevels()); + const DataArrayInt *famField(getFamilyFieldAtLevel(0)); + if(famField) + { + MEDCouplingAutoRefCountObjectPtr famFieldCpy(famField->deepCpy()); + ret->setFamilyFieldArr(0,famFieldCpy); + } + famField=getFamilyFieldAtLevel(1); + if(famField) + { + MEDCouplingAutoRefCountObjectPtr fam(famField->selectByTupleId2(0,zeCoords->getNumberOfTuples(),1)); + ret->setFamilyFieldArr(1,fam); + } + ret->copyFamGrpMapsFrom(*this); + for(std::vector::const_iterator lev=levs.begin();lev!=levs.end();lev++) + { + if(*lev==0) + continue; + MEDCouplingAutoRefCountObjectPtr m1Tmp(getMeshAtLevel(*lev)); + MEDCouplingAutoRefCountObjectPtr m1(dynamic_cast(m1Tmp->deepCpy())); + m1->convertQuadraticCellsToLinear(); + m1->zipCoords(); + DataArrayInt *b(0); + bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b)); + MEDCouplingAutoRefCountObjectPtr bSafe(b); + if(!a) + { + std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + m1->renumberNodesInConn(b->begin()); + m1->setCoords(zeCoords); + ret->setMeshAtLevel(*lev,m1); + famField=getFamilyFieldAtLevel(*lev); + if(famField) + { + MEDCouplingAutoRefCountObjectPtr famFieldCpy(famField->deepCpy()); + ret->setFamilyFieldArr(*lev,famFieldCpy); + } + } + return ret.retn(); } -void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::serialize(std::vector& tinyDouble, std::vector& tinyInt, std::vector& tinyStr, std::vector< MEDCouplingAutoRefCountObjectPtr >& bigArraysI, MEDCouplingAutoRefCountObjectPtr& bigArrayD) { - setMeshAtLevelGen(meshDimRelToMax,m,newOrOld); + clearNonDiscrAttributes(); + forceComputationOfParts(); + tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0; + std::vector layer0; + layer0.push_back(_order); //0 i + layer0.push_back(_iteration);//1 i + layer0.push_back(getSpaceDimension());//2 i + tinyDouble.push_back(_time);//0 d + tinyStr.push_back(_name);//0 s + tinyStr.push_back(_desc_name);//1 s + for(int i=0;igetInfoOnComponent(i)); + layer0.push_back((int)_families.size());//3 i <- key info aa layer#0 + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + { + tinyStr.push_back((*it).first); + layer0.push_back((*it).second); + } + layer0.push_back((int)_groups.size());//3+aa i <- key info bb layer#0 + for(std::map >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++) + { + layer0.push_back((int)(*it0).second.size()); + tinyStr.push_back((*it0).first); + for(std::vector::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++) + tinyStr.push_back(*it1); + } + // sizeof(layer0)==3+aa+1+bb layer#0 + bigArrayD=_coords;// 0 bd + bigArraysI.push_back(_fam_coords);// 0 bi + bigArraysI.push_back(_num_coords);// 1 bi + const PartDefinition *pd(_part_coords); + if(!pd) + layer0.push_back(-1); + else + { + std::vector tmp0; + pd->serialize(tmp0,bigArraysI); + tinyInt.push_back(tmp0.size()); + tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end()); + } + // + std::vector layer1; + std::vector levs(getNonEmptyLevels()); + layer1.push_back((int)levs.size());// 0 i <- key + layer1.insert(layer1.end(),levs.begin(),levs.end()); + for(std::vector::const_iterator it=levs.begin();it!=levs.end();it++) + { + const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it)); + lev->serialize(layer1,bigArraysI); + } + // put layers all together. + tinyInt.push_back(layer0.size()); + tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end()); + tinyInt.push_back(layer1.size()); + tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end()); } -void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::unserialize(std::vector& tinyDouble, std::vector& tinyInt, std::vector& tinyStr, + std::vector< MEDCouplingAutoRefCountObjectPtr >& bigArraysI, MEDCouplingAutoRefCountObjectPtr& bigArrayD) { - dealWithTinyInfo(m); - std::vector levSet=getNonEmptyLevels(); - if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end()) + int sz0(tinyInt[0]); + std::vector layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0); + int sz1(tinyInt[sz0+1]); + std::vector layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1); + // + std::reverse(layer0.begin(),layer0.end()); + std::reverse(layer1.begin(),layer1.end()); + std::reverse(tinyDouble.begin(),tinyDouble.end()); + std::reverse(tinyStr.begin(),tinyStr.end()); + std::reverse(bigArraysI.begin(),bigArraysI.end()); + // + _order=layer0.back(); layer0.pop_back(); + _iteration=layer0.back(); layer0.pop_back(); + int spaceDim(layer0.back()); layer0.pop_back(); + _time=tinyDouble.back(); tinyDouble.pop_back(); + _name=tinyStr.back(); tinyStr.pop_back(); + _desc_name=tinyStr.back(); tinyStr.pop_back(); + _coords=bigArrayD; _coords->rearrange(spaceDim); + for(int i=0;isetInfoOnComponent(i,tinyStr.back()); + tinyStr.pop_back(); + } + int nbOfFams(layer0.back()); layer0.pop_back(); + _families.clear(); + for(int i=0;i fams(nbOfFamsOnGrp); + for(int j=0;jgetCoords(); - if(c) - c->incrRef(); + fams[j]=tinyStr.back(); tinyStr.pop_back(); + } + _groups[grpName]=fams; + } + _fam_coords=bigArraysI.back(); bigArraysI.pop_back(); + _num_coords=bigArraysI.back(); bigArraysI.pop_back(); + _part_coords=0; + int isPd(layer0.back()); layer0.pop_back(); + if(isPd!=-1) + { + std::vector tmp0(layer0.begin(),layer0.begin()+isPd); + layer0.erase(layer0.begin(),layer0.begin()+isPd); + _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI); + } + if(!layer0.empty()) + throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !"); + // + int nbLevs(layer1.back()); layer1.pop_back(); + std::vector levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end()); + _ms.clear(); + int maxLev(-(*std::min_element(levs.begin(),levs.end()))); + _ms.resize(maxLev+1); + for(int i=0;igetName() == "". + * \throw If \a ids does not respect the MED file norm. + * \throw If a group with name \a ids->getName() already exists. + */ +void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) +{ + const DataArrayDouble *coords(_coords); + if(!coords) + throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !"); + int nbOfNodes(coords->getNumberOfTuples()); + if(!((DataArrayInt *)_fam_coords)) + { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); } + // + addGroupUnderground(true,ids,_fam_coords); +} + +/*! + * Adds a group of nodes/cells/faces/edges to \a this mesh. + * + * \param [in] ids - a DataArrayInt providing ids and a name of the group to add. + * The ids should be sorted and different each other (MED file norm). + * + * \warning this method can alter default "FAMILLE_ZERO" family. + * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session. + * + * \throw If the node coordinates array is not set. + * \throw If \a ids == \c NULL. + * \throw If \a ids->getName() == "". + * \throw If \a ids does not respect the MED file norm. + * \throw If a group with name \a ids->getName() already exists. + */ +void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) +{ + std::vector levs(getNonEmptyLevelsExt()); + if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end()) + { + std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in "; + std::copy(levs.begin(),levs.end(),std::ostream_iterator(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + if(meshDimRelToMaxExt==1) + { addNodeGroup(ids); return ; } + MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt)); + DataArrayInt *fam(lev->getOrCreateAndGetFamilyField()); + addGroupUnderground(false,ids,fam); +} + +/*! + * Changes a name of a family specified by its id. + * \param [in] id - the id of the family of interest. + * \param [in] newFamName - the new family name. + * \throw If no family with the given \a id exists. + */ +void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) +{ + std::string oldName=getFamilyNameGivenId(id); + _families.erase(oldName); + _families[newFamName]=id; +} + +/*! + * Removes a mesh of a given dimension. + * \param [in] meshDimRelToMax - the relative dimension of interest. + * \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh. + */ +void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) +{ + std::vector levSet=getNonEmptyLevels(); + std::vector::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax); + if(it==levSet.end()) + throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !"); + int pos=(-meshDimRelToMax); + _ms[pos]=0; +} + +/*! + * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh. + * \param [in] meshDimRelToMax - a relative level to set the mesh at. + * \param [in] m - the new mesh to set. + * \throw If the name or the description of \a this mesh and \a m are not empty and are + * different. + * \throw If the node coordinates array is set \a this in mesh and \a m refers to + * another node coordinates array. + * \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or + * to the existing meshes of other levels of \a this mesh. + */ +void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m) +{ + MEDCouplingAutoRefCountObjectPtr elt(new MEDFileUMeshSplitL1(m)); + checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt; +} + +/*! + * Sets a new MEDCouplingUMesh at a given level in \a this mesh. + * \param [in] meshDimRelToMax - a relative level to set the mesh at. + * \param [in] m - the new mesh to set. + * \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for + * writing \a this mesh in a MED file. + * \throw If the name or the description of \a this mesh and \a m are not empty and are + * different. + * \throw If the node coordinates array is set \a this in mesh and \a m refers to + * another node coordinates array. + * \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or + * to the existing meshes of other levels of \a this mesh. + */ +void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) +{ + MEDCouplingAutoRefCountObjectPtr elt(new MEDFileUMeshSplitL1(m,newOrOld)); + checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt; +} + +MEDCouplingAutoRefCountObjectPtr& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m) +{ + dealWithTinyInfo(m); + std::vector levSet=getNonEmptyLevels(); + if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end()) + { + if((DataArrayDouble *)_coords==0) + { + DataArrayDouble *c=m->getCoords(); + if(c) + c->incrRef(); _coords=c; } if(m->getCoords()!=_coords) @@ -2609,13 +4371,73 @@ void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, b if(sz>=(int)_ms.size()) _ms.resize(sz); checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax); - _ms[sz-1]=new MEDFileUMeshSplitL1(m,newOrOld); + return _ms[sz-1]; } else - _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld); + return _ms[-meshDimRelToMax]; +} + +/*! + * This method allows to set at once the content of different levels in \a this. + * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel. + * + * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion. + * \param [in] renum - the parameter (set to false by default) that tells the beheviour if there is a mesh on \a ms that is not geo type sorted. + * If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false. + * + * \throw If \a there is a null pointer in \a ms. + * \sa MEDFileUMesh::setMeshAtLevel + */ +void MEDFileUMesh::setMeshes(const std::vector& ms, bool renum) +{ + if(ms.empty()) + return ; + const MEDCouplingUMesh *mRef=ms[0]; + if(!mRef) + throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !"); + std::string name(mRef->getName()); + const DataArrayDouble *coo(mRef->getCoords()); + std::set s; + int zeDim=-1; + for(std::vector::const_iterator it=ms.begin();it!=ms.end();it++) + { + const MEDCouplingUMesh *cur(*it); + if(!cur) + throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !"); + if(coo!=cur->getCoords()) + throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !"); + int mdim=cur->getMeshDimension(); + zeDim=std::max(zeDim,mdim); + if(s.find(mdim)!=s.end()) + throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !"); + } + for(std::vector::const_iterator it=ms.begin();it!=ms.end();it++) + { + int mdim=(*it)->getMeshDimension(); + setName((*it)->getName()); + setMeshAtLevel(mdim-zeDim,const_cast(*it),renum); + } + setName(name); } -void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector& ms) throw(INTERP_KERNEL::Exception) +/*! + * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of + * meshes each representing a group, and creates corresponding groups in \a this mesh. + * The given meshes must share the same node coordinates array. + * \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at. + * \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to + * create in \a this mesh. + * \throw If \a ms is empty. + * \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or + * to the existing meshes of other levels of \a this mesh. + * \throw If the meshes in \a ms do not share the same node coordinates array. + * \throw If the node coordinates array of \a this mesh (if any) is not the same as that + * of the given meshes. + * \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()). + * \throw If names of some meshes in \a ms are equal. + * \throw If \a ms includes a mesh with an empty name. + */ +void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector& ms, bool renum) { if(ms.empty()) throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !"); @@ -2635,12 +4457,31 @@ void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector corr; MEDCouplingAutoRefCountObjectPtr m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr); std::vector< MEDCouplingAutoRefCountObjectPtr > corr3(corr.begin(),corr.end()); - setMeshAtLevel(meshDimRelToMax,m); + setMeshAtLevel(meshDimRelToMax,m,renum); std::vector corr2(corr.begin(),corr.end()); setGroupsAtLevel(meshDimRelToMax,corr2,true); } -void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector& ms, bool renum) throw(INTERP_KERNEL::Exception) +/*! + * Creates groups at a given level in \a this mesh from a sequence of + * meshes each representing a group. + * The given meshes must share the same node coordinates array. + * \param [in] meshDimRelToMax - the relative dimension to create the groups at. + * \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to + * create in \a this mesh. + * \param [in] renum - if \c true, then the optional numbers of entities are taken into + * account. + * \throw If \a ms is empty. + * \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or + * to the existing meshes of other levels of \a this mesh. + * \throw If the meshes in \a ms do not share the same node coordinates array. + * \throw If the node coordinates array of \a this mesh (if any) is not the same as that + * of the given meshes. + * \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()). + * \throw If names of some meshes in \a ms are equal. + * \throw If \a ms includes a mesh with an empty name. + */ +void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector& ms, bool renum) { if(ms.empty()) throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !"); @@ -2675,7 +4516,7 @@ void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector& ms) const throw(INTERP_KERNEL::Exception) +DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector& ms) const { const DataArrayDouble *ret=ms[0]->getCoords(); int mdim=ms[0]->getMeshDimension(); @@ -2690,7 +4531,15 @@ DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector(ret); } -void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception) +/*! + * Sets the family field of a given relative dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of entities for which + * the family field is set. + * \param [in] famArr - the array of the family field. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a famArr has an invalid size. + */ +void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) { if(meshDimRelToMaxExt==1) { @@ -2711,13 +4560,20 @@ void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famAr throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !"); int traducedRk=-meshDimRelToMaxExt; if(traducedRk>=(int)_ms.size()) - throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !"); + throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !"); if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0) throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !"); return _ms[traducedRk]->setFamilyArr(famArr); } -void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception) +/*! + * Sets the optional numbers of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \param [in] renumArr - the array of the numbers. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a renumArr has an invalid size. + */ +void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) { if(meshDimRelToMaxExt==1) { @@ -2740,13 +4596,20 @@ void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumA throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !"); int traducedRk=-meshDimRelToMaxExt; if(traducedRk>=(int)_ms.size()) - throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !"); + throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !"); if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0) throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !"); return _ms[traducedRk]->setRenumArr(renumArr); } -void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception) +/*! + * Sets the optional names of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \param [in] nameArr - the array of the names. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a nameArr has an invalid size. + */ +void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) { if(meshDimRelToMaxExt==1) { @@ -2757,17 +4620,17 @@ void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiCha } DataArrayDouble *coo(_coords); if(!coo) - throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !"); - nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! "); + throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !"); + nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! "); nameArr->incrRef(); _name_coords=nameArr; return ; } if(meshDimRelToMaxExt>1) - throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !"); + throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !"); int traducedRk=-meshDimRelToMaxExt; if(traducedRk>=(int)_ms.size()) - throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !"); + throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !"); if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0) throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !"); return _ms[traducedRk]->setNameArr(nameArr); @@ -2783,7 +4646,7 @@ void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const /*! * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification. */ -void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) { DataArrayInt *arr=_fam_coords; if(arr) @@ -2827,25 +4690,51 @@ void MEDFileUMesh::computeRevNum() const } } -std::size_t MEDFileStructuredMesh::getHeapMemorySize() const +std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const { - std::size_t ret=MEDFileMesh::getHeapMemorySize(); - if((const DataArrayInt*)_fam_nodes) - ret+=_fam_nodes->getHeapMemorySize(); - if((const DataArrayInt*)_num_nodes) - ret+=_num_nodes->getHeapMemorySize(); - if((const DataArrayInt*)_fam_cells) - ret+=_fam_cells->getHeapMemorySize(); - if((const DataArrayInt*)_num_cells) - ret+=_num_cells->getHeapMemorySize(); - if((const DataArrayInt*)_rev_num_nodes) - ret+=_rev_num_nodes->getHeapMemorySize(); - if((const DataArrayInt*)_rev_num_cells) - ret+=_rev_num_cells->getHeapMemorySize(); + return MEDFileMesh::getHeapMemorySizeWithoutChildren(); +} + +std::vector MEDFileStructuredMesh::getDirectChildrenWithNull() const +{ + std::vector ret(MEDFileMesh::getDirectChildrenWithNull()); + ret.push_back((const DataArrayInt *)_fam_nodes); + ret.push_back((const DataArrayInt *)_num_nodes); + ret.push_back((const DataArrayAsciiChar *)_names_nodes); + ret.push_back((const DataArrayInt *)_fam_cells); + ret.push_back((const DataArrayInt *)_num_cells); + ret.push_back((const DataArrayAsciiChar *)_names_cells); + ret.push_back((const DataArrayInt *)_fam_faces); + ret.push_back((const DataArrayInt *)_num_faces); + ret.push_back((const DataArrayInt *)_rev_num_nodes); + ret.push_back((const DataArrayAsciiChar *)_names_faces); + ret.push_back((const DataArrayInt *)_rev_num_cells); + ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary); + return ret; +} + +int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const +{ + int ret=-std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_nodes) + { + int val=_fam_nodes->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + if((const DataArrayInt *)_fam_cells) + { + int val=_fam_cells->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + if((const DataArrayInt *)_fam_faces) + { + int val=_fam_faces->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } return ret; } -int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) +int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const { int ret=-std::numeric_limits::max(),tmp=-1; if((const DataArrayInt *)_fam_nodes) @@ -2858,10 +4747,15 @@ int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::E int val=_fam_cells->getMaxValue(tmp); ret=std::max(ret,val); } + if((const DataArrayInt *)_fam_faces) + { + int val=_fam_faces->getMaxValue(tmp); + ret=std::max(ret,val); + } return ret; } -int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) +int MEDFileStructuredMesh::getMinFamilyIdInArrays() const { int ret=std::numeric_limits::max(),tmp=-1; if((const DataArrayInt *)_fam_nodes) @@ -2874,6 +4768,11 @@ int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::E int val=_fam_cells->getMinValue(tmp); ret=std::min(ret,val); } + if((const DataArrayInt *)_fam_faces) + { + int val=_fam_faces->getMinValue(tmp); + ret=std::min(ret,val); + } return ret; } @@ -2919,6 +4818,22 @@ bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::s return false; } } + famc1=_fam_faces; + famc2=otherC->_fam_faces; + if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0)) + { + what="Mismatch of families arr on faces ! One is defined and not other !"; + return false; + } + if(famc1) + { + bool ret=famc1->isEqual(*famc2); + if(!ret) + { + what="Families arr on faces differ !"; + return false; + } + } famc1=_num_nodes; famc2=otherC->_num_nodes; if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0)) @@ -2951,6 +4866,22 @@ bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::s return false; } } + famc1=_num_faces; + famc2=otherC->_num_faces; + if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0)) + { + what="Mismatch of numbering arr on faces ! One is defined and not other !"; + return false; + } + if(famc1) + { + bool ret=famc1->isEqual(*famc2); + if(!ret) + { + what="Numbering arr on faces differ !"; + return false; + } + } const DataArrayAsciiChar *d1=_names_cells; const DataArrayAsciiChar *d2=otherC->_names_cells; if((d1==0 && d2!=0) || (d1!=0 && d2==0)) @@ -2967,6 +4898,22 @@ bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::s return false; } } + d1=_names_faces; + d2=otherC->_names_faces; + if((d1==0 && d2!=0) || (d1!=0 && d2==0)) + { + what="Mismatch of naming arr on faces ! One is defined and not other !"; + return false; + } + if(d1) + { + bool ret=d1->isEqual(*d2); + if(!ret) + { + what="Naming arr on faces differ !"; + return false; + } + } d1=_names_nodes; d2=otherC->_names_nodes; if((d1==0 && d2!=0) || (d1!=0 && d2==0)) @@ -3001,139 +4948,336 @@ void MEDFileStructuredMesh::clearNonDiscrAttributes() const tmp=_num_cells; if(tmp) (const_cast(tmp))->setName(""); + tmp=_fam_faces; + if(tmp) + (const_cast(tmp))->setName(""); + tmp=_num_faces; + if(tmp) + (const_cast(tmp))->setName(""); } -DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * Returns ids of mesh entities contained in given families of a given dimension. + * \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids + * are required. + * \param [in] fams - the names of the families of interest. + * \param [in] renum - if \c true, the optional numbers of entities, if available, are + * returned instead of ids. + * \return DataArrayInt * - a new instance of DataArrayInt holding either ids or + * numbers, if available and required, of mesh entities of the families. The caller + * is to delete this array using decrRef() as it is no more needed. + * \throw If the family field is missing for \a meshDimRelToMaxExt. + */ +DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !"); - std::vector famIds=getFamiliesIds(fams); - if(meshDimRelToMaxExt==1) - { - if((const DataArrayInt *)_fam_nodes) - { - MEDCouplingAutoRefCountObjectPtr da; - if(!famIds.empty()) - da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size()); - else - da=_fam_nodes->getIdsEqualList(0,0); - if(renum) - return MEDFileUMeshSplitL1::Renumber(_num_nodes,da); - else - return da.retn(); - } - else - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !"); - } - else - { - if((const DataArrayInt *)_fam_cells) - { - MEDCouplingAutoRefCountObjectPtr da; - if(!famIds.empty()) - da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size()); - else - da=_fam_cells->getIdsEqualList(0,0); - if(renum) - return MEDFileUMeshSplitL1::Renumber(_num_cells,da); - else - return da.retn(); - } - else - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !"); - } + std::vector famIds(getFamiliesIds(fams)); + switch(meshDimRelToMaxExt) + { + case 1: + { + if((const DataArrayInt *)_fam_nodes) + { + MEDCouplingAutoRefCountObjectPtr da; + if(!famIds.empty()) + da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size()); + else + da=_fam_nodes->getIdsEqualList(0,0); + if(renum) + return MEDFileUMeshSplitL1::Renumber(_num_nodes,da); + else + return da.retn(); + } + else + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !"); + break; + } + case 0: + { + if((const DataArrayInt *)_fam_cells) + { + MEDCouplingAutoRefCountObjectPtr da; + if(!famIds.empty()) + da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size()); + else + da=_fam_cells->getIdsEqualList(0,0); + if(renum) + return MEDFileUMeshSplitL1::Renumber(_num_cells,da); + else + return da.retn(); + } + else + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !"); + break; + } + case -1: + { + if((const DataArrayInt *)_fam_faces) + { + MEDCouplingAutoRefCountObjectPtr da; + if(!famIds.empty()) + da=_fam_faces->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size()); + else + da=_fam_faces->getIdsEqualList(0,0); + if(renum) + return MEDFileUMeshSplitL1::Renumber(_num_faces,da); + else + return da.retn(); + } + else + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !"); + break; + } + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !"); + } + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !"); } -void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception) +/*! + * Sets the family field of a given relative dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of entities for which + * the family field is set. + * \param [in] famArr - the array of the family field. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a famArr has an invalid size. + * \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1. + */ +void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !"); - const MEDCouplingStructuredMesh *mesh=getStructuredMesh(); + const MEDCouplingStructuredMesh *mesh(getStructuredMesh()); if(!mesh) throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !"); - if(meshDimRelToMaxExt==0) - { - int nbCells=mesh->getNumberOfCells(); - famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !"); - _fam_cells=famArr; - } - else - { - int nbNodes=mesh->getNumberOfNodes(); - famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !"); - _fam_nodes=famArr; - } + switch(meshDimRelToMaxExt) + { + case 0: + { + int nbCells=mesh->getNumberOfCells(); + famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !"); + _fam_cells=famArr; + break; + } + case 1: + { + int nbNodes=mesh->getNumberOfNodes(); + famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !"); + _fam_nodes=famArr; + break; + } + case -1: + { + int nbCells=mesh->getNumberOfCellsOfSubLevelMesh(); + famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !"); + _fam_faces=famArr; + break; + } + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !"); + } if(famArr) famArr->incrRef(); } -void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception) +/*! + * Sets the optional numbers of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \param [in] renumArr - the array of the numbers. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a renumArr has an invalid size. + * \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1. + */ +void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !"); const MEDCouplingStructuredMesh *mesh=getStructuredMesh(); if(!mesh) throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !"); - if(meshDimRelToMaxExt==0) - { - int nbCells=mesh->getNumberOfCells(); - renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !"); - _num_cells=renumArr; - } - else - { - int nbNodes=mesh->getNumberOfNodes(); - renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !"); - _num_nodes=renumArr; - } + switch(meshDimRelToMaxExt) + { + case 0: + { + int nbCells=mesh->getNumberOfCells(); + renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !"); + _num_cells=renumArr; + break; + } + case 1: + { + int nbNodes=mesh->getNumberOfNodes(); + renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !"); + _num_nodes=renumArr; + break; + } + case -1: + { + int nbCells=mesh->getNumberOfCellsOfSubLevelMesh(); + renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !"); + _num_faces=renumArr; + break; + } + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !"); + } if(renumArr) renumArr->incrRef(); } -void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception) +/*! + * Sets the optional names of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \param [in] nameArr - the array of the names. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a nameArr has an invalid size. + */ +void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !"); - const MEDCouplingStructuredMesh *mesh=getStructuredMesh(); + const MEDCouplingStructuredMesh *mesh(getStructuredMesh()); if(!mesh) throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !"); - if(meshDimRelToMaxExt==0) - { - int nbCells=mesh->getNumberOfCells(); - nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !"); - _names_cells=nameArr; - } - else - { - int nbNodes=mesh->getNumberOfNodes(); - nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !"); - _names_nodes=nameArr; - } + switch(meshDimRelToMaxExt) + { + case 0: + { + int nbCells=mesh->getNumberOfCells(); + nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !"); + _names_cells=nameArr; + break; + } + case 1: + { + int nbNodes=mesh->getNumberOfNodes(); + nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !"); + _names_nodes=nameArr; + break; + } + case -1: + { + int nbCells=mesh->getNumberOfCellsOfSubLevelMesh(); + nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !"); + _names_cells=nameArr; + } + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !"); + } if(nameArr) nameArr->incrRef(); } -const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * Adds a group of nodes to \a this mesh. + * \param [in] ids - a DataArrayInt providing ids and a name of the group to add. + * The ids should be sorted and different each other (MED file norm). + * + * \warning this method can alter default "FAMILLE_ZERO" family. + * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session. + * + * \throw If the node coordinates array is not set. + * \throw If \a ids == \c NULL. + * \throw If \a ids->getName() == "". + * \throw If \a ids does not respect the MED file norm. + * \throw If a group with name \a ids->getName() already exists. + */ +void MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids) { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !"); - if(meshDimRelToMaxExt==0) - return _fam_cells; - else - return _fam_nodes; + addGroup(1,ids); } -const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * Adds a group of nodes/cells/faces/edges to \a this mesh. + * + * \param [in] ids - a DataArrayInt providing ids and a name of the group to add. + * The ids should be sorted and different each other (MED file norm). + * + * \warning this method can alter default "FAMILLE_ZERO" family. + * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session. + * + * \throw If the node coordinates array is not set. + * \throw If \a ids == \c NULL. + * \throw If \a ids->getName() == "". + * \throw If \a ids does not respect the MED file norm. + * \throw If a group with name \a ids->getName() already exists. + */ +void MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !"); - if(meshDimRelToMaxExt==0) - return _num_cells; - else - return _num_nodes; + DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt)); + addGroupUnderground(false,ids,fam); + return ; +} + +/*! + * Returns the family field for mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the family field. It is an array of ids of families + * each mesh entity belongs to. It can be \c NULL. + * \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1. + */ +const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const +{ + switch(meshDimRelToMaxExt) + { + case 0: + return _fam_cells; + case 1: + return _fam_nodes; + case -1: + return _fam_faces; + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !"); + } +} + +/*! + * Returns the family field for mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the family field. It is an array of ids of families + * each mesh entity belongs to. It can be \c NULL. + * \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1. + */ +DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) +{ + switch(meshDimRelToMaxExt) + { + case 0: + return _fam_cells; + case 1: + return _fam_nodes; + case -1: + return _fam_faces; + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !"); + } +} + +/*! + * Returns the optional numbers of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the array of the entity numbers. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1. + */ +const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const +{ + switch(meshDimRelToMaxExt) + { + case 0: + return _num_cells; + case 1: + return _num_nodes; + case -1: + return _num_faces; + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !"); + } } -const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * Returns the optional numbers of mesh entities of a given dimension transformed using + * DataArrayInt::invertArrayN2O2O2N(). + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the array of the entity numbers transformed using + * DataArrayInt::invertArrayN2O2O2N(). + * \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ +const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !"); @@ -3163,39 +5307,100 @@ const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimR } } -const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !"); - if(meshDimRelToMaxExt==0) - return _names_cells; - else - return _names_nodes; + switch(meshDimRelToMaxExt) + { + case 0: + return _names_cells; + case 1: + return _names_nodes; + case -1: + return _names_faces; + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !"); + } } +/*! + * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh. + * \return std::vector - a sequence of the relative dimensions: [0]. + */ std::vector MEDFileStructuredMesh::getNonEmptyLevels() const { - std::vector ret(1); + std::vector ret(1); + return ret; +} + +/*! + * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh. + * \return std::vector - a sequence of the relative dimensions: [1,0]. + */ +std::vector MEDFileStructuredMesh::getNonEmptyLevelsExt() const +{ + std::vector ret(2); + ret[0]=1; + return ret; +} + +/*! + * Returns the set of extensive levels (nodes included) where not NULL family arr are defined. + */ +std::vector MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells),*famFaces(_fam_faces); + if(famNodes) + ret.push_back(1); + if(famCells) + ret.push_back(0); + if(famFaces) + ret.push_back(-1); + return ret; +} + +/*! + * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined. + */ +std::vector MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const +{ + std::vector ret; + const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells),*numFaces(_num_faces); + if(numNodes) + ret.push_back(1); + if(numCells) + ret.push_back(0); + if(numFaces) + ret.push_back(-1); return ret; } -std::vector MEDFileStructuredMesh::getNonEmptyLevelsExt() const +/*! + * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined. + */ +std::vector MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const { - std::vector ret(2); - ret[0]=1; + std::vector ret; + const DataArrayAsciiChar *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces); + if(namesNodes) + ret.push_back(1); + if(namesCells) + ret.push_back(0); + if(namesFaces) + ret.push_back(-1); return ret; } /*! * no implementation here, it is not a bug, but intresically no polyhedra in \a this. */ -bool MEDFileStructuredMesh::unPolyze(std::vector& oldCode, std::vector& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception) +bool MEDFileStructuredMesh::unPolyze(std::vector& oldCode, std::vector& newCode, DataArrayInt *& o2nRenumCell) { oldCode.clear(); newCode.clear(); o2nRenumCell=0; return false; } -void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception) +void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) { DataArrayInt *arr=_fam_nodes; if(arr) @@ -3203,18 +5408,46 @@ void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP arr=_fam_cells; if(arr) arr->changeValue(oldId,newId); + arr=_fam_faces; + if(arr) + arr->changeValue(oldId,newId); +} + +std::list< MEDCouplingAutoRefCountObjectPtr > MEDFileStructuredMesh::getAllNonNullFamilyIds() const +{ + std::list< MEDCouplingAutoRefCountObjectPtr > ret; + const DataArrayInt *da(_fam_nodes); + if(da) + { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr(const_cast(da))); } + da=_fam_cells; + if(da) + { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr(const_cast(da))); } + da=_fam_faces; + if(da) + { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr(const_cast(da))); } + return ret; } -void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception) +void MEDFileStructuredMesh::deepCpyAttributes() { if((const DataArrayInt*)_fam_nodes) _fam_nodes=_fam_nodes->deepCpy(); if((const DataArrayInt*)_num_nodes) _num_nodes=_num_nodes->deepCpy(); + if((const DataArrayAsciiChar*)_names_nodes) + _names_nodes=_names_nodes->deepCpy(); if((const DataArrayInt*)_fam_cells) _fam_cells=_fam_cells->deepCpy(); if((const DataArrayInt*)_num_cells) _num_cells=_num_cells->deepCpy(); + if((const DataArrayAsciiChar*)_names_cells) + _names_cells=_names_cells->deepCpy(); + if((const DataArrayInt*)_fam_faces) + _fam_faces=_fam_faces->deepCpy(); + if((const DataArrayInt*)_num_faces) + _num_faces=_num_faces->deepCpy(); + if((const DataArrayAsciiChar*)_names_faces) + _names_faces=_names_faces->deepCpy(); if((const DataArrayInt*)_rev_num_nodes) _rev_num_nodes=_rev_num_nodes->deepCpy(); if((const DataArrayInt*)_rev_num_cells) @@ -3227,133 +5460,317 @@ void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception) * \return a pointer to cartesian mesh that need to be managed by the caller. * \warning the returned pointer has to be managed by the caller. */ -MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception) + +/*! + * Returns a pointer to MEDCouplingStructuredMesh held by \a this. + * \param [in] meshDimRelToMax - it must be \c 0 or \c -1. + * \param [in] renum - it must be \c false. + * \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to + * delete using decrRef() as it is no more needed. + */ +MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const { if(renum) throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !"); - if(meshDimRelToMax!=0) - throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !"); - const MEDCouplingStructuredMesh *m=getStructuredMesh(); - if(m) - m->incrRef(); - return const_cast(m); + const MEDCouplingStructuredMesh *m(getStructuredMesh()); + switch(meshDimRelToMax) + { + case 0: + { + if(m) + m->incrRef(); + return const_cast(m); + } + case -1: + { + if(!m) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGenMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !"); + buildMinusOneImplicitPartIfNeeded(); + MEDCouplingMesh *ret(_faces_if_necessary); + if(ret) + ret->incrRef(); + return ret; + } + default: + throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !"); + } } -int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * Returns number of mesh entities of a given relative dimension in \a this mesh. + * \param [in] meshDimRelToMaxExt - the relative dimension of interest. + * \return int - the number of entities. + * \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh. + */ +int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !"); - const MEDCouplingStructuredMesh *cmesh=getStructuredMesh(); + const MEDCouplingStructuredMesh *cmesh(getStructuredMesh()); if(!cmesh) throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !"); - if(meshDimRelToMaxExt==0) - return cmesh->getNumberOfCells(); - else - return cmesh->getNumberOfNodes(); + switch(meshDimRelToMaxExt) + { + case 0: + return cmesh->getNumberOfCells(); + case 1: + return cmesh->getNumberOfNodes(); + case -1: + return cmesh->getNumberOfCellsOfSubLevelMesh(); + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !"); + } } -int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) +int MEDFileStructuredMesh::getNumberOfNodes() const { - const MEDCouplingStructuredMesh *cmesh=getStructuredMesh(); + const MEDCouplingStructuredMesh *cmesh(getStructuredMesh()); if(!cmesh) throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !"); return cmesh->getNumberOfNodes(); } -med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception) +int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const +{ + const MEDCouplingStructuredMesh *cmesh(getStructuredMesh()); + if(!cmesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !"); + switch(meshDimRelToMaxExt) + { + case 0: + return cmesh->getNumberOfCells(); + case -1: + return cmesh->getNumberOfCellsOfSubLevelMesh(); + default: + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !"); + } +} + +bool MEDFileStructuredMesh::hasImplicitPart() const +{ + return true; +} + +/*! + * \sa MEDFileStructuredMesh::getImplicitFaceMesh + */ +int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const { - med_geometry_type geoTypeReq=MED_NONE; - switch(meshDim) + static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !"; + const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary); + if(!zeFaceMesh) { - case 3: - geoTypeReq=MED_HEXA8; - break; - case 2: - geoTypeReq=MED_QUAD4; - break; - case 1: - geoTypeReq=MED_SEG2; - break; + const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))); + if(cm.getReverseExtrudedType()!=gt) + throw INTERP_KERNEL::Exception(MSG); + buildImplicitPart(); + return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh(); + } + else + { + if(gt!=zeFaceMesh->getCellModelEnum()) + throw INTERP_KERNEL::Exception(MSG); + return zeFaceMesh->getNumberOfCells(); + } +} + +void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const +{ + const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary); + if(!zeFaceMesh) + buildImplicitPart(); +} + +void MEDFileStructuredMesh::buildImplicitPart() const +{ + const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh()); + if(!mcmesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !"); + _faces_if_necessary=mcmesh->build1SGTSubLevelMesh(); +} + +void MEDFileStructuredMesh::releaseImplicitPartIfAny() const +{ + _faces_if_necessary=0; +} + +/*! + * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any. + * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method. + * + * \sa MEDFileStructuredMesh::buildImplicitPartIfAny + */ +MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const +{ + return _faces_if_necessary; +} + +std::vector MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const +{ + const MEDCouplingStructuredMesh *cmesh(getStructuredMesh()); + if(!cmesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !"); + switch(meshDimRelToMax) + { case 0: - geoTypeReq=MED_POINT1; - break; + { + std::vector ret(1,cmesh->getTypeOfCell(0)); + return ret; + } + case -1: + { + int mdim(cmesh->getMeshDimension()); + if(mdim<1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !"); + std::vector ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1)); + return ret; + } default: - throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !"); + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !"); + } +} + +void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector& nodesFetched) const +{ + if(st.getNumberOfItems()!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on single geo type ! it is not managed yet for structured mesh !"); + if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !"); + if(getNumberOfNodes()!=(int)nodesFetched.size()) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !"); + if(st[0].getPflName().empty()) + { + std::fill(nodesFetched.begin(),nodesFetched.end(),true); + return ; + } + const DataArrayInt *arr(globs->getProfile(st[0].getPflName())); + const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before + int sz(nodesFetched.size()); + for(const int *work=arr->begin();work!=arr->end();work++) + { + std::vector conn; + cmesh->getNodeIdsOfCell(*work,conn); + for(std::vector::const_iterator it=conn.begin();it!=conn.end();it++) + if(*it>=0 && *it& famCells, MEDCouplingAutoRefCountObjectPtr& numCells, MEDCouplingAutoRefCountObjectPtr& namesCells) { - setName(strm->getName()); - setDescription(strm->getDescription()); - setIteration(strm->getIteration()); - setOrder(strm->getOrder()); - setTimeValue(strm->getTime()); - setTimeUnit(strm->getTimeUnit()); - MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups); med_bool chgt=MED_FALSE,trsf=MED_FALSE; - int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf); + med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim); + int nbOfElt(0); + nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf); if(nbOfElt>0) { - _fam_nodes=DataArrayInt::New(); - _fam_nodes->alloc(nbOfElt,1); - MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()); + if(!mrs || mrs->isCellFamilyFieldReading()) + { + famCells=DataArrayInt::New(); + famCells->alloc(nbOfElt,1); + MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer())); + } } - nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf); + nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf); if(nbOfElt>0) { - _num_nodes=DataArrayInt::New(); - _num_nodes->alloc(nbOfElt,1); - MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()); + if(!mrs || mrs->isCellNumFieldReading()) + { + numCells=DataArrayInt::New(); + numCells->alloc(nbOfElt,1); + MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer())); + } } - int meshDim=getStructuredMesh()->getMeshDimension(); - med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim); - nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf); + nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf); if(nbOfElt>0) { - _fam_cells=DataArrayInt::New(); - _fam_cells->alloc(nbOfElt,1); - MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer()); + if(!mrs || mrs->isCellNameFieldReading()) + { + namesCells=DataArrayAsciiChar::New(); + namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end + MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer())); + namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end + } } - nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf); +} + +void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + setName(strm->getName()); + setDescription(strm->getDescription()); + setUnivName(strm->getUnivName()); + setIteration(strm->getIteration()); + setOrder(strm->getOrder()); + setTimeValue(strm->getTime()); + setTimeUnit(strm->getTimeUnit()); + MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs); + med_bool chgt=MED_FALSE,trsf=MED_FALSE; + int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf)); if(nbOfElt>0) { - _num_cells=DataArrayInt::New(); - _num_cells->alloc(nbOfElt,1); - MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer()); + if(!mrs || mrs->isNodeFamilyFieldReading()) + { + int nbNodes(getNumberOfNodes()); + if(nbOfElt>nbNodes) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !"); + _fam_nodes=DataArrayInt::New(); + _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line. + if(nbNodes>nbOfElt)//yes it appends some times... It explains surely the mdump implementation. Bug revealed by PARAVIS EDF #2475 on structured.med file where only 12 first nodes are !=0 so nbOfElt=12 and nbOfNodes=378... + _fam_nodes->fillWithZero(); + MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer())); + } } - nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf); + nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf); if(nbOfElt>0) { - _names_cells=DataArrayAsciiChar::New(); - _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end - MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer()); - _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end + if(!mrs || mrs->isNodeNumFieldReading()) + { + _num_nodes=DataArrayInt::New(); + _num_nodes->alloc(nbOfElt,1); + MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer())); + } } - nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf); + nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf); if(nbOfElt>0) { - _names_nodes=DataArrayAsciiChar::New(); - _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end - MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer()); - _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end + if(!mrs || mrs->isNodeNameFieldReading()) + { + _names_nodes=DataArrayAsciiChar::New(); + _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end + MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer())); + _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end + } } + int meshDim(getStructuredMesh()->getMeshDimension()); + LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells); + if(meshDim>=1) + LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces); } -void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception) +void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const { - int meshDim=getStructuredMesh()->getMeshDimension(); - med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim); + int meshDim(getStructuredMesh()->getMeshDimension()); + med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1)); // if((const DataArrayInt *)_fam_cells) - MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()); + MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer())); + if((const DataArrayInt *)_fam_faces) + MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer())); if((const DataArrayInt *)_fam_nodes) - MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()); + MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer())); if((const DataArrayInt *)_num_cells) - MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()); + MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer())); + if((const DataArrayInt *)_num_faces) + MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer())); if((const DataArrayInt *)_num_nodes) - MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()); + MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer())); if((const DataArrayAsciiChar *)_names_cells) { if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE) @@ -3362,7 +5779,17 @@ void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) cons oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()); + MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer())); + } + if((const DataArrayAsciiChar *)_names_faces) + { + if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE) + { + std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE; + oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer())); } if((const DataArrayAsciiChar *)_names_nodes) { @@ -3372,18 +5799,33 @@ void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) cons oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); } - MEDmeshEntityNameWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()); + MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer())); } // - MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str); + MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str); } +/*! + * Returns an empty instance of MEDFileCMesh. + * \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + */ MEDFileCMesh *MEDFileCMesh::New() { return new MEDFileCMesh; } -MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED + * file. The first mesh in the file is loaded. + * \param [in] fileName - the name of MED file to read. + * \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + * \throw If the file is not readable. + * \throw If there is no meshes in the file. + * \throw If the mesh in the file is not a Cartesian one. + */ +MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs) { std::vector ms=MEDLoader::GetMeshNames(fileName); if(ms.empty()) @@ -3392,53 +5834,101 @@ MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep throw INTERP_KERNEL::Exception(oss.str().c_str()); } MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); int dt,it; ParaMEDMEM::MEDCouplingMeshType meshType; std::string dummy2; - MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2); - return new MEDFileCMesh(fid,ms.front().c_str(),dt,it); + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2); + return new MEDFileCMesh(fid,ms.front(),dt,it,mrs); } -MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +/*! + * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED + * file. The mesh to load is specified by its name and numbers of a time step and an + * iteration. + * \param [in] fileName - the name of MED file to read. + * \param [in] mName - the name of the mesh to read. + * \param [in] dt - the number of a time step. + * \param [in] it - the number of an iteration. + * \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + * \throw If the file is not readable. + * \throw If there is no mesh with given attributes in the file. + * \throw If the mesh in the file is not a Cartesian one. + */ +MEDFileCMesh *MEDFileCMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - return new MEDFileCMesh(fid,mName,dt,it); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); + return new MEDFileCMesh(fid,mName,dt,it,mrs); +} + +std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const +{ + return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren(); } -std::size_t MEDFileCMesh::getHeapMemorySize() const +std::vector MEDFileCMesh::getDirectChildrenWithNull() const { - std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize(); - if((const MEDCouplingCMesh *)_cmesh) - ret+=_cmesh->getHeapMemorySize(); + std::vector ret(MEDFileStructuredMesh::getDirectChildrenWithNull()); + ret.push_back((const MEDCouplingCMesh *)_cmesh); return ret; } -int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) +/*! + * Returns the dimension on cells in \a this mesh. + * \return int - the mesh dimension. + * \throw If there are no cells in this mesh. + */ +int MEDFileCMesh::getMeshDimension() const { if(!((const MEDCouplingCMesh*)_cmesh)) throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !"); return _cmesh->getMeshDimension(); } +/*! + * Returns the dimension on nodes in \a this mesh. + * \return int - the space dimension. + * \throw If there are no cells in this mesh. + */ +int MEDFileCMesh::getSpaceDimension() const +{ + if(!((const MEDCouplingCMesh*)_cmesh)) + throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !"); + return _cmesh->getSpaceDimension(); +} + +/*! + * Returns a string describing \a this mesh. + * \return std::string - the mesh information string. + */ std::string MEDFileCMesh::simpleRepr() const { return MEDFileStructuredMesh::simpleRepr(); } +/*! + * Returns a full textual description of \a this mesh. + * \return std::string - the string holding the mesh description. + */ std::string MEDFileCMesh::advancedRepr() const { return simpleRepr(); } -MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileCMesh::shallowCpy() const { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCMesh(*this); return ret.retn(); } -MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileCMesh::createNewEmpty() const +{ + return new MEDFileCMesh; +} + +MEDFileMesh *MEDFileCMesh::deepCpy() const { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCMesh(*this); if((const MEDCouplingCMesh*)_cmesh) @@ -3447,6 +5937,13 @@ MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception) return ret.retn(); } +/*! + * Checks if \a this and another mesh are equal. + * \param [in] other - the mesh to compare with. + * \param [in] eps - a precision used to compare real values. + * \param [in,out] what - the string returning description of unequal data. + * \return bool - \c true if the meshes are equal, \c false, else. + */ bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const { if(!MEDFileStructuredMesh::isEqual(other,eps,what)) @@ -3478,6 +5975,9 @@ bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh return true; } +/*! + * Clears redundant attributes of incorporated data arrays. + */ void MEDFileCMesh::clearNonDiscrAttributes() const { MEDFileStructuredMesh::clearNonDiscrAttributes(); @@ -3488,17 +5988,18 @@ MEDFileCMesh::MEDFileCMesh() { } -MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) try - { - loadCMeshFromFile(fid,mName,dt,it); - } +{ + loadCMeshFromFile(fid,mName,dt,it,mrs); + loadJointsFromFile(fid); +} catch(INTERP_KERNEL::Exception& e) - { +{ throw e; - } +} -void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { ParaMEDMEM::MEDCouplingMeshType meshType; int dummy0,dummy1; @@ -3514,9 +6015,13 @@ void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int MEDCouplingCMesh *mesh=loaderl2.getMesh(); mesh->incrRef(); _cmesh=mesh; - loadStrMeshFromFile(&loaderl2,fid,mName,dt,it); + loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs); } +/*! + * Returns a const pointer to MEDCouplingCMesh held by \a this mesh. + * \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh. + */ const MEDCouplingCMesh *MEDFileCMesh::getMesh() const { synchronizeTinyInfoOnLeaves(); @@ -3529,7 +6034,13 @@ const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const return _cmesh; } -void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception) +/*! + * Sets the MEDCouplingCMesh holding the data of \a this mesh. + * \param [in] m - the new MEDCouplingCMesh to refer to. + * \throw If the name or the description of \a this mesh and \a m are not empty and are + * different. + */ +void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) { dealWithTinyInfo(m); if(m) @@ -3537,7 +6048,7 @@ void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception) _cmesh=m; } -void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileCMesh::writeLL(med_idt fid) const { INTERP_KERNEL::AutoPtr maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE); @@ -3545,8 +6056,7 @@ void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str); MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str); MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str); - int spaceDim=_cmesh->getSpaceDimension(); - int meshDim=_cmesh->getMeshDimension(); + int spaceDim(_cmesh->getSpaceDimension()); INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE); INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE); for(int i=0;igetCoordsAt(i); - MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()); + MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer())); } // - MEDFileStructuredMesh::writeStructuredLL(fid,maa); + std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE)); + MEDFileStructuredMesh::writeStructuredLL(fid,meshName); + + writeJoints(fid); } void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const @@ -3573,10 +6087,10 @@ void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const const MEDCouplingCMesh *cmesh=_cmesh; if(!cmesh) return; - (const_cast(cmesh))->setName(_name.c_str()); - (const_cast(cmesh))->setDescription(_desc_name.c_str()); + (const_cast(cmesh))->setName(_name); + (const_cast(cmesh))->setDescription(_desc_name); (const_cast(cmesh))->setTime(_time,_iteration,_order); - (const_cast(cmesh))->setTimeUnit(_dt_unit.c_str()); + (const_cast(cmesh))->setTimeUnit(_dt_unit); } MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New() @@ -3584,7 +6098,7 @@ MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New() return new MEDFileCurveLinearMesh; } -MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs) { std::vector ms=MEDLoader::GetMeshNames(fileName); if(ms.empty()) @@ -3593,36 +6107,45 @@ MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw( throw INTERP_KERNEL::Exception(oss.str().c_str()); } MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); int dt,it; ParaMEDMEM::MEDCouplingMeshType meshType; std::string dummy2; - MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2); - return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it); + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2); + return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs); } -MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - return new MEDFileCurveLinearMesh(fid,mName,dt,it); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); + return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs); +} + +std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const +{ + return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren(); } -std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const +std::vector MEDFileCurveLinearMesh::getDirectChildrenWithNull() const { - std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize(); - if((const MEDCouplingCurveLinearMesh *)_clmesh) - ret+=_clmesh->getHeapMemorySize(); + std::vector ret(MEDFileStructuredMesh::getDirectChildrenWithNull()); + ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh); return ret; } -MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCurveLinearMesh(*this); return ret.retn(); } -MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const +{ + return new MEDFileCurveLinearMesh; +} + +MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const { MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCurveLinearMesh(*this); if((const MEDCouplingCurveLinearMesh*)_clmesh) @@ -3631,7 +6154,7 @@ MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Except return ret.retn(); } -int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) +int MEDFileCurveLinearMesh::getMeshDimension() const { if(!((const MEDCouplingCurveLinearMesh*)_clmesh)) throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !"); @@ -3690,10 +6213,10 @@ void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const const MEDCouplingCurveLinearMesh *clmesh=_clmesh; if(!clmesh) return; - (const_cast(clmesh))->setName(_name.c_str()); - (const_cast(clmesh))->setDescription(_desc_name.c_str()); + (const_cast(clmesh))->setName(_name); + (const_cast(clmesh))->setDescription(_desc_name); (const_cast(clmesh))->setTime(_time,_iteration,_order); - (const_cast(clmesh))->setTimeUnit(_dt_unit.c_str()); + (const_cast(clmesh))->setTimeUnit(_dt_unit); } const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const @@ -3702,7 +6225,7 @@ const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const return _clmesh; } -void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) throw(INTERP_KERNEL::Exception) +void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) { dealWithTinyInfo(m); if(m) @@ -3720,17 +6243,18 @@ MEDFileCurveLinearMesh::MEDFileCurveLinearMesh() { } -MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) try - { - loadCLMeshFromFile(fid,mName,dt,it); - } +{ + loadCLMeshFromFile(fid,mName,dt,it,mrs); + loadJointsFromFile(fid); +} catch(INTERP_KERNEL::Exception& e) - { +{ throw e; - } +} -void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileCurveLinearMesh::writeLL(med_idt fid) const { INTERP_KERNEL::AutoPtr maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); INTERP_KERNEL::AutoPtr desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE); @@ -3753,17 +6277,21 @@ void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exc MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE-1,comp+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE-1,unit+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo } - MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit); - MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID); + MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit)); + MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa)); + MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID)); std::vector nodeGridSt=_clmesh->getNodeGridStructure(); - MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]); - - MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()); + MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0])); + + MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin())); // - MEDFileStructuredMesh::writeStructuredLL(fid,maa); + std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE)); + MEDFileStructuredMesh::writeStructuredLL(fid,meshName); + + writeJoints(fid); } -void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { ParaMEDMEM::MEDCouplingMeshType meshType; int dummy0,dummy1; @@ -3779,7 +6307,7 @@ void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh(); mesh->incrRef(); _clmesh=mesh; - loadStrMeshFromFile(&loaderl2,fid,mName,dt,it); + loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs); } MEDFileMeshMultiTS *MEDFileMeshMultiTS::New() @@ -3787,17 +6315,17 @@ MEDFileMeshMultiTS *MEDFileMeshMultiTS::New() return new MEDFileMeshMultiTS; } -MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception) +MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName) { return new MEDFileMeshMultiTS(fileName); } -MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception) +MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName) { return new MEDFileMeshMultiTS(fileName,mName); } -MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const { MEDCouplingAutoRefCountObjectPtr ret=MEDFileMeshMultiTS::New(); std::vector< MEDCouplingAutoRefCountObjectPtr > meshOneTs(_mesh_one_ts.size()); @@ -3809,22 +6337,27 @@ MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exc return ret.retn(); } -std::size_t MEDFileMeshMultiTS::getHeapMemorySize() const +std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const +{ + return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); +} + +std::vector MEDFileMeshMultiTS::getDirectChildrenWithNull() const { - std::size_t ret=_mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); + std::vector ret; for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) - ret+=(*it)->getHeapMemorySize(); + ret.push_back((const MEDFileMesh *)*it); return ret; } -const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception) +std::string MEDFileMeshMultiTS::getName() const { if(_mesh_one_ts.empty()) throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !"); return _mesh_one_ts[0]->getName(); } -void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::Exception) +void MEDFileMeshMultiTS::setName(const std::string& newMeshName) { std::string oldName(getName()); std::vector< std::pair > v(1); @@ -3832,7 +6365,7 @@ void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::E changeNames(v); } -bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair >& modifTab) { bool ret=false; for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) @@ -3844,14 +6377,14 @@ bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair(static_cast(_mesh_one_ts[0])); } -void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP_KERNEL::Exception) +void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) { if(!mesh1TimeStep) throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !"); @@ -3861,77 +6394,112 @@ void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP _mesh_one_ts[0]=mesh1TimeStep; } -void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception) +MEDFileJoints * MEDFileMeshMultiTS::getJoints() const +{ + if ( MEDFileMesh* m = getOneTimeStep() ) + return m->getJoints(); + return 0; +} + +/*! + * \brief Set Joints that are common to all time-stamps + */ +void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints ) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) + { + (*it)->setJoints( joints ); + } +} + +void MEDFileMeshMultiTS::write(med_idt fid) const { + MEDFileJoints *joints(getJoints()); + bool jointsWritten(false); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) { + if ( jointsWritten ) + const_cast(**it).setJoints( 0 ); + else + jointsWritten = true; + (*it)->copyOptionsFrom(*this); (*it)->write(fid); } + + (const_cast(this))->setJoints( joints ); // restore joints } -void MEDFileMeshMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception) +void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const { med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod); std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; - MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str()); + MEDFileUtilities::CheckMEDCode(fid,fid,oss.str()); write(fid); } -void MEDFileMeshMultiTS::loadFromFile(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception) -{//for the moment to be improved - _mesh_one_ts.resize(1); - _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1); +void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName) +{ + MEDFileJoints* joints = 0; + if ( !_mesh_one_ts.empty() && getOneTimeStep() ) + { + // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading + joints = getOneTimeStep()->getJoints(); + } + + _mesh_one_ts.clear(); //for the moment to be improved + _mesh_one_ts.push_back( MEDFileMesh::New(fileName,mName,-1,-1,0, joints )); } MEDFileMeshMultiTS::MEDFileMeshMultiTS() { } -MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception) +MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName) try - { +{ std::vector ms=MEDLoader::GetMeshNames(fileName); if(ms.empty()) - { - std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); - } + { + std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); int dt,it; ParaMEDMEM::MEDCouplingMeshType meshType; std::string dummy2; - MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2); - loadFromFile(fileName,ms.front().c_str()); - } + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2); + loadFromFile(fileName,ms.front()); +} catch(INTERP_KERNEL::Exception& e) - { +{ throw e; - } +} -MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception) +MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName) try - { +{ loadFromFile(fileName,mName); - } +} catch(INTERP_KERNEL::Exception& e) - { +{ throw e; - } +} MEDFileMeshes *MEDFileMeshes::New() { return new MEDFileMeshes; } -MEDFileMeshes *MEDFileMeshes::New(const char *fileName) throw(INTERP_KERNEL::Exception) +MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName) { return new MEDFileMeshes(fileName); } -void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileMeshes::write(med_idt fid) const { checkCoherency(); for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_meshes.begin();it!=_meshes.end();it++) @@ -3941,27 +6509,28 @@ void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception) } } -void MEDFileMeshes::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception) +void MEDFileMeshes::write(const std::string& fileName, int mode) const { med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod); std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; - MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str()); + MEDFileUtilities::CheckMEDCode(fid,fid,oss.str()); checkCoherency(); write(fid); } -int MEDFileMeshes::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception) +int MEDFileMeshes::getNumberOfMeshes() const { return _meshes.size(); } -MEDFileMeshesIterator *MEDFileMeshes::iterator() throw(INTERP_KERNEL::Exception) +MEDFileMeshesIterator *MEDFileMeshes::iterator() { return new MEDFileMeshesIterator(this); } -MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception) +/** Return a borrowed reference (caller is not responsible) */ +MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const { if(i<0 || i>=(int)_meshes.size()) { @@ -3971,7 +6540,8 @@ MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Excep return _meshes[i]->getOneTimeStep(); } -MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTERP_KERNEL::Exception) +/** Return a borrowed reference (caller is not responsible) */ +MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const { std::vector ms=getMeshesNames(); std::vector::iterator it=std::find(ms.begin(),ms.end(),mname); @@ -3984,7 +6554,7 @@ MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTER return getMeshAtPos((int)std::distance(ms.begin(),it)); } -std::vector MEDFileMeshes::getMeshesNames() const throw(INTERP_KERNEL::Exception) +std::vector MEDFileMeshes::getMeshesNames() const { std::vector ret(_meshes.size()); int i=0; @@ -4003,8 +6573,18 @@ std::vector MEDFileMeshes::getMeshesNames() const throw(INTERP_KERN } return ret; } +/*const MEDFileJoints* MEDFileMeshes::getJoints() const +{ + const MEDFileJoints *ret=_joints; + if(!ret) + { + std::ostringstream oss; oss << "MEDFileMeshes::getJoints : joints is not defined !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + return ret; +}*/ -bool MEDFileMeshes::changeNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception) +bool MEDFileMeshes::changeNames(const std::vector< std::pair >& modifTab) { bool ret=false; for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_meshes.begin();it!=_meshes.end();it++) @@ -4016,12 +6596,12 @@ bool MEDFileMeshes::changeNames(const std::vector< std::pair=(int)_meshes.size()) { @@ -4051,29 +6631,29 @@ void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception) _meshes.erase(_meshes.begin()+i); } -void MEDFileMeshes::loadFromFile(const char *fileName) throw(INTERP_KERNEL::Exception) +void MEDFileMeshes::loadFromFile(const std::string& fileName) { std::vector ms=MEDLoader::GetMeshNames(fileName); int i=0; _meshes.resize(ms.size()); for(std::vector::const_iterator it=ms.begin();it!=ms.end();it++,i++) - _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it).c_str()); + _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it)); } MEDFileMeshes::MEDFileMeshes() { } -MEDFileMeshes::MEDFileMeshes(const char *fileName) throw(INTERP_KERNEL::Exception) +MEDFileMeshes::MEDFileMeshes(const std::string& fileName) try - { +{ loadFromFile(fileName); - } -catch(INTERP_KERNEL::Exception& e) - { - } +} +catch(INTERP_KERNEL::Exception& /*e*/) +{ +} -MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception) +MEDFileMeshes *MEDFileMeshes::deepCpy() const { std::vector< MEDCouplingAutoRefCountObjectPtr > meshes(_meshes.size()); std::size_t i=0; @@ -4085,13 +6665,17 @@ MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception) return ret.retn(); } -std::size_t MEDFileMeshes::getHeapMemorySize() const +std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const { - std::size_t ret=_meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); + return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); +} + +std::vector MEDFileMeshes::getDirectChildrenWithNull() const +{ + std::vector ret; for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_meshes.begin();it!=_meshes.end();it++) - if((const MEDFileMeshMultiTS*)*it) - ret+=(*it)->getHeapMemorySize(); - return ret; + ret.push_back((const MEDFileMeshMultiTS *)*it); + return ret; } std::string MEDFileMeshes::simpleRepr() const @@ -4111,7 +6695,7 @@ void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const oss << " - #" << i << " \"" << mns[i] << "\"\n"; } -void MEDFileMeshes::checkCoherency() const throw(INTERP_KERNEL::Exception) +void MEDFileMeshes::checkCoherency() const { static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank "; int i=0;