From 64c983f87b3bb4a4253a6c2005040d6e05b82011 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Sun, 19 Apr 2020 18:06:11 +0200 Subject: [PATCH] WIP --- src/MEDCoupling/MEDCouplingMemArray.hxx | 3 +- src/MEDCoupling/MEDCouplingMemArray.txx | 61 ++++++++++++++++--- src/MEDCoupling/MEDCouplingSkyLineArray.cxx | 14 +++++ src/MEDCoupling/MEDCouplingSkyLineArray.hxx | 2 + src/MEDCoupling_Swig/DataArrayInt.i | 1 + .../MEDCouplingBasicsTest7.py | 18 ++++++ src/MEDCoupling_Swig/MEDCouplingCommon.i | 3 + src/MEDCoupling_Swig/MEDCouplingMemArray.i | 2 + src/ParaMEDMEM/ParaSkyLineArray.cxx | 21 +++++++ src/ParaMEDMEM/ParaSkyLineArray.hxx | 5 +- 10 files changed, 121 insertions(+), 9 deletions(-) diff --git a/src/MEDCoupling/MEDCouplingMemArray.hxx b/src/MEDCoupling/MEDCouplingMemArray.hxx index f03822707..a06cfefdd 100755 --- a/src/MEDCoupling/MEDCouplingMemArray.hxx +++ b/src/MEDCoupling/MEDCouplingMemArray.hxx @@ -569,7 +569,7 @@ namespace MEDCoupling DataArrayIdType *findIdsEqual(T val) const; DataArrayIdType *transformWithIndArrR(const T *indArr2Bg, const T *indArrEnd) const; void splitByValueRange(const T *arrBg, const T *arrEnd, - DataArrayType *& castArr, DataArrayType *& rankInsideCast, DataArrayType *& castsPresent) const; + DataArrayType *& castArr, DataArrayType *& rankInsideCast, DataArrayType *& castsPresent) const; bool isRange(T& strt, T& sttoopp, T& stteepp) const; DataArrayIdType *invertArrayO2N2N2O(mcIdType newNbOfElem) const; DataArrayIdType *invertArrayN2O2O2N(mcIdType oldNbOfElem) const; @@ -622,6 +622,7 @@ namespace MEDCoupling DataArrayType *buildSubstractionOptimized(const DataArrayType *other) const; DataArrayType *buildUnion(const DataArrayType *other) const; DataArrayType *buildIntersection(const DataArrayType *other) const; + DataArrayIdType *indexOfSameConsecutiveValueGroups() const; DataArrayType *buildUnique() const; DataArrayType *buildUniqueNotSorted() const; DataArrayType *deltaShiftIndex() const; diff --git a/src/MEDCoupling/MEDCouplingMemArray.txx b/src/MEDCoupling/MEDCouplingMemArray.txx index e4ff8dd76..a52d83f2a 100755 --- a/src/MEDCoupling/MEDCouplingMemArray.txx +++ b/src/MEDCoupling/MEDCouplingMemArray.txx @@ -5705,6 +5705,53 @@ struct NotInRange arrs[0]=dynamic_cast(this); arrs[1]=other; return DataArrayDiscrete::BuildIntersection(arrs); } + /*! + * This method can be applied on allocated with one component DataArrayInt instance. + * Locate groups of all consecutive same values in \a this and return them into an indexed array of positions pointing to \a this starting with 0. + * Number of tuples of returned array is equal to size of \a this->buildUnique() + 1. + * Last value of returned array is equal to \a this->getNumberOfTuples() + * + * \b Example: + * - \a this : [0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 11] + * - \a return is : [0, 1, 3, 5, 6, 8, 11, 12] + * + * \return a newly allocated array containing the indexed array of + * \throw if \a this is not allocated or if \a this has not exactly one component or if number of tuples is equal to 0. + * \sa DataArrayInt::buildUnique, MEDCouplingSkyLineArray::groupPacks + */ + template + DataArrayIdType *DataArrayDiscrete::indexOfSameConsecutiveValueGroups() const + { + this->checkAllocated(); + if(this->getNumberOfComponents()!=1) + throw INTERP_KERNEL::Exception("DataArrayInt::indexOfSameConsecutiveValueGroups : only single component allowed !"); + if(this->getNumberOfTuples()==0) + throw INTERP_KERNEL::Exception("DataArrayInt::indexOfSameConsecutiveValueGroups : number of tuples must be > 0 !"); + const T *pt(this->begin()); + const T *const ptEnd(this->end()) , * const ptBg(this->begin()); + const T *oldPt(pt); + // first find nb of different values in this + std::size_t nbOfTuplesOut(0); + while( pt != ptEnd ) + { + T val(*pt); + const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; })); + pt = endOfPack; + ++nbOfTuplesOut; + } + MCAuto ret(DataArrayIdType::New()); ret->alloc(nbOfTuplesOut+1,1); + mcIdType *retPtr(ret->getPointer()); *retPtr++ = 0; + pt = this->begin(); + while( pt != ptEnd ) + { + T val(*pt); + const T *endOfPack(std::find_if(pt+1,ptEnd,[val](T elt){ return val!=elt; })); + *retPtr++ = ToIdType( std::distance(ptBg,endOfPack) ); + pt = endOfPack; + ++nbOfTuplesOut; + } + return ret.retn(); + } /*! * This method can be applied on allocated with one component DataArrayInt instance. @@ -5713,7 +5760,7 @@ struct NotInRange * * \return a newly allocated array that contain the result of the unique operation applied on \a this. * \throw if \a this is not allocated or if \a this has not exactly one component. - * \sa DataArrayInt::buildUniqueNotSorted + * \sa DataArrayInt::buildUniqueNotSorted, DataArrayInt::indexOfSameConsecutiveValueGroups */ template typename Traits::ArrayType *DataArrayDiscrete::buildUnique() const @@ -5721,12 +5768,12 @@ struct NotInRange this->checkAllocated(); if(this->getNumberOfComponents()!=1) throw INTERP_KERNEL::Exception("DataArrayInt::buildUnique : only single component allowed !"); - std::size_t nbOfElements=this->getNumberOfTuples(); - MCAuto tmp=DataArrayType::New(); - tmp->deepCopyFrom (*this); - T *data=tmp->getPointer(); - T *last=std::unique(data,data+nbOfElements); - MCAuto ret=DataArrayType::New(); + std::size_t nbOfElements(this->getNumberOfTuples()); + MCAuto tmp(DataArrayType::New()); + tmp->deepCopyFrom(*this); + T *data(tmp->getPointer()); + T *last(std::unique(data,data+nbOfElements)); + MCAuto ret(DataArrayType::New()); ret->alloc(std::distance(data,last),1); std::copy(data,last,ret->getPointer()); return ret.retn(); diff --git a/src/MEDCoupling/MEDCouplingSkyLineArray.cxx b/src/MEDCoupling/MEDCouplingSkyLineArray.cxx index dcbb24a4c..bc216096a 100755 --- a/src/MEDCoupling/MEDCouplingSkyLineArray.cxx +++ b/src/MEDCoupling/MEDCouplingSkyLineArray.cxx @@ -312,6 +312,20 @@ std::string MEDCouplingSkyLineArray::simpleRepr() const return oss.str(); } +MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::groupPacks(const DataArrayIdType *indexedPacks) const +{ + indexedPacks->checkAllocated(); + if( indexedPacks->getNumberOfComponents() != 1 ) + throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of components must be 1 !"); + std::size_t nbTuples(indexedPacks->getNumberOfTuples()); + if( nbTuples == 0 ) + throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of tuples must be > 0 !"); + const DataArrayIdType *index(this->getIndexArray()); + MCAuto partIndex(index->selectByTupleIdSafe(indexedPacks->begin(),indexedPacks->end())); + MCAuto ret(MEDCouplingSkyLineArray::New(partIndex,this->getValuesArray())); + return ret.retn(); +} + /** * For a 2- or 3-level SkyLine array, return a copy of the absolute pack with given identifier. */ diff --git a/src/MEDCoupling/MEDCouplingSkyLineArray.hxx b/src/MEDCoupling/MEDCouplingSkyLineArray.hxx index f7280c1be..21fba35eb 100644 --- a/src/MEDCoupling/MEDCouplingSkyLineArray.hxx +++ b/src/MEDCoupling/MEDCouplingSkyLineArray.hxx @@ -107,6 +107,8 @@ namespace MEDCoupling std::string simpleRepr() const; + MEDCouplingSkyLineArray *groupPacks(const DataArrayIdType *indexedPacks) const; + void getSimplePackSafe(const mcIdType absolutePackId, std::vector & pack) const; const mcIdType * getSimplePackSafePtr(const mcIdType absolutePackId, mcIdType & packSize) const; void findPackIds(const std::vector & superPackIndices, const mcIdType *packBg, const mcIdType *packEnd, diff --git a/src/MEDCoupling_Swig/DataArrayInt.i b/src/MEDCoupling_Swig/DataArrayInt.i index 15484e476..2d1d07e1e 100644 --- a/src/MEDCoupling_Swig/DataArrayInt.i +++ b/src/MEDCoupling_Swig/DataArrayInt.i @@ -133,6 +133,7 @@ ARRAY *buildSubstractionOptimized(const ARRAY *other) const; ARRAY *buildUnion(const ARRAY *other) const; ARRAY *buildIntersection(const ARRAY *other) const; + DataArrayIdType *indexOfSameConsecutiveValueGroups() const; ARRAY *buildUnique() const; ARRAY *buildUniqueNotSorted() const; ARRAY *deltaShiftIndex() const; diff --git a/src/MEDCoupling_Swig/MEDCouplingBasicsTest7.py b/src/MEDCoupling_Swig/MEDCouplingBasicsTest7.py index f73300fa4..953d72927 100644 --- a/src/MEDCoupling_Swig/MEDCouplingBasicsTest7.py +++ b/src/MEDCoupling_Swig/MEDCouplingBasicsTest7.py @@ -759,6 +759,24 @@ class MEDCouplingBasicsTest7(unittest.TestCase): arr=DataArrayInt([5,3,2,1,4,5,2,1,0,11,5,4]) self.assertTrue(arr.occurenceRankInThis().isEqual(DataArrayInt([0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 2, 1]))) + def testDAIFindPermutationFromFirstToSecondDuplicate(self): + arr0 = DataArrayInt([5,3,2,1,4,5,2,1,0,11,5,4]) + arr1 = DataArrayInt([0,1,1,2,2,3,4,4,5,5,5,11]) + self.assertTrue(DataArrayInt.FindPermutationFromFirstToSecondDuplicate(arr0,arr1).isEqual(DataArrayInt([8,5,3,1,6,9,4,2,0,11,10,7]))) + self.assertTrue(DataArrayInt.FindPermutationFromFirstToSecondDuplicate(arr1,arr0).isEqual(DataArrayInt([8,3,7,2,6,1,4,11,0,5,10,9]))) + + def testDAIIndexOfSameConsecutiveValueGroups(self): + arr = DataArrayInt([0,1,1,2,2,3,4,4,5,5,5,11]) + self.assertTrue(arr.indexOfSameConsecutiveValueGroups().isEqual(DataArrayInt([0, 1, 3, 5, 6, 8, 11, 12]))) + + def testSkyLineGroupPacks(self): + arr = DataArrayInt([1,4,5,0,2,4,5,6,1,3,5,6,7,2,6,7,0,1,5,8,9,0,1,2,4,6,8,9,10,1,2,3,5,7,9,10,11,2,3,6,10,11,4,5,9,12,13,4,5,6,8,10,12,13,14,5,6,7,9,11,13,14,15,6,7,10,14,15,8,9,13,8,9,10,12,14,9,10,11,13,15,10,11,14]) + arrI = DataArrayInt([0,3,8,13,16,21,29,37,42,47,55,63,68,71,76,81,84]) + sk = MEDCouplingSkyLineArray(arrI,arr) + part = DataArrayInt([0,3,4,7,16]) + sk2 = sk.groupPacks(part) + self.assertTrue(sk2.getValuesArray().isEqual(arr)) + self.assertTrue(sk2.getIndexArray().isEqual(DataArrayInt([0,13,16,37,84]))) pass if __name__ == '__main__': diff --git a/src/MEDCoupling_Swig/MEDCouplingCommon.i b/src/MEDCoupling_Swig/MEDCouplingCommon.i index d90474d78..b3b806995 100644 --- a/src/MEDCoupling_Swig/MEDCouplingCommon.i +++ b/src/MEDCoupling_Swig/MEDCouplingCommon.i @@ -466,6 +466,7 @@ typedef long int mcIdType; %newobject MEDCoupling::MEDCouplingSkyLineArray::getSuperIndexArray; %newobject MEDCoupling::MEDCouplingSkyLineArray::getIndexArray; %newobject MEDCoupling::MEDCouplingSkyLineArray::getValuesArray; +%newobject MEDCoupling::MEDCouplingSkyLineArray::groupPacks; %feature("unref") MEDCouplingPointSet "$this->decrRef();" %feature("unref") MEDCouplingMesh "$this->decrRef();" @@ -1296,6 +1297,8 @@ namespace MEDCoupling void deleteSimplePack(const int i); void deleteSimplePacks(const DataArrayIdType* idx); + + MEDCouplingSkyLineArray *groupPacks(const DataArrayIdType *indexedPacks) const; %extend { diff --git a/src/MEDCoupling_Swig/MEDCouplingMemArray.i b/src/MEDCoupling_Swig/MEDCouplingMemArray.i index aa591ba51..2152f9a1f 100644 --- a/src/MEDCoupling_Swig/MEDCouplingMemArray.i +++ b/src/MEDCoupling_Swig/MEDCouplingMemArray.i @@ -129,6 +129,7 @@ %newobject MEDCoupling::DataArrayInt32::buildSubstraction; %newobject MEDCoupling::DataArrayInt32::buildSubstractionOptimized; %newobject MEDCoupling::DataArrayInt32::buildIntersection; +%newobject MEDCoupling::DataArrayInt32::indexOfSameConsecutiveValueGroups; %newobject MEDCoupling::DataArrayInt32::buildUnique; %newobject MEDCoupling::DataArrayInt32::buildUniqueNotSorted; %newobject MEDCoupling::DataArrayInt32::deltaShiftIndex; @@ -203,6 +204,7 @@ %newobject MEDCoupling::DataArrayInt64::buildSubstraction; %newobject MEDCoupling::DataArrayInt64::buildSubstractionOptimized; %newobject MEDCoupling::DataArrayInt64::buildIntersection; +%newobject MEDCoupling::DataArrayInt64::indexOfSameConsecutiveValueGroups; %newobject MEDCoupling::DataArrayInt64::buildUnique; %newobject MEDCoupling::DataArrayInt64::buildUniqueNotSorted; %newobject MEDCoupling::DataArrayInt64::deltaShiftIndex; diff --git a/src/ParaMEDMEM/ParaSkyLineArray.cxx b/src/ParaMEDMEM/ParaSkyLineArray.cxx index a7f0d22b9..e75283a4a 100644 --- a/src/ParaMEDMEM/ParaSkyLineArray.cxx +++ b/src/ParaMEDMEM/ParaSkyLineArray.cxx @@ -37,6 +37,11 @@ using namespace MEDCoupling; +ParaSkyLineArray *ParaSkyLineArray::New(MEDCouplingSkyLineArray *ska, DataArrayIdType *globalIds) +{ + return new ParaSkyLineArray(ska,globalIds); +} + ParaSkyLineArray::ParaSkyLineArray(MEDCouplingSkyLineArray *ska, DataArrayIdType *globalIds) { _ska.takeRef(ska); @@ -95,4 +100,20 @@ MCAuto ParaSkyLineArray::equiRedistribute(mcIdType nbOfEntitie ci.allToAllArrays(comm,valuesToBeSent,myRkSkValues); values = DataArrayIdType::Aggregate(FromVecAutoToVecOfConst(myRkSkValues)); } + // Reorder results coming from other procs + MCAuto aggregatedIdsSort(aggregatedIds->deepCopy()); aggregatedIds->sort(); + MCAuto idsIntoAggregatedIds(DataArrayIdType::FindPermutationFromFirstToSecondDuplicate(aggregatedIdsSort,aggregatedIds)); + MCAuto indicesSorted,valuesSorted; + { + DataArrayIdType *indicesSortedTmp(nullptr),*valuesSortedTmp(nullptr); + DataArrayIdType::ExtractFromIndexedArrays(idsIntoAggregatedIds->begin(),idsIntoAggregatedIds->end(),values,indices,valuesSortedTmp,indicesSortedTmp); + indicesSorted = indicesSortedTmp; valuesSorted=valuesSortedTmp; + } + MCAuto idxOfSameIds(aggregatedIdsSort->indexOfSameConsecutiveValueGroups()); + // + MCAuto globalIdsOut(aggregatedIds->buildUnique()); + MCAuto skOut(MEDCouplingSkyLineArray::New(valuesSorted,indicesSorted)); + skOut = skOut->groupPacks(idxOfSameIds); + MCAuto ret(ParaSkyLineArray::New(skOut,globalIdsOut)); + return ret.retn(); } \ No newline at end of file diff --git a/src/ParaMEDMEM/ParaSkyLineArray.hxx b/src/ParaMEDMEM/ParaSkyLineArray.hxx index e012f9609..19dad005a 100644 --- a/src/ParaMEDMEM/ParaSkyLineArray.hxx +++ b/src/ParaMEDMEM/ParaSkyLineArray.hxx @@ -37,10 +37,13 @@ namespace MEDCoupling class ParaSkyLineArray : public RefCountObject { public: - ParaSkyLineArray(MEDCouplingSkyLineArray *ska, DataArrayIdType *globalIds); + static ParaSkyLineArray *New(MEDCouplingSkyLineArray *ska, DataArrayIdType *globalIds); MCAuto equiRedistribute(mcIdType nbOfEntities) const; virtual ~ParaSkyLineArray() { } + private: + ParaSkyLineArray(MEDCouplingSkyLineArray *ska, DataArrayIdType *globalIds); protected: + std::string getClassName() const override { return "ParaSkyLineArray"; } std::size_t getHeapMemorySizeWithoutChildren() const override; std::vector getDirectChildrenWithNull() const override; private: -- 2.39.2