]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Gauss Points localization computation in MEDCoupling.
authorageay <ageay>
Thu, 24 Feb 2011 09:00:11 +0000 (09:00 +0000)
committerageay <ageay>
Thu, 24 Feb 2011 09:00:11 +0000 (09:00 +0000)
src/MEDCoupling/MEDCouplingField.cxx
src/MEDCoupling/MEDCouplingField.hxx
src/MEDCoupling/MEDCouplingFieldDiscretization.cxx
src/MEDCoupling/MEDCouplingFieldDiscretization.hxx
src/MEDCoupling/MEDCouplingMemArray.cxx
src/MEDCoupling/MEDCouplingMemArray.hxx
src/MEDCoupling/Makefile.am

index c1879a752a6c29aedfcdad76a09db2650d296b13..82d13c9069e8a65d7675593381fd67c18ec21d0c 100644 (file)
@@ -104,6 +104,19 @@ void MEDCouplingField::setNature(NatureOfField nat) throw(INTERP_KERNEL::Excepti
   _nature=nat;
 }
 
+/*!
+ * This method returns is case of success an instance of DataArrayDouble the user is in reponsability to deal with.
+ * If 'this->_mesh' is not set an exception will be thrown.
+ * For a field on node the array of coords will be returned. For a field on cell a ParaMEDMEM::DataArrayDouble instance
+ * containing the barycenter of cells will be returned. And for a field on gauss point the explicit position of gauss points.
+ */
+DataArrayDouble *MEDCouplingField::getLocalizationOfDiscr() const throw(INTERP_KERNEL::Exception)
+{
+  if(!_mesh)
+    throw INTERP_KERNEL::Exception("MEDCouplingField::getLocalizationOfDiscr : No mesh set !");
+  return _type->getLocalizationOfDiscValues(_mesh);
+}
+
 /*!
  * This method retrieves the measure field of 'this'. If no '_mesh' is defined an exception will be thrown.
  * Warning the retrieved field life cycle is the responsability of caller.
index 09244c9cbeaf79c42874223a0c3cade997133620..840c8a6e74128f75ce8be4ac412fdabbd9b8a6e5 100644 (file)
@@ -33,6 +33,7 @@
 namespace ParaMEDMEM
 {
   class DataArrayInt;
+  class DataArrayDouble;
   class MEDCouplingMesh;
   class MEDCouplingFieldDouble;
   class MEDCouplingFieldDiscretization;
@@ -55,6 +56,7 @@ namespace ParaMEDMEM
     TypeOfField getTypeOfField() const;
     NatureOfField getNature() const { return _nature; }
     virtual void setNature(NatureOfField nat) throw(INTERP_KERNEL::Exception);
+    DataArrayDouble *getLocalizationOfDiscr() const throw(INTERP_KERNEL::Exception);
     MEDCouplingFieldDouble *buildMeasureField(bool isAbs) const throw(INTERP_KERNEL::Exception);
     MEDCouplingMesh *buildSubMeshData(const int *start, const int *end, DataArrayInt *&di) const;
     MEDCouplingFieldDiscretization *getDiscretization() const { return _type; }
index 92ba480997a222c812a7221cbf70813d717b31f9..898b4d2b312ee217affb00e44a6c309eca729127 100644 (file)
 
 #include "MEDCouplingFieldDiscretization.hxx"
 #include "MEDCouplingCMesh.hxx"
+#include "MEDCouplingUMesh.hxx"
 #include "MEDCouplingFieldDouble.hxx"
-#include "CellModel.hxx"
+#include "MEDCouplingAutoRefCountObjectPtr.hxx"
 
+#include "CellModel.hxx"
 #include "InterpolationUtils.hxx"
 #include "InterpKernelAutoPtr.hxx"
+#include "InterpKernelGaussCoords.hxx"
 
 #include <set>
+#include <list>
 #include <limits>
 #include <algorithm>
 #include <functional>
@@ -42,6 +46,8 @@ const char MEDCouplingFieldDiscretizationP1::REPR[]="P1";
 
 const TypeOfField MEDCouplingFieldDiscretizationP1::TYPE=ON_NODES;
 
+const int MEDCouplingFieldDiscretizationPerCell::DFT_INVALID_LOCID_VALUE=-1;
+
 const char MEDCouplingFieldDiscretizationGauss::REPR[]="GAUSS";
 
 const TypeOfField MEDCouplingFieldDiscretizationGauss::TYPE=ON_GAUSS_PT;
@@ -660,10 +666,19 @@ void MEDCouplingFieldDiscretizationPerCell::buildDiscrPerCellIfNecessary(const M
       int nbTuples=m->getNumberOfCells();
       _discr_per_cell->alloc(nbTuples,1);
       int *ptr=_discr_per_cell->getPointer();
-      std::fill(ptr,ptr+nbTuples,-1);
+      std::fill(ptr,ptr+nbTuples,DFT_INVALID_LOCID_VALUE);
     }
 }
 
+void MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells() const throw(INTERP_KERNEL::Exception)
+{
+  if(!_discr_per_cell)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells : no discretization defined !");
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> test=_discr_per_cell->getIdsEqual(DFT_INVALID_LOCID_VALUE);
+  if(test->getNumberOfTuples()!=0)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationPerCell::checkNoOrphanCells : presence of orphan cells !");
+}
+
 MEDCouplingFieldDiscretizationGauss::MEDCouplingFieldDiscretizationGauss()
 {
 }
@@ -761,7 +776,44 @@ void MEDCouplingFieldDiscretizationGauss::renumberArraysForCell(const MEDCouplin
 
 DataArrayDouble *MEDCouplingFieldDiscretizationGauss::getLocalizationOfDiscValues(const MEDCouplingMesh *mesh) const
 {
-  throw INTERP_KERNEL::Exception("Not implemented yet !");
+  checkNoOrphanCells();
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> umesh=mesh->buildUnstructured();//in general do nothing
+  int nbOfTuples=getNumberOfTuples(mesh);
+  DataArrayDouble *ret=DataArrayDouble::New();
+  int spaceDim=mesh->getSpaceDimension();
+  ret->alloc(nbOfTuples,spaceDim);
+  std::vector< std::vector<int> > locIds;
+  std::vector<DataArrayInt *> parts=splitIntoSingleGaussDicrPerCellType(locIds);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > parts2(parts.size());
+  std::copy(parts.begin(),parts.end(),parts2.begin());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=buildNbOfGaussPointPerCellField();
+  offsets->computeOffsets();
+  const int *ptrOffsets=offsets->getConstPointer();
+  const double *coords=umesh->getCoords()->getConstPointer();
+  const int *connI=umesh->getNodalConnectivityIndex()->getConstPointer();
+  const int *conn=umesh->getNodalConnectivity()->getConstPointer();
+  double *valsToFill=ret->getPointer();
+  for(std::size_t i=0;i<parts2.size();i++)
+    {
+      INTERP_KERNEL::GaussCoords calculator;
+      for(std::vector<int>::const_iterator it=locIds[i].begin();it!=locIds[i].end();it++)
+        {
+          const MEDCouplingGaussLocalization& cli=_loc[*it];//curLocInfo
+          INTERP_KERNEL::NormalizedCellType typ=cli.getType();
+          const std::vector<double>& wg=cli.getWeights();
+          calculator.addGaussInfo(typ,INTERP_KERNEL::CellModel::getCellModel(typ).getDimension(),
+                                  &cli.getGaussCoords()[0],wg.size(),&cli.getRefCoords()[0],
+                                  INTERP_KERNEL::CellModel::getCellModel(typ).getNumberOfNodes());
+        }
+      int nbt=parts2[i]->getNumberOfTuples();
+      for(const int *w=parts2[i]->getConstPointer();w!=parts2[i]->getConstPointer()+nbt;w++)
+        {
+          const MEDCouplingGaussLocalization& cli=_loc[*w];
+          calculator.calculateCoords(cli.getType(),coords,spaceDim,conn+connI[*w]+1,valsToFill+spaceDim*(ptrOffsets[*w]));
+        }
+    }
+  ret->copyStringInfoFrom(*umesh->getCoords());
+  return ret;
 }
 
 void MEDCouplingFieldDiscretizationGauss::computeMeshRestrictionFromTupleIds(const MEDCouplingMesh *mesh, const int *partBg, const int *partEnd,
@@ -921,6 +973,13 @@ void MEDCouplingFieldDiscretizationGauss::renumberValuesOnCellsR(const MEDCoupli
 void MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType(const MEDCouplingMesh *m, INTERP_KERNEL::NormalizedCellType type, const std::vector<double>& refCoo,
                                                                      const std::vector<double>& gsCoo, const std::vector<double>& wg) throw(INTERP_KERNEL::Exception)
 {
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::getCellModel(type);
+  if((int)cm.getDimension()!=m->getMeshDimension())
+    {
+      std::ostringstream oss; oss << "MEDCouplingFieldDiscretizationGauss::setGaussLocalizationOnType : mismatch of dimensions ! MeshDim==" << m->getMeshDimension();
+      oss << " whereas Type '" << cm.getRepr() << "' has dimension " << cm.getDimension() << " !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
   buildDiscrPerCellIfNecessary(m);
   int id=_loc.size();
   MEDCouplingGaussLocalization elt(type,refCoo,gsCoo,wg);
@@ -1038,6 +1097,30 @@ int MEDCouplingFieldDiscretizationGauss::getOffsetOfCell(int cellId) const throw
   return ret;
 }
 
+/*!
+ * This method do the assumption that there is no orphan cell. If there is an exception is thrown.
+ * This method makes the assumption too that '_discr_per_cell' is defined. If not an exception is thrown.
+ * This method returns a newly created array with number of tuples equals to '_discr_per_cell->getNumberOfTuples' and number of components equal to 1.
+ * The i_th tuple in returned array is the number of gauss point if the corresponding cell.
+ */
+DataArrayInt *MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField() const throw(INTERP_KERNEL::Exception)
+{
+  if(!_discr_per_cell)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : no discretization array set !");
+  int nbOfTuples=_discr_per_cell->getNumberOfTuples();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
+  const int *w=_discr_per_cell->getConstPointer();
+  ret->alloc(nbOfTuples,1);
+  int *valsToFill=ret->getPointer();
+  for(int i=0;i<nbOfTuples;i++,w++)
+    if(*w!=DFT_INVALID_LOCID_VALUE)
+      valsToFill[i]=_loc[*w].getNumberOfGaussPt();
+    else
+      throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::buildNbOfGaussPointPerCellField : orphan cell detected !");
+  ret->incrRef();
+  return ret;
+}
+
 /*!
  * This method makes the assumption that _discr_per_cell is set.
  * This method reduces as much as possible number size of _loc.
@@ -1073,6 +1156,68 @@ void MEDCouplingFieldDiscretizationGauss::zipGaussLocalizations()
   _loc=tmpLoc;
 }
 
+/*!
+ * This method is usefull when 'this' describes a field discretization with several gauss discretization on a \b same cell type.
+ * For example same NORM_TRI3 cells having 6 gauss points and others with 12 gauss points.
+ * This method returns 2 arrays with same size : the return value and 'locIds' output parameter.
+ * For a given i into [0,locIds.size) ret[i] represents the set of cell ids of i_th set an locIds[i] represents the set of discretisation of the set.
+ * The return vector contains a set of newly created instance to deal with.
+ * The returned vector represents a \b partition of cells ids with a gauss discretization set.
+ * 
+ * If no descretization is set in 'this' and exception will be thrown.
+ */
+std::vector<DataArrayInt *> MEDCouplingFieldDiscretizationGauss::splitIntoSingleGaussDicrPerCellType(std::vector< std::vector<int> >& locIds) const throw(INTERP_KERNEL::Exception)
+{
+  if(!_discr_per_cell)
+    throw INTERP_KERNEL::Exception("MEDCouplingFieldDiscretizationGauss::splitIntoSingleGaussDicrPerCellType : no descretization set !");
+  locIds.clear();
+  std::vector<DataArrayInt *> ret;
+  const int *discrPerCell=_discr_per_cell->getConstPointer();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=_discr_per_cell->getIdsNotEqual(-1);
+  int nbOfTuplesSet=ret2->getNumberOfTuples();
+  std::list<int> idsRemaining(ret2->getConstPointer(),ret2->getConstPointer()+nbOfTuplesSet);
+  std::list<int>::iterator it=idsRemaining.begin();
+  while(it!=idsRemaining.end())
+    {
+      std::vector<int> ids;
+      std::set<int> curLocIds;
+      std::set<INTERP_KERNEL::NormalizedCellType> curCellTypes;
+      while(it!=idsRemaining.end())
+        {
+          int curDiscrId=discrPerCell[*it];
+          INTERP_KERNEL::NormalizedCellType typ=_loc[curDiscrId].getType();
+          if(curCellTypes.find(typ)!=curCellTypes.end())
+            {
+              if(curLocIds.find(curDiscrId)!=curLocIds.end())
+                {
+                  curLocIds.insert(curDiscrId);
+                  curCellTypes.insert(typ);
+                  ids.push_back(*it);
+                  it=idsRemaining.erase(it);
+                }
+              else
+                it++;
+            }
+          else
+            {
+              curLocIds.insert(curDiscrId);
+              curCellTypes.insert(typ);
+              ids.push_back(*it);
+              it=idsRemaining.erase(it);
+            }
+        }
+      it=idsRemaining.begin();
+      ret.resize(ret.size()+1);
+      DataArrayInt *part=DataArrayInt::New();
+      part->alloc(ids.size(),1);
+      std::copy(ids.begin(),ids.end(),part->getPointer());
+      ret.back()=part;
+      locIds.resize(locIds.size()+1);
+      locIds.back().insert(locIds.back().end(),curLocIds.begin(),curLocIds.end());
+    }
+  return ret;
+}
+
 MEDCouplingFieldDiscretizationGaussNE::MEDCouplingFieldDiscretizationGaussNE()
 {
 }
index 80a3f49aeb2561f8866fb120be310e89389318dc..2f543fe96272bcbc36b62c01a97c6e4521025417 100644 (file)
@@ -164,10 +164,12 @@ namespace ParaMEDMEM
     bool isEqual(const MEDCouplingFieldDiscretization *other, double eps) const;
     bool isEqualWithoutConsideringStr(const MEDCouplingFieldDiscretization *other, double eps) const;
     void renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception);
+    void checkNoOrphanCells() const throw(INTERP_KERNEL::Exception);
   protected:
     void buildDiscrPerCellIfNecessary(const MEDCouplingMesh *m);
   protected:
     DataArrayInt *_discr_per_cell;
+    static const int DFT_INVALID_LOCID_VALUE;
   };
 
   class MEDCOUPLING_EXPORT MEDCouplingFieldDiscretizationGauss : public MEDCouplingFieldDiscretizationPerCell
@@ -211,6 +213,8 @@ namespace ParaMEDMEM
     int getGaussLocalizationIdOfOneType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception);
     void getCellIdsHavingGaussLocalization(int locId, std::vector<int>& cellIds) const throw(INTERP_KERNEL::Exception);
     const MEDCouplingGaussLocalization& getGaussLocalization(int locId) const throw(INTERP_KERNEL::Exception);
+    std::vector<DataArrayInt *> splitIntoSingleGaussDicrPerCellType(std::vector< std::vector<int> >& locIds) const throw(INTERP_KERNEL::Exception);
+    DataArrayInt *buildNbOfGaussPointPerCellField() const throw(INTERP_KERNEL::Exception);
   protected:
     MEDCouplingFieldDiscretizationGauss(const MEDCouplingFieldDiscretizationGauss& other);
     void zipGaussLocalizations();
index 4e0fd0f4fe0df9e040064770b4452e3b3015dc82..bb57d0dea4fd7eed95c834153ec3854b3671f75c 100644 (file)
@@ -2344,6 +2344,22 @@ DataArrayInt *DataArrayInt::getIdsEqual(int val) const throw(INTERP_KERNEL::Exce
   return ret;
 }
 
+DataArrayInt *DataArrayInt::getIdsNotEqual(int val) const throw(INTERP_KERNEL::Exception)
+{
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayInt::getIdsNotEqual : the array must have only one component !");
+  const int *cptr=getConstPointer();
+  std::vector<int> res;
+  int nbOfTuples=getNumberOfTuples();
+  for(int i=0;i<nbOfTuples;i++,cptr++)
+    if(*cptr!=val)
+      res.push_back(i);
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(res.size(),1);
+  std::copy(res.begin(),res.end(),ret->getPointer());
+  return ret;
+}
+
 DataArrayInt *DataArrayInt::getIdsEqualList(const std::vector<int>& vals) const throw(INTERP_KERNEL::Exception)
 {
   if(getNumberOfComponents()!=1)
@@ -2361,6 +2377,23 @@ DataArrayInt *DataArrayInt::getIdsEqualList(const std::vector<int>& vals) const
   return ret;
 }
 
+DataArrayInt *DataArrayInt::getIdsNotEqualList(const std::vector<int>& vals) const throw(INTERP_KERNEL::Exception)
+{
+  if(getNumberOfComponents()!=1)
+    throw INTERP_KERNEL::Exception("DataArrayInt::getIdsNotEqualList : the array must have only one component !");
+  std::set<int> vals2(vals.begin(),vals.end());
+  const int *cptr=getConstPointer();
+  std::vector<int> res;
+  int nbOfTuples=getNumberOfTuples();
+  for(int i=0;i<nbOfTuples;i++,cptr++)
+    if(vals2.find(*cptr)==vals2.end())
+      res.push_back(i);
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(res.size(),1);
+  std::copy(res.begin(),res.end(),ret->getPointer());
+  return ret;
+}
+
 DataArrayInt *DataArrayInt::Aggregate(const DataArrayInt *a1, const DataArrayInt *a2, int offsetA2)
 {
   int nbOfComp=a1->getNumberOfComponents();
@@ -2676,6 +2709,31 @@ DataArrayInt *DataArrayInt::deltaShiftIndex() const throw(INTERP_KERNEL::Excepti
   return ret;
 }
 
+/*!
+ * This method performs the work on itself. This method works on array with number of component equal to one and allocated. If not an exception is thrown.
+ * This method conserves the number of tuples and number of components (1). No reallocation is done.
+ * For an array [3,5,1,2,0,8] it becomes [0,3,8,9,11,11]. For each i>0 new[i]=new[i-1]+old[i-1] for i==0 new[i]=0.
+ * This could be usefull for allToAllV in MPI with contiguous policy.
+ */
+void DataArrayInt::computeOffsets() throw(INTERP_KERNEL::Exception)
+{
+  checkAllocated();
+  if(getNumberOfComponents()!=1)
+     throw INTERP_KERNEL::Exception("DataArrayInt::computeOffsets : only single component allowed !");
+  int nbOfTuples=getNumberOfTuples();
+  if(nbOfTuples==0)
+    return ;
+  int *work=getPointer();
+  int tmp=work[0];
+  work[0]=0;
+  for(int i=1;i<nbOfTuples;i++)
+    {
+      int tmp2=work[i];
+      work[i]=work[i-1]+tmp;
+      tmp=tmp2;
+    }
+}
+
 /*!
  * This method returns all different values found in 'this'.
  */
index 2faf6cfa26f42e5e6945a8586131ea99853645be..4bf9f4a785a2d297b2fefe06c42f5f2793b15b6e 100644 (file)
@@ -282,7 +282,9 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT static void SetArrayIn(DataArrayInt *newArray, DataArrayInt* &arrayToSet);
     MEDCOUPLING_EXPORT const int *getConstPointer() const { return _mem.getConstPointer(); }
     MEDCOUPLING_EXPORT DataArrayInt *getIdsEqual(int val) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayInt *getIdsNotEqual(int val) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayInt *getIdsEqualList(const std::vector<int>& vals) const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT DataArrayInt *getIdsNotEqualList(const std::vector<int>& vals) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT int getMaxValue(int& tupleId) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT int getMinValue(int& tupleId) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void applyLin(int a, int b, int compoId) throw(INTERP_KERNEL::Exception);
@@ -298,6 +300,7 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT DataArrayInt *buildUnion(const DataArrayInt *other) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayInt *buildIntersection(const DataArrayInt *other) const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT DataArrayInt *deltaShiftIndex() const throw(INTERP_KERNEL::Exception);
+    MEDCOUPLING_EXPORT void computeOffsets() throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT std::set<int> getDifferentValues() const throw(INTERP_KERNEL::Exception);
     MEDCOUPLING_EXPORT void useArray(const int *array, bool ownership, DeallocType type, int nbOfTuple, int nbOfCompo);
     MEDCOUPLING_EXPORT void writeOnPlace(int id, int element0, const int *others, int sizeOfOthers) { _mem.writeOnPlace(id,element0,others,sizeOfOthers); }
index 37058285bd1f1c057537bba2ff3ff2a0644a0aa8..14146ff615badab6009d390cd8cfb53651c0ea43 100644 (file)
@@ -57,7 +57,7 @@ libmedcoupling_la_LDFLAGS=
 libmedcoupling_la_CPPFLAGS=  @CXXTMPDPTHFLAGS@ \
        -I$(srcdir) -I$(srcdir)/../INTERP_KERNEL/Bases \
        -I$(srcdir)/../INTERP_KERNEL -I$(srcdir)/../INTERP_KERNEL/Geometric2D \
-       -I$(srcdir)/../INTERP_KERNEL/ExprEval
+       -I$(srcdir)/../INTERP_KERNEL/ExprEval -I$(srcdir)/../INTERP_KERNEL/GaussPoints
 
 # the geom2D library is included in the interpkernel one
 libmedcoupling_la_LIBADD= ../INTERP_KERNEL/libinterpkernel.la