-// Copyright (C) 2007-2014 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2024 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
#include "MEDCouplingMesh.hxx"
#include "MEDCouplingUMesh.hxx"
-#include "MEDCouplingMemArray.hxx"
+#include "MEDCouplingMemArray.txx"
#include "MEDCouplingFieldDouble.hxx"
#include "MEDCouplingFieldDiscretization.hxx"
-#include "MEDCouplingAutoRefCountObjectPtr.hxx"
+#include "MCAuto.hxx"
#include <set>
#include <cmath>
#include <fstream>
#include <iterator>
-using namespace ParaMEDMEM;
+using namespace MEDCoupling;
MEDCouplingMesh::MEDCouplingMesh():_time(0.),_iteration(-1),_order(-1)
{
* to be compared. An interpolation using MEDCouplingRemapper class should be then used.
*/
void MEDCouplingMesh::checkGeoEquivalWith(const MEDCouplingMesh *other, int levOfCheck, double prec,
- DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const
+ DataArrayIdType *&cellCor, DataArrayIdType *&nodeCor) const
{
cellCor=0;
nodeCor=0;
* \param [in] partBg - the array of node ids.
* \param [in] partEnd - end of \a partBg, i.e. a pointer to a (last+1)-th element
* of \a partBg.
- * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
+ * \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of found
* cells. The caller is to delete this array using decrRef() as it is no
* more needed.
*/
-DataArrayInt *MEDCouplingMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
+DataArrayIdType *MEDCouplingMesh::getCellIdsFullyIncludedInNodeIds(const mcIdType *partBg, const mcIdType *partEnd) const
{
- std::vector<int> crest;
- std::set<int> p(partBg,partEnd);
- int nbOfCells=getNumberOfCells();
- for(int i=0;i<nbOfCells;i++)
+ std::vector<mcIdType> crest;
+ std::set<mcIdType> p(partBg,partEnd);
+ mcIdType nbOfCells=getNumberOfCells();
+ for(mcIdType i=0;i<nbOfCells;i++)
{
- std::vector<int> conn;
+ std::vector<mcIdType> conn;
getNodeIdsOfCell(i,conn);
bool cont=true;
- for(std::vector<int>::const_iterator iter=conn.begin();iter!=conn.end() && cont;iter++)
+ for(std::vector<mcIdType>::const_iterator iter=conn.begin();iter!=conn.end() && cont;iter++)
if(p.find(*iter)==p.end())
cont=false;
if(cont)
crest.push_back(i);
}
- DataArrayInt *ret=DataArrayInt::New();
- ret->alloc((int)crest.size(),1);
+ DataArrayIdType *ret=DataArrayIdType::New();
+ ret->alloc(crest.size(),1);
std::copy(crest.begin(),crest.end(),ret->getPointer());
return ret;
}
}
/*!
- * This method is very poor and looks only if \a this and \a other are candidate for merge of fields lying repectively on them.
+ * This method is very poor and looks only if \a this and \a other are candidate for merge of fields lying respectively on them.
*/
bool MEDCouplingMesh::areCompatibleForMerge(const MEDCouplingMesh *other) const
{
*
* \sa MEDCouplingMesh::buildPart
*/
-MEDCouplingMesh *MEDCouplingMesh::buildPartRange(int beginCellIds, int endCellIds, int stepCellIds) const
+MEDCouplingMesh *MEDCouplingMesh::buildPartRange(mcIdType beginCellIds, mcIdType endCellIds, mcIdType stepCellIds) const
{
if(beginCellIds==0 && endCellIds==getNumberOfCells() && stepCellIds==1)
{
}
else
{
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
+ MCAuto<DataArrayIdType> cellIds=DataArrayIdType::Range(beginCellIds,endCellIds,stepCellIds);
return buildPart(cellIds->begin(),cellIds->end());
}
}
*
* \sa MEDCouplingMesh::buildPartAndReduceNodes
*/
-MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt*& arr) const
+MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(mcIdType beginCellIds, mcIdType endCellIds, mcIdType stepCellIds, mcIdType& beginOut, mcIdType& endOut, mcIdType& stepOut, DataArrayIdType*& arr) const
{
- MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
+ MCAuto<DataArrayIdType> cellIds=DataArrayIdType::Range(beginCellIds,endCellIds,stepCellIds);
return buildPartAndReduceNodes(cellIds->begin(),cellIds->end(),arr);
}
*/
MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbOfComp, FunctionToEvaluate func) const
{
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
+ MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
ret->setMesh(this);
ret->fillFromAnalytic(nbOfComp,func);
ret->synchronizeTimeWithSupport();
* Creates a new MEDCouplingFieldDouble of a given type, one time, with given number of
* components, lying on \a this mesh, with contents got by applying a specified
* function to coordinates of field location points (defined by the given field type).
- * For example, if \a t == ParaMEDMEM::ON_CELLS, the function is applied to cell
+ * For example, if \a t == MEDCoupling::ON_CELLS, the function is applied to cell
* barycenters.<br>
* For more info on supported expressions that can be used in the function, see \ref
* MEDCouplingArrayApplyFuncExpr. The function can include arbitrary named variables
*/
MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbOfComp, const std::string& func) const
{
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
+ MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
ret->setMesh(this);
ret->fillFromAnalytic(nbOfComp,func);
ret->synchronizeTimeWithSupport();
* Creates a new MEDCouplingFieldDouble of a given type, one time, with given number of
* components, lying on \a this mesh, with contents got by applying a specified
* function to coordinates of field location points (defined by the given field type).
- * For example, if \a t == ParaMEDMEM::ON_CELLS, the function is applied to cell
+ * For example, if \a t == MEDCoupling::ON_CELLS, the function is applied to cell
* barycenters. This method differs from
* \ref MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbOfComp, const std::string& func) const "fillFromAnalytic()"
* by the way how variable
* \ref py_mcmesh_fillFromAnalytic2 "Here is a Python example".
* \endif
*/
-MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic2(TypeOfField t, int nbOfComp, const std::string& func) const
+MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalyticCompo(TypeOfField t, int nbOfComp, const std::string& func) const
{
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
+ MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
ret->setMesh(this);
- ret->fillFromAnalytic2(nbOfComp,func);
+ ret->fillFromAnalyticCompo(nbOfComp,func);
ret->synchronizeTimeWithSupport();
return ret.retn();
}
* Creates a new MEDCouplingFieldDouble of a given type, one time, with given number of
* components, lying on \a this mesh, with contents got by applying a specified
* function to coordinates of field location points (defined by the given field type).
- * For example, if \a t == ParaMEDMEM::ON_CELLS, the function is applied to cell
+ * For example, if \a t == MEDCoupling::ON_CELLS, the function is applied to cell
* barycenters. This method differs from \ref \ref mcmesh_fillFromAnalytic
* "fillFromAnalytic()" by the way how variable
* names, used in the function, are associated with components of coordinates of field
* \ref py_mcmesh_fillFromAnalytic3 "Here is a Python example".
* \endif
*/
-MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic3(TypeOfField t, int nbOfComp, const std::vector<std::string>& varsOrder, const std::string& func) const
+MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalyticNamedCompo(TypeOfField t, int nbOfComp, const std::vector<std::string>& varsOrder, const std::string& func) const
{
- MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
+ MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(t,ONE_TIME);
ret->setMesh(this);
- ret->fillFromAnalytic3(nbOfComp,varsOrder,func);
+ ret->fillFromAnalyticNamedCompo(nbOfComp,varsOrder,func);
ret->synchronizeTimeWithSupport();
return ret.retn();
}
*/
MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(std::vector<const MEDCouplingMesh *>& meshes)
{
- std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms1(meshes.size());
+ std::vector< MCAuto<MEDCouplingUMesh> > ms1(meshes.size());
std::vector< const MEDCouplingUMesh * > ms2(meshes.size());
for(std::size_t i=0;i<meshes.size();i++)
{
* \throw if type is dynamic as \c INTERP_KERNEL::NORM_POLYHED , \c INTERP_KERNEL::NORM_POLYGON , \c INTERP_KERNEL::NORM_QPOLYG
* \throw if type is equal to \c INTERP_KERNEL::NORM_ERROR or to an unexisting geometric type.
*/
-int MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCellType type)
+mcIdType MEDCouplingMesh::GetNumberOfNodesOfGeometricType(INTERP_KERNEL::NormalizedCellType type)
{
const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
if(cm.isDynamic())
throw INTERP_KERNEL::Exception("MEDCouplingMesh::GetNumberOfNodesOfGeometricType : the input geometric type is dynamic ! Impossible to return a fixed number of nodes constituting it !");
- return (int) cm.getNumberOfNodes();
+ return ToIdType( cm.getNumberOfNodes());
}
/*!
return cm.getRepr();
}
-/*!
- * Finds cells in contact with a ball (i.e. a point with precision).
- * \warning This method is suitable if the caller intends to evaluate only one
- * point, for more points getCellsContainingPoints() is recommended as it is
- * faster.
- * \param [in] pos - array of coordinates of the ball central point.
- * \param [in] eps - ball radius.
- * \param [in,out] elts - vector returning ids of the found cells. It is cleared
- * before inserting ids.
- *
- * \if ENABLE_EXAMPLES
- * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
- * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
- * \endif
- */
-void MEDCouplingMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
-{
- int ret=getCellContainingPoint(pos,eps);
- elts.push_back(ret);
-}
-
/*!
* Finds cells in contact with several balls (i.e. points with precision).
* This method is an extension of getCellContainingPoint() and
* \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
* \endif
*/
-void MEDCouplingMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
+void MEDCouplingMesh::getCellsContainingPoints(const double *pos, mcIdType nbOfPoints, double eps, MCAuto<DataArrayIdType>& elts, MCAuto<DataArrayIdType>& eltsIndex) const
{
- eltsIndex=DataArrayInt::New(); elts=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
- int *eltsIndexPtr(eltsIndex->getPointer());
+ eltsIndex=DataArrayIdType::New(); elts=DataArrayIdType::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
+ mcIdType *eltsIndexPtr(eltsIndex->getPointer());
int spaceDim(getSpaceDimension());
const double *work(pos);
- for(int i=0;i<nbOfPoints;i++,work+=spaceDim)
+ for(mcIdType i=0;i<nbOfPoints;i++,work+=spaceDim)
{
- int ret=getCellContainingPoint(work,eps);
- if(ret>=0)
- {
- elts->pushBackSilent(ret);
- eltsIndexPtr[i+1]=eltsIndexPtr[i]+1;
- }
- else
- eltsIndexPtr[i+1]=eltsIndexPtr[i];
+ std::vector<mcIdType> ret;
+ getCellsContainingPoint(work,eps,ret);
+ elts->insertAtTheEnd(ret.begin(),ret.end());
+ eltsIndexPtr[i+1]=elts->getNumberOfTuples();
}
}
+/*!
+ * Behaves like MEDCouplingMesh::getCellsContainingPoints for cells in \a this that are linear.
+ * For quadratic cells in \a this, this method behaves by just considering linear part of cells.
+ * This method is here only for backward compatibility (interpolation GaussPoints to GaussPoints).
+ *
+ * \sa MEDCouplingMesh::getCellsContainingPoints, MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss
+ */
+void MEDCouplingMesh::getCellsContainingPointsLinearPartOnlyOnNonDynType(const double *pos, mcIdType nbOfPoints, double eps, MCAuto<DataArrayIdType>& elts, MCAuto<DataArrayIdType>& eltsIndex) const
+{
+ this->getCellsContainingPoints(pos,nbOfPoints,eps,elts,eltsIndex);
+}
+
+/*!
+ * Method computing center of mass of whole mesh (\a this)
+ * \return DataArrayDouble * - a new instance of DataArrayDouble with one tuple of n components where n is space dimension
+ */
+MCAuto<DataArrayDouble> MEDCouplingMesh::computeMeshCenterOfMass() const
+{
+ MCAuto<DataArrayDouble> cellCenters( this->computeCellCenterOfMass() );
+ MCAuto<MEDCouplingFieldDouble> vol( this->getMeasureField(true) );
+ MCAuto<DataArrayDouble> volXCenter( DataArrayDouble::Multiply(cellCenters,vol->getArray()) );
+ MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(1, this->getSpaceDimension());
+ volXCenter->accumulate( ret->getPointer() );
+ double volOfMesh(vol->accumulate(0));
+ ret->applyLin(1.0/volOfMesh,0.0);
+ return ret;
+}
+
/*!
* Writes \a this mesh into a VTK format file named as specified.
- * \param [in] fileName - the name of the file to write in.
+ * \param [in] fileName - the name of the file to write in. If the extension is OK the fileName will be used directly.
+ * If extension is invalid or no extension the right extension will be appended.
+ * \return - the real fileName
* \throw If \a fileName is not a writable file.
+ * \sa getVTKFileNameOf
*/
-void MEDCouplingMesh::writeVTK(const std::string& fileName, bool isBinary) const
+std::string MEDCouplingMesh::writeVTK(const std::string& fileName, bool isBinary) const
{
+ std::string ret(getVTKFileNameOf(fileName));
+ //
std::string cda,pda;
- MEDCouplingAutoRefCountObjectPtr<DataArrayByte> byteArr;
+ MCAuto<DataArrayByte> byteArr;
if(isBinary)
{ byteArr=DataArrayByte::New(); byteArr->alloc(0,1); }
- writeVTKAdvanced(fileName,cda,pda,byteArr);
+ writeVTKAdvanced(ret,cda,pda,byteArr);
+ return ret;
+}
+
+/*!
+ * This method takes in input a file name \a fileName and considering the VTK extension of \a this (depending on the type of \a this)
+ * returns a right file name. If the input \a fileName has a valid extension the returned string is equal to \a fileName.
+ *
+ * \sa getVTKFileExtension
+ */
+std::string MEDCouplingMesh::getVTKFileNameOf(const std::string& fileName) const
+{
+ std::string ret;
+ std::string part0,part1;
+ SplitExtension(fileName,part0,part1);
+ std::string ext("."); ext+=getVTKFileExtension();
+ if(part1==ext)
+ ret=fileName;
+ else
+ ret=fileName+ext;
+ return ret;
}
+/// @cond INTERNAL
void MEDCouplingMesh::writeVTKAdvanced(const std::string& fileName, const std::string& cda, const std::string& pda, DataArrayByte *byteData) const
{
std::ofstream ofs(fileName.c_str());
ofs.close();
}
}
+
+void MEDCouplingMesh::SplitExtension(const std::string& fileName, std::string& baseName, std::string& extension)
+{
+ std::size_t pos(fileName.find_last_of('.'));
+ if(pos==std::string::npos)
+ {
+ baseName=fileName;
+ extension.clear();
+ return ;
+ }
+ baseName=fileName.substr(0,pos);
+ extension=fileName.substr(pos);
+}
+/// @endcond