]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
[EDF30179] : fuse of MEDFileUMesh instances. Management of family field arr management.
authorAnthony Geay <anthony.geay@edf.fr>
Wed, 28 Aug 2024 16:08:47 +0000 (18:08 +0200)
committerAnthony Geay <anthony.geay@edf.fr>
Wed, 28 Aug 2024 16:08:47 +0000 (18:08 +0200)
src/MEDCoupling/MCAuto.hxx
src/MEDCoupling/MEDCouplingMemArray.hxx
src/MEDCoupling/MEDCouplingMemArray.txx

index 4b6347704444d30d964d50830e5ff635a451c304..b2125aed13497a1a996daeef8b68b49e69cce0c8 100644 (file)
@@ -44,7 +44,7 @@ namespace MEDCoupling
     bool operator==(const T *other) const { return _ptr==other; }
     MCAuto &operator=(const MCAuto& other) { if(_ptr!=other._ptr) { destroyPtr(); referPtr(other._ptr); } return *this; }
     MCAuto &operator=(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; } return *this; }
-    void takeRef(T *ptr) { if(_ptr!=ptr) { destroyPtr(); _ptr=ptr; if(_ptr) _ptr->incrRef(); } }
+    void takeRef(T *ptr) { if(_ptr!=ptr) { destroyPtr(); referPtr(ptr); } }
     T *operator->() { return _ptr ; }
     const T *operator->() const { return _ptr; }
     T& operator*() { return *_ptr; }
index d4b9ab5e27997b65dca0a3cf2d7f5b774c28b43b..bde9a3816414627fc88cb314d8101843b20dc036 100755 (executable)
@@ -273,7 +273,8 @@ namespace MEDCoupling
     void rearrange(std::size_t newNbOfCompo);
     void transpose();
     void pushBackSilent(T val);
-    void pushBackValsSilent(const T *valsBg, const T *valsEnd);
+    template<class InputIterator>
+    void pushBackValsSilent(InputIterator valsBg, InputIterator valsEnd);
     T popBackSilent();
     T front() const;
     T back() const;
@@ -656,14 +657,14 @@ namespace MEDCoupling
     void sortToHaveConsecutivePairs();
     MCAuto<DataArrayType> fromLinkedListOfPairToList() const;
     DataArrayType *getDifferentValues() const;
+    MCAuto<DataArrayType> forThisAsPartitionBuildReduction(const MCAuto<DataArrayIdType>& commonEntities, const MCAuto<DataArrayIdType>& commonEntitiesIndex,
+      MCAuto<DataArrayType>& partitionsToBeModified, MCAuto<DataArrayIdType>& partitionsToBeModifiedIndex) const;
     std::vector<DataArrayIdType *> partitionByDifferentValues(std::vector<T>& differentIds) const;
     std::vector< std::pair<mcIdType,mcIdType> > splitInBalancedSlices(mcIdType nbOfSlices) const;
     static DataArrayType *Modulus(const DataArrayType *a1, const DataArrayType *a2);
     void modulusEqual(const DataArrayType *other);
     static DataArrayType *Pow(const DataArrayType *a1, const DataArrayType *a2);
     void powEqual(const DataArrayType *other);
-    //MemArray<T>& accessToMemArray() { return _mem; }
-    //const MemArray<T>& accessToMemArray() const { return _mem; }
   public:
     static DataArrayIdType *FindPermutationFromFirstToSecond(const DataArrayType *ids1, const DataArrayType *ids2);
     static DataArrayIdType *FindPermutationFromFirstToSecondDuplicate(const DataArrayType *ids1, const DataArrayType *ids2);
@@ -1086,4 +1087,33 @@ namespace MEDCoupling
     else
       throw INTERP_KERNEL::Exception("DataArrayDouble::insertAtTheEnd : not available for DataArrayDouble with number of components different than 1 !");
   }
+
+    /*!
+    * This method adds at the end of \a this a series of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
+    * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
+    *
+    *  \param [in] valsBg - an array of values to push at the end of \c this.
+    *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
+    *              the last value of \a valsBg is \a valsEnd[ -1 ].
+    * \throw If \a this has already been allocated with number of components different from one.
+    * \sa DataArrayDouble::pushBackSilent
+    */
+    template<class T>
+    template<class InputIterator>
+    void DataArrayTemplate<T>::pushBackValsSilent(InputIterator valsBg, InputIterator valsEnd)
+    {
+      std::size_t nbCompo(getNumberOfComponents());
+      if(nbCompo==1)
+        _mem.insertAtTheEnd(valsBg,valsEnd);
+      else if(nbCompo==0)
+        {
+          _info_on_compo.resize(1);
+          _mem.insertAtTheEnd(valsBg,valsEnd);
+        }
+      else
+        {
+          std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
 }
index b3d517532cbe27f7c24b48e28af1e63d1c9aad66..b284360d350818758964709fe35642a4c331e532 100755 (executable)
 #include "MCAuto.hxx"
 #include "MEDCouplingMap.txx"
 
+#include <set>
 #include <sstream>
 #include <cstdlib>
 #include <numeric>
 #include <algorithm>
+#include <iterator>
 
 namespace MEDCoupling
 {
@@ -893,34 +895,6 @@ namespace MEDCoupling
       }
   }
 
-  /*!
-   * This method adds at the end of \a this a series of values [\c valsBg,\c valsEnd). This method do \b not update its time label to avoid useless incrementation
-   * of counter. So the caller is expected to call TimeLabel::declareAsNew on \a this at the end of the push session.
-   *
-   *  \param [in] valsBg - an array of values to push at the end of \c this.
-   *  \param [in] valsEnd - specifies the end of the array \a valsBg, so that
-   *              the last value of \a valsBg is \a valsEnd[ -1 ].
-   * \throw If \a this has already been allocated with number of components different from one.
-   * \sa DataArrayDouble::pushBackSilent
-   */
-  template<class T>
-  void DataArrayTemplate<T>::pushBackValsSilent(const T *valsBg, const T *valsEnd)
-  {
-    std::size_t nbCompo(getNumberOfComponents());
-    if(nbCompo==1)
-      _mem.insertAtTheEnd(valsBg,valsEnd);
-    else if(nbCompo==0)
-      {
-        _info_on_compo.resize(1);
-        _mem.insertAtTheEnd(valsBg,valsEnd);
-      }
-    else
-      {
-        std::ostringstream oss; oss << Traits<T>::ArrayTypeName << "::pushBackValsSilent : not available for DataArrayDouble with number of components different than 1 !";
-        throw INTERP_KERNEL::Exception(oss.str().c_str());
-      }
-  }
-
   /*!
    * This method returns silently ( without updating time label in \a this ) the last value, if any and suppress it.
    * \throw If \a this is already empty.
@@ -6460,6 +6434,97 @@ struct NotInRange
     return ret2.retn();
   }
 
+  template<class T>
+  class PartitionCfg : public std::set<T>
+  {
+    public:
+      PartitionCfg() = default;
+      void setID(T id) { _id = id; }
+      T getID() const { return _id; }
+      bool operator<(const PartitionCfg<T>& other) { return std::set<T>::operator<( other._data ); }
+      bool operator>(const PartitionCfg<T>& other) { return std::set<T>::operator>( other._data ); }
+      bool operator==(const PartitionCfg<T>& other) { return std::set<T>::operator==( other._data ); }
+    private:
+      T _id = 0;
+  };
+
+  /*!
+   * \a this is considered as an array defining a partition. It means that values in \a this define partition-ids. All tuples in \a this with same value can be considered as partition.
+   * Typically MED stores families uses this compact storage method.
+   * 
+   * This method computes and returns the partition stored in \a this on reduced space using a reduction operation specified by pairs \a commonEntities and \a commonEntitiesIndex parameters.
+   * The reduction operation is the consequence of a fusion of enties. It explains the storage format defining reduction.
+   * 
+   * An another way to consider this method : This method can be seen as an interpolation on integer field (\a this). For fused entities it returns in compact way all combinations of partition configuration.
+   * 
+   * \param [out] partitionsToBeModified - For all partitions impacted by the reduction a n-uplet is returned (n is deduced thanks to \a partitionsToBeModifiedIndex)
+   *                                       Each n-uplet represents a list of partitions impacted by reduction. The first element of n-uplet represents the ID to locate entities (using for example findIdsEqual in returned array)
+   *                                       Remaining IDs in n-uplet are Partition IDs impacted.
+   * \param [out] partitionsToBeModifiedIndex - Index attached to \a partitionsToBeModified to interprete.
+   * 
+   * \return - The partition array that is the output of the reduction of \a this. 
+   * 
+   * \sa MEDCouplingUMesh::findCommonCells, DataArrayDouble::findCommonTuples
+   */
+  template <class T>
+  MCAuto< typename DataArrayDiscrete<T>::DataArrayType > DataArrayDiscrete<T>::forThisAsPartitionBuildReduction(const MCAuto<DataArrayIdType>& commonEntities, const MCAuto<DataArrayIdType>& commonEntitiesIndex, MCAuto<DataArrayType>& partitionsToBeModified, MCAuto<DataArrayIdType>& partitionsToBeModifiedIndex) const
+  {
+    constexpr char MSG[] = "this should have only one component";
+    this->checkAllocated(); this->checkNbOfComps(1,MSG);
+    commonEntities->checkAllocated(); commonEntities->checkNbOfComps(1,MSG);
+    commonEntitiesIndex->checkAllocated(); commonEntitiesIndex->checkNbOfComps(1,MSG);
+    std::size_t initialSpaceSz( this->getNumberOfTuples() );
+    mcIdType returnedSpaceSz( 0 );// store size of reducted returned size
+    //
+    MCAuto<DataArrayIdType> sizeOfPacks( commonEntitiesIndex->deltaShiftIndex() );
+    mcIdType maxSizeOfPacks = sizeOfPacks->getMaxValueInArray();// store the max size of common entities
+    T newValueInThis = this->getMaxValueInArray() + 1;
+    //
+    MCAuto<DataArrayIdType> o2n( DataArrayIdType::ConvertIndexArrayToO2N(initialSpaceSz,commonEntities->begin(),commonEntitiesIndex->begin(),commonEntitiesIndex->end(),returnedSpaceSz) );
+    MCAuto< DataArrayType > ret( DataArrayDiscrete<T>::New() );
+    ret->alloc( returnedSpaceSz, 1 );
+    ret->fillWithValue( std::numeric_limits<T>::max() );
+    // First deal with entities not fused.
+    MCAuto<DataArrayIdType> eltsNotFused( commonEntities->copySorted() );
+    eltsNotFused = eltsNotFused->buildComplement( initialSpaceSz );
+    MCAuto<DataArrayType> partionIdsOfNotFused = this->mySelectByTupleIdSafe(eltsNotFused->begin(),eltsNotFused->end());
+    MCAuto<DataArrayIdType> tupleIdsToSelect = o2n->selectByTupleIdSafe(eltsNotFused->begin(),eltsNotFused->end());
+    ret->setPartOfValues3(partionIdsOfNotFused,tupleIdsToSelect->begin(),tupleIdsToSelect->end(),0,1,1);
+    T *retPt( ret->getPointer() );
+    const mcIdType *o2nPt( o2n->begin() );
+    //
+    partitionsToBeModified = DataArrayType::New(); partitionsToBeModified->alloc(0,1); 
+    partitionsToBeModifiedIndex = DataArrayIdType::New(); partitionsToBeModifiedIndex->alloc(1,1); partitionsToBeModifiedIndex->setIJSilent(0,0,0);
+    const T *ptOfThisData( this->begin() );
+    const mcIdType *ceBg( commonEntities->begin() ), *ceiBg( commonEntitiesIndex->begin() );
+    for(mcIdType szOfPack = 2 ; szOfPack <= maxSizeOfPacks ; ++szOfPack)
+    {
+      MCAuto<DataArrayIdType> idsInThisWithSamePackSz = findIdsEqual( FromIdType<T>( szOfPack ) );
+      std::set< PartitionCfg<T> > partitionCfgHolder;
+      for( const mcIdType *idsInThisWithSamePackSzIt = idsInThisWithSamePackSz->begin() ; idsInThisWithSamePackSzIt != idsInThisWithSamePackSz->end() ; ++idsInThisWithSamePackSzIt )
+      {
+        PartitionCfg<T> partitionCfg;
+        std::transform(ceBg + ceiBg[*idsInThisWithSamePackSzIt],ceBg + ceiBg[*idsInThisWithSamePackSzIt + 1], std::inserter(partitionCfg,partitionCfg.end()),[ptOfThisData](mcIdType elt) { return ptOfThisData[elt]; });
+        auto existCfg = partitionCfgHolder.find( partitionCfg );
+        if( existCfg != partitionCfgHolder.end() )
+        {//partition already exist by a previous pack -> reuse it !
+          T newPartitionID = existCfg->getID();
+          retPt[ o2nPt[ ceBg [ ceiBg[*idsInThisWithSamePackSzIt] ] ] ] = newPartitionID;// hypothesis that o2n is so that all o2n[ceBg + ceiBg[*idsInThisWithSamePackSzIt],ceBg + ceiBg[*idsInThisWithSamePackSzIt + 1]) points to the same point in new renumbering
+        }
+        else
+        {//partition does not exist yet -> create it !
+          partitionCfg.setID( newValueInThis++ );
+          partitionCfgHolder.insert( partitionCfg );
+          retPt[ o2nPt[ ceBg [ ceiBg[*idsInThisWithSamePackSzIt] ] ] ] = partitionCfg.getID();
+          partitionsToBeModified->pushBackSilent( partitionCfg.getID() );
+          partitionsToBeModified->pushBackValsSilent(partitionCfg.begin(),partitionCfg.end());
+          partitionsToBeModifiedIndex->pushBackSilent( partitionsToBeModifiedIndex->back() + szOfPack + 1 );
+        }
+      }
+    }
+    return ret;
+  }
+
   /*!
    * This method is a refinement of DataArrayInt::getDifferentValues because it returns not only different values in \a this but also, for each of
    * them it tells which tuple id have this id.