return ret;
}
+/*!
+ * This method operates only on maps in \a this. The arrays are not considered here. So this method will remove a family (except "FAMILLE_ZERO" family) if no group lies on it whatever
+ * this family is orphan or not.
+ *
+ * \warning this method is different from removeOrphanFamilies that scans family field array to find orphan families.
+ */
+void MEDFileMesh::removeFamiliesReferedByNoGroups()
+{
+ std::map<std::string,int> fams;
+ std::set<std::string> sfams;
+ for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+ sfams.insert((*it).first);
+ for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
+ for(std::vector<std::string>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
+ sfams.erase(*it1);
+ for(std::set<std::string>::const_iterator it=sfams.begin();it!=sfams.end();it++)
+ if(*it!=DFT_FAM_NAME)
+ _families.erase(*it);
+}
+
+/*!
+ * This method has no impact on groups. This method only works on families. This method firstly removes families not refered by any groups in \a this, then all unused entities
+ * are put as belonging to family 0 ("FAMILLE_ZERO"). Finally, all orphanFamilies are killed.
+ * This method raises an exception if "FAMILLE_ZERO" is already belonging to a group.
+ *
+ * \sa MEDFileMesh::removeOrphanFamilies
+ */
+void MEDFileMesh::rearrangeFamilies()
+{
+ checkOrphanFamilyZero();
+ removeFamiliesReferedByNoGroups();
+ //
+ std::vector<int> levels(getNonEmptyLevelsExt());
+ std::set<int> idsRefed;
+ for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+ idsRefed.insert((*it).second);
+ for(std::vector<int>::const_iterator it=levels.begin();it!=levels.end();it++)
+ {
+ const DataArrayInt *fams(0);
+ try
+ {
+ fams=getFamilyFieldAtLevel(*it);
+ }
+ catch(INTERP_KERNEL::Exception& e) { }
+ if(!fams)
+ continue;
+ std::vector<bool> v(fams->getNumberOfTuples(),false);
+ for(std::set<int>::const_iterator pt=idsRefed.begin();pt!=idsRefed.end();pt++)
+ fams->switchOnTupleEqualTo(*pt,v);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> unfetchedIds(DataArrayInt::BuildListOfSwitchedOff(v));
+ if(!unfetchedIds->empty())
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFams(fams->deepCpy());
+ newFams->setPartOfValuesSimple3(0,unfetchedIds->begin(),unfetchedIds->end(),0,1,1);
+ setFamilyFieldArr(*it,newFams);
+ }
+ }
+ removeOrphanFamilies();
+}
+
+/*!
+ * This method only checks that "FAMILLE_ZERO" is orphan (not belonging to a group).
+ */
+void MEDFileMesh::checkOrphanFamilyZero() const
+{
+ for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
+ {
+ if(std::find((*it).second.begin(),(*it).second.end(),DFT_FAM_NAME)!=(*it).second.end())
+ {
+ std::ostringstream oss; oss << "MEDFileMesh::rearrangeFamilies : Groups \"" << (*it).first << "\" is lying on family \"" << DFT_FAM_NAME << "\" !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ }
+}
+
/*!
* Renames a group in \a this mesh.
* \param [in] oldName - a current name of the group to rename.
throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
int tracucedRk=-meshDimRelToMaxExt;
if(tracucedRk>=(int)_ms.size())
- throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
+ throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
return _ms[tracucedRk];
throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
int tracucedRk=-meshDimRelToMaxExt;
if(tracucedRk>=(int)_ms.size())
- throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
+ throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
return _ms[tracucedRk];
return ret.retn();
}
+/*!
+ * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
+ * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
+ * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
+ *
+ * \param [in] conversionType - conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
+ * corresponding quadratic cells. 1 is those creating the 'most' complex.
+ * \param [in] eps - detection threshold for coordinates.
+ * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
+ *
+ * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
+ */
+MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
+{
+ MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
+ int initialNbNodes(getNumberOfNodes());
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
+ }
+ DataArrayDouble *zeCoords(m0->getCoords());
+ ret->setMeshAtLevel(0,m0);
+ std::vector<int> levs(getNonEmptyLevels());
+ const DataArrayInt *famField(getFamilyFieldAtLevel(0));
+ if(famField)
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+ ret->setFamilyFieldArr(0,famFieldCpy);
+ }
+ famField=getFamilyFieldAtLevel(1);
+ if(famField)
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
+ fam->fillWithZero();
+ fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
+ ret->setFamilyFieldArr(1,fam);
+ }
+ ret->copyFamGrpMapsFrom(*this);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> partZeCoords(zeCoords->selectByTupleId2(initialNbNodes,zeCoords->getNumberOfTuples(),1));
+ for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
+ {
+ if(*lev==0)
+ continue;
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
+ }
+ MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleId2(initialNbNodes,m1->getNumberOfNodes(),1));
+ DataArrayInt *b(0);
+ bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
+ if(!a)
+ {
+ std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ b->applyLin(1,initialNbNodes);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
+ std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum(DataArrayInt::Aggregate(v));
+ m1->renumberNodesInConn(renum->begin());
+ m1->setCoords(zeCoords);
+ ret->setMeshAtLevel(*lev,m1);
+ famField=getFamilyFieldAtLevel(*lev);
+ if(famField)
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+ ret->setFamilyFieldArr(*lev,famFieldCpy);
+ }
+ }
+ return ret.retn();
+}
+
+/*!
+ * This method converts all quadratic cells in \a this into linear cells.
+ * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
+ * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
+ *
+ * \param [in] eps - detection threshold for coordinates.
+ * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
+ *
+ * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
+ */
+MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
+{
+ MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
+ m0->convertQuadraticCellsToLinear();
+ m0->zipCoords();
+ DataArrayDouble *zeCoords(m0->getCoords());
+ ret->setMeshAtLevel(0,m0);
+ std::vector<int> levs(getNonEmptyLevels());
+ const DataArrayInt *famField(getFamilyFieldAtLevel(0));
+ if(famField)
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+ ret->setFamilyFieldArr(0,famFieldCpy);
+ }
+ famField=getFamilyFieldAtLevel(1);
+ if(famField)
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(famField->selectByTupleId2(0,zeCoords->getNumberOfTuples(),1));
+ ret->setFamilyFieldArr(1,fam);
+ }
+ ret->copyFamGrpMapsFrom(*this);
+ for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
+ {
+ if(*lev==0)
+ continue;
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
+ MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
+ m1->convertQuadraticCellsToLinear();
+ m1->zipCoords();
+ DataArrayInt *b(0);
+ bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
+ if(!a)
+ {
+ std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ m1->renumberNodesInConn(b->begin());
+ m1->setCoords(zeCoords);
+ ret->setMeshAtLevel(*lev,m1);
+ famField=getFamilyFieldAtLevel(*lev);
+ if(famField)
+ {
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+ ret->setFamilyFieldArr(*lev,famFieldCpy);
+ }
+ }
+ return ret.retn();
+}
+
void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI, MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>& bigArrayD)
{
clearNonDiscrAttributes();
* Adds a group of nodes to \a this mesh.
* \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
* The ids should be sorted and different each other (MED file norm).
+ *
+ * \warning this method can alter default "FAMILLE_ZERO" family.
+ * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
+ *
* \throw If the node coordinates array is not set.
* \throw If \a ids == \c NULL.
* \throw If \a ids->getName() == "".
/*!
* Adds a group of nodes/cells/faces/edges to \a this mesh.
+ *
* \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
* The ids should be sorted and different each other (MED file norm).
+ *
+ * \warning this method can alter default "FAMILLE_ZERO" family.
+ * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
+ *
* \throw If the node coordinates array is not set.
* \throw If \a ids == \c NULL.
* \throw If \a ids->getName() == "".
throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : Dimension request is invalid (>1) !");
int traducedRk=-meshDimRelToMaxExt;
if(traducedRk>=(int)_ms.size())
- throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
+ throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
return _ms[traducedRk]->setFamilyArr(famArr);
throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
int traducedRk=-meshDimRelToMaxExt;
if(traducedRk>=(int)_ms.size())
- throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
+ throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
return _ms[traducedRk]->setRenumArr(renumArr);
throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
int traducedRk=-meshDimRelToMaxExt;
if(traducedRk>=(int)_ms.size())
- throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
+ throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
return _ms[traducedRk]->setNameArr(nameArr);