class MCAuto
{
public:
- static MCAuto TakeRef(T *ptr) { MCAuto ret(MCAuto(nullptr)); ret.takeRef(ptr); return ret; }
- MCAuto(const MCAuto& other):_ptr(0) { referPtr(other._ptr); }
- MCAuto(T *ptr=0):_ptr(ptr) { }
+ static MCAuto TakeRef(T *ptr) { MCAuto ret; ret.takeRef(ptr); return ret; }
+ MCAuto(const MCAuto& other):_ptr(nullptr) { referPtr(other._ptr); }
+ MCAuto(T *ptr=nullptr):_ptr(ptr) { }
~MCAuto() { destroyPtr(); }
void checkNotNull() const { if(!_ptr) throw INTERP_KERNEL::Exception("Pointer is nullptr !"); }
- bool isNull() const { return _ptr==0; }
+ bool isNull() const { return _ptr==nullptr; }
bool isNotNull() const { return !isNull(); }
- void nullify() { destroyPtr(); _ptr=0; }
+ void nullify() { destroyPtr(); _ptr=nullptr; }
bool operator==(const MCAuto& other) const { return _ptr==other._ptr; }
bool operator==(const T *other) const { return _ptr==other; }
MCAuto &operator=(const MCAuto& other) { if(_ptr!=other._ptr) { destroyPtr(); referPtr(other._ptr); } return *this; }
return ret;
}
+ template<class T>
+ std::vector<MCAuto<T>> FromVecToVecAuto(const std::vector<T*>& inputVec)
+ {
+ std::size_t size(inputVec.size());
+ std::vector<MCAuto<T>> ret(size);
+ typename std::vector<MCAuto<T>>::iterator itArrays(ret.begin());
+ std::for_each(inputVec.begin(),inputVec.end(),[&itArrays](T *elt) { (*itArrays).takeRef(elt); itArrays++; });
+ return ret;
+ }
+
+ template<class T>
+ std::vector<MCAuto<T>> FromVecConstToVecAuto(const std::vector<const T*>& inputVec)
+ {
+ std::size_t size(inputVec.size());
+ std::vector<MCAuto<T>> ret(size);
+ typename std::vector<MCAuto<T>>::iterator itArrays(ret.begin());
+ std::for_each(inputVec.begin(),inputVec.end(),[&itArrays](const T *elt) { (*itArrays).takeRef(const_cast<T*>(elt)); itArrays++; });
+ return ret;
+ }
+
template<class T, class U>
typename MEDCoupling::MCAuto<U> DynamicCast(typename MEDCoupling::MCAuto<T>& autoSubPtr) throw()
{
void setPartOfValuesBase3(const DataArray *aBase, const mcIdType *bgTuples, const mcIdType *endTuples, mcIdType bgComp, mcIdType endComp, mcIdType stepComp, bool strictCompoCompare=true);
virtual void *getVoidStarPointer() = 0;
virtual DataArray *deepCopy() const = 0;
+ virtual DataArray *copySorted(bool asc=true) const = 0;
virtual DataArray *buildNewEmptyInstance() const = 0;
virtual bool isAllocated() const = 0;
virtual void checkAllocated() const = 0;
typedef T Type;
public:
static MCAuto< typename Traits<T>::ArrayTypeCh > NewFromStdVector(const typename std::vector<T>& v);
+ static MCAuto< typename Traits<T>::ArrayTypeCh > NewFromArray(const T *arrBegin, const T *arrEnd);
std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > explodeComponents() const;
//
std::size_t getHeapMemorySizeWithoutChildren() const;
MemArray<T>& accessToMemArray() { return _mem; }
const MemArray<T>& accessToMemArray() const { return _mem; }
protected:
+ typename Traits<T>::ArrayTypeCh *copySortedImpl(bool asc) const;
typename Traits<T>::ArrayType *mySelectByTupleId(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const;
typename Traits<T>::ArrayType *mySelectByTupleId(const DataArrayIdType& di) const;
typename Traits<T>::ArrayType *mySelectByTupleIdSafe(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const;
static DataArrayFloat *New();
public:// abstract method overload
DataArrayFloat *deepCopy() const;
+ DataArrayFloat *copySorted(bool asc=true) const override { return this->copySortedImpl(asc); }
std::string getClassName() const override { return std::string("DataArrayFloat"); }
DataArrayFloat *buildNewEmptyInstance() const { return DataArrayFloat::New(); }
DataArrayFloat *selectByTupleRanges(const std::vector<std::pair<mcIdType,mcIdType> >& ranges) const { return DataArrayTemplateFP<float>::mySelectByTupleRanges(ranges); }
static DataArrayDouble *New();
double doubleValue() const;
DataArrayDouble *deepCopy() const;
+ DataArrayDouble *copySorted(bool asc=true) const override { return this->copySortedImpl(asc); }
std::string getClassName() const override { return std::string("DataArrayDouble"); }
DataArrayDouble *buildNewEmptyInstance() const { return DataArrayDouble::New(); }
void checkMonotonic(bool increasing, double eps) const;
using DataArrayType = typename Traits<T>::ArrayType;
public:
static DataArrayType *New();
- static MCAuto<DataArrayType> NewFromArray(const T *arrBegin, const T *arrEnd);
T intValue() const;
bool isEqual(const DataArrayDiscrete<T>& other) const;
bool isEqualIfNotWhy(const DataArrayDiscrete<T>& other, std::string& reason) const;
{
friend class DataArrayDiscrete<Int32>;
public:
- DataArrayInt32 *deepCopy() const;//ok
- DataArrayInt32 *buildNewEmptyInstance() const { return DataArrayInt32::New(); }//ok
+ DataArrayInt32 *deepCopy() const;
+ DataArrayInt32 *copySorted(bool asc=true) const override { return this->copySortedImpl(asc); }
+ DataArrayInt32 *buildNewEmptyInstance() const { return DataArrayInt32::New(); }
public:
DataArrayInt32 *selectByTupleId(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const { return this->mySelectByTupleId(new2OldBg,new2OldEnd); }
DataArrayInt32 *selectByTupleId(const DataArrayIdType& di) const { return this->mySelectByTupleId(di); }
friend class DataArrayDiscrete<Int64>;
public:
DataArrayInt64 *deepCopy() const;
+ DataArrayInt64 *copySorted(bool asc=true) const override { return this->copySortedImpl(asc); }
DataArrayInt64 *buildNewEmptyInstance() const { return DataArrayInt64::New(); }//ok
public:
DataArrayInt64 *selectByTupleId(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const { return this->mySelectByTupleId(new2OldBg,new2OldEnd); }
DataArrayChar *buildEmptySpecializedDAChar() const;
DataArrayByteIterator *iterator();
DataArrayByte *deepCopy() const;
+ DataArrayByte *copySorted(bool asc=true) const override { return this->copySortedImpl(asc); }
DataArrayByte *performCopyOrIncrRef(bool deepCopy) const;
DataArrayByte *buildNewEmptyInstance() const { return DataArrayByte::New(); }
char byteValue() const;
DataArrayChar *buildEmptySpecializedDAChar() const;
DataArrayAsciiCharIterator *iterator();
DataArrayAsciiChar *deepCopy() const;
+ DataArrayAsciiChar *copySorted(bool asc=true) const override { throw INTERP_KERNEL::Exception("DataArrayAsciiChar::copySorted : not implemented for DataArrayByte"); }
DataArrayAsciiChar *performCopyOrIncrRef(bool deepCopy) const;
DataArrayAsciiChar *buildNewEmptyInstance() const { return DataArrayAsciiChar::New(); }
char asciiCharValue() const;
std::copy(v.begin(),v.end(),pt);
return ret;
}
+
+ /*!
+ * Returns a newly created array containing a copy of the input array defined by [ \a arrBegin, \a arrEnd )
+ */
+ template<class T>
+ MCAuto< typename Traits<T>::ArrayTypeCh > DataArrayTemplate<T>::NewFromArray(const T *arrBegin, const T *arrEnd)
+ {
+ using DataArrayT = typename Traits<T>::ArrayTypeCh;
+ MCAuto< DataArrayT > ret(DataArrayT::New());
+ std::size_t nbElts(std::distance(arrBegin,arrEnd));
+ ret->alloc(nbElts,1);
+ std::copy(arrBegin,arrEnd,ret->getPointer());
+ return ret;
+ }
template<class T>
std::vector< MCAuto< typename Traits<T>::ArrayTypeCh > > DataArrayTemplate<T>::explodeComponents() const
}
/*!
- * Sorts values of the array.
+ * Sorts values of the array. \b Warning, this method is not const, it alterates \a this content.
+ *
* \param [in] asc - \a true means ascending order, \a false, descending.
* \throw If \a this is not allocated.
* \throw If \a this->getNumberOfComponents() != 1.
+ * \sa copySorted
*/
template<class T>
void DataArrayTemplate<T>::sort(bool asc)
declareAsNew();
}
+ /*!
+ * Sorts values of the array and put the result in a newly allocated returned array.
+ * This method does not alterate \a this content.
+ *
+ * \param [in] asc - \a true means ascending order, \a false, descending.
+ * \throw If \a this is not allocated.
+ * \throw If \a this->getNumberOfComponents() != 1.
+ * \sa sort
+ */
+ template<class T>
+ typename Traits<T>::ArrayTypeCh *DataArrayTemplate<T>::copySortedImpl(bool asc) const
+ {
+ MCAuto<typename Traits<T>::ArrayTypeCh> ret(static_cast<typename Traits<T>::ArrayTypeCh *>(this->deepCopy()));
+ ret->sort(asc);
+ return ret.retn();
+ }
+
/*!
* Returns a copy of \a this array with values permuted as required by \a old2New array.
* The values are permuted so that \c new[ \a old2New[ i ]] = \c old[ i ].
return new typename Traits<T>::ArrayType;
}
- /*!
- * Returns a newly created array containing a copy of the input array defined by [ \a arrBegin, \a arrEnd )
- */
- template<class T>
- MCAuto< typename Traits<T>::ArrayType > DataArrayDiscrete<T>::NewFromArray(const T *arrBegin, const T *arrEnd)
- {
- MCAuto< typename Traits<T>::ArrayType > ret(DataArrayDiscrete<T>::New());
- std::size_t nbElts(std::distance(arrBegin,arrEnd));
- ret->alloc(nbElts,1);
- std::copy(arrBegin,arrEnd,ret->getPointer());
- return ret;
- }
-
/*!
* Checks if values of \a this and another DataArrayInt are equal. For more info see
* \ref MEDCouplingArrayBasicsCompare.
* - \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.
+ * \return a newly allocated array containing the indexed array format of groups by same consecutive value.
+ * \throw if \a this is not allocated or if \a this has not exactly one component.
* \sa DataArrayInt::buildUnique, MEDCouplingSkyLineArray::groupPacks
*/
template <class T>
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);
return const_cast<MEDCouplingSkyLineArray*>(this)->_values;
}
+MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::deepCopy() const
+{
+ MCAuto<DataArrayIdType> indexCpy(this->_index->deepCopy());
+ MCAuto<DataArrayIdType> valuesCpy(this->_values->deepCopy());
+ MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(indexCpy,valuesCpy));
+ if(_super_index.isNotNull())
+ {
+ MCAuto<DataArrayIdType> superIndexCpy(this->_super_index->deepCopy());
+ ret->_super_index = superIndexCpy;
+ }
+ return ret.retn();
+}
+
void MEDCouplingSkyLineArray::checkSuperIndex(const std::string& func) const
{
if (!_super_index->getNbOfElems())
MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(retIndex,retValues));
return ret.retn();
}
+/*!
+ * Take as input skylinearrays containing the same number of packs ( \a this->getNumberOf ).
+ * For each packs, this method aggregates corresponding pack in \a sks.
+ *
+ * \throw if either a lenght of not nullptr instances in \a sks is zero or if number of packs of not nullptr instances in \a sks is not the same.
+ * \return a newly allocated skyline array that is the aggregated packs of inputs
+ */
+MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::AggregatePacks(const std::vector<const MEDCouplingSkyLineArray *>& sks)
+{
+ std::vector<const MEDCouplingSkyLineArray *>sksEff;
+ mcIdType nbOfPacks(std::numeric_limits<mcIdType>::max());
+ constexpr char MSG[]="MEDCouplingSkyLineArray::AggregatePacks : ";
+ for(auto sk : sks)
+ {
+ if(sk)
+ {
+ mcIdType curNbPacks(sk->getNumberOf());
+ if(sksEff.empty())
+ nbOfPacks = curNbPacks;
+ if(nbOfPacks != curNbPacks)
+ {
+ std::ostringstream oss; oss << MSG << "first not null input ska has " << nbOfPacks << " whereas there is presence of ska with " << curNbPacks << " !";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ sksEff.push_back(sk);
+ }
+ }
+ if(sksEff.empty())
+ {
+ std::ostringstream oss; oss << MSG << "input vector contains no not nullptr elements !";
+ throw INTERP_KERNEL::Exception(oss.str());
+ }
+ //
+ MCAuto<DataArrayIdType> index(DataArrayIdType::New()); index->alloc(nbOfPacks+1,1);
+ mcIdType *indexPtr(index->getPointer()); *indexPtr=0;
+ std::vector<const mcIdType *> indicesIn(SkyLineArrayIndexIterator(0,&sksEff),SkyLineArrayIndexIterator(sksEff.size(),&sksEff));
+ for( mcIdType packId = 0 ; packId < nbOfPacks ; ++packId, ++indexPtr )
+ {
+ mcIdType nbOfAggPacks(0);
+ std::for_each(indicesIn.begin(),indicesIn.end(),[packId,&nbOfAggPacks](const mcIdType *elt) { nbOfAggPacks+=elt[packId+1]-elt[packId]; });
+ indexPtr[1] = indexPtr[0] + nbOfAggPacks;
+ }
+ mcIdType nbOfTuplesOut(index->back());
+ MCAuto<DataArrayIdType> values(DataArrayIdType::New()); values->alloc(nbOfTuplesOut,1);
+ mcIdType *valuesPtr(values->getPointer());
+ // let's go to populate values array
+ std::vector<const mcIdType *> valuesIn(SkyLineArrayValuesIterator(0,&sksEff),SkyLineArrayValuesIterator(sksEff.size(),&sksEff));
+ for( mcIdType packId = 0 ; packId < nbOfPacks ; ++packId )
+ {
+ std::size_t pos(0);
+ std::for_each(valuesIn.begin(),valuesIn.end(),[packId,&indicesIn,&valuesPtr,&pos](const mcIdType *elt)
+ { valuesPtr=std::copy(elt+indicesIn[pos][packId],elt+indicesIn[pos][packId+1],valuesPtr); ++pos; }
+ );
+ }
+ //
+ MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(index,values));
+ return ret.retn();
+}
/**
* For a 2- or 3-level SkyLine array, return a copy of the absolute pack with given identifier.
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-#ifndef __PARAMEDMEM_MEDCOUPLINGSKYLINEARRAY_HXX__
-#define __PARAMEDMEM_MEDCOUPLINGSKYLINEARRAY_HXX__
+#pragma once
#include "MEDCoupling.hxx"
#include "MEDCouplingMemArray.hxx"
DataArrayIdType* getIndexArray() const;
DataArrayIdType* getValuesArray() const;
+ MEDCouplingSkyLineArray *deepCopy() const;
+
std::string simpleRepr() const;
MEDCouplingSkyLineArray *groupPacks(const DataArrayIdType *indexedPacks) const;
MEDCouplingSkyLineArray *uniqueNotSortedByPack() const;
+ static MEDCouplingSkyLineArray *AggregatePacks(const std::vector<const MEDCouplingSkyLineArray *>& sks);
void getSimplePackSafe(const mcIdType absolutePackId, std::vector<mcIdType> & pack) const;
const mcIdType * getSimplePackSafePtr(const mcIdType absolutePackId, mcIdType & packSize) const;
MCAuto<DataArrayIdType> _values;
};
+ template<typename T>
+ class SkyLineArrayGenIterator : public std::iterator< std::input_iterator_tag, const mcIdType *, mcIdType, const mcIdType **, const mcIdType *>
+ {
+ std::size_t _num = 0;
+ std::vector<const MEDCouplingSkyLineArray *> *_data = nullptr;
+ public:
+ explicit SkyLineArrayGenIterator(std::size_t num , std::vector<const MEDCouplingSkyLineArray *> *data) : _num(num),_data(data) {}
+ SkyLineArrayGenIterator<T>& operator++() { ++_num; return *this; }
+ bool operator==(const SkyLineArrayGenIterator& other) const { return _num == other._num; }
+ bool operator!=(const SkyLineArrayGenIterator& other) const { return !(*this == other); }
+ reference operator*() const { T tt; return tt((*_data)[_num]); }
+ };
+
+ struct SkyLineArrayIndexPtrFunctor { const mcIdType *operator()(const MEDCouplingSkyLineArray *ska) { return ska->getIndex(); } };
+
+ using SkyLineArrayIndexIterator = SkyLineArrayGenIterator<SkyLineArrayIndexPtrFunctor>;
+
+ struct SkyLineArrayValuesPtrFunctor { const mcIdType *operator()(const MEDCouplingSkyLineArray *ska) { return ska->getValues(); } };
+
+ using SkyLineArrayValuesIterator = SkyLineArrayGenIterator<SkyLineArrayValuesPtrFunctor>;
}
-# endif
template<class T>
struct MEDCOUPLING_EXPORT Traits
{
- typedef T EltType;
+ using EltType = T;
};
class DataArrayInt32;
//
// Author : Anthony Geay (CEA/DEN)
-#ifndef __PARAMEDMEM_MEDCOUPLINGUMESH_HXX__
-#define __PARAMEDMEM_MEDCOUPLINGUMESH_HXX__
+#pragma once
#include "MEDCoupling.hxx"
#include "MEDCouplingPointSet.hxx"
mcIdType _conn_lgth;
static const int NOTICABLE_FIRST_VAL=-7;
};
+
+ template<typename T, typename TOUT>
+ class UMeshGenIterator : public std::iterator< std::input_iterator_tag, const TOUT *, mcIdType, const TOUT **, const TOUT *>
+ {
+ std::size_t _num = 0;
+ std::vector<const MEDCouplingUMesh *> *_data = nullptr;
+ using my_reference = typename std::iterator< std::input_iterator_tag, const TOUT *, mcIdType, const TOUT **, const TOUT *>::reference;
+ public:
+ explicit UMeshGenIterator(std::size_t num , std::vector<const MEDCouplingUMesh *> *data) : _num(num),_data(data) {}
+ UMeshGenIterator<T,TOUT>& operator++() { ++_num; return *this; }
+ bool operator==(const UMeshGenIterator& other) const { return _num == other._num; }
+ bool operator!=(const UMeshGenIterator& other) const { return !(*this == other); }
+ my_reference operator*() const { T tt; return tt((*_data)[_num]); }
+ };
+
+ struct UMeshIndexConnectivityFunctor { const DataArrayIdType *operator()(const MEDCouplingUMesh *um) { return um->getNodalConnectivityIndex(); } };
+
+ using UMeshConnectivityIndexIterator = UMeshGenIterator<UMeshIndexConnectivityFunctor,DataArrayIdType>;
+
+ struct UMeshConnectivityFunctor { const DataArrayIdType *operator()(const MEDCouplingUMesh *um) { return um->getNodalConnectivity(); } };
+
+ using UMeshConnectivityIterator = UMeshGenIterator<UMeshConnectivityFunctor,DataArrayIdType>;
+
+ struct UMeshCoordsFunctor { const DataArrayDouble *operator()(const MEDCouplingUMesh *um) { return um->getCoords(); } };
+
+ using UMeshCoordsIterator = UMeshGenIterator<UMeshCoordsFunctor,DataArrayDouble>;
}
-#endif
# -*- coding: utf-8 -*-
-# Copyright (C) 2007-2020 CEA/DEN, EDF R&D
+# Copyright (C) 2007-2020 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
# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
+# version 2.1 of the License,or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# License along with this library; if not,write to the Free Software
+# Foundation,Inc.,59 Temple Place,Suite 330,Boston,MA 02111-1307 USA
#
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
from math import pi,e,sqrt,cos,sin
from datetime import datetime
from MEDCouplingDataForTest import MEDCouplingDataForTest
-import rlcompleter,readline # this line has to be here, to ensure a usability of MEDCoupling/MEDLoader. B4 removing it please notify to anthony.geay@cea.fr
+import rlcompleter,readline # this line has to be here,to ensure a usability of MEDCoupling/MEDLoader. B4 removing it please notify to anthony.geay@cea.fr
class MEDCouplingBasicsTest7(unittest.TestCase):
def testDAIAggregateMulti1(self):
a=DataArrayInt64.New()
- a.setValues(list(range(4)), 2, 2)
+ a.setValues(list(range(4)),2, 2)
a.setName("aa")
b=DataArrayInt64.New()
b.setValues(list(range(6)), 3, 2)
sk2 = sk.uniqueNotSortedByPack()
self.assertTrue(sk2.getIndexArray().isEqual(DataArrayInt([0,3,8,13,16,21,29,37,42])))
self.assertTrue(sk2.getValuesArray().isEqual(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])))
+
+ def testSkyLineAggregatePacks1(self):
+ arr = DataArrayDouble(3) ; arr.iota()
+ m = MEDCouplingCMesh() ; m.setCoords(arr,arr) ; m = m.buildUnstructured()
+ a,b = m.computeEnlargedNeighborsOfNodes()
+ sk = MEDCouplingSkyLineArray(b,a)
+ sk1 = sk.deepCopy()
+ sk1.getValuesArray()[:] *= 2
+ sk2 = sk.deepCopy()
+ sk2.getValuesArray()[:] *= 3
+ skOut = MEDCouplingSkyLineArray.AggregatePacks([sk,sk1,sk2])
+ self.assertTrue(skOut.getIndexArray().isEqual(DataArrayInt([0,9,24,33,48,72,87,96,111,120])))
+ self.assertTrue(skOut.getValuesArray().isEqual(DataArrayInt([1,3,4,2,6,8,3,9,12,0,2,3,4,5,0,4,6,8,10,0,6,9,12,15,1,4,5,2,8,10,3,12,15,0,1,4,6,7,0,2,8,12,14,0,3,12,18,21,0,1,2,3,5,6,7,8,0,2,4,6,10,12,14,16,0,3,6,9,15,18,21,24,1,2,4,7,8,2,4,8,14,16,3,6,12,21,24,3,4,7,6,8,14,9,12,21,3,4,5,6,8,6,8,10,12,16,9,12,15,18,24,4,5,7,8,10,14,12,15,21])))
+
+ def testDACopySorted1(self):
+ d = DataArrayInt32([5,1,100,20])
+ self.assertTrue(d.copySorted().isEqual(DataArrayInt32([1,5,20,100])))
+ d = DataArrayInt64([5,1,100,20])
+ self.assertTrue(d.copySorted().isEqual(DataArrayInt64([1,5,20,100])))
+ d = DataArrayInt([5,1,100,20])
+ self.assertTrue(d.copySorted().isEqual(DataArrayInt([1,5,20,100])))
+ d = DataArrayDouble([5,1,100,20])
+ self.assertTrue(d.copySorted().isEqual(DataArrayDouble([1,5,20,100]),1e-10))
pass
%newobject MEDCoupling::MEDCouplingSkyLineArray::getValuesArray;
%newobject MEDCoupling::MEDCouplingSkyLineArray::groupPacks;
%newobject MEDCoupling::MEDCouplingSkyLineArray::uniqueNotSortedByPack;
+%newobject MEDCoupling::MEDCouplingSkyLineArray::AggregatePacks;
+%newobject MEDCoupling::MEDCouplingSkyLineArray::deepCopy;
%feature("unref") MEDCouplingPointSet "$this->decrRef();"
%feature("unref") MEDCouplingMesh "$this->decrRef();"
MEDCouplingSkyLineArray *groupPacks(const DataArrayIdType *indexedPacks) const;
MEDCouplingSkyLineArray *uniqueNotSortedByPack() const;
+
+ MEDCouplingSkyLineArray *deepCopy() const;
%extend
{
convertFromPyObjVectorOfObj<const MEDCoupling::DataArrayIdType*>(listePacks,SWIGTITraits<mcIdType>::TI,"DataArrayIdType",packs);
self->replaceSimplePacks(idx, packs);
}
+
+ static MEDCouplingSkyLineArray *AggregatePacks(PyObject *sks)
+ {
+ std::vector<const MEDCouplingSkyLineArray *> sksCpp;
+ convertFromPyObjVectorOfObj<const MEDCoupling::MEDCouplingSkyLineArray*>(sks,SWIGTYPE_p_MEDCoupling__MEDCouplingSkyLineArray,"MEDCouplingSkyLineArray",sksCpp);
+ return MEDCoupling::MEDCouplingSkyLineArray::AggregatePacks(sksCpp);
+ }
void replacePack(const mcIdType superIdx, const mcIdType idx, PyObject *pack)
{
throw INTERP_KERNEL::Exception("convertFromPyObjVectorOfObj : not a list nor a tuple");
}
+//convertFromVectorAutoObjToPyObj<MEDCoupling::MEDCouplingUMesh>(inpv,SWIGTYPE_p_MEDCoupling__MEDCouplingUMesh)
+template<class T>
+static PyObject *convertFromVectorAutoObjToPyObj(std::vector< MCAuto<T> >& inpVector, swig_type_info *ty)
+{
+ std::size_t sz(inpVector.size());
+ PyObject *ret = PyList_New(sz);
+ for(std::size_t i=0;i<sz;++i)
+ PyList_SetItem(ret,i,SWIG_NewPointerObj(SWIG_as_voidptr(inpVector[i].retn()),ty, SWIG_POINTER_OWN | 0 ));
+ return ret;
+}
+
/*!
* if python int -> cpp int sw=1
* if python list[int] -> cpp vector<int> sw=2
//$$$$$$$$$$$$$$$$$$
%newobject MEDCoupling::DataArray::deepCopy;
+%newobject MEDCoupling::DataArray::copySorted;
%newobject MEDCoupling::DataArray::buildNewEmptyInstance;
%newobject MEDCoupling::DataArray::selectByTupleRanges;
%newobject MEDCoupling::DataArray::selectByTupleId;
virtual std::size_t getNbOfElems() const;
virtual std::size_t getNbOfElemAllocated() const;
virtual DataArray *deepCopy() const;
+ virtual DataArray *copySorted() const;
virtual DataArray *buildNewEmptyInstance() const;
virtual DataArray *selectByTupleIdSafeSlice(int bg, int end2, int step) const;
virtual void rearrange(int newNbOfCompo);
//DataArrayMedInt *buildNewEmptyInstance() const { return new DataArrayMedInt(); }//ko
DataArray *buildNewEmptyInstance() const { if ( sizeof(med_int)==sizeof(int)) return DataArrayInt32::New(); return DataArrayInt64::New(); }
public:
+ DataArrayMedInt *copySorted(bool asc=true) const override { MCAuto<DataArrayMedInt> ret(this->deepCopy()); ret->sort(); return ret.retn(); }
DataArray *selectByTupleId(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const { return this->mySelectByTupleId(new2OldBg,new2OldEnd); }
DataArray *selectByTupleId(const DataArrayIdType& di) const { return this->mySelectByTupleId(di); }
DataArray *selectByTupleIdSafe(const mcIdType *new2OldBg, const mcIdType *new2OldEnd) const { return this->mySelectByTupleIdSafe(new2OldBg,new2OldEnd); }
#include "CommInterface.hxx"
-#include <numeric>
-
namespace MEDCoupling
{
+ MPI_Datatype ParaTraits<double>::MPIDataType = MPI_DOUBLE;
+
+ MPI_Datatype ParaTraits<Int32>::MPIDataType = MPI_INT;
+
+ MPI_Datatype ParaTraits<Int64>::MPIDataType = MPI_LONG;
+
/*! \anchor CommInterface-det
\class CommInterface
* Generalized AllGather collective communication.
* This method send input \a array to all procs.
*/
- void CommInterface::allGatherArrays(MPI_Comm comm, const DataArrayIdType *array, std::unique_ptr<mcIdType[]>& result, std::unique_ptr<mcIdType[]>& resultIndex) const
+ void CommInterface::allGatherArrays(MPI_Comm comm, const DataArrayIdType *array, std::vector< MCAuto<DataArrayIdType> >& arraysOut) const
+ {
+ std::unique_ptr<mcIdType[]> result, resultIndex;
+ int size(this->allGatherArrays(comm,array,result,resultIndex));
+ arraysOut.resize(size);
+ for(int i = 0 ; i < size ; ++i)
+ {
+ arraysOut[i] = DataArrayIdType::New();
+ mcIdType nbOfEltPack(resultIndex[i+1]-resultIndex[i]);
+ arraysOut[i]->alloc(nbOfEltPack,1);
+ std::copy(result.get()+resultIndex[i],result.get()+resultIndex[i+1],arraysOut[i]->getPointer());
+ }
+ }
+
+ /*!
+ * Generalized AllGather collective communication.
+ * This method send input \a array to all procs.
+ */
+ int CommInterface::allGatherArrays(MPI_Comm comm, const DataArrayIdType *array, std::unique_ptr<mcIdType[]>& result, std::unique_ptr<mcIdType[]>& resultIndex) const
{
int size;
this->commSize(comm,&size);
std::unique_ptr<int[]> nbOfElemsInt( CommInterface::ToIntArray<mcIdType>(nbOfElems,size) );
std::unique_ptr<int[]> offsetsIn( CommInterface::ComputeOffset(nbOfElemsInt,size) );
this->allGatherV(array->begin(),nbOfCellsRequested,MPI_ID_TYPE,result.get(),nbOfElemsInt.get(),offsetsIn.get(),MPI_ID_TYPE,comm);
- resultIndex = std::move(nbOfElems);
+ resultIndex = ComputeOffsetFull<mcIdType>(nbOfElems,size);
+ return size;
+ }
+
+ void CommInterface::allToAllArrays(MPI_Comm comm, const std::vector< MCAuto<DataArrayDouble> >& arrays, std::vector< MCAuto<DataArrayDouble> >& arraysOut) const
+ {
+ this->allToAllArraysT<double>(comm,arrays,arraysOut);
+ }
+
+ void CommInterface::allToAllArrays(MPI_Comm comm, const std::vector< MCAuto<DataArrayDouble> >& arrays, MCAuto<DataArrayDouble>& arraysOut) const
+ {
+ std::unique_ptr<mcIdType[]> notUsed1;
+ mcIdType notUsed2;
+ this->allToAllArraysT2<double>(comm,arrays,arraysOut,notUsed1,notUsed2);
}
/*!
*/
void CommInterface::allToAllArrays(MPI_Comm comm, const std::vector< MCAuto<DataArrayIdType> >& arrays, std::vector< MCAuto<DataArrayIdType> >& arraysOut) const
{
- int size;
- this->commSize(comm,&size);
- if( arrays.size() != ToSizeT(size) )
- throw INTERP_KERNEL::Exception("AllToAllArrays : internal error ! Invalid size of input array.");
-
- std::vector< const DataArrayIdType *> arraysBis(FromVecAutoToVecOfConst<DataArrayIdType>(arrays));
- std::unique_ptr<mcIdType[]> nbOfElems2(new mcIdType[size]),nbOfElems3(new mcIdType[size]);
- for(int curRk = 0 ; curRk < size ; ++curRk)
- {
- nbOfElems3[curRk] = arrays[curRk]->getNumberOfTuples();
- }
- this->allToAll(nbOfElems3.get(),1,MPI_ID_TYPE,nbOfElems2.get(),1,MPI_ID_TYPE,comm);
- mcIdType nbOfCellIdsSum(std::accumulate(nbOfElems2.get(),nbOfElems2.get()+size,0));
- MCAuto<DataArrayIdType> cellIdsFromProcs(DataArrayIdType::New());
- cellIdsFromProcs->alloc(nbOfCellIdsSum,1);
- std::unique_ptr<int[]> nbOfElemsInt( CommInterface::ToIntArray<mcIdType>(nbOfElems3,size) ),nbOfElemsOutInt( CommInterface::ToIntArray<mcIdType>(nbOfElems2,size) );
- std::unique_ptr<int[]> offsetsIn( CommInterface::ComputeOffset(nbOfElemsInt,size) ), offsetsOut( CommInterface::ComputeOffset(nbOfElemsOutInt,size) );
- {
- MCAuto<DataArrayIdType> arraysAcc(DataArrayIdType::Aggregate(arraysBis));
- this->allToAllV(arraysAcc->begin(),nbOfElemsInt.get(),offsetsIn.get(),MPI_ID_TYPE,
- cellIdsFromProcs->getPointer(),nbOfElemsOutInt.get(),offsetsOut.get(),MPI_ID_TYPE,comm);
- }
- std::unique_ptr<mcIdType[]> offsetsOutIdType( CommInterface::ComputeOffset(nbOfElems2,size) );
- // build output arraysOut by spliting cellIdsFromProcs into parts
- arraysOut.resize(size);
- for(int curRk = 0 ; curRk < size ; ++curRk)
- {
- arraysOut[curRk] = DataArrayIdType::NewFromArray(cellIdsFromProcs->begin()+offsetsOutIdType[curRk],cellIdsFromProcs->begin()+offsetsOutIdType[curRk]+nbOfElems2[curRk]);
- }
+ this->allToAllArraysT<mcIdType>(comm,arrays,arraysOut);
}
+
}
#include <mpi.h>
#include <memory>
+#include <numeric>
namespace MEDCoupling
{
+ template<class T>
+ struct ParaTraits
+ {
+ using EltType = T;
+ };
+
+ template<>
+ struct ParaTraits<double>
+ {
+ static MPI_Datatype MPIDataType;
+ };
+
+ template<>
+ struct ParaTraits<Int32>
+ {
+ static MPI_Datatype MPIDataType;
+ };
+
+ template<>
+ struct ParaTraits<Int64>
+ {
+ static MPI_Datatype MPIDataType;
+ };
class CommInterface
{
MPI_Op op, int root, MPI_Comm comm) const { return MPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm); }
int allReduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) const { return MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm); }
public:
- void allGatherArrays(MPI_Comm comm, const DataArrayIdType *array, std::unique_ptr<mcIdType[]>& result, std::unique_ptr<mcIdType[]>& resultIndex) const;
+ void allGatherArrays(MPI_Comm comm, const DataArrayIdType *array, std::vector< MCAuto<DataArrayIdType> >& arraysOut) const;
+ int allGatherArrays(MPI_Comm comm, const DataArrayIdType *array, std::unique_ptr<mcIdType[]>& result, std::unique_ptr<mcIdType[]>& resultIndex) const;
void allToAllArrays(MPI_Comm comm, const std::vector< MCAuto<DataArrayIdType> >& arrays, std::vector< MCAuto<DataArrayIdType> >& arraysOut) const;
+ void allToAllArrays(MPI_Comm comm, const std::vector< MCAuto<DataArrayDouble> >& arrays, std::vector< MCAuto<DataArrayDouble> >& arraysOut) const;
+ void allToAllArrays(MPI_Comm comm, const std::vector< MCAuto<DataArrayDouble> >& arrays, MCAuto<DataArrayDouble>& arraysOut) const;
+ template<class T>
+ int allToAllArraysT2(MPI_Comm comm, const std::vector< MCAuto<typename Traits<T>::ArrayType> >& arrays, MCAuto<typename Traits<T>::ArrayType>& arrayOut, std::unique_ptr<mcIdType[]>& nbOfElems2, mcIdType& nbOfComponents) const
+ {
+ using DataArrayT = typename Traits<T>::ArrayType;
+ int size;
+ this->commSize(comm,&size);
+ if( arrays.size() != ToSizeT(size) )
+ throw INTERP_KERNEL::Exception("AllToAllArrays : internal error ! Invalid size of input array.");
+
+ std::vector< const DataArrayT *> arraysBis(FromVecAutoToVecOfConst<DataArrayT>(arrays));
+ std::unique_ptr<mcIdType[]> nbOfElems3(new mcIdType[size]);
+ nbOfElems2.reset(new mcIdType[size]);
+ nbOfComponents = std::numeric_limits<mcIdType>::max();
+ for(int curRk = 0 ; curRk < size ; ++curRk)
+ {
+ mcIdType curNbOfCompo( ToIdType( arrays[curRk]->getNumberOfComponents() ) );
+ if(nbOfComponents != std::numeric_limits<mcIdType>::max())
+ {
+ if( nbOfComponents != curNbOfCompo )
+ throw INTERP_KERNEL::Exception("AllToAllArrays : internal error ! Nb of components is not homogeneous !");
+ }
+ else
+ {
+ nbOfComponents = curNbOfCompo;
+ }
+ nbOfElems3[curRk] = arrays[curRk]->getNbOfElems();
+ }
+ this->allToAll(nbOfElems3.get(),1,MPI_ID_TYPE,nbOfElems2.get(),1,MPI_ID_TYPE,comm);
+ mcIdType nbOfCellIdsSum(std::accumulate(nbOfElems2.get(),nbOfElems2.get()+size,0));
+ arrayOut = DataArrayT::New();
+ arrayOut->alloc(nbOfCellIdsSum/nbOfComponents,nbOfComponents);
+ std::unique_ptr<int[]> nbOfElemsInt( CommInterface::ToIntArray<mcIdType>(nbOfElems3,size) ),nbOfElemsOutInt( CommInterface::ToIntArray<mcIdType>(nbOfElems2,size) );
+ std::unique_ptr<int[]> offsetsIn( CommInterface::ComputeOffset(nbOfElemsInt,size) ), offsetsOut( CommInterface::ComputeOffset(nbOfElemsOutInt,size) );
+ {
+ MCAuto<DataArrayT> arraysAcc(DataArrayT::Aggregate(arraysBis));
+ this->allToAllV(arraysAcc->begin(),nbOfElemsInt.get(),offsetsIn.get(),ParaTraits<T>::MPIDataType,
+ arrayOut->getPointer(),nbOfElemsOutInt.get(),offsetsOut.get(),ParaTraits<T>::MPIDataType,comm);
+ }
+ return size;
+ }
+
+ template<class T>
+ void allToAllArraysT(MPI_Comm comm, const std::vector< MCAuto<typename Traits<T>::ArrayType> >& arrays, std::vector< MCAuto<typename Traits<T>::ArrayType> >& arraysOut) const
+ {
+ using DataArrayT = typename Traits<T>::ArrayType;
+ MCAuto<DataArrayT> cellIdsFromProcs;
+ std::unique_ptr<mcIdType[]> nbOfElems2;
+ mcIdType nbOfComponents(0);
+ int size(this->allToAllArraysT2<T>(comm,arrays,cellIdsFromProcs,nbOfElems2,nbOfComponents));
+ std::unique_ptr<mcIdType[]> offsetsOutIdType( CommInterface::ComputeOffset(nbOfElems2,size) );
+ // build output arraysOut by spliting cellIdsFromProcs into parts
+ arraysOut.resize(size);
+ for(int curRk = 0 ; curRk < size ; ++curRk)
+ {
+ arraysOut[curRk] = DataArrayT::NewFromArray(cellIdsFromProcs->begin()+offsetsOutIdType[curRk],cellIdsFromProcs->begin()+offsetsOutIdType[curRk]+nbOfElems2[curRk]);
+ arraysOut[curRk]->rearrange(nbOfComponents);
+ }
+ }
public:
/*!
}
return ret;
}
+
+ /*!
+ * Helper of alltoallv and allgatherv
+ */
+ template<class T>
+ static std::unique_ptr<T []> ComputeOffsetFull(const std::unique_ptr<T []>& counts, std::size_t sizeOfCounts)
+ {
+ std::unique_ptr<T []> ret(new T[sizeOfCounts+1]);
+ ret[0] = static_cast<T>(0);
+ for(std::size_t i = 1 ; i < sizeOfCounts+1 ; ++i)
+ {
+ ret[i] = ret[i-1] + counts[i-1];
+ }
+ return ret;
+ }
};
}
using namespace MEDCoupling;
+ParaUMesh *ParaUMesh::New(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds)
+{
+ return new ParaUMesh(mesh,globalCellIds,globalNodeIds);
+}
+
ParaUMesh::ParaUMesh(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds)
{
_mesh.takeRef(mesh);
throw INTERP_KERNEL::Exception("ParaUMesh constructor : mismatch between # cells and len of global # cells.");
}
+std::size_t ParaUMesh::getHeapMemorySizeWithoutChildren() const
+{
+ return 0;
+}
+
+std::vector<const BigMemoryObject *> ParaUMesh::getDirectChildrenWithNull() const
+{
+ return {_mesh,_cell_global,_node_global};
+}
+
/*!
* This method computes the cells part of distributed mesh lying on \a globalNodeIds nodes.
* The input \a globalNodeIds are not supposed to reside on the current process.
}
/*!
+ * Return part of \a this mesh split over COMM_WORLD. Part is defined by global cell ids array \a globaCellIds.
*/
-MCAuto<ParaUMesh> ParaUMesh::redistributeCells(const DataArrayIdType *globalCellIds) const
+ParaUMesh *ParaUMesh::redistributeCells(const DataArrayIdType *globalCellIds) const
{
MPI_Comm comm(MPI_COMM_WORLD);
CommInterface ci;
- int size;
- ci.commSize(comm,&size);
- std::unique_ptr<mcIdType[]> nbOfElems(new mcIdType[size]);
- mcIdType nbOfCellsRequested(globalCellIds->getNumberOfTuples());
- ci.allGather(&nbOfCellsRequested,1,MPI_ID_TYPE,nbOfElems.get(),1,MPI_ID_TYPE,comm);
- mcIdType nbOfCellIdsSum(std::accumulate(nbOfElems.get(),nbOfElems.get()+size,0));
- std::unique_ptr<mcIdType[]> allGlobalCellIds(new mcIdType[nbOfCellIdsSum]);
- std::unique_ptr<int[]> nbOfElemsInt( CommInterface::ToIntArray<mcIdType>(nbOfElems,size) );
- std::unique_ptr<int[]> offsetsIn( CommInterface::ComputeOffset(nbOfElemsInt,size) );
- ci.allGatherV(globalCellIds->begin(),nbOfCellsRequested,MPI_ID_TYPE,allGlobalCellIds.get(),nbOfElemsInt.get(),offsetsIn.get(),MPI_ID_TYPE,comm);
- mcIdType offset(0);
+ std::unique_ptr<mcIdType[]> allGlobalCellIds,allGlobalCellIdsIndex;
+ int size(ci.allGatherArrays(comm,globalCellIds,allGlobalCellIds,allGlobalCellIdsIndex));
// Prepare ParaUMesh parts to be sent : compute for each proc the contribution of current rank.
std::vector< MCAuto<DataArrayIdType> > globalCellIdsToBeSent(size),globalNodeIdsToBeSent(size);
std::vector< MCAuto<MEDCouplingUMesh> > meshPartsToBeSent(size);
for(int curRk = 0 ; curRk < size ; ++curRk)
{
+ mcIdType offset(allGlobalCellIdsIndex[curRk]);
MCAuto<DataArrayIdType> globalCellIdsOfCurProc(DataArrayIdType::New());
- globalCellIdsOfCurProc->useArray(allGlobalCellIds.get()+offset,false,DeallocType::CPP_DEALLOC,nbOfElems[curRk],1);
- offset += nbOfElems[curRk];
+ globalCellIdsOfCurProc->useArray(allGlobalCellIds.get()+offset,false,DeallocType::CPP_DEALLOC,allGlobalCellIdsIndex[curRk+1]-offset,1);
// the key call is here : compute for rank curRk the cells to be sent
MCAuto<DataArrayIdType> globalCellIdsCaptured(_cell_global->buildIntersection(globalCellIdsOfCurProc));// OK for the global cellIds
- MCAuto<DataArrayIdType> localCellIdsCaptured(_node_global->findIdForEach(globalCellIdsCaptured->begin(),globalCellIdsCaptured->end()));
+ MCAuto<DataArrayIdType> localCellIdsCaptured(_cell_global->findIdForEach(globalCellIdsCaptured->begin(),globalCellIdsCaptured->end()));
MCAuto<MEDCouplingUMesh> meshPart(_mesh->buildPartOfMySelf(localCellIdsCaptured->begin(),localCellIdsCaptured->end(),true));
MCAuto<DataArrayIdType> o2n(meshPart->zipCoordsTraducer());// OK for the mesh
MCAuto<DataArrayIdType> n2o(o2n->invertArrayO2N2N2O(meshPart->getNumberOfNodes()));
globalCellIdsToBeSent[curRk] = globalCellIdsCaptured;
globalNodeIdsToBeSent[curRk] = globalNodeIdsPart;
}
- // Receive
+ // Receive
+ std::vector< MCAuto<DataArrayIdType> > globalCellIdsReceived,globalNodeIdsReceived;
+ ci.allToAllArrays(comm,globalCellIdsToBeSent,globalCellIdsReceived);
+ ci.allToAllArrays(comm,globalNodeIdsToBeSent,globalNodeIdsReceived);
+ //now exchange the 3 arrays for the umesh : connectivity, connectivityindex and coordinates
+ std::vector<const MEDCouplingUMesh *> meshPartsToBeSent2(FromVecAutoToVecOfConst<MEDCouplingUMesh>(meshPartsToBeSent));
+ //connectivityindex
+ std::vector< MCAuto<DataArrayIdType> > connectivityIndexReceived,connectivityReceived;
+ {
+ std::vector<const DataArrayIdType *> connectivityIndexToBeSent(UMeshConnectivityIndexIterator(0,&meshPartsToBeSent2),UMeshConnectivityIndexIterator(meshPartsToBeSent2.size(),&meshPartsToBeSent2));
+ ci.allToAllArrays(comm,FromVecConstToVecAuto<DataArrayIdType>(connectivityIndexToBeSent),connectivityIndexReceived);
+ }
+ //connectivity
+ {
+ std::vector<const DataArrayIdType *> connectivityToBeSent(UMeshConnectivityIterator(0,&meshPartsToBeSent2),UMeshConnectivityIterator(meshPartsToBeSent2.size(),&meshPartsToBeSent2));
+ ci.allToAllArrays(comm,FromVecConstToVecAuto<DataArrayIdType>(connectivityToBeSent),connectivityReceived);
+ }
+ //coordinates
+ MCAuto<DataArrayDouble> coords;
+ {
+ std::vector<const DataArrayDouble *> coordsToBeSent(UMeshCoordsIterator(0,&meshPartsToBeSent2),UMeshCoordsIterator(meshPartsToBeSent2.size(),&meshPartsToBeSent2));
+ ci.allToAllArrays(comm,FromVecConstToVecAuto<DataArrayDouble>(coordsToBeSent),coords);
+ }
+ /////// Sort it all !
+ // firstly deal with nodes.
+ MCAuto<DataArrayIdType> aggregatedNodeIds( DataArrayIdType::Aggregate(FromVecAutoToVecOfConst<DataArrayIdType>(globalNodeIdsReceived)) );
+ MCAuto<DataArrayIdType> aggregatedNodeIdsSorted(aggregatedNodeIds->copySorted());
+ MCAuto<DataArrayIdType> nodeIdsIntoAggregatedIds(DataArrayIdType::FindPermutationFromFirstToSecondDuplicate(aggregatedNodeIdsSorted,aggregatedNodeIds));
+ MCAuto<DataArrayIdType> idxOfSameNodeIds(aggregatedNodeIdsSorted->indexOfSameConsecutiveValueGroups());
+ MCAuto<DataArrayIdType> n2o_nodes(nodeIdsIntoAggregatedIds->selectByTupleIdSafe(idxOfSameNodeIds->begin(),idxOfSameNodeIds->end()-1));//new == new ordering so that global node ids are sorted . old == coarse ordering implied by the aggregation
+ MCAuto<DataArrayIdType> finalGlobalNodeIds(aggregatedNodeIdsSorted->selectByTupleIdSafe(idxOfSameNodeIds->begin(),idxOfSameNodeIds->end()-1));
+ MCAuto<DataArrayDouble> finalCoords(coords->selectByTupleIdSafe(n2o_nodes->begin(),n2o_nodes->end()));
+ finalCoords->copyStringInfoFrom(*_mesh->getCoords());
+ // secondly renumbering of node ids in connectivityReceived
+ for(int curRk = 0 ; curRk < size ; ++curRk)
+ {
+ auto current(globalNodeIdsReceived[curRk]);
+ MCAuto<DataArrayIdType> aa(finalGlobalNodeIds->findIdForEach(current->begin(),current->end()));
+ // work on connectivityReceived[curRk] with transformWithIndArr but do not forget type of cells that should be excluded !
+ auto connectivityToModify(connectivityReceived[curRk]);
+ auto connectivityIndex(connectivityIndexReceived[curRk]);
+ MCAuto<DataArrayIdType> types(connectivityToModify->selectByTupleIdSafe(connectivityIndex->begin(),connectivityIndex->end()-1));
+ connectivityToModify->setPartOfValuesSimple3(0,connectivityIndex->begin(),connectivityIndex->end()-1,0,1,1);
+ connectivityToModify->transformWithIndArr(aa->begin(),aa->end());
+ connectivityToModify->setPartOfValues3(types,connectivityIndex->begin(),connectivityIndex->end()-1,0,1,1,true);
+ }
+ // thirdly renumber cells
+ MCAuto<DataArrayIdType> aggregatedCellIds( DataArrayIdType::Aggregate(FromVecAutoToVecOfConst<DataArrayIdType>(globalCellIdsReceived)) );
+ MCAuto<DataArrayIdType> aggregatedCellIdsSorted(aggregatedCellIds->copySorted());
+ MCAuto<DataArrayIdType> idsIntoAggregatedIds(DataArrayIdType::FindPermutationFromFirstToSecondDuplicate(aggregatedCellIdsSorted,aggregatedCellIds));
+ MCAuto<DataArrayIdType> cellIdsOfSameNodeIds(aggregatedCellIdsSorted->indexOfSameConsecutiveValueGroups());
+ MCAuto<DataArrayIdType> n2o_cells(idsIntoAggregatedIds->selectByTupleIdSafe(cellIdsOfSameNodeIds->begin(),cellIdsOfSameNodeIds->end()-1));//new == new ordering so that global cell ids are sorted . old == coarse ordering implied by the aggregation
+ // TODO : check coordsReceived==globalCellIds
+ MCAuto<DataArrayIdType> connSorted,indicesSorted;
+ {
+ MCAuto<DataArrayIdType> conn(DataArrayIdType::Aggregate(FromVecAutoToVecOfConst<DataArrayIdType>(connectivityReceived)));
+ MCAuto<DataArrayIdType> connIndex(DataArrayIdType::AggregateIndexes(FromVecAutoToVecOfConst<DataArrayIdType>(connectivityIndexReceived)));
+ {
+ DataArrayIdType *indicesSortedTmp(nullptr),*valuesSortedTmp(nullptr);
+ DataArrayIdType::ExtractFromIndexedArrays(n2o_cells->begin(),n2o_cells->end(),conn,connIndex,valuesSortedTmp,indicesSortedTmp);
+ indicesSorted = indicesSortedTmp; connSorted=valuesSortedTmp;
+ }
+ }
+ // finalize all
+ MCAuto<MEDCouplingUMesh> mesh(MEDCouplingUMesh::New(_mesh->getName(),_mesh->getMeshDimension()));
+ mesh->setConnectivity(connSorted,indicesSorted,true);
+ mesh->setCoords(finalCoords);
+ mesh->setDescription(_mesh->getDescription());
+ MCAuto<ParaUMesh> ret(ParaUMesh::New(mesh,aggregatedCellIdsSorted,finalGlobalNodeIds));
+ return ret.retn();
}
*
* This class is very specific to the requirement of parallel code computations.
*/
- class ParaUMesh
+ class ParaUMesh : public RefCountObject
{
public:
- ParaUMesh(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds);
+ static ParaUMesh *New(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds);
MCAuto<DataArrayIdType> getCellIdsLyingOnNodes(const DataArrayIdType *globalNodeIds, bool fullyIn) const;
- MCAuto<ParaUMesh> redistributeCells(const DataArrayIdType *globalCellIds) const;
+ ParaUMesh *redistributeCells(const DataArrayIdType *globalCellIds) const;
+ MEDCouplingUMesh *getMesh() { return _mesh; }
+ DataArrayIdType *getGlobalCellIds() { return _cell_global; }
+ DataArrayIdType *getGlobalNodeIds() { return _node_global; }
+ protected:
virtual ~ParaUMesh() { }
+ ParaUMesh(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds);
+ std::string getClassName() const override { return "ParaUMesh"; }
+ std::size_t getHeapMemorySizeWithoutChildren() const override;
+ std::vector<const BigMemoryObject *> getDirectChildrenWithNull() const override;
private:
MCAuto<MEDCouplingUMesh> _mesh;
MCAuto<DataArrayIdType> _cell_global;
%rename(ICoCoMEDField) ICoCo::MEDField;
%include "ICoCoMEDField.hxx"
+%newobject MEDCoupling::ParaUMesh::New;
+%newobject MEDCoupling::ParaUMesh::getMesh;
+%newobject MEDCoupling::ParaUMesh::getGlobalCellIds;
+%newobject MEDCoupling::ParaUMesh::getGlobalNodeIds;
%newobject MEDCoupling::ParaUMesh::getCellIdsLyingOnNodes;
+%newobject MEDCoupling::ParaUMesh::redistributeCells;
+%newobject MEDCoupling::ParaSkyLineArray::New;
%newobject MEDCoupling::ParaSkyLineArray::equiRedistribute;
%newobject MEDCoupling::ParaSkyLineArray::getSkyLineArray;
%newobject MEDCoupling::ParaSkyLineArray::getGlobalIdsArray;
%feature("unref") ParaSkyLineArray "$this->decrRef();"
+%feature("unref") ParaUMesh "$this->decrRef();"
%nodefaultctor;
int reduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) const;
int allReduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm) const;
+ %extend
+ {
+ PyObject *allGatherArrays(const DataArrayIdType *array) const
+ {
+ std::vector< MCAuto<DataArrayIdType> > ret;
+ self->allGatherArrays(MPI_COMM_WORLD,array,ret);
+ return convertFromVectorAutoObjToPyObj<DataArrayIdType>(ret,SWIGTITraits<mcIdType>::TI);
+ }
+
+ PyObject *allToAllArrays(PyObject *arrays) const
+ {
+ std::vector< DataArrayIdType * > arraysIn;
+ std::vector< MCAuto<DataArrayIdType> > arrayOut;
+ convertFromPyObjVectorOfObj<MEDCoupling::DataArrayIdType*>(arrays,SWIGTITraits<mcIdType>::TI,"DataArrayIdType",arraysIn);
+ std::vector< MCAuto<DataArrayIdType> > arraysIn2(FromVecToVecAuto<DataArrayIdType>(arraysIn));
+ self->allToAllArrays(MPI_COMM_WORLD,arraysIn2,arrayOut);
+ return convertFromVectorAutoObjToPyObj<DataArrayIdType>(arrayOut,SWIGTITraits<mcIdType>::TI);
+ }
+ }
};
- class ParaUMesh
+ class ParaUMesh : public RefCountObject
{
public:
- ParaUMesh(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds);
+ static ParaUMesh *New(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds);
+ ParaUMesh *redistributeCells(const DataArrayIdType *globalCellIds) const;
%extend
{
+ ParaUMesh(MEDCouplingUMesh *mesh, DataArrayIdType *globalCellIds, DataArrayIdType *globalNodeIds)
+ {
+ return ParaUMesh::New(mesh,globalCellIds,globalNodeIds);
+ }
+
+ MEDCouplingUMesh *getMesh()
+ {
+ MEDCouplingUMesh *ret(self->getMesh());
+ if(ret) ret->incrRef();
+ return ret;
+ }
+
+ DataArrayIdType *getGlobalCellIds()
+ {
+ DataArrayIdType *ret(self->getGlobalCellIds());
+ if(ret) ret->incrRef();
+ return ret;
+ }
+
+ DataArrayIdType *getGlobalNodeIds()
+ {
+ DataArrayIdType *ret(self->getGlobalNodeIds());
+ if(ret) ret->incrRef();
+ return ret;
+ }
+
DataArrayIdType *getCellIdsLyingOnNodes(const DataArrayIdType *globalNodeIds, bool fullyIn) const
{
MCAuto<DataArrayIdType> ret(self->getCellIdsLyingOnNodes(globalNodeIds,fullyIn));