Salome HOME
Update copyrights
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMesh.cxx
index 668fb98114c41a976e74c730fc7129e40407d3b2..af878faa5dd50a35d61db7d4e71a6a74104b5891 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2019  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
 
 #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>
@@ -31,7 +31,7 @@
 #include <fstream>
 #include <iterator>
 
-using namespace ParaMEDMEM;
+using namespace MEDCoupling;
 
 MEDCouplingMesh::MEDCouplingMesh():_time(0.),_iteration(-1),_order(-1)
 {
@@ -146,7 +146,7 @@ bool MEDCouplingMesh::isEqual(const MEDCouplingMesh *other, double prec) const
  * 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 throw(INTERP_KERNEL::Exception)
+                                          DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const
 {
   cellCor=0;
   nodeCor=0;
@@ -237,7 +237,7 @@ void MEDCouplingMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double
 }
 
 /*!
- * 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
 {
@@ -269,7 +269,7 @@ MEDCouplingMesh *MEDCouplingMesh::buildPartRange(int beginCellIds, int endCellId
     }
   else
     {
-      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
+      MCAuto<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
       return buildPart(cellIds->begin(),cellIds->end());
     }
 }
@@ -281,7 +281,7 @@ MEDCouplingMesh *MEDCouplingMesh::buildPartRange(int beginCellIds, int endCellId
  */
 MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds, int endCellIds, int stepCellIds, int& beginOut, int& endOut, int& stepOut, DataArrayInt*& arr) const
 {
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
+  MCAuto<DataArrayInt> cellIds=DataArrayInt::Range(beginCellIds,endCellIds,stepCellIds);
   return buildPartAndReduceNodes(cellIds->begin(),cellIds->end(),arr);
 }
 
@@ -303,7 +303,7 @@ MEDCouplingMesh *MEDCouplingMesh::buildPartRangeAndReduceNodes(int beginCellIds,
  */
 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();
@@ -329,10 +329,10 @@ void MEDCouplingMesh::copyTinyStringsFrom(const MEDCouplingMesh *other)
  */
 void MEDCouplingMesh::copyTinyInfoFrom(const MEDCouplingMesh *other)
 {
-  copyTinyStringsFrom(other);
   _time=other->_time;
   _iteration=other->_iteration;
   _order=other->_order;
+  copyTinyStringsFrom(other);
 }
 
 /*!
@@ -340,7 +340,7 @@ void MEDCouplingMesh::copyTinyInfoFrom(const MEDCouplingMesh *other)
  * 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
@@ -378,7 +378,7 @@ void MEDCouplingMesh::copyTinyInfoFrom(const MEDCouplingMesh *other)
  */
 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();
@@ -389,7 +389,7 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbO
  * 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
@@ -428,11 +428,11 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic(TypeOfField t, int nbO
  *  \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();
 }
@@ -441,7 +441,7 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic2(TypeOfField t, int nb
  * 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
@@ -481,11 +481,11 @@ MEDCouplingFieldDouble *MEDCouplingMesh::fillFromAnalytic2(TypeOfField t, int nb
  *  \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();
 }
@@ -532,7 +532,7 @@ MEDCouplingMesh *MEDCouplingMesh::MergeMeshes(const MEDCouplingMesh *mesh1, cons
  */
 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++)
     {
@@ -622,27 +622,6 @@ const char *MEDCouplingMesh::GetReprOfGeometricType(INTERP_KERNEL::NormalizedCel
   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
@@ -668,7 +647,7 @@ void MEDCouplingMesh::getCellsContainingPoint(const double *pos, double eps, std
  *  \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, int nbOfPoints, double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& 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());
@@ -676,31 +655,65 @@ void MEDCouplingMesh::getCellsContainingPoints(const double *pos, int nbOfPoints
   const double *work(pos);
   for(int 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<int> 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, int nbOfPoints, double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
+{
+  this->getCellsContainingPoints(pos,nbOfPoints,eps,elts,eltsIndex);
+}
+
 /*!
  * 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());
@@ -720,3 +733,17 @@ void MEDCouplingMesh::writeVTKAdvanced(const std::string& fileName, const std::s
       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