X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FMEDLoader%2FMEDFileMesh.cxx;h=74a40b7f0443866c973a137b50c5211237253715;hb=48e3deca564ef5e3d0b5db1b23993b1f73e1682a;hp=6f77ac21770c9d32dba7126cf8ad001dfb18952c;hpb=293a6104470482e450701aa8061d9b244f2057d5;p=tools%2Fmedcoupling.git diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index 6f77ac217..74a40b7f0 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D +// Copyright (C) 2007-2013 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 @@ -34,11 +34,35 @@ 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) { } -MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +std::size_t MEDFileMesh::getHeapMemorySize() 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; +} + +/*! + * 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 char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { std::vector ms=MEDLoader::GetMeshNames(fileName); if(ms.empty()) @@ -57,16 +81,20 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Excepti 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().c_str(),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().c_str(),dt,it,mrs); + return (MEDFileCMesh *)ret.retn(); + } + case CURVE_LINEAR: + { + MEDCouplingAutoRefCountObjectPtr ret=MEDFileCurveLinearMesh::New(); + ret->loadCLMeshFromFile(fid,ms.front().c_str(),dt,it,mrs); + return (MEDFileCurveLinearMesh *)ret.retn(); } default: { @@ -76,7 +104,21 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Excepti } } -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 char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { MEDFileUtilities::CheckFileForRead(fileName); ParaMEDMEM::MEDCouplingMeshType meshType; @@ -89,16 +131,20 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, i 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: { @@ -108,6 +154,13 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, i } } +/*! + * 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 throw(INTERP_KERNEL::Exception) { if(!existsFamily(0)) @@ -117,6 +170,16 @@ void MEDFileMesh::write(med_idt fid) const throw(INTERP_KERNEL::Exception) writeLL(fid); } +/*! + * 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 char *fileName, int mode) const throw(INTERP_KERNEL::Exception) { med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); @@ -126,6 +189,13 @@ void MEDFileMesh::write(const char *fileName, int mode) const throw(INTERP_KERNE 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 +223,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,6 +236,9 @@ bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wha return true; } +/*! + * Clears redundant attributes of incorporated data arrays. + */ void MEDFileMesh::clearNonDiscrAttributes() const { @@ -188,19 +257,29 @@ bool MEDFileMesh::changeNames(const std::vector< std::pair - a sequence of names of the families. + * \throw If the name of a nonexistent group is specified. + */ std::vector MEDFileMesh::getFamiliesOnGroup(const char *name) const throw(INTERP_KERNEL::Exception) { 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,6 +287,12 @@ std::vector MEDFileMesh::getFamiliesOnGroup(const char *name) const return (*it).second; } +/*! + * 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 throw(INTERP_KERNEL::Exception) { std::set fams; @@ -217,8 +302,8 @@ std::vector MEDFileMesh::getFamiliesOnGroups(const std::vector grps=getGroupsNames(); oss << "\" !\nAvailable groups are :"; - std::copy(grps.begin(),grps.end(),std::ostream_iterator(oss," ")); + std::vector grps2=getGroupsNames(); oss << "\" !\nAvailable groups are :"; + std::copy(grps2.begin(),grps2.end(),std::ostream_iterator(oss," ")); throw INTERP_KERNEL::Exception(oss.str().c_str()); } fams.insert((*it2).second.begin(),(*it2).second.end()); @@ -227,6 +312,12 @@ std::vector MEDFileMesh::getFamiliesOnGroups(const std::vector - sequence of ids of the families. + * \throw If the name of a nonexistent group is specified. + */ std::vector MEDFileMesh::getFamiliesIdsOnGroup(const char *name) const throw(INTERP_KERNEL::Exception) { std::string oname(name); @@ -242,8 +333,11 @@ 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) { @@ -258,8 +352,12 @@ void MEDFileMesh::setFamiliesOnGroup(const char *name, const std::vector& famIds) throw(INTERP_KERNEL::Exception) { @@ -274,6 +372,11 @@ void MEDFileMesh::setFamiliesIdsOnGroup(const char *name, const std::vector _groups[oname]=fams; } +/*! + * 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 char *name) const throw(INTERP_KERNEL::Exception) { std::vector ret; @@ -290,7 +393,10 @@ 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) { @@ -316,6 +422,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 +435,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,7 +449,8 @@ 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) { @@ -370,6 +485,32 @@ void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception _groups=groups; } +/*! + * 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() throw(INTERP_KERNEL::Exception) +{ + 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 char *name) throw(INTERP_KERNEL::Exception) { std::string oname(name); @@ -384,6 +525,11 @@ void MEDFileMesh::removeGroup(const char *name) throw(INTERP_KERNEL::Exception) _groups.erase(it); } +/*! + * 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 char *name) throw(INTERP_KERNEL::Exception) { std::string oname(name); @@ -405,6 +551,69 @@ void MEDFileMesh::removeFamily(const char *name) 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() throw(INTERP_KERNEL::Exception) +{ + 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() throw(INTERP_KERNEL::Exception) +{ + 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.c_str()); + 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 char *oldName, const char *newName) throw(INTERP_KERNEL::Exception) { std::string oname(oldName); @@ -417,8 +626,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,8 +638,10 @@ 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) { @@ -446,6 +657,13 @@ void MEDFileMesh::changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exce _families=fam2; } +/*! + * 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 char *oldName, const char *newName) throw(INTERP_KERNEL::Exception) { std::string oname(oldName); @@ -476,6 +694,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 +716,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) @@ -543,12 +776,22 @@ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) cons return ret; } +/*! + * 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 char *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,12 +800,22 @@ bool MEDFileMesh::existsFamily(int famId) const return false; } +/*! + * 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 char *familyName) const { std::string fname(familyName); return _families.find(fname)!=_families.end(); } +/*! + * 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 char *familyName, int id) { std::string fname(familyName); @@ -585,8 +838,10 @@ 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) { @@ -615,12 +870,17 @@ 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) { @@ -644,9 +904,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,10 +915,13 @@ 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) { @@ -678,9 +941,9 @@ 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; @@ -698,10 +961,12 @@ 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) { @@ -749,6 +1014,39 @@ void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *ot } } +void MEDFileMesh::changeAllGroupsContainingFamily(const char *familyNameToChange, const std::vector& newFamiliesNames) throw(INTERP_KERNEL::Exception) +{ + ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames); +} + +void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map >& groups, const char *familyNameToChange, const std::vector& newFamiliesNames) throw(INTERP_KERNEL::Exception) +{ + 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) throw(INTERP_KERNEL::Exception) +{ + 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 +1055,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) throw(INTERP_KERNEL::Exception) { - 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,20 +1074,35 @@ 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; } +/*! + * 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 char *name) const throw(INTERP_KERNEL::Exception) { std::string oname(name); @@ -804,6 +1117,12 @@ int MEDFileMesh::getFamilyId(const char *name) const throw(INTERP_KERNEL::Except return (*it).second; } +/*! + * 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 throw(INTERP_KERNEL::Exception) { std::vector ret(fams.size()); @@ -823,10 +1142,32 @@ std::vector MEDFileMesh::getFamiliesIds(const std::vector& fam return ret; } +/*! + * 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 throw(INTERP_KERNEL::Exception) +{ + 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 throw(INTERP_KERNEL::Exception) { 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 +1176,15 @@ int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception) return ret; } +/*! + * 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 throw(INTERP_KERNEL::Exception) { 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,6 +1193,53 @@ int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception) return ret; } +/*! + * Returns a maximal id of families in \a this mesh. Not only named families are + * considered but all family fields as well. + * \return int - the maximal family id. + */ +int MEDFileMesh::getTheMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception) +{ + 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 throw(INTERP_KERNEL::Exception) +{ + 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 throw(INTERP_KERNEL::Exception) +{ + 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 throw(INTERP_KERNEL::Exception) { MEDCouplingAutoRefCountObjectPtr ret=DataArrayInt::New(); @@ -855,7 +1248,28 @@ 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 throw(INTERP_KERNEL::Exception) +{ + 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(); } /*! @@ -873,13 +1287,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()) @@ -932,15 +1346,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 +1372,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 +1396,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,7 +1420,7 @@ 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) @@ -1024,15 +1438,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 +1460,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,7 +1493,11 @@ 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) { @@ -1090,6 +1508,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,6 +1522,19 @@ std::string MEDFileMesh::simpleRepr() const return oss.str(); } +/*! + * 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 char *grp, bool renum) const throw(INTERP_KERNEL::Exception) { std::vector tmp(1); @@ -1108,12 +1544,37 @@ DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const char *grp, return ret; } +/*! + * 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 throw(INTERP_KERNEL::Exception) { std::vector fams2=getFamiliesOnGroups(grps); return getFamiliesArr(meshDimRelToMaxExt,fams2,renum); } +/*! + * 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 char *fam, bool renum) const throw(INTERP_KERNEL::Exception) { std::vector tmp(1); @@ -1123,6 +1584,17 @@ DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const char *fam, return ret; } +/*! + * 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 char *grp, bool renum) const throw(INTERP_KERNEL::Exception) { std::vector tmp(1); @@ -1132,11 +1604,33 @@ DataArrayInt *MEDFileMesh::getNodeGroupArr(const char *grp, bool renum) const th return ret; } +/*! + * 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 throw(INTERP_KERNEL::Exception) { return getGroupsArr(1,grps,renum); } +/*! + * 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 char *fam, bool renum) const throw(INTERP_KERNEL::Exception) { std::vector tmp(1); @@ -1146,11 +1640,33 @@ DataArrayInt *MEDFileMesh::getNodeFamilyArr(const char *fam, bool renum) const t return ret; } +/*! + * 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 throw(INTERP_KERNEL::Exception) { return getFamiliesArr(1,fams,renum); } +/*! + * 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) throw(INTERP_KERNEL::Exception) { if(grps.empty()) @@ -1188,9 +1704,9 @@ void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector 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 +1716,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); @@ -1222,9 +1738,13 @@ void MEDFileMesh::appendFamilyEntries(const std::set& famIds, const std::ve 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)); + } } /*! @@ -1287,6 +1807,8 @@ int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector& code, int str */ void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m) throw(INTERP_KERNEL::Exception) { + if(!m) + throw INTERP_KERNEL::Exception("MEDFileMesh::dealWithTinyInfo : input mesh in NULL !"); if(_name.empty()) _name=m->getName(); else @@ -1302,6 +1824,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 @@ -1317,14 +1854,38 @@ void MEDFileMesh::getFamilyRepr(std::ostream& oss) const } } -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 char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { MEDFileUtilities::CheckFileForRead(fileName); MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - return new MEDFileUMesh(fid,mName,dt,it); + 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 char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { std::vector ms=MEDLoader::GetMeshNames(fileName); if(ms.empty()) @@ -1338,14 +1899,79 @@ MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep 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); + return new MEDFileUMesh(fid,ms.front().c_str(),dt,it,mrs); } +/*! + * Returns an empty instance of MEDFileUMesh. + * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this + * mesh using decrRef() as it is no more needed. + */ MEDFileUMesh *MEDFileUMesh::New() { return new MEDFileUMesh; } +std::size_t MEDFileUMesh::getHeapMemorySize() const +{ + std::size_t ret=MEDFileMesh::getHeapMemorySize(); + if((const DataArrayDouble*)_coords) + ret+=_coords->getHeapMemorySize(); + if((const DataArrayInt *)_fam_coords) + ret+=_fam_coords->getHeapMemorySize(); + if((const DataArrayInt *)_num_coords) + ret+=_num_coords->getHeapMemorySize(); + if((const DataArrayInt *)_rev_num_coords) + ret+=_rev_num_coords->getHeapMemorySize(); + if((const DataArrayAsciiChar *)_name_coords) + ret+=_name_coords->getHeapMemorySize(); + ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_ms.begin();it!=_ms.end();it++) + if((const MEDFileUMeshSplitL1*) *it) + ret+=(*it)->getHeapMemorySize(); + return ret; +} + +MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileUMesh(*this); + return ret.retn(); +} + +MEDFileMesh *MEDFileUMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileUMesh; +} + +MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception) +{ + 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(); + } + 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)) @@ -1406,6 +2032,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 +2070,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 +2088,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); @@ -1456,17 +2103,17 @@ MEDFileUMesh::MEDFileUMesh() { } -MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) 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 char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { MEDFileUMeshL2 loaderl2; ParaMEDMEM::MEDCouplingMeshType meshType; @@ -1478,7 +2125,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(); } @@ -1526,13 +2178,18 @@ 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); + MEDFileUMeshL2::WriteCoords(fid,maa,_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); } +/*! + * 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 +2201,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,19 +2218,74 @@ std::vector MEDFileUMesh::getNonEmptyLevelsExt() const return ret0; } -/*! - * This methods returns all relative mesh levels where group 'grp' is defined \b excluded \b nodes. - * To include nodes call MEDFileUMesh::getGrpNonEmptyLevelsExt method. - */ -std::vector MEDFileUMesh::getGrpNonEmptyLevels(const char *grp) const throw(INTERP_KERNEL::Exception) +std::vector MEDFileUMesh::getFamArrNonEmptyLevelsExt() const { - std::vector fams=getFamiliesOnGroup(grp); - return getFamsNonEmptyLevels(fams); + 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; } -/*! - * 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. - */ +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; +} + +/*! + * 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 fams=getFamiliesOnGroup(grp); + return getFamsNonEmptyLevels(fams); +} + +/*! + * 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 fams=getFamiliesOnGroup(grp); @@ -1577,8 +2293,10 @@ std::vector MEDFileUMesh::getGrpNonEmptyLevelsExt(const char *grp) const th } /*! - * 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) { @@ -1587,7 +2305,9 @@ std::vector MEDFileUMesh::getFamNonEmptyLevels(const char *fam) const throw } /*! - * 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) { @@ -1596,8 +2316,10 @@ std::vector MEDFileUMesh::getFamNonEmptyLevelsExt(const char *fam) const th } /*! - * 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) { @@ -1606,7 +2328,9 @@ std::vector MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector - a sequence of the relative dimensions. */ std::vector MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector& grps) const throw(INTERP_KERNEL::Exception) { @@ -1615,8 +2339,10 @@ std::vector MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector - a sequence of the relative dimensions. */ std::vector MEDFileUMesh::getFamsNonEmptyLevels(const std::vector& fams) const throw(INTERP_KERNEL::Exception) { @@ -1630,7 +2356,9 @@ 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) { @@ -1651,7 +2379,10 @@ 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) { @@ -1666,6 +2397,80 @@ std::vector MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToM return ret; } +int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) +{ + 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 throw(INTERP_KERNEL::Exception) +{ + 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 throw(INTERP_KERNEL::Exception) +{ + 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 throw(INTERP_KERNEL::Exception) { int lev=0; @@ -1675,6 +2480,12 @@ int MEDFileUMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !"); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { const DataArrayDouble *coo=_coords; @@ -1683,6 +2494,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,11 +2546,21 @@ 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(); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -1747,6 +2572,12 @@ int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERN return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize(); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -1755,6 +2586,12 @@ const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) return l1->getFamilyField(); } +/*! + * Returns the optional numbers of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \return const DataArrayInt * - the array of the entity numbers. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + */ const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -1763,6 +2600,14 @@ const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) return l1->getNumberField(); } +const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt==1) + return _name_coords; + const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt); + return l1->getNameField(); +} + int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) { const DataArrayDouble *coo=_coords; @@ -1771,6 +2616,14 @@ int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) return coo->getNumberOfTuples(); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -1784,7 +2637,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,33 +2650,88 @@ DataArrayDouble *MEDFileUMesh::getCoords() const return 0; } +/*! + * 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 char *grp, bool renum) const throw(INTERP_KERNEL::Exception) { synchronizeTinyInfoOnLeaves(); std::vector tmp(1); tmp[0]=grp; - MEDCouplingUMesh *ret=getGroups(meshDimRelToMaxExt,tmp,renum); - ret->setName(grp); - return ret; + return getGroups(meshDimRelToMaxExt,tmp,renum); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { 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].c_str()); + return zeRet.retn(); } +/*! + * 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 char *fam, bool renum) const throw(INTERP_KERNEL::Exception) { synchronizeTinyInfoOnLeaves(); std::vector tmp(1); tmp[0]=fam; - MEDCouplingUMesh *ret=getFamilies(meshDimRelToMaxExt,tmp,renum); - ret->setName(fam); - return ret; + return getFamilies(meshDimRelToMaxExt,tmp,renum); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { synchronizeTinyInfoOnLeaves(); @@ -1832,17 +2741,32 @@ 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].c_str()); + return zeRet.retn(); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { std::vector famIds=getFamiliesIds(fams); @@ -1858,10 +2782,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,6 +2794,20 @@ DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::ve return l1->getFamilyPartArr(0,0,renum); } +/*! + * Returns a MEDCouplingUMesh of a given relative dimension. + * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not + * valid**. This is a feature, because MEDLoader does not create cells that do not exist! + * To build a valid MEDCouplingUMesh from the returned one in this case, + * call MEDCouplingUMesh::Build0DMeshFromCoords(). + * \param [in] meshDimRelToMax - the relative dimension of interest. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \sa getGenMeshAtLevel() + */ MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception) { synchronizeTinyInfoOnLeaves(); @@ -1892,26 +2827,72 @@ MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renu return l1->getWholeMesh(renum); } +/*! + * Returns a MEDCouplingUMesh of a given relative dimension. + * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not + * valid**. This is a feature, because MEDLoader does not create cells that do not exist! + * To build a valid MEDCouplingUMesh from the returned one in this case, + * call MEDCouplingUMesh::Build0DMeshFromCoords(). + * \param [in] meshDimRelToMax - the relative dimension of interest. + * \param [in] renum - if \c true, the returned mesh is permuted according to the + * optional numbers of mesh entities. + * \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to + * delete using decrRef() as it is no more needed. + * \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh. + * \sa getMeshAtLevel() + */ MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception) { return getMeshAtLevel(meshDimRelToMax,renum); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { return getMeshAtLevel(0,renum); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { return getMeshAtLevel(-1,renum); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { return getMeshAtLevel(-2,renum); } +/*! + * 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 throw(INTERP_KERNEL::Exception) { return getMeshAtLevel(-3,renum); @@ -1961,6 +2942,12 @@ void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const } } +/*! + * 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) throw(INTERP_KERNEL::Exception) { if(!coords) @@ -1974,6 +2961,11 @@ void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Excep _fam_coords->fillWithZero(); } +/*! + * 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) throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -1987,6 +2979,9 @@ void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNE optimizeFamilies(); } +/*! + * Removes all families with ids not present in the family fields of \a this mesh. + */ void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception) { std::vector levs=getNonEmptyLevelsExt(); @@ -1994,9 +2989,9 @@ void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception) 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; @@ -2110,9 +3105,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(); } /*! @@ -2132,7 +3127,7 @@ bool MEDFileUMesh::unPolyze(std::vector& oldCode, std::vector& newCode std::vector< MEDCouplingAutoRefCountObjectPtr > memorySaverIfThrow;//same than renumCellsSplited only in case of throw int start=0; int end=0; - for(std::vector::const_reverse_iterator it=levs.rbegin();it!=levs.rend();it++) + for(std::vector::reverse_iterator it=levs.rbegin();it!=levs.rend();it++) { MEDCouplingAutoRefCountObjectPtr m=getMeshAtLevel(*it); std::vector code1=m->getDistributionOfTypes(); @@ -2180,21 +3175,199 @@ 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 +{ + MEDLoaderAccVisit1():_new_nb_of_nodes(0) { } + int operator()(bool val) { return val?_new_nb_of_nodes++:-1; } + int _new_nb_of_nodes; +}; + +/*! + * 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() throw(INTERP_KERNEL::Exception) +{ + 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(); +} + +/*! + * 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) throw(INTERP_KERNEL::Exception) { 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()); - + 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) throw(INTERP_KERNEL::Exception) +{ + std::vector levs=getNonEmptyLevelsExt(); + if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end()) + { + std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in "; + std::copy(levs.begin(),levs.end(),std::ostream_iterator(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + 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) throw(INTERP_KERNEL::Exception) +{ + if(!ids) + throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !"); + std::string grpName(ids->getName()); + if(grpName.empty()) + throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !"); + ids->checkStrictlyMonotonic(true); + famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr famArrTmp(famArr); + std::vector grpsNames=getGroupsNames(); + if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end()) + { + 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).c_str(),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).c_str(),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) throw(INTERP_KERNEL::Exception) { std::string oldName=getFamilyNameGivenId(id); @@ -2202,6 +3375,11 @@ void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamNa _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) throw(INTERP_KERNEL::Exception) { std::vector levSet=getNonEmptyLevels(); @@ -2212,12 +3390,20 @@ void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::E _ms[pos]=0; } +/*! + * 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) throw(INTERP_KERNEL::Exception) -{ - setMeshAtLevelGen(meshDimRelToMax,m,newOrOld); -} - -void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception) { dealWithTinyInfo(m); std::vector levSet=getNonEmptyLevels(); @@ -2242,7 +3428,67 @@ void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, b _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld); } -void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector& ms) throw(INTERP_KERNEL::Exception) +/*! + * 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) throw(INTERP_KERNEL::Exception) +{ + 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.c_str()); +} + +/*! + * 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) throw(INTERP_KERNEL::Exception) { if(ms.empty()) throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !"); @@ -2262,11 +3508,30 @@ 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); } +/*! + * 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) throw(INTERP_KERNEL::Exception) { if(ms.empty()) @@ -2317,6 +3582,14 @@ DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector(ret); } +/*! + * 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) throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -2344,6 +3617,13 @@ void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famAr return _ms[traducedRk]->setFamilyArr(famArr); } +/*! + * 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) throw(INTERP_KERNEL::Exception) { if(meshDimRelToMaxExt==1) @@ -2373,6 +3653,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) throw(INTERP_KERNEL::Exception) +{ + 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++) @@ -2398,6 +3712,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,80 +3741,82 @@ void MEDFileUMesh::computeRevNum() const } } -MEDFileCMesh *MEDFileCMesh::New() +std::size_t MEDFileStructuredMesh::getHeapMemorySize() const { - return new MEDFileCMesh; + std::size_t ret=MEDFileMesh::getHeapMemorySize(); + if((const DataArrayInt*)_fam_nodes) + ret+=_fam_nodes->getHeapMemorySize(); + if((const DataArrayInt*)_num_nodes) + ret+=_num_nodes->getHeapMemorySize(); + if((const DataArrayInt*)_fam_cells) + ret+=_fam_cells->getHeapMemorySize(); + if((const DataArrayInt*)_num_cells) + ret+=_num_cells->getHeapMemorySize(); + if((const DataArrayInt*)_rev_num_nodes) + ret+=_rev_num_nodes->getHeapMemorySize(); + if((const DataArrayInt*)_rev_num_cells) + ret+=_rev_num_cells->getHeapMemorySize(); + return ret; } -MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception) +int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) { - std::vector ms=MEDLoader::GetMeshNames(fileName); - if(ms.empty()) + int ret=-std::numeric_limits::max(),tmp=-1; + if((const DataArrayInt *)_fam_nodes) { - std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !"; - throw INTERP_KERNEL::Exception(oss.str().c_str()); + int val=_fam_nodes->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); } - 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); -} - -MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) -{ - MEDFileUtilities::CheckFileForRead(fileName); - MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); - return new MEDFileCMesh(fid,mName,dt,it); + if((const DataArrayInt *)_fam_cells) + { + int val=_fam_cells->getMaxValue(tmp); + ret=std::max(ret,std::abs(val)); + } + return ret; } -int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) +int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) { - if(!((const MEDCouplingCMesh*)_cmesh)) - throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !"); - return _cmesh->getMeshDimension(); -} - -std::string MEDFileCMesh::simpleRepr() 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); + } + return ret; } -std::string MEDFileCMesh::advancedRepr() const +int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception) { - 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); + } + 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)) - { - 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; - } - } const DataArrayInt *famc1=_fam_nodes; const DataArrayInt *famc2=otherC->_fam_nodes; if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0)) @@ -2546,13 +3881,44 @@ bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh 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_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(""); @@ -2567,61 +3933,388 @@ void MEDFileCMesh::clearNonDiscrAttributes() const (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 throw(INTERP_KERNEL::Exception) { + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !"); + std::vector famIds=getFamiliesIds(fams); + if(meshDimRelToMaxExt==1) + { + if((const DataArrayInt *)_fam_nodes) + { + MEDCouplingAutoRefCountObjectPtr da; + if(!famIds.empty()) + da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size()); + else + da=_fam_nodes->getIdsEqualList(0,0); + if(renum) + return MEDFileUMeshSplitL1::Renumber(_num_nodes,da); + else + return da.retn(); + } + else + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !"); + } + else + { + if((const DataArrayInt *)_fam_cells) + { + MEDCouplingAutoRefCountObjectPtr da; + if(!famIds.empty()) + da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size()); + else + da=_fam_cells->getIdsEqualList(0,0); + if(renum) + return MEDFileUMeshSplitL1::Renumber(_num_cells,da); + else + return da.retn(); + } + else + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !"); + } } -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) - { - throw e; - } +/*! + * 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. + */ +void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !"); + const MEDCouplingStructuredMesh *mesh=getStructuredMesh(); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !"); + if(meshDimRelToMaxExt==0) + { + int nbCells=mesh->getNumberOfCells(); + famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !"); + _fam_cells=famArr; + } + else + { + int nbNodes=mesh->getNumberOfNodes(); + famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !"); + _fam_nodes=famArr; + } + if(famArr) + famArr->incrRef(); +} -void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception) +/*! + * Sets the optional numbers of mesh entities of a given dimension. + * \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities. + * \param [in] renumArr - the array of the numbers. + * \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh. + * \throw If \a renumArr has an invalid size. + * \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1. + */ +void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) 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) + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !"); + const MEDCouplingStructuredMesh *mesh=getStructuredMesh(); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !"); + if(meshDimRelToMaxExt==0) { - 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()); + 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; } - 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); - 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); - if(nbOfElt>0) + else { - _fam_nodes=DataArrayInt::New(); - _fam_nodes->alloc(nbOfElt,1); - MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()); + 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; } - nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf); - if(nbOfElt>0) + 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) throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 !"); + const MEDCouplingStructuredMesh *mesh=getStructuredMesh(); + if(!mesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !"); + if(meshDimRelToMaxExt==0) + { + int nbCells=mesh->getNumberOfCells(); + nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !"); + _names_cells=nameArr; + } + else + { + int nbNodes=mesh->getNumberOfNodes(); + nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !"); + _names_nodes=nameArr; + } + 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 throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !"); + if(meshDimRelToMaxExt==0) + return _fam_cells; + else + return _fam_nodes; +} + +/*! + * 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 throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !"); + if(meshDimRelToMaxExt==0) + return _num_cells; + else + return _num_nodes; +} + +/*! + * 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 throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !"); + if(meshDimRelToMaxExt==0) { - _num_nodes=DataArrayInt::New(); - _num_nodes->alloc(nbOfElt,1); - MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()); + 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 + { + 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 !"); } - int spaceDim=mesh->getSpaceDimension(); +} + +const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 !"); + if(meshDimRelToMaxExt==0) + return _names_cells; + else + return _names_nodes; +} + +/*! + * 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); + if(famNodes) + ret.push_back(1); + if(famCells) + ret.push_back(0); + 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); + if(numNodes) + ret.push_back(1); + if(numCells) + ret.push_back(0); + 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 *namesCells(_names_cells); + if(namesCells) + ret.push_back(0); + return ret; +} + +/*! + * no implementation here, it is not a bug, but intresically no polyhedra in \a this. + */ +bool MEDFileStructuredMesh::unPolyze(std::vector& oldCode, std::vector& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception) +{ + oldCode.clear(); newCode.clear(); o2nRenumCell=0; + return false; +} + +void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception) +{ + DataArrayInt *arr=_fam_nodes; + if(arr) + arr->changeValue(oldId,newId); + arr=_fam_cells; + if(arr) + arr->changeValue(oldId,newId); +} + +void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception) +{ + if((const DataArrayInt*)_fam_nodes) + _fam_nodes=_fam_nodes->deepCpy(); + if((const DataArrayInt*)_num_nodes) + _num_nodes=_num_nodes->deepCpy(); + if((const DataArrayInt*)_fam_cells) + _fam_cells=_fam_cells->deepCpy(); + if((const DataArrayInt*)_num_cells) + _num_cells=_num_cells->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. + * \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 throw(INTERP_KERNEL::Exception) +{ + if(renum) + throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !"); + if(meshDimRelToMax!=0) + throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !"); + const MEDCouplingStructuredMesh *m=getStructuredMesh(); + if(m) + m->incrRef(); + return const_cast(m); +} + +/*! + * 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 throw(INTERP_KERNEL::Exception) +{ + if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !"); + const MEDCouplingStructuredMesh *cmesh=getStructuredMesh(); + if(!cmesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !"); + if(meshDimRelToMaxExt==0) + return cmesh->getNumberOfCells(); + else + return cmesh->getNumberOfNodes(); +} + +int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception) +{ + const MEDCouplingStructuredMesh *cmesh=getStructuredMesh(); + if(!cmesh) + throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !"); + return cmesh->getNumberOfNodes(); +} + +med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception) +{ med_geometry_type geoTypeReq=MED_NONE; - switch(spaceDim) + switch(meshDim) { case 3: geoTypeReq=MED_HEXA8; @@ -2636,52 +4329,343 @@ void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int geoTypeReq=MED_POINT1; break; default: - throw INTERP_KERNEL::Exception("Invalid spacedim detected for cartesian mesh ! Must be in (1,2,3) !"); + throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !"); } + return geoTypeReq; +} + +void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) +{ + 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,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf); + if(nbOfElt>0) + { + if(!mrs || mrs->isNodeFamilyFieldReading()) + { + _fam_nodes=DataArrayInt::New(); + _fam_nodes->alloc(nbOfElt,1); + MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer()); + } + } + nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf); + if(nbOfElt>0) + { + if(!mrs || mrs->isNodeNumFieldReading()) + { + _num_nodes=DataArrayInt::New(); + _num_nodes->alloc(nbOfElt,1); + MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()); + } + } + int meshDim=getStructuredMesh()->getMeshDimension(); + med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim); nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf); 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->isCellFamilyFieldReading()) + { + _fam_cells=DataArrayInt::New(); + _fam_cells->alloc(nbOfElt,1); + MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer()); + } } nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf); if(nbOfElt>0) { - _num_cells=DataArrayInt::New(); - _num_cells->alloc(nbOfElt,1); - MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer()); + if(!mrs || mrs->isCellNumFieldReading()) + { + _num_cells=DataArrayInt::New(); + _num_cells->alloc(nbOfElt,1); + MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer()); + } + } + nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf); + if(nbOfElt>0) + { + if(!mrs || mrs->isCellNameFieldReading()) + { + _names_cells=DataArrayAsciiChar::New(); + _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end + MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer()); + _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end + } + } + nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf); + if(nbOfElt>0) + { + 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,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 + } } } -void MEDFileCMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception) +void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception) +{ + int meshDim=getStructuredMesh()->getMeshDimension(); + med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim); + // + 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()); + if((const DataArrayInt *)_num_cells) + MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()); + if((const DataArrayInt *)_num_nodes) + MEDmeshEntityNumberWr(fid,maa,_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,_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->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,_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()); + } + // + MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_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 char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) +{ + 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,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 char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + return new MEDFileCMesh(fid,mName,dt,it,mrs); +} + +std::size_t MEDFileCMesh::getHeapMemorySize() const +{ + std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize(); + if((const MEDCouplingCMesh *)_cmesh) + ret+=_cmesh->getHeapMemorySize(); + 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 throw(INTERP_KERNEL::Exception) +{ + if(!((const MEDCouplingCMesh*)_cmesh)) + throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !"); + return _cmesh->getMeshDimension(); +} + +/*! + * Returns a string describing \a this mesh. + * \return std::string - the mesh information string. + */ +std::string MEDFileCMesh::simpleRepr() const +{ + return MEDFileStructuredMesh::simpleRepr(); +} + +/*! + * Returns a full textual description of \a this mesh. + * \return std::string - the string holding the mesh description. + */ +std::string MEDFileCMesh::advancedRepr() const +{ + return simpleRepr(); +} + +MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCMesh(*this); + return ret.retn(); +} + +MEDFileMesh *MEDFileCMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception) +{ + return new MEDFileCMesh; +} + +MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception) +{ + 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 char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) +try + { + loadCMeshFromFile(fid,mName,dt,it,mrs); + } +catch(INTERP_KERNEL::Exception& e) + { + throw e; + } + +void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { - DataArrayInt *arr=_fam_nodes; - if(arr) - arr->changeValue(oldId,newId); - arr=_fam_cells; - if(arr) - arr->changeValue(oldId,newId); + 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; } +/*! + * 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) throw(INTERP_KERNEL::Exception) { dealWithTinyInfo(m); @@ -2699,6 +4683,7 @@ void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str); MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str); int spaceDim=_cmesh->getSpaceDimension(); + int meshDim=_cmesh->getMeshDimension(); 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(); + MEDFileStructuredMesh::writeStructuredLL(fid,maa); } void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const { const MEDCouplingCMesh *cmesh=_cmesh; + if(!cmesh) + return; (const_cast(cmesh))->setName(_name.c_str()); (const_cast(cmesh))->setDescription(_desc_name.c_str()); (const_cast(cmesh))->setTime(_time,_iteration,_order); (const_cast(cmesh))->setTimeUnit(_dt_unit.c_str()); } -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 char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { - 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,MED_ACC_RDONLY); + int dt,it; + ParaMEDMEM::MEDCouplingMeshType meshType; + std::string dummy2; + MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2); + return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it,mrs); } -std::vector MEDFileCMesh::getNonEmptyLevelsExt() const +MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { - std::vector ret(2); - ret[0]=1; + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY); + return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs); +} + +std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const +{ + std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize(); + if((const MEDCouplingCurveLinearMesh *)_clmesh) + ret+=_clmesh->getHeapMemorySize(); return ret; } -DataArrayInt *MEDFileCMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector& fams, bool renum) const throw(INTERP_KERNEL::Exception) +MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception) { - 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 throw(INTERP_KERNEL::Exception) +{ + return new MEDFileCurveLinearMesh; +} + +MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception) +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileCurveLinearMesh(*this); + if((const MEDCouplingCurveLinearMesh*)_clmesh) + ret->_clmesh=static_cast(_clmesh->deepCpy()); + ret->deepCpyAttributes(); + return ret.retn(); +} + +int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception) +{ + 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)) { - if((const DataArrayInt *)_fam_cells) + what="Mismatch of curve linear meshes ! One is defined and not other !"; + return false; + } + if(coo1) + { + 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.c_str()); + (const_cast(clmesh))->setDescription(_desc_name.c_str()); + (const_cast(clmesh))->setTime(_time,_iteration,_order); + (const_cast(clmesh))->setTimeUnit(_dt_unit.c_str()); } -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) throw(INTERP_KERNEL::Exception) { - 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 char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) +try + { + loadCLMeshFromFile(fid,mName,dt,it,mrs); + } +catch(INTERP_KERNEL::Exception& e) + { + throw e; + } + +void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception) +{ + 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()); + // + MEDFileStructuredMesh::writeStructuredLL(fid,maa); } -/*! - * 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 char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception) { - 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() @@ -2931,6 +4941,26 @@ MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mN return new MEDFileMeshMultiTS(fileName,mName); } +MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception) +{ + 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::getHeapMemorySize() const +{ + std::size_t ret=_mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) + ret+=(*it)->getHeapMemorySize(); + return ret; +} + const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception) { if(_mesh_one_ts.empty()) @@ -3187,6 +5217,27 @@ catch(INTERP_KERNEL::Exception& e) { } +MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception) +{ + 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::getHeapMemorySize() const +{ + std::size_t ret=_meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_meshes.begin();it!=_meshes.end();it++) + if((const MEDFileMeshMultiTS*)*it) + ret+=(*it)->getHeapMemorySize(); + return ret; +} + std::string MEDFileMeshes::simpleRepr() const { std::ostringstream oss;