X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDLoader%2FMEDFileMesh.cxx;h=90375565ad85666a92bd45a143b6840813e3dbde;hb=f13ce72017fd205546293a53f7b041824cb50eec;hp=5c5ccd8f86eb99458176ac048df611bf8194cac0;hpb=c66a21a11fed90a9536b758a162785908cfe87da;p=tools%2Fmedcoupling.git diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index 5c5ccd8f8..90375565a 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -1,9 +1,9 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D +// Copyright (C) 2007-2014 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,6 +20,8 @@ #include "MEDFileMesh.hxx" #include "MEDFileUtilities.hxx" +#include "MEDFileFieldOverView.hxx" +#include "MEDFileField.hxx" #include "MEDLoader.hxx" #include "MEDLoaderBase.hxx" @@ -30,15 +32,46 @@ #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::getHeapMemorySizeWithoutChildren() const +{ + 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); + for(std::vector::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++) + ret+=(*it2).capacity(); + } + for(std::map::const_iterator it=_families.begin();it!=_families.end();it++) + ret+=(*it).first.capacity()+sizeof(int); + return ret; +} + +std::vector MEDFileMesh::getDirectChildren() const { + return std::vector(); } -MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +/*! + * 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()) @@ -48,67 +81,96 @@ 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->incrRef(); - return (MEDFileUMesh *)ret; + ret->loadUMeshFromFile(fid,ms.front(),dt,it,mrs); + return (MEDFileUMesh *)ret.retn(); } case CARTESIAN: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCMesh::New(); - ret->loadCMeshFromFile(fid,ms.front().c_str(),dt,it); - ret->incrRef(); - return (MEDFileCMesh *)ret; + ret->loadCMeshFromFile(fid,ms.front(),dt,it,mrs); + return (MEDFileCMesh *)ret.retn(); + } + case CURVE_LINEAR: + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileCurveLinearMesh::New(); + ret->loadCLMeshFromFile(fid,ms.front(),dt,it,mrs); + 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. + * \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) { 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->incrRef(); - return (MEDFileUMesh *)ret; + ret->loadUMeshFromFile(fid,mName,dt,it,mrs); + return (MEDFileUMesh *)ret.retn(); } case CARTESIAN: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCMesh::New(); - ret->loadCMeshFromFile(fid,mName,dt,it); - ret->incrRef(); - return (MEDFileCMesh *)ret; + ret->loadCMeshFromFile(fid,mName,dt,it,mrs); + return (MEDFileCMesh *)ret.retn(); + } + case CURVE_LINEAR: + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileCurveLinearMesh::New(); + ret->loadCLMeshFromFile(fid,mName,dt,it,mrs); + 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); @@ -117,15 +179,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) @@ -153,11 +232,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 !"; @@ -170,12 +245,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++) { @@ -188,19 +271,68 @@ 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); - std::vector grps=getGroupsNames(); if(it==_groups.end()) { + std::vector grps=getGroupsNames(); std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :"; std::copy(grps.begin(),grps.end(),std::ostream_iterator(oss," ")); throw INTERP_KERNEL::Exception(oss.str().c_str()); @@ -208,7 +340,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++) @@ -227,7 +365,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); @@ -242,10 +386,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; @@ -258,10 +405,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()); @@ -274,7 +425,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++) @@ -290,9 +446,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); @@ -316,6 +475,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()); @@ -325,6 +488,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()); @@ -335,15 +502,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()) @@ -370,7 +538,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); @@ -384,7 +578,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); @@ -405,7 +604,70 @@ 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; +} + +/*! + * 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); @@ -417,8 +679,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()); @@ -429,10 +691,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; @@ -446,7 +710,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); @@ -476,6 +747,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) @@ -491,6 +769,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) @@ -529,7 +815,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++) @@ -543,12 +829,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++) @@ -557,19 +853,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++) @@ -585,23 +891,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 { @@ -615,14 +923,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(); @@ -644,9 +957,9 @@ void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(meshDimRelToMaxExt); if(fieldFamIds==0) throw INTERP_KERNEL::Exception("MEDFileMesh::createGroupOnAll : Family field arr ids is not defined for this level !"); - std::set famIds=fieldFamIds->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr famIds=fieldFamIds->getDifferentValues(); std::vector familiesOnWholeGroup; - for(std::set::const_iterator it=famIds.begin();it!=famIds.end();it++) + for(const int *it=famIds->begin();it!=famIds->end();it++) { bool tmp; familiesOnWholeGroup.push_back(findOrCreateAndGiveFamilyWithId(*it,tmp)); @@ -655,12 +968,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(); @@ -678,16 +994,16 @@ bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector& famIds, const std const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(*it); if(fieldFamIds) { - std::set famIds3=fieldFamIds->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr famIds3=fieldFamIds->getDifferentValues(); std::vector tmp; - std::set_intersection(famIds3.begin(),famIds3.end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector >(tmp)); + std::set_intersection(famIds3->begin(),famIds3->end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector >(tmp)); for(std::vector::const_iterator it2=tmp.begin();it2!=tmp.end();it2++) { ret=false; 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++; @@ -698,12 +1014,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); @@ -735,7 +1053,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); @@ -749,6 +1067,39 @@ void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *ot } } +void MEDFileMesh::changeAllGroupsContainingFamily(const std::string& familyNameToChange, const std::vector& newFamiliesNames) +{ + ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames); +} + +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++) + { + std::vector& fams((*it).second); + std::vector::iterator it2=std::find(fams.begin(),fams.end(),fam); + if(it2!=fams.end()) + { + fams.erase(it2); + fams.insert(fams.end(),newFamiliesNames.begin(),newFamiliesNames.end()); + } + } +} + +/*! + * Returns a name of the family having a given id or, if no such a family exists, creates + * a new uniquely named family and returns its name. + * \param [in] id - the id of the family whose name is required. + * \param [out] created - returns \c true if the new family has been created, \c false, else. + * \return std::string - the name of the existing or the created family. + * \throw If it is not possible to create a unique family name. + */ +std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created) +{ + return FindOrCreateAndGiveFamilyWithId(_families,id,created); +} + /*! * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId. * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false. @@ -757,11 +1108,11 @@ void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *ot * will be modified. * This method will throws an exception if it is not possible to create a unique family name. */ -std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created) throw(INTERP_KERNEL::Exception) +std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map& families, int id, bool& created) { - std::vector famAlreadyExisting(_families.size()); + std::vector famAlreadyExisting(families.size()); int ii=0; - for(std::map::const_iterator it=_families.begin();it!=_families.end();it++,ii++) + for(std::map::const_iterator it=families.begin();it!=families.end();it++,ii++) { if((*it).second!=id) { @@ -776,21 +1127,36 @@ std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created) created=true; std::ostringstream oss; oss << "Family_" << id; std::string ret=CreateNameNotIn(oss.str(),famAlreadyExisting); - _families[ret]=id; + families[ret]=id; return ret; } +/*! + * Sets names and ids of all families in \a this mesh. + * \param [in] info - a map of a family name to a family id. + */ void MEDFileMesh::setFamilyInfo(const 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); @@ -804,7 +1170,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; @@ -823,10 +1195,32 @@ 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("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(std::abs((*it).second),ret); + } + return ret; +} + +/*! + * 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::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++) { @@ -835,10 +1229,15 @@ int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception) return ret; } -int MEDFileMesh::getMinFamilyId() 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 { if(_families.empty()) - throw INTERP_KERNEL::Exception("MEDFileUMesh::getMinFamilyId : no families set !"); + 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++) { @@ -847,7 +1246,54 @@ int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception) return ret; } -DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception) +/*! + * 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); +} + +/*! + * 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++) + m1=std::min((*it).second,m1); + int m2=getMinFamilyIdInArrays(); + return std::min(m1,m2); +} + +/*! + * 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; @@ -855,14 +1301,35 @@ DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERN v.insert((*it).second); ret->alloc((int)v.size(),1); std::copy(v.begin(),v.end(),ret->getPointer()); - ret->incrRef(); return ret; + 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; @@ -873,13 +1340,13 @@ bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception const DataArrayInt *fam=getFamilyFieldAtLevel(*it); if(fam) { - std::set tmp=fam->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); std::set r2; - std::set_intersection(tmp.begin(),tmp.end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end())); + std::set_intersection(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end())); if(!r2.empty()) famIdsToRenum[*it].insert(famIdsToRenum[*it].end(),r2.begin(),r2.end()); std::set r3; - std::set_union(tmp.begin(),tmp.end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end())); + std::set_union(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end())); } } if(famIdsToRenum.empty()) @@ -895,12 +1362,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()); @@ -917,7 +1384,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(); @@ -932,15 +1399,15 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception) if(fam) { int refId=1; - std::set tmp=fam->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); std::map ren; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId++) + for(const int *it=tmp->begin();it!=tmp->end();it++,refId++) ren[*it]=refId; int nbOfTuples=fam->getNumberOfTuples(); int *start=const_cast(fam)->getPointer(); for(int *w=start;w!=start+nbOfTuples;w++) *w=ren[*w]; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + for(const int *it=tmp->begin();it!=tmp->end();it++) { if(allIds->presenceOfValue(*it)) { @@ -958,15 +1425,15 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception) if(fam) { int refId=-1; - std::set tmp=fam->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); std::map ren; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId--) + for(const int *it=tmp->begin();it!=tmp->end();it++,refId--) ren[*it]=refId; int nbOfTuples=fam->getNumberOfTuples(); int *start=const_cast(fam)->getPointer(); for(int *w=start;w!=start+nbOfTuples;w++) *w=ren[*w]; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + for(const int *it=tmp->begin();it!=tmp->end();it++) { if(allIds->presenceOfValue(*it)) { @@ -982,9 +1449,9 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception) DataArrayInt *fam=const_cast(getFamilyFieldAtLevel(*it2)); if(fam) { - std::set tmp=fam->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); fam->fillWithZero(); - for(std::set::const_iterator it3=tmp.begin();it3!=tmp.end();it3++) + for(const int *it3=tmp->begin();it3!=tmp->end();it3++) if(allIds->presenceOfValue(*it3)) { std::string famName=getFamilyNameGivenId(*it3); @@ -1006,10 +1473,10 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception) /*! * This method normalizes fam id with the following policy. * Level #0 famids < 0, Level #-1 famids < 0 and for Level #1 famids >= 0 - * This policy is those used by SMESH and Trio and that is the opposite of those in MED file. + * 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(); @@ -1024,15 +1491,15 @@ void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception) const DataArrayInt *fam=getFamilyFieldAtLevel(1); if(fam) { - std::set tmp=fam->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); std::map ren; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId++) + for(const int *it=tmp->begin();it!=tmp->end();it++,refId++) ren[*it]=refId; int nbOfTuples=fam->getNumberOfTuples(); int *start=const_cast(fam)->getPointer(); for(int *w=start;w!=start+nbOfTuples;w++) *w=ren[*w]; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + for(const int *it=tmp->begin();it!=tmp->end();it++) { if(allIds->presenceOfValue(*it)) { @@ -1046,18 +1513,18 @@ 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) { - std::set tmp=fam->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr tmp=fam->getDifferentValues(); std::map ren; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++,refId--) + for(const int *it=tmp->begin();it!=tmp->end();it++,refId--) ren[*it]=refId; int nbOfTuples=fam->getNumberOfTuples(); int *start=const_cast(fam)->getPointer(); for(int *w=start;w!=start+nbOfTuples;w++) *w=ren[*w]; - for(std::set::const_iterator it=tmp.begin();it!=tmp.end();it++) + for(const int *it=tmp->begin();it!=tmp->end();it++) { if(allIds->presenceOfValue(*it)) { @@ -1079,9 +1546,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) @@ -1090,6 +1561,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; @@ -1099,7 +1575,20 @@ std::string MEDFileMesh::simpleRepr() const return oss.str(); } -DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * 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; @@ -1108,13 +1597,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; @@ -1123,7 +1637,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; @@ -1132,12 +1657,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; @@ -1146,12 +1693,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 ; @@ -1181,16 +1750,16 @@ 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); - std::set ids=fam->getDifferentValues(); + offset=getMaxAbsFamilyId()+1; + TranslateFamilyIds(meshDimRelToMaxExt==1?offset:-offset,fam,fidsOfGroups); + MEDCouplingAutoRefCountObjectPtr ids=fam->getDifferentValues(); appendFamilyEntries(ids,fidsOfGroups,grpsName2); setFamilyFieldArr(meshDimRelToMaxExt,fam); } @@ -1200,10 +1769,10 @@ void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector& famIds, const std::vector< std::vector >& fidsOfGrps, const std::vector& grpNames) +void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vector< std::vector >& fidsOfGrps, const std::vector& grpNames) { std::map famInv; - for(std::set::const_iterator it=famIds.begin();it!=famIds.end();it++) + for(const int *it=famIds->begin();it!=famIds->end();it++) { std::ostringstream oss; oss << "Family_" << (*it); @@ -1220,11 +1789,33 @@ void MEDFileMesh::appendFamilyEntries(const std::set& famIds, const std::ve } } +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)); + } } /*! @@ -1232,7 +1823,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()) @@ -1265,7 +1856,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) @@ -1285,8 +1876,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 @@ -1302,6 +1895,21 @@ void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m) throw(INTERP_KERNEL } } } + if(_desc_name.empty()) + _desc_name=m->getDescription(); + else + { + std::string name(m->getDescription()); + if(!name.empty()) + { + if(_desc_name!=name) + { + std::ostringstream oss; oss << "MEDFileMesh::dealWithTinyInfo : description of current MEDfile mesh is '" << _desc_name << "' whereas name of input mesh is : '"; + oss << name << "' ! Names must match !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + } } void MEDFileMesh::getFamilyRepr(std::ostream& oss) const @@ -1311,20 +1919,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()) @@ -1333,25 +1965,96 @@ 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; } -bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const +std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const { - if(!MEDFileMesh::isEqual(other,eps,what)) - return false; - const MEDFileUMesh *otherC=dynamic_cast(other); - if(!otherC) + std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren()); + ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); + return ret; +} + +std::vector MEDFileUMesh::getDirectChildren() const +{ + std::vector ret(MEDFileMesh::getDirectChildren()); + if((const DataArrayDouble*)_coords) + ret.push_back((const DataArrayDouble*)_coords); + if((const DataArrayInt *)_fam_coords) + ret.push_back((const DataArrayInt *)_fam_coords); + if((const DataArrayInt *)_num_coords) + ret.push_back((const DataArrayInt *)_num_coords); + if((const DataArrayInt *)_rev_num_coords) + ret.push_back((const DataArrayInt *)_rev_num_coords); + if((const DataArrayAsciiChar *)_name_coords) + ret.push_back((const DataArrayAsciiChar *)_name_coords); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) + if((const MEDFileUMeshSplitL1*) *it) + ret.push_back((const MEDFileUMeshSplitL1*) *it); + return ret; +} + +MEDFileMesh *MEDFileUMesh::shallowCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileUMesh(*this); + return ret.retn(); +} + +MEDFileMesh *MEDFileUMesh::createNewEmpty() const +{ + return new MEDFileUMesh; +} + +MEDFileMesh *MEDFileUMesh::deepCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileUMesh(*this); + if((const DataArrayDouble*)_coords) + ret->_coords=_coords->deepCpy(); + if((const DataArrayInt*)_fam_coords) + ret->_fam_coords=_fam_coords->deepCpy(); + if((const DataArrayInt*)_num_coords) + ret->_num_coords=_num_coords->deepCpy(); + if((const DataArrayInt*)_rev_num_coords) + ret->_rev_num_coords=_rev_num_coords->deepCpy(); + if((const DataArrayAsciiChar*)_name_coords) + ret->_name_coords=_name_coords->deepCpy(); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++) + { + if((const MEDFileUMeshSplitL1 *)(*it)) + ret->_ms[i]=(*it)->deepCpy(ret->_coords); + } + 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)) + return false; + const MEDFileUMesh *otherC=dynamic_cast(other); + if(!otherC) { what="Mesh types differ ! This is unstructured and other is NOT !"; return false; @@ -1406,6 +2109,22 @@ bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh return false; } } + const DataArrayAsciiChar *namec1=_name_coords; + const DataArrayAsciiChar *namec2=otherC->_name_coords; + if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0)) + { + what="Mismatch of naming arr on nodes ! One is defined and not other !"; + return false; + } + if(namec1) + { + bool ret=namec1->isEqual(*namec2); + if(!ret) + { + what="Names arr on node differ !"; + return false; + } + } if(_ms.size()!=otherC->_ms.size()) { what="Number of levels differs !"; @@ -1428,10 +2147,12 @@ bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh return false; } } - //std::vector< MEDCouplingAutoRefCountObjectPtr > _ms; return true; } +/*! + * Clears redundant attributes of incorporated data arrays. + */ void MEDFileUMesh::clearNonDiscrAttributes() const { MEDFileMesh::clearNonDiscrAttributes(); @@ -1444,6 +2165,9 @@ void MEDFileUMesh::clearNonDiscrAttributes() const const DataArrayInt *numc1=_num_coords; if(numc1) (const_cast(numc1))->setName("");//This parameter is not discriminant for comparison + const DataArrayAsciiChar *namc1=_name_coords; + if(namc1) + (const_cast(namc1))->setName("");//This parameter is not discriminant for comparison for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) { const MEDFileUMeshSplitL1 *tmp=(*it); @@ -1452,21 +2176,29 @@ 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); +} catch(INTERP_KERNEL::Exception& e) - { +{ throw e; - } +} -void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { MEDFileUMeshL2 loaderl2; ParaMEDMEM::MEDCouplingMeshType meshType; @@ -1478,7 +2210,7 @@ void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int 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); 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(); computeRevNum(); } @@ -1506,7 +2243,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); @@ -1526,13 +2263,19 @@ void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) 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,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit); - MEDFileUMeshL2::WriteCoords(fid,maa,_iteration,_order,_time,_coords,_fam_coords,_num_coords); + MEDmeshUniversalNameWr(fid,maa); + std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE)); + MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords); for(std::vector< MEDCouplingAutoRefCountObjectPtr >::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); } +/*! + * 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; @@ -1544,6 +2287,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(); @@ -1557,68 +2304,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(); @@ -1630,9 +2442,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; @@ -1651,22 +2465,99 @@ 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::getMeshDimension() 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) + { + int val=_fam_coords->getMaxValue(tmp); + ret=std::max(ret,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,val); + } + } + } + return ret; +} + +int MEDFileUMesh::getMinFamilyIdInArrays() const +{ + int ret=std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_coords) + { + int val=_fam_coords->getMinValue(tmp); + ret=std::min(ret,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->getMinValue(tmp); + ret=std::min(ret,val); + } + } + } + return ret; +} + +/*! + * 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++) @@ -1675,7 +2566,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) @@ -1683,6 +2580,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; @@ -1731,12 +2632,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) { @@ -1747,7 +2658,13 @@ 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; @@ -1755,7 +2672,13 @@ const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) return l1->getFamilyField(); } -const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +/*! + * 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; @@ -1763,7 +2686,15 @@ const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) return l1->getNumberField(); } -int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) +const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const +{ + if(meshDimRelToMaxExt==1) + return _name_coords; + const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt); + return l1->getNameField(); +} + +int MEDFileUMesh::getNumberOfNodes() const { const DataArrayDouble *coo=_coords; if(!coo) @@ -1771,7 +2702,47 @@ int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) return coo->getNumberOfTuples(); } -const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +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) { @@ -1784,7 +2755,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 { @@ -1796,34 +2768,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) @@ -1832,18 +2859,33 @@ MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::v MEDCouplingAutoRefCountObjectPtr ret=MEDCouplingUMesh::New(); MEDCouplingAutoRefCountObjectPtr c=_coords->selectByTupleId(arr->getConstPointer(),arr->getConstPointer()+arr->getNbOfElems()); ret->setCoords(c); - ret->incrRef(); - return ret; + return ret.retn(); } 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) @@ -1858,10 +2900,7 @@ DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::ve if(renum) return MEDFileUMeshSplitL1::Renumber(_num_coords,da); else - { - da->incrRef(); - return da; - } + return da.retn(); } else throw INTERP_KERNEL::Exception("MEDFileUMesh::getFamiliesArr : no family array specified on nodes !"); @@ -1873,7 +2912,21 @@ DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::ve return l1->getFamilyPartArr(0,0,renum); } -MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * 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 { synchronizeTinyInfoOnLeaves(); if(meshDimRelToMaxExt==1) @@ -1892,32 +2945,165 @@ MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renu return l1->getWholeMesh(renum); } -MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception) +/*! + * 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 { 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); +} + +const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const { if(meshDimRelToMaxExt==1) throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !"); @@ -1931,9 +3117,9 @@ const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt 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) !"); @@ -1945,7 +3131,7 @@ MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) thro 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' !"); @@ -1961,7 +3147,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 !"); @@ -1972,9 +3163,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) { @@ -1987,16 +3186,19 @@ 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; for(std::vector::const_iterator it=levs.begin();it!=levs.end();it++) { const DataArrayInt *ffield=getFamilyFieldAtLevel(*it); - std::set ids=ffield->getDifferentValues(); + MEDCouplingAutoRefCountObjectPtr ids=ffield->getDifferentValues(); std::set res; - std::set_union(ids.begin(),ids.end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin())); + std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin())); allFamsIds=res; } std::set famNamesToKill; @@ -2025,7 +3227,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()) @@ -2098,8 +3300,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) @@ -2110,9 +3312,9 @@ void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt * newFam->setPartOfValuesSimple1(0,nbNodes,newNbOfNodes,1,0,1,1); _fam_coords=newFam; } - nodesDuplicated=nodeIdsToDuplicate; nodeIdsToDuplicate->incrRef(); - cellsModified=cellsToModifyConn0; cellsToModifyConn0->incrRef(); - cellsNotModified=cellsToModifyConn1; cellsToModifyConn1->incrRef(); + nodesDuplicated=nodeIdsToDuplicate.retn(); + cellsModified=cellsToModifyConn0.retn(); + cellsNotModified=cellsToModifyConn1.retn(); } /*! @@ -2123,7 +3325,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(); @@ -2141,7 +3343,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) @@ -2180,30 +3382,213 @@ bool MEDFileUMesh::unPolyze(std::vector& oldCode, std::vector& newCode { MEDCouplingAutoRefCountObjectPtr renumCells=DataArrayInt::Aggregate(renumCellsSplited); MEDCouplingAutoRefCountObjectPtr o2nRenumCellRet=renumCells->buildPermArrPerLevel(); - o2nRenumCell=o2nRenumCellRet; o2nRenumCellRet->incrRef(); + o2nRenumCell=o2nRenumCellRet.retn(); } return ret; } -void MEDFileUMesh::addNodeGroup(const std::string& name, const std::vector& ids) throw(INTERP_KERNEL::Exception) +struct MEDLoaderAccVisit1 { - const DataArrayDouble *coords=_coords; - if(!coords) - throw INTERP_KERNEL::Exception("addNodeGroup : no coords set !"); - DataArrayInt *sub=_fam_coords->selectByTupleIdSafe(&ids[0],&ids[0]+ids.size()); - std::set ssub(sub->getConstPointer(),sub->getConstPointer()+sub->getNumberOfTuples()); - -} + MEDLoaderAccVisit1():_new_nb_of_nodes(0) { } + int operator()(bool val) { return val?_new_nb_of_nodes++:-1; } + int _new_nb_of_nodes; +}; -void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception) +/*! + * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller. + * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method. + * 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 \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() { - std::string oldName=getFamilyNameGivenId(id); - _families.erase(oldName); - _families[newFamName]=id; + const DataArrayDouble *coo=getCoords(); + if(!coo) + throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !"); + int nbOfNodes=coo->getNumberOfTuples(); + std::vector nodeIdsInUse(nbOfNodes,false); + std::vector neLevs=getNonEmptyLevels(); + for(std::vector::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++) + { + MEDCouplingAutoRefCountObjectPtr m=getMeshAtLevel(*lev); + m->computeNodeIdsAlg(nodeIdsInUse); + } + int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true); + if(nbrOfNodesInUse==nbOfNodes) + return 0; + 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 newFamCoords; + MEDCouplingAutoRefCountObjectPtr newNameCoords; + if((const DataArrayInt *)_fam_coords) + newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()); + MEDCouplingAutoRefCountObjectPtr newNumCoords; + if((const DataArrayInt *)_num_coords) + newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()); + if((const DataArrayAsciiChar *)_name_coords) + newNameCoords=static_cast(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end())); + _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_ms.begin();it!=_ms.end();it++) + { + if((MEDFileUMeshSplitL1*)*it) + (*it)->renumberNodesInConn(ret->begin()); + } + return ret.retn(); } -void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) 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). + * \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::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). + * \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); +} + +/*! + * \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 MEDFileUMesh::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; +} + +/*! + * 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()) @@ -2212,12 +3597,43 @@ void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::E _ms[pos]=0; } -void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception) +/*! + * 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) { - setMeshAtLevelGen(meshDimRelToMax,m,newOrOld); + MEDCouplingAutoRefCountObjectPtr elt(new MEDFileUMeshSplitL1(m,newOrOld)); + checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt; } -void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception) +MEDCouplingAutoRefCountObjectPtr& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m) { dealWithTinyInfo(m); std::vector levSet=getNonEmptyLevels(); @@ -2236,13 +3652,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 !"); @@ -2262,12 +3738,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 !"); @@ -2302,7 +3797,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(); @@ -2317,7 +3812,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) { @@ -2344,7 +3847,14 @@ void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famAr 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) { @@ -2373,6 +3883,40 @@ void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumA return _ms[traducedRk]->setRenumArr(renumArr); } +/*! + * 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) + { + if(!nameArr) + { + _name_coords=0; + return ; + } + DataArrayDouble *coo(_coords); + if(!coo) + 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::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 !"); + if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0) + throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !"); + return _ms[traducedRk]->setNameArr(nameArr); +} + void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const { for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) @@ -2383,7 +3927,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) @@ -2398,6 +3942,25 @@ void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL:: } } +std::list< MEDCouplingAutoRefCountObjectPtr > MEDFileUMesh::getAllNonNullFamilyIds() const +{ + std::list< MEDCouplingAutoRefCountObjectPtr > ret; + const DataArrayInt *da(_fam_coords); + if(da) + { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr(const_cast(da))); } + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) + { + const MEDFileUMeshSplitL1 *elt(*it); + if(elt) + { + da=elt->getFamilyField(); + if(da) + { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr(const_cast(da))); } + } + } + return ret; +} + void MEDFileUMesh::computeRevNum() const { if((const DataArrayInt *)_num_coords) @@ -2408,85 +3971,135 @@ void MEDFileUMesh::computeRevNum() const } } -MEDFileCMesh *MEDFileCMesh::New() -{ - return new MEDFileCMesh; -} - -MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const { - 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()); - } - MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,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); + return MEDFileMesh::getHeapMemorySizeWithoutChildren(); } -MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +std::vector MEDFileStructuredMesh::getDirectChildren() const { - MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - return new MEDFileCMesh(fid,mName,dt,it); + std::vector ret(MEDFileMesh::getDirectChildren()); + if((const DataArrayInt *)_fam_nodes) + ret.push_back((const DataArrayInt *)_fam_nodes); + if((const DataArrayInt *)_num_nodes) + ret.push_back((const DataArrayInt *)_num_nodes); + if((const DataArrayAsciiChar *)_names_nodes) + ret.push_back((const DataArrayAsciiChar *)_names_nodes); + if((const DataArrayInt *)_fam_cells) + ret.push_back((const DataArrayInt *)_fam_cells); + if((const DataArrayInt *)_num_cells) + ret.push_back((const DataArrayInt *)_num_cells); + if((const DataArrayAsciiChar *)_names_cells) + ret.push_back((const DataArrayAsciiChar *)_names_cells); + if((const DataArrayInt *)_fam_faces) + ret.push_back((const DataArrayInt *)_fam_faces); + if((const DataArrayInt *)_num_faces) + ret.push_back((const DataArrayInt *)_num_faces); + if((const DataArrayInt *)_rev_num_nodes) + ret.push_back((const DataArrayInt *)_rev_num_nodes); + if((const DataArrayAsciiChar *)_names_faces) + ret.push_back((const DataArrayAsciiChar *)_names_faces); + if((const DataArrayInt *)_rev_num_cells) + ret.push_back((const DataArrayInt *)_rev_num_cells); + if((const MEDCoupling1SGTUMesh*)_faces_if_necessary) + ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary); + return ret; } -int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) +int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const { - if(!((const MEDCouplingCMesh*)_cmesh)) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !"); - return _cmesh->getMeshDimension(); + 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; } -std::string MEDFileCMesh::simpleRepr() const +int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const { - return MEDFileMesh::simpleRepr(); + int ret=-std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_nodes) + { + int val=_fam_nodes->getMaxValue(tmp); + ret=std::max(ret,val); + } + if((const DataArrayInt *)_fam_cells) + { + 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; } -std::string MEDFileCMesh::advancedRepr() const +int MEDFileStructuredMesh::getMinFamilyIdInArrays() const { - return simpleRepr(); + int ret=std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_nodes) + { + int val=_fam_nodes->getMinValue(tmp); + ret=std::min(ret,val); + } + if((const DataArrayInt *)_fam_cells) + { + 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; } -bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const +bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const { if(!MEDFileMesh::isEqual(other,eps,what)) return false; - const MEDFileCMesh *otherC=dynamic_cast(other); + const MEDFileStructuredMesh *otherC=dynamic_cast(other); if(!otherC) { - what="Mesh types differ ! This is cartesian and other is NOT !"; + what="Mesh types differ ! This is structured and other is NOT !"; return false; } - clearNonDiscrAttributes(); - otherC->clearNonDiscrAttributes(); - const MEDCouplingCMesh *coo1=_cmesh; - const MEDCouplingCMesh *coo2=otherC->_cmesh; - if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0)) + const DataArrayInt *famc1=_fam_nodes; + const DataArrayInt *famc2=otherC->_fam_nodes; + if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0)) { - what="Mismatch of cartesian meshes ! One is defined and not other !"; + what="Mismatch of families arr on nodes ! One is defined and not other !"; return false; } - if(coo1) + if(famc1) { - bool ret=coo1->isEqual(coo2,eps); + bool ret=famc1->isEqual(*famc2); if(!ret) { - what="cartesian meshes differ !"; + what="Families arr on nodes differ !"; return false; } } - const DataArrayInt *famc1=_fam_nodes; - const DataArrayInt *famc2=otherC->_fam_nodes; + famc1=_fam_cells; + famc2=otherC->_fam_cells; if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0)) { - what="Mismatch of families arr on nodes ! One is defined and not other !"; + what="Mismatch of families arr on cells ! One is defined and not other !"; return false; } if(famc1) @@ -2494,15 +4107,15 @@ bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh bool ret=famc1->isEqual(*famc2); if(!ret) { - what="Families arr on nodes differ !"; + what="Families arr on cells differ !"; return false; } } - famc1=_fam_cells; - famc2=otherC->_fam_cells; + famc1=_fam_faces; + famc2=otherC->_fam_faces; if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0)) { - what="Mismatch of families arr on cells ! One is defined and not other !"; + what="Mismatch of families arr on faces ! One is defined and not other !"; return false; } if(famc1) @@ -2510,7 +4123,7 @@ bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh bool ret=famc1->isEqual(*famc2); if(!ret) { - what="Families arr on cells differ !"; + what="Families arr on faces differ !"; return false; } } @@ -2546,13 +4159,76 @@ bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh 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)) + { + what="Mismatch of naming arr on cells ! One is defined and not other !"; + return false; + } + if(d1) + { + bool ret=d1->isEqual(*d2); + if(!ret) + { + what="Naming arr on cells differ !"; + 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)) + { + what="Mismatch of naming arr on nodes ! One is defined and not other !"; + return false; + } + if(d1) + { + bool ret=d1->isEqual(*d2); + if(!ret) + { + what="Naming arr on nodes differ !"; + return false; + } + } return true; } -void MEDFileCMesh::clearNonDiscrAttributes() const +void MEDFileStructuredMesh::clearNonDiscrAttributes() const { MEDFileMesh::clearNonDiscrAttributes(); - MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh); const DataArrayInt *tmp=_fam_nodes; if(tmp) (const_cast(tmp))->setName(""); @@ -2565,124 +4241,1005 @@ void MEDFileCMesh::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(""); } -MEDFileCMesh::MEDFileCMesh() +/*! + * 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 { -} - -MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) -try - { - loadCMeshFromFile(fid,mName,dt,it); - } -catch(INTERP_KERNEL::Exception& e) + std::vector famIds(getFamiliesIds(fams)); + switch(meshDimRelToMaxExt) { - throw e; + 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 MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) -{ - MEDFileCMeshL2 loaderl2; - ParaMEDMEM::MEDCouplingMeshType meshType; - int dummy0,dummy1; - std::string dtunit; - int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit); - if(meshType!=CARTESIAN) +/*! + * 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) +{ + const MEDCouplingStructuredMesh *mesh(getStructuredMesh()); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !"); + 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(); +} + +/*! + * 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) +{ + const MEDCouplingStructuredMesh *mesh=getStructuredMesh(); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !"); + 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(); +} + +/*! + * 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) +{ + const MEDCouplingStructuredMesh *mesh(getStructuredMesh()); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !"); + 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(); +} + +/*! + * 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 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 !"); + } +} + +/*! + * 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 !"); + if(meshDimRelToMaxExt==0) { - std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); + if((const DataArrayInt *)_num_cells) + { + int pos; + int maxValue=_num_cells->getMaxValue(pos); + _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1); + return _rev_num_cells; + } + else + throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !"); } - loaderl2.loadAll(fid,mid,mName,dt,it); - MEDCouplingCMesh *mesh=loaderl2.getMesh(); - mesh->incrRef(); - _cmesh=mesh; - setName(loaderl2.getName()); - setDescription(loaderl2.getDescription()); - setIteration(loaderl2.getIteration()); - setOrder(loaderl2.getOrder()); - setTimeValue(loaderl2.getTime()); - setTimeUnit(loaderl2.getTimeUnit()); - MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups); + else + { + if((const DataArrayInt *)_num_nodes) + { + int pos; + int maxValue=_num_nodes->getMaxValue(pos); + _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1); + return _rev_num_nodes; + } + else + throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !"); + } +} + +const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const +{ + 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); + 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; +} + +/*! + * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined. + */ +std::vector MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const +{ + 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) +{ + oldCode.clear(); newCode.clear(); o2nRenumCell=0; + return false; +} + +void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) +{ + DataArrayInt *arr=_fam_nodes; + if(arr) + arr->changeValue(oldId,newId); + arr=_fam_cells; + if(arr) + arr->changeValue(oldId,newId); + arr=_fam_faces; + if(arr) + arr->changeValue(oldId,newId); +} + +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) + _rev_num_cells=_rev_num_cells->deepCpy(); +} + +/*! + * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh). + * + * \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. + */ + +/*! + * 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 !"); + 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 !"); + } +} + +/*! + * 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 +{ + const MEDCouplingStructuredMesh *cmesh(getStructuredMesh()); + if(!cmesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !"); + 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 +{ + const MEDCouplingStructuredMesh *cmesh(getStructuredMesh()); + if(!cmesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !"); + return cmesh->getNumberOfNodes(); +} + +bool MEDFileStructuredMesh::hasImplicitPart() const +{ + return true; +} + +/*! + * \sa MEDFileStructuredMesh::getImplicitFaceMesh + */ +int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const +{ + 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) + { + 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: + { + 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("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) +{ 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); + 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); + MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()); + } } - int spaceDim=mesh->getSpaceDimension(); - med_geometry_type geoTypeReq=MED_NONE; - switch(spaceDim) + nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf); + if(nbOfElt>0) { - case 3: - geoTypeReq=MED_HEXA8; - break; - case 2: - geoTypeReq=MED_QUAD4; - break; - case 1: - geoTypeReq=MED_SEG2; - break; - case 0: - geoTypeReq=MED_POINT1; - break; - default: - throw INTERP_KERNEL::Exception("Invalid spacedim detected for cartesian mesh ! Must be in (1,2,3) !"); + 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 + 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 + } + } +} + +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) + { + 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(); + MEDmeshEntityFamilyNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()); + } } - 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_NODE,MED_NONE,MED_NUMBER,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->isNodeNumFieldReading()) + { + _num_nodes=DataArrayInt::New(); + _num_nodes->alloc(nbOfElt,1); + MEDmeshEntityNumberRd(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()); + } } - nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,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) { - _num_cells=DataArrayInt::New(); - _num_cells->alloc(nbOfElt,1); - MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer()); + 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 + 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 MEDFileCMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception) +void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const { - DataArrayInt *arr=_fam_nodes; - if(arr) - arr->changeValue(oldId,newId); - arr=_fam_cells; - if(arr) - arr->changeValue(oldId,newId); + int meshDim(getStructuredMesh()->getMeshDimension()); + med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1)); + // + if((const DataArrayInt *)_fam_cells) + MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()); + if((const DataArrayInt *)_fam_faces) + MEDmeshEntityFamilyNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()); + if((const DataArrayInt *)_fam_nodes) + 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.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()); + if((const DataArrayInt *)_num_faces) + MEDmeshEntityNumberWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()); + if((const DataArrayInt *)_num_nodes) + 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) + { + std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE; + oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + 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()); + } + MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()); + } + if((const DataArrayAsciiChar *)_names_nodes) + { + if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE) + { + std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE; + oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + MEDmeshEntityNameWr(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()); + } + // + 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; +} + +/*! + * 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()) + { + 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.c_str(),MED_ACC_RDONLY); + int dt,it; + ParaMEDMEM::MEDCouplingMeshType meshType; + std::string dummy2; + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2); + return new MEDFileCMesh(fid,ms.front(),dt,it,mrs); +} + +/*! + * 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.c_str(),MED_ACC_RDONLY); + return new MEDFileCMesh(fid,mName,dt,it,mrs); +} + +std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const +{ + return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren(); +} + +std::vector MEDFileCMesh::getDirectChildren() const +{ + std::vector ret(MEDFileStructuredMesh::getDirectChildren()); + if((const MEDCouplingCMesh *)_cmesh) + ret.push_back((const MEDCouplingCMesh *)_cmesh); + return ret; +} + +/*! + * 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 +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCMesh(*this); + return ret.retn(); +} + +MEDFileMesh *MEDFileCMesh::createNewEmpty() const +{ + return new MEDFileCMesh; +} + +MEDFileMesh *MEDFileCMesh::deepCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCMesh(*this); + if((const MEDCouplingCMesh*)_cmesh) + ret->_cmesh=static_cast(_cmesh->deepCpy()); + ret->deepCpyAttributes(); + 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)) + return false; + const MEDFileCMesh *otherC=dynamic_cast(other); + if(!otherC) + { + what="Mesh types differ ! This is cartesian and other is NOT !"; + return false; + } + clearNonDiscrAttributes(); + otherC->clearNonDiscrAttributes(); + const MEDCouplingCMesh *coo1=_cmesh; + const MEDCouplingCMesh *coo2=otherC->_cmesh; + if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0)) + { + what="Mismatch of cartesian meshes ! One is defined and not other !"; + return false; + } + if(coo1) + { + bool ret=coo1->isEqual(coo2,eps); + if(!ret) + { + what="cartesian meshes differ !"; + return false; + } + } + return true; +} + +/*! + * Clears redundant attributes of incorporated data arrays. + */ +void MEDFileCMesh::clearNonDiscrAttributes() const +{ + MEDFileStructuredMesh::clearNonDiscrAttributes(); + MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_cmesh);//to it is not a bug umeshsplit have already the method implemented +} + +MEDFileCMesh::MEDFileCMesh() +{ +} + +MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) +try +{ + loadCMeshFromFile(fid,mName,dt,it,mrs); +} +catch(INTERP_KERNEL::Exception& e) +{ + throw e; +} + +void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) +{ + ParaMEDMEM::MEDCouplingMeshType meshType; + int dummy0,dummy1; + std::string dtunit; + int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit); + if(meshType!=CARTESIAN) + { + std::ostringstream oss; oss << "Trying to load as cartesian an existing mesh with name '" << mName << "' that is NOT cartesian !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + MEDFileCMeshL2 loaderl2; + loaderl2.loadAll(fid,mid,mName,dt,it); + MEDCouplingCMesh *mesh=loaderl2.getMesh(); + mesh->incrRef(); + _cmesh=mesh; + 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(); return _cmesh; } -MEDCouplingMesh *MEDFileCMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception) +const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const { - if(renum) - throw INTERP_KERNEL::Exception("MEDFileCMesh does not support renumbering ! To do it perform request of renum array directly !"); - if(meshDimRelToMax!=0) - throw INTERP_KERNEL::Exception("MEDFileCMesh does not support multi level for mesh 0 expected as input !"); - const MEDCouplingCMesh *m=getMesh(); - if(m) - m->incrRef(); - return const_cast(m); + synchronizeTinyInfoOnLeaves(); + 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) @@ -2690,7 +5247,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); @@ -2698,7 +5255,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 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;igetNumberOfTuples(),da->getConstPointer()); } // - med_geometry_type geoTypeReq=MED_NONE; - switch(spaceDim) - { - case 3: - geoTypeReq=MED_HEXA8; - break; - case 2: - geoTypeReq=MED_QUAD4; - break; - case 1: - geoTypeReq=MED_SEG2; - break; - case 0: - geoTypeReq=MED_POINT1; - break; - default: - throw INTERP_KERNEL::Exception("Invalid spacedim detected for cartesian mesh ! Must be in (1,2,3) !"); - } - // - if((const DataArrayInt *)_fam_cells) - MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()); - if((const DataArrayInt *)_fam_nodes) - MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()); - // - MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str); -} - -int MEDFileCMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) -{ - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getSizeAtLevel : Only available for levels 0 or 1 !"); - if(!((const MEDCouplingCMesh *)_cmesh)) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getSizeAtLevel : No cartesian mesh set !"); - if(meshDimRelToMaxExt==0) - return _cmesh->getNumberOfCells(); - else - return _cmesh->getNumberOfNodes(); + std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE)); + MEDFileStructuredMesh::writeStructuredLL(fid,meshName); } void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const { const MEDCouplingCMesh *cmesh=_cmesh; - (const_cast(cmesh))->setName(_name.c_str()); - (const_cast(cmesh))->setDescription(_desc_name.c_str()); + if(!cmesh) + return; + (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); } -int MEDFileCMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) +MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New() { - const MEDCouplingCMesh *cmesh(_cmesh); - if(!cmesh) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getNumberOfNodes : no cartesian mesh set !"); - return cmesh->getNumberOfNodes(); + return new MEDFileCurveLinearMesh; } -std::vector MEDFileCMesh::getNonEmptyLevels() const +MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs) { - std::vector ret(1); - return ret; + 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()); + } + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY); + int dt,it; + ParaMEDMEM::MEDCouplingMeshType meshType; + std::string dummy2; + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2); + return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs); } -std::vector MEDFileCMesh::getNonEmptyLevelsExt() const +MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { - std::vector ret(2); - ret[0]=1; + MEDFileUtilities::CheckFileForRead(fileName); + 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::vector MEDFileCurveLinearMesh::getDirectChildren() const +{ + std::vector ret(MEDFileStructuredMesh::getDirectChildren()); + if((const MEDCouplingCurveLinearMesh *)_clmesh) + ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh); return ret; } -DataArrayInt *MEDFileCMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getFamiliesArr : Only available for levels 0 or 1 !"); - std::vector famIds=getFamiliesIds(fams); - if(meshDimRelToMaxExt==1) + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCurveLinearMesh(*this); + return ret.retn(); +} + +MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const +{ + return new MEDFileCurveLinearMesh; +} + +MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCurveLinearMesh(*this); + if((const MEDCouplingCurveLinearMesh*)_clmesh) + ret->_clmesh=static_cast(_clmesh->deepCpy()); + ret->deepCpyAttributes(); + return ret.retn(); +} + +int MEDFileCurveLinearMesh::getMeshDimension() const +{ + if(!((const MEDCouplingCurveLinearMesh*)_clmesh)) + throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !"); + return _clmesh->getMeshDimension(); +} + +std::string MEDFileCurveLinearMesh::simpleRepr() const +{ + return MEDFileStructuredMesh::simpleRepr(); +} + +std::string MEDFileCurveLinearMesh::advancedRepr() const +{ + return simpleRepr(); +} + +bool MEDFileCurveLinearMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const +{ + if(!MEDFileStructuredMesh::isEqual(other,eps,what)) + return false; + const MEDFileCurveLinearMesh *otherC=dynamic_cast(other); + if(!otherC) { - 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 - { - da->incrRef(); - return da; - } - } - else - throw INTERP_KERNEL::Exception("MEDFileCMesh::getFamiliesArr : no family array specified on nodes !"); + what="Mesh types differ ! This is curve linear and other is NOT !"; + return false; } - else + clearNonDiscrAttributes(); + otherC->clearNonDiscrAttributes(); + const MEDCouplingCurveLinearMesh *coo1=_clmesh; + const MEDCouplingCurveLinearMesh *coo2=otherC->_clmesh; + if((coo1==0 && coo2!=0) || (coo1!=0 && coo2==0)) + { + what="Mismatch of curve linear meshes ! One is defined and not other !"; + return false; + } + if(coo1) { - if((const DataArrayInt *)_fam_cells) + bool ret=coo1->isEqual(coo2,eps); + if(!ret) { - 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 - { - da->incrRef(); - return da; - } + what="curve linear meshes differ !"; + return false; } - else - throw INTERP_KERNEL::Exception("MEDFileCMesh::getFamiliesArr : no family array specified on cells !"); } + return true; } -void MEDFileCMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception) +void MEDFileCurveLinearMesh::clearNonDiscrAttributes() const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileCMesh::setRenumFieldArr : Only available for levels 0 or 1 !"); - if(famArr) - famArr->incrRef(); - if(meshDimRelToMaxExt==0) - _fam_cells=famArr; - else - _fam_nodes=famArr; + MEDFileStructuredMesh::clearNonDiscrAttributes(); + MEDFileUMeshSplitL1::ClearNonDiscrAttributes(_clmesh);//to it is not a bug umeshsplit have already the method implemented } -void MEDFileCMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception) +void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileCMesh::setRenumFieldArr : Only available for levels 0 or 1 !"); - if(renumArr) - renumArr->incrRef(); - if(meshDimRelToMaxExt==0) - _num_cells=renumArr; - else - _num_nodes=renumArr; + const MEDCouplingCurveLinearMesh *clmesh=_clmesh; + if(!clmesh) + return; + (const_cast(clmesh))->setName(_name); + (const_cast(clmesh))->setDescription(_desc_name); + (const_cast(clmesh))->setTime(_time,_iteration,_order); + (const_cast(clmesh))->setTimeUnit(_dt_unit); } -const DataArrayInt *MEDFileCMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !"); - if(meshDimRelToMaxExt==0) - return _fam_cells; - else - return _fam_nodes; + synchronizeTinyInfoOnLeaves(); + return _clmesh; } -const DataArrayInt *MEDFileCMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !"); - if(meshDimRelToMaxExt==0) - return _num_cells; - else - return _num_nodes; + dealWithTinyInfo(m); + if(m) + m->incrRef(); + _clmesh=m; } -const DataArrayInt *MEDFileCMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +const MEDCouplingStructuredMesh *MEDFileCurveLinearMesh::getStructuredMesh() const { - if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !"); - if(meshDimRelToMaxExt==0) - { - if((const DataArrayInt *)_num_cells) - { - int pos; - int maxValue=_num_cells->getMaxValue(pos); - _rev_num_cells=_num_cells->invertArrayN2O2O2N(maxValue+1); - return _rev_num_cells; - } - else - throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no cell renumbering for a request on reverse numbering !"); - } - else + synchronizeTinyInfoOnLeaves(); + return _clmesh; +} + +MEDFileCurveLinearMesh::MEDFileCurveLinearMesh() +{ +} + +MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) +try +{ + loadCLMeshFromFile(fid,mName,dt,it,mrs); +} +catch(INTERP_KERNEL::Exception& e) +{ + throw e; +} + +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); + INTERP_KERNEL::AutoPtr dtunit=MEDLoaderBase::buildEmptyString(MED_LNAME_SIZE); + 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=_clmesh->getSpaceDimension(); + int meshDim=_clmesh->getMeshDimension(); + INTERP_KERNEL::AutoPtr comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE); + INTERP_KERNEL::AutoPtr unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE); + const DataArrayDouble *coords=_clmesh->getCoords(); + if(!coords) + throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::writeLL : no coordinates set !"); + for(int i=0;igetMaxValue(pos); - _rev_num_nodes=_num_nodes->invertArrayN2O2O2N(maxValue+1); - return _rev_num_nodes; - } - else - throw INTERP_KERNEL::Exception("MEDFileCMesh::getRevNumberFieldAtLevel : no node renumbering for a request on reverse numbering !"); + std::string info(_clmesh->getCoords()->getInfoOnComponent(i)); + std::string c,u; + MEDLoaderBase::splitIntoNameAndUnit(info,c,u); + 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); + MEDmeshUniversalNameWr(fid,maa); + 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()); + // + std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE)); + MEDFileStructuredMesh::writeStructuredLL(fid,meshName); } -/*! - * no implementation here, it is not a bug, but intresically no polyhedra in \a this. - */ -bool MEDFileCMesh::unPolyze(std::vector& oldCode, std::vector& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception) +void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) { - oldCode.clear(); newCode.clear(); o2nRenumCell=0; - return false; + ParaMEDMEM::MEDCouplingMeshType meshType; + int dummy0,dummy1; + std::string dtunit; + int mid=MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dtunit); + if(meshType!=CURVE_LINEAR) + { + std::ostringstream oss; oss << "Trying to load as curve linear an existing mesh with name '" << mName << "' that is NOT curve linear !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + MEDFileCLMeshL2 loaderl2; + loaderl2.loadAll(fid,mid,mName,dt,it); + MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh(); + mesh->incrRef(); + _clmesh=mesh; + loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs); } MEDFileMeshMultiTS *MEDFileMeshMultiTS::New() @@ -2921,24 +5510,53 @@ 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); } -const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception) +MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=MEDFileMeshMultiTS::New(); + std::vector< MEDCouplingAutoRefCountObjectPtr > meshOneTs(_mesh_one_ts.size()); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++,i++) + if((const MEDFileMesh *)*it) + meshOneTs[i]=(*it)->deepCpy(); + ret->_mesh_one_ts=meshOneTs; + return ret.retn(); +} + +std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const +{ + return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); +} + +std::vector MEDFileMeshMultiTS::getDirectChildren() const +{ + std::vector ret; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) + { + const MEDFileMesh *cur(*it); + if(cur) + ret.push_back(cur); + } + return ret; +} + +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); @@ -2946,7 +5564,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++) @@ -2958,14 +5576,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 !"); @@ -2975,7 +5593,7 @@ void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP _mesh_one_ts[0]=mesh1TimeStep; } -void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception) +void MEDFileMeshMultiTS::write(med_idt fid) const { for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) { @@ -2984,16 +5602,16 @@ void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception } } -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) +void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName) {//for the moment to be improved _mesh_one_ts.resize(1); _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1); @@ -3003,49 +5621,49 @@ 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++) @@ -3055,27 +5673,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()) { @@ -3085,7 +5704,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); @@ -3098,7 +5718,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; @@ -3118,7 +5738,7 @@ std::vector MEDFileMeshes::getMeshesNames() const throw(INTERP_KERN 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++) @@ -3130,12 +5750,12 @@ bool MEDFileMeshes::changeNames(const std::vector< std::pair=(int)_meshes.size()) { @@ -3165,27 +5785,56 @@ 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 +{ + std::vector< MEDCouplingAutoRefCountObjectPtr > meshes(_meshes.size()); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_meshes.begin();it!=_meshes.end();it++,i++) + if((const MEDFileMeshMultiTS *)*it) + meshes[i]=(*it)->deepCpy(); + MEDCouplingAutoRefCountObjectPtr ret=MEDFileMeshes::New(); + ret->_meshes=meshes; + return ret.retn(); +} + +std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const +{ + return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); +} + +std::vector MEDFileMeshes::getDirectChildren() const +{ + std::vector ret; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_meshes.begin();it!=_meshes.end();it++) + { + const MEDFileMeshMultiTS *cur(*it); + if(cur) + ret.push_back(cur); + } + return ret; +} std::string MEDFileMeshes::simpleRepr() const { @@ -3204,7 +5853,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;