From 1ca2b215a1ae474745fabc87dd9c5c98e9af6354 Mon Sep 17 00:00:00 2001 From: imn Date: Tue, 19 May 2015 14:59:01 +0300 Subject: [PATCH] 0022875: EDF 7690 MED: Creating joints with medpartitioner in the MEDCoupling API --- src/CMakeLists.txt | 3 + src/MEDCoupling/CMakeLists.txt | 1 + src/MEDCoupling/MEDCouplingSkyLineArray.cxx | 102 +++ src/MEDCoupling/MEDCouplingSkyLineArray.hxx | 56 ++ src/MEDCoupling/MEDCouplingUMesh.cxx | 77 ++ src/MEDCoupling/MEDCouplingUMesh.hxx | 2 + src/MEDCoupling_Swig/MEDCouplingBasicsTest.py | 61 ++ src/MEDCoupling_Swig/MEDCouplingCommon.i | 25 + src/MEDLoader/CMakeLists.txt | 1 + src/MEDLoader/MEDFileData.cxx | 1 + src/MEDLoader/MEDFileField.cxx | 8 +- src/MEDLoader/MEDFileJoint.cxx | 838 ++++++++++++++++++ src/MEDLoader/MEDFileJoint.hxx | 194 ++++ src/MEDLoader/MEDFileMesh.cxx | 130 ++- src/MEDLoader/MEDFileMesh.hxx | 11 +- src/MEDLoader/Swig/MEDLoaderCommon.i | 226 +++++ src/MEDLoader/Swig/MEDLoaderTest3.py | 126 +++ src/MEDPartitioner/CMakeLists.txt | 4 +- .../MEDPARTITIONER_ConnectZone.cxx | 158 ++-- .../MEDPARTITIONER_ConnectZone.hxx | 27 +- src/MEDPartitioner/MEDPARTITIONER_Graph.cxx | 16 +- src/MEDPartitioner/MEDPARTITIONER_Graph.hxx | 23 +- .../MEDPARTITIONER_MEDPartitioner.cxx | 159 ++++ .../MEDPARTITIONER_MEDPartitioner.hxx | 62 ++ .../MEDPARTITIONER_MeshCollection.cxx | 556 ++++++++---- .../MEDPARTITIONER_MeshCollection.hxx | 24 +- .../MEDPARTITIONER_MeshCollectionDriver.cxx | 392 ++++---- .../MEDPARTITIONER_MeshCollectionDriver.hxx | 16 +- ...RTITIONER_MeshCollectionMedAsciiDriver.cxx | 39 +- ...RTITIONER_MeshCollectionMedAsciiDriver.hxx | 3 +- ...PARTITIONER_MeshCollectionMedXmlDriver.cxx | 18 +- .../MEDPARTITIONER_MetisGraph.cxx | 4 +- .../MEDPARTITIONER_MetisGraph.hxx | 2 +- .../MEDPARTITIONER_ParMetisGraph.cxx | 4 +- .../MEDPARTITIONER_ParMetisGraph.hxx | 2 +- .../MEDPARTITIONER_ParaDomainSelector.cxx | 4 +- .../MEDPARTITIONER_ParallelTopology.cxx | 72 +- .../MEDPARTITIONER_ParallelTopology.hxx | 10 +- .../MEDPARTITIONER_ScotchGraph.cxx | 4 +- .../MEDPARTITIONER_ScotchGraph.hxx | 3 +- .../MEDPARTITIONER_SkyLineArray.cxx | 45 - .../MEDPARTITIONER_SkyLineArray.hxx | 47 - .../MEDPARTITIONER_Topology.hxx | 3 +- .../MEDPARTITIONER_UserGraph.cxx | 4 +- .../MEDPARTITIONER_UserGraph.hxx | 4 +- src/MEDPartitioner/MEDPARTITIONER_Utils.cxx | 1 + src/MEDPartitioner/MEDPARTITIONER_Utils.hxx | 1 + src/MEDPartitioner/medpartitioner.cxx | 4 + src/MEDPartitioner_Swig/CMakeLists.txt | 76 ++ .../CTestTestfileInstall.cmake | 21 + src/MEDPartitioner_Swig/MEDPartitioner.i | 140 +++ .../MEDPartitionerCommon.i | 70 ++ src/MEDPartitioner_Swig/MEDPartitionerTest.py | 100 +++ 53 files changed, 3455 insertions(+), 525 deletions(-) create mode 100644 src/MEDCoupling/MEDCouplingSkyLineArray.cxx create mode 100644 src/MEDCoupling/MEDCouplingSkyLineArray.hxx create mode 100644 src/MEDLoader/MEDFileJoint.cxx create mode 100644 src/MEDLoader/MEDFileJoint.hxx create mode 100644 src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.cxx create mode 100644 src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.hxx delete mode 100644 src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.cxx delete mode 100644 src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.hxx create mode 100644 src/MEDPartitioner_Swig/CMakeLists.txt create mode 100644 src/MEDPartitioner_Swig/CTestTestfileInstall.cmake create mode 100644 src/MEDPartitioner_Swig/MEDPartitioner.i create mode 100644 src/MEDPartitioner_Swig/MEDPartitionerCommon.i create mode 100644 src/MEDPartitioner_Swig/MEDPartitionerTest.py diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c4296a583..d3d23be80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,9 @@ IF(NOT SALOME_MED_MICROMED) ENDIF(SALOME_MED_ENABLE_RENUMBER) IF(SALOME_MED_ENABLE_PARTITIONER) ADD_SUBDIRECTORY(MEDPartitioner) + IF(SALOME_MED_ENABLE_PYTHON) + ADD_SUBDIRECTORY(MEDPartitioner_Swig) + ENDIF(SALOME_MED_ENABLE_PYTHON) ENDIF(SALOME_MED_ENABLE_PARTITIONER) IF(SALOME_BUILD_TESTS) ADD_SUBDIRECTORY(INTERP_KERNELTest) diff --git a/src/MEDCoupling/CMakeLists.txt b/src/MEDCoupling/CMakeLists.txt index 085f40422..014f69a41 100644 --- a/src/MEDCoupling/CMakeLists.txt +++ b/src/MEDCoupling/CMakeLists.txt @@ -59,6 +59,7 @@ SET(medcoupling_SOURCES MEDCouplingAMRAttribute.cxx MEDCouplingMatrix.cxx MEDCouplingPartDefinition.cxx + MEDCouplingSkyLineArray.cxx ) SET(medcouplingremapper_SOURCES diff --git a/src/MEDCoupling/MEDCouplingSkyLineArray.cxx b/src/MEDCoupling/MEDCouplingSkyLineArray.cxx new file mode 100644 index 000000000..87f1bae2d --- /dev/null +++ b/src/MEDCoupling/MEDCouplingSkyLineArray.cxx @@ -0,0 +1,102 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "MEDCouplingSkyLineArray.hxx" + +using namespace ParaMEDMEM; + +MEDCouplingSkyLineArray::MEDCouplingSkyLineArray(): + _index( DataArrayInt::New() ), _value( DataArrayInt::New() ) +{ +} + +MEDCouplingSkyLineArray::MEDCouplingSkyLineArray(const MEDCouplingSkyLineArray &myArray) +{ + _index=myArray._index; + _value=myArray._value; +} + +MEDCouplingSkyLineArray::~MEDCouplingSkyLineArray() +{ +} + +MEDCouplingSkyLineArray::MEDCouplingSkyLineArray(DataArrayInt* index, DataArrayInt* value) +{ + set( index, value ); +} + +MEDCouplingSkyLineArray::MEDCouplingSkyLineArray( const std::vector& index, + const std::vector& value ): + _index( DataArrayInt::New() ), _value( DataArrayInt::New() ) +{ + _index->reserve( index.size() ); + _index->insertAtTheEnd( index.begin(), index.end() ); + _value->reserve( value.size() ); + _value->insertAtTheEnd( value.begin(), value.end() ); +} + +void MEDCouplingSkyLineArray::set( DataArrayInt* index, DataArrayInt* value ) +{ + _index=index; + _value=value; + if ( (DataArrayInt*)_index ) _index->incrRef(); + else _index = DataArrayInt::New(); + if ( (DataArrayInt*)_value ) _value->incrRef(); + else _value = DataArrayInt::New(); +} + +DataArrayInt* MEDCouplingSkyLineArray::getIndexArray() const +{ + return ((MEDCouplingSkyLineArray*)this)->_index; +} + +DataArrayInt* MEDCouplingSkyLineArray::getValueArray() const +{ + return ((MEDCouplingSkyLineArray*)this)->_value; +} + +std::string MEDCouplingSkyLineArray::simpleRepr() const +{ + std::ostringstream oss; + oss << "MEDCouplingSkyLineArray" << std::endl; + oss << " Nb of items: " << getNumberOf() << std::endl; + oss << " Nb of values: " << getLength() << std::endl; + oss << " Index:" << std::endl; + oss << " "; + const int * i = _index->begin(); + for ( ; i != _index->end(); ++i ) + oss << *i << " "; + oss << std::endl; + oss << " Value:" << std::endl; + oss << " "; + const int * v = _value->begin(); + int cnt = 0; + for ( i = _index->begin(); v != _value->end(); ++v, ++cnt ) + { + if ( cnt == *i ) + { + oss << "| "; + ++i; + } + oss << *v << " "; + } + oss << std::endl; + + return oss.str(); +} diff --git a/src/MEDCoupling/MEDCouplingSkyLineArray.hxx b/src/MEDCoupling/MEDCouplingSkyLineArray.hxx new file mode 100644 index 000000000..c12dc6b68 --- /dev/null +++ b/src/MEDCoupling/MEDCouplingSkyLineArray.hxx @@ -0,0 +1,56 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef __PARAMEDMEM_MEDCOUPLINGSKYLINEARRAY_HXX__ +#define __PARAMEDMEM_MEDCOUPLINGSKYLINEARRAY_HXX__ + +#include "MEDCoupling.hxx" +#include "MEDCouplingMemArray.hxx" +#include "MEDCouplingAutoRefCountObjectPtr.hxx" + +#include + +namespace ParaMEDMEM +{ + class MEDCOUPLING_EXPORT MEDCouplingSkyLineArray + { + private: + MEDCouplingAutoRefCountObjectPtr _index; + MEDCouplingAutoRefCountObjectPtr _value; + public: + MEDCouplingSkyLineArray(); + MEDCouplingSkyLineArray( const MEDCouplingSkyLineArray &myArray ); + MEDCouplingSkyLineArray( const std::vector& index, const std::vector& value ); + MEDCouplingSkyLineArray( DataArrayInt* index, DataArrayInt* value ); + ~MEDCouplingSkyLineArray(); + + void set( DataArrayInt* index, DataArrayInt* value ); + + int getNumberOf() const { return _index->getNbOfElems()-1; } + int getLength() const { return _value->getNbOfElems(); } + const int* getIndex() const { return _index->begin(); } + const int* getValue() const { return _value->begin(); } + + DataArrayInt* getIndexArray() const; + DataArrayInt* getValueArray() const; + + std::string simpleRepr() const; + }; +} +# endif diff --git a/src/MEDCoupling/MEDCouplingUMesh.cxx b/src/MEDCoupling/MEDCouplingUMesh.cxx index ab7425894..4f7ee4b68 100644 --- a/src/MEDCoupling/MEDCouplingUMesh.cxx +++ b/src/MEDCoupling/MEDCouplingUMesh.cxx @@ -22,6 +22,7 @@ #include "MEDCoupling1GTUMesh.hxx" #include "MEDCouplingMemArray.txx" #include "MEDCouplingFieldDouble.hxx" +#include "MEDCouplingSkyLineArray.hxx" #include "CellModel.hxx" #include "VolSurfUser.txx" #include "InterpolationUtils.hxx" @@ -8679,6 +8680,82 @@ DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const return ret.retn(); } +/*! + * \brief Creates a graph of cell neighbors + * \return MEDCouplingSkyLineArray * - an sky line array the user should delete. + * In the sky line array, graph arcs are stored in terms of (index,value) notation. + * For example + * - index: 0 3 5 6 6 + * - value: 1 2 3 2 3 3 + * means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3) + * Arcs are not doubled but reflexive (1,1) arcs are present for each cell + */ +MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const +{ + checkConnectivityFullyDefined(); + + int meshDim = this->getMeshDimension(); + ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New(); + ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New(); + this->getReverseNodalConnectivity(revConn,indexr); + const int* indexr_ptr=indexr->getConstPointer(); + const int* revConn_ptr=revConn->getConstPointer(); + + const ParaMEDMEM::DataArrayInt* index; + const ParaMEDMEM::DataArrayInt* conn; + conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!! + index=this->getNodalConnectivityIndex(); + int nbCells=this->getNumberOfCells(); + const int* index_ptr=index->getConstPointer(); + const int* conn_ptr=conn->getConstPointer(); + + //creating graph arcs (cell to cell relations) + //arcs are stored in terms of (index,value) notation + // 0 3 5 6 6 + // 1 2 3 2 3 3 + // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3) + // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell + + //warning here one node have less than or equal effective number of cell with it + //but cell could have more than effective nodes + //because other equals nodes in other domain (with other global inode) + std::vector cell2cell_index(nbCells+1,0); + std::vector cell2cell; + cell2cell.reserve(3*nbCells); + + for (int icell=0; icell counter; + for (int iconn=index_ptr[icell]+1; iconn::iterator iter=counter.find(icell2); + if (iter!=counter.end()) (iter->second)++; + else counter.insert(std::make_pair(icell2,1)); + } + } + for (std::map::const_iterator iter=counter.begin(); + iter!=counter.end(); iter++) + if (iter->second >= meshDim) + { + cell2cell_index[icell+1]++; + cell2cell.push_back(iter->first); + } + } + indexr->decrRef(); + revConn->decrRef(); + cell2cell_index[0]=0; + for (int icell=0; icell& v1, const std::vector& v2, double eps); }; + + class MEDCouplingSkyLineArray + { + public: + MEDCouplingSkyLineArray(); + MEDCouplingSkyLineArray( const MEDCouplingSkyLineArray &myArray ); + MEDCouplingSkyLineArray( DataArrayInt* index, DataArrayInt* value ); + MEDCouplingSkyLineArray( const std::vector& index, const std::vector& value ); + + void set( DataArrayInt* index, DataArrayInt* value ); + int getNumberOf() const; + int getLength() const; + DataArrayInt* getIndexArray() const; + DataArrayInt* getValueArray() const; + %extend + { + std::string __str__() const throw(INTERP_KERNEL::Exception) + { + return self->simpleRepr(); + } + } + }; } %include "MEDCouplingFieldDiscretization.i" @@ -1783,6 +1807,7 @@ namespace ParaMEDMEM DataArrayInt *convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception); DataArrayInt *buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception); DataArrayInt *buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception); + MEDCouplingSkyLineArray *generateGraph() const throw(INTERP_KERNEL::Exception); DataArrayInt *orderConsecutiveCells1D() const throw(INTERP_KERNEL::Exception); DataArrayDouble *getBoundingBoxForBBTreeFast() const throw(INTERP_KERNEL::Exception); DataArrayDouble *getBoundingBoxForBBTree2DQuadratic(double arcDetEps=1e-12) const throw(INTERP_KERNEL::Exception); diff --git a/src/MEDLoader/CMakeLists.txt b/src/MEDLoader/CMakeLists.txt index 5b8d96c09..40538ed30 100644 --- a/src/MEDLoader/CMakeLists.txt +++ b/src/MEDLoader/CMakeLists.txt @@ -62,6 +62,7 @@ SET(medloader_SOURCES MEDFileBasis.cxx MEDFileMeshLL.cxx MEDFileField.cxx + MEDFileJoint.cxx MEDFileParameter.cxx MEDFileData.cxx MEDFileFieldOverView.cxx diff --git a/src/MEDLoader/MEDFileData.cxx b/src/MEDLoader/MEDFileData.cxx index b9a6a20ba..a979b38f5 100644 --- a/src/MEDLoader/MEDFileData.cxx +++ b/src/MEDLoader/MEDFileData.cxx @@ -43,6 +43,7 @@ MEDFileData *MEDFileData::deepCpy() const MEDCouplingAutoRefCountObjectPtr params; if((const MEDFileParameters *)_params) params=_params->deepCpy(); + MEDCouplingAutoRefCountObjectPtr joints; MEDCouplingAutoRefCountObjectPtr ret=MEDFileData::New(); ret->_fields=fields; ret->_meshes=meshes; ret->_params=params; return ret.retn(); diff --git a/src/MEDLoader/MEDFileField.cxx b/src/MEDLoader/MEDFileField.cxx index d89c3ea9d..8b54ffacf 100644 --- a/src/MEDLoader/MEDFileField.cxx +++ b/src/MEDLoader/MEDFileField.cxx @@ -4346,10 +4346,10 @@ std::vector< MEDCouplingAutoRefCountObjectPtr for(std::vector::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++) allEnt.insert(*it2); } - if(allEnt.size()!=1) - throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::splitMultiDiscrPerGeoTypes : this field is expected to be defined only on one spatial discretization !"); - if(nbOfMDPGT==0) - throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::splitMultiDiscrPerGeoTypes : empty field !"); + if(allEnt.size()!=1) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::splitMultiDiscrPerGeoTypes : this field is expected to be defined only on one spatial discretization !"); + if(nbOfMDPGT==0) + throw INTERP_KERNEL::Exception("MEDFileAnyTypeField1TSWithoutSDA::splitMultiDiscrPerGeoTypes : empty field !"); if(nbOfMDPGT==1) { std::vector< MEDCouplingAutoRefCountObjectPtr > ret0(1); diff --git a/src/MEDLoader/MEDFileJoint.cxx b/src/MEDLoader/MEDFileJoint.cxx new file mode 100644 index 000000000..bbd24ce7b --- /dev/null +++ b/src/MEDLoader/MEDFileJoint.cxx @@ -0,0 +1,838 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "MEDFileJoint.hxx" +#include "MEDFileUtilities.hxx" +#include "MEDLoader.hxx" +#include "MEDLoaderBase.hxx" + +#include "CellModel.hxx" +#include "InterpKernelAutoPtr.hxx" + +extern med_geometry_type typmai[MED_N_CELL_FIXED_GEO]; +extern INTERP_KERNEL::NormalizedCellType typmai2[MED_N_CELL_FIXED_GEO]; +extern med_geometry_type typmai3[34]; + +using namespace ParaMEDMEM; + +std::size_t MEDFileJointCorrespondence::getHeapMemorySizeWithoutChildren() const +{ + return sizeof(MEDCouplingAutoRefCountObjectPtr); +} + +std::vector MEDFileJointCorrespondence::getDirectChildrenWithNull() const +{ + return std::vector(); +} + +MEDFileJointCorrespondence::MEDFileJointCorrespondence(): + _is_nodal( true ), + _loc_geo_type( INTERP_KERNEL::NORM_ERROR ), + _rem_geo_type( INTERP_KERNEL::NORM_ERROR ) +{ +} + +/*! + * Constructor. + * \param [in] correspondence - correspondence. + * \param [in] is_nodal - is the correspondence of cells or nodes. + * \param [in] loc_geo_type - the local geometry type of correspondence. + * \param [in] rem_geo_type - the remote geometry type of correspondence. + */ +MEDFileJointCorrespondence::MEDFileJointCorrespondence(DataArrayInt* correspondence, + bool isNodal, + INTERP_KERNEL::NormalizedCellType loc_geo_type, + INTERP_KERNEL::NormalizedCellType rem_geo_type): + _is_nodal( isNodal ), + _loc_geo_type( loc_geo_type ), + _rem_geo_type( rem_geo_type ) +{ + MEDFileJointCorrespondence::setCorrespondence( correspondence ); +} + +MEDFileJointCorrespondence* MEDFileJointCorrespondence::New(DataArrayInt* correspondence, + INTERP_KERNEL::NormalizedCellType loc_geo_type, + INTERP_KERNEL::NormalizedCellType rem_geo_type) +{ + return new MEDFileJointCorrespondence(correspondence, /*isNodal=*/false, loc_geo_type, rem_geo_type ); +} + +/*! + * Returns a new MEDFileJointCorrespondence of nodes + */ +MEDFileJointCorrespondence *MEDFileJointCorrespondence::New(DataArrayInt* correspondence) +{ + return new MEDFileJointCorrespondence(correspondence); +} + +/*! + * Returns a new undefined MEDFileJointCorrespondence + */ + +MEDFileJointCorrespondence *MEDFileJointCorrespondence::New() +{ + return new MEDFileJointCorrespondence(); +} + +/*! + * Writes \a this joint into a MED file specified by its name. + * \param [in] fileName - the MED file name. + * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. + * - 2 - erase; an existing file is removed. + * - 1 - append; same data should not be present in an existing file. + * - 0 - overwrite; same data present in an existing file is overwritten. + * \param [in] order - order. + * \param [in] iteration - iteration. + * \throw If the mesh name is not set. + * \throw If \a mode == 1 and the same data is present in an existing file. + */ +void MEDFileJointCorrespondence::write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName, int order, int iteration) const +{ + med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod); + + std::ostringstream oss; oss << "MEDFileJointCorrespondence : error on attempt to write in file : \"" << fileName << "\""; + MEDFileUtilities::CheckMEDCode(fid,fid,oss.str()); + + if (( !_is_nodal ) && + ( _loc_geo_type == INTERP_KERNEL::NORM_ERROR || + _rem_geo_type == INTERP_KERNEL::NORM_ERROR )) + { + throw INTERP_KERNEL::Exception( "Geometric type not specified for a cell Joint" ); + } + + if ( (const DataArrayInt *)_correspondence ) + { + writeLL(fid, localMeshName, jointName, order, iteration); + } + else + { + throw INTERP_KERNEL::Exception("MEDFileJointCorrespondence::write : correspondence array not defined"); + } +} + +void MEDFileJointCorrespondence::writeLL(med_idt fid, const std::string& localMeshName, const std::string& jointName, int order, int iteration) const +{ + if ( _is_nodal ) + { + MEDsubdomainCorrespondenceWr(fid, localMeshName.c_str(), jointName.c_str(), + order, iteration, + MED_NODE, MED_NONE, + MED_NODE, MED_NONE, + _correspondence->getNbOfElems()/2, + _correspondence->getConstPointer()); + } + else + { + MEDsubdomainCorrespondenceWr(fid, localMeshName.c_str(), jointName.c_str(), + order, iteration, + MED_CELL, typmai3[ _loc_geo_type ], + MED_CELL, typmai3[ _rem_geo_type ], + _correspondence->getNbOfElems()/2, + _correspondence->getConstPointer()); + } +} + +void MEDFileJointCorrespondence::setCorrespondence(DataArrayInt *corr) +{ + _correspondence=corr; + if ( corr ) + corr->incrRef(); +} + +/*! + * Checks if \a this and another mesh are equal. + * \param [in] other - the mesh to compare with. + * \return bool - \c true if the meshes are equal, \c false, else. + */ +bool MEDFileJointCorrespondence::isEqual(const MEDFileJointCorrespondence *other) const +{ + if(_is_nodal!=other->_is_nodal) + return false; + if(_loc_geo_type!=other->_loc_geo_type) + return false; + if(_rem_geo_type!=other->_rem_geo_type) + return false; + if(!_correspondence->isEqual(*other->_correspondence)) + return false; + return true; +} + +MEDFileJointCorrespondence *MEDFileJointCorrespondence::deepCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileJointCorrespondence(*this); + return ret.retn(); +} + +MEDFileJointCorrespondence *MEDFileJointCorrespondence::shallowCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileJointCorrespondence(*this); + return ret.retn(); +} + +/*! + * Returns a string describing \a this mesh. This description includes the correspondence and + * the number correspondence. + * \return std::string - the joint information string. + */ +std::string MEDFileJointCorrespondence::simpleRepr() const +{ + std::ostringstream oss; + oss << "(*************************************)\n(* JOINT_CORRESPOND INFORMATION: *)\n(*************************************)\n"; + oss << "- entity type of the correspondence : " << ( getIsNodal() ? "NODE" : "CELL" ) << "\n"; + oss << "- Local geometry type of the correspondence : " << INTERP_KERNEL::CellModel::GetCellModel( _loc_geo_type ).getRepr() << "\n"; + oss << "- Remote geometry type of the correspondence : " << INTERP_KERNEL::CellModel::GetCellModel( _rem_geo_type ).getRepr() << "\n"; + if ( (const DataArrayInt *)_correspondence ) + { + oss << "- Number entity of the correspondence : " << getCorrespondence()->getNumberOfTuples() << "\n"; + + const DataArrayInt* tmp=getCorrespondence(); + oss << "- Correspondence : <<"; + for(const int *it=tmp->begin();it!=tmp->end();it++) + oss<< *it << " "; + } + else + { + oss << "- Number entity of the correspondence : 0\n"; + } + oss << std::endl; + return oss.str(); +} + + +MEDFileJointOneStep::MEDFileJointOneStep():_order(-1),_iteration(-1) +{ +} + +std::size_t MEDFileJointOneStep::getHeapMemorySizeWithoutChildren() const +{ + return _correspondences.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr); +} + +std::vector MEDFileJointOneStep::getDirectChildrenWithNull() const +{ + return std::vector(); +} + +MEDFileJointOneStep *MEDFileJointOneStep::New(int dt, int it) +{ + MEDFileJointOneStep* j = new MEDFileJointOneStep(); + j->setOrder( dt ); + j->setIteration( it ); + return j; +} + +/*! + * Returns a new MEDFileJointOneStep. + * \param [in] fileName - the name of MED file to read. + * \param [in] mName - the name of the mesh to read. + * \param [in] jointName - the joint name. + * \param [in] num - the number of an iteration. + * \return MEDFileMesh * - a new instance of MEDFileJointOneStep. + * \throw If the file is not readable. + * \throw If there is no mesh with given attributes in the file. + */ +MEDFileJointOneStep *MEDFileJointOneStep::New(const std::string& fileName, const std::string& mName, const std::string& jointName, int num) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(), MED_ACC_RDONLY); + return new MEDFileJointOneStep(fid, mName, jointName, num); +} + +MEDFileJointOneStep* MEDFileJointOneStep::New(med_idt fid, const std::string& mName, const std::string& jointName, int num) +{ + return new MEDFileJointOneStep( fid, mName, jointName, num); +} + +MEDFileJointOneStep::MEDFileJointOneStep(med_idt fid, const std::string& mName, const std::string& jointName, int num) +{ + int order, iteration, ncorrespondence; + MEDsubdomainComputingStepInfo(fid, mName.c_str(), jointName.c_str(), num, &order, &iteration, &ncorrespondence); + MEDFileJointOneStep::setOrder(order); + MEDFileJointOneStep::setIteration(iteration); + for ( int cur_it = 1; cur_it <= ncorrespondence; ++cur_it ) + { + int num_entity; + med_entity_type loc_ent_type, rem_ent_type; + med_geometry_type loc_geo_type, rem_geo_type; + MEDsubdomainCorrespondenceSizeInfo(fid, mName.c_str(), jointName.c_str(), order, iteration, cur_it, + &loc_ent_type, &loc_geo_type, &rem_ent_type, &rem_geo_type, &num_entity); + if ( num_entity > 0 ) + { + MEDCouplingAutoRefCountObjectPtr correspondence=DataArrayInt::New(); + correspondence->alloc(num_entity*2, 1); + MEDsubdomainCorrespondenceRd(fid, mName.c_str(), jointName.c_str(), order, iteration, loc_ent_type, + loc_geo_type, rem_ent_type, rem_geo_type, correspondence->getPointer()); + MEDFileJointCorrespondence *cor=MEDFileJointCorrespondence::New(); + cor->setIsNodal( loc_ent_type == MED_NODE ); + cor->setLocalGeometryType ( convertGeometryType( loc_geo_type )); + cor->setRemoteGeometryType( convertGeometryType( rem_geo_type )); + cor->setCorrespondence( correspondence ); + _correspondences.push_back(cor); + } + } +} + +/*! + * Writes \a this joint into a MED file specified by its name. + * \param [in] fileName - the MED file name. + * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. + * - 2 - erase; an existing file is removed. + * - 1 - append; same data should not be present in an existing file. + * - 0 - overwrite; same data present in an existing file is overwritten. + * \throw If the mesh name is not set. + * \throw If \a mode == 1 and the same data is present in an existing file. + */ +void MEDFileJointOneStep::write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName) const +{ + med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod); + std::ostringstream oss; oss << "MEDFileJointOneStep : error on attempt to write in file : \"" << fileName << "\""; + MEDFileUtilities::CheckMEDCode(fid,fid,oss.str()); + if ( _correspondences.empty() ) + throw INTERP_KERNEL::Exception("MEDFileJointOneStep::write : no correspondences defined !"); + writeLL(fid, localMeshName, jointName); +} + +void MEDFileJointOneStep::writeLL(med_idt fid, const std::string& localMeshName, const std::string& jointName) const +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_correspondences.begin();it!=_correspondences.end();it++) + { + (*it)->writeLL(fid, localMeshName, jointName, getOrder(), getIteration()); + } +} + +void MEDFileJointOneStep::pushCorrespondence(MEDFileJointCorrespondence* correspondence) +{ + if(!correspondence) + throw INTERP_KERNEL::Exception("MEDFileJointCorrespondence::pushCorrespondence : invalid input pointer ! should be different from 0 !"); + _correspondences.push_back(correspondence); + correspondence->incrRef(); +} + +int MEDFileJointOneStep::getNumberOfCorrespondences() const +{ + return _correspondences.size(); +} + +/** Return a borrowed reference (caller is not responsible) */ +MEDFileJointCorrespondence *MEDFileJointOneStep::getCorrespondenceAtPos(int i) const +{ + if(i<0 || i>=(int)_correspondences.size()) + { + std::ostringstream oss; oss << "MEDFileJointOneStep::getCorrespondenceAtPos : invalid correspondence id given in parameter ! Should be in [0;" << _correspondences.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + const MEDFileJointCorrespondence* ret = _correspondences[i]; + return const_cast( ret ); +} + +/*! + * Checks if \a this and another Joint are equal. + * \param [in] other - the Joint to compare with. + * \return bool - \c true if the Joints are equal, \c false, else. + */ +bool MEDFileJointOneStep::isEqual(const MEDFileJointOneStep *other) const +{ + if(_order!=other->_order) + return false; + if(_iteration!=other->_iteration) + return false; + if ( getNumberOfCorrespondences() != other->getNumberOfCorrespondences() ) + return false; + + std::vector found( getNumberOfCorrespondences(), false ); + for(int i=0; iisEqual(other->getCorrespondenceAtPos(j))) + { + found[ j ] = true; + break; + } + } + if ( j == getNumberOfCorrespondences() ) + return false; + } + return true; +} + +MEDFileJointOneStep *MEDFileJointOneStep::deepCpy() const +{ + std::vector< MEDCouplingAutoRefCountObjectPtr > correspondences(_correspondences.size()); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_correspondences.begin();it!=_correspondences.end();it++,i++) + if((const MEDFileJointCorrespondence *)*it) + correspondences[i]=(*it)->deepCpy(); + MEDCouplingAutoRefCountObjectPtr ret= new MEDFileJointOneStep; + ret->_correspondences=correspondences; + return ret.retn(); +} + +MEDFileJointOneStep *MEDFileJointOneStep::shallowCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileJointOneStep(*this); + return ret.retn(); +} + +/*! + * Returns a string describing \a this Joint. This description includes the correspondence and + * the number of correspondences. + * \return std::string - the joint information string. + */ +std::string MEDFileJointOneStep::simpleRepr() const +{ + std::ostringstream oss; + oss << "(*************************************)\n(* JOINT_ONE_STEP INFORMATION: *)\n(*************************************)\n"; + oss << "- Number of the correspondences : <<" << _correspondences.size() << ">>\n"; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_correspondences.begin();it!=_correspondences.end();it++) + { + oss << (*it)->simpleRepr(); + } + return oss.str(); +} +INTERP_KERNEL::NormalizedCellType MEDFileJointOneStep::convertGeometryType(med_geometry_type geotype) +{ + INTERP_KERNEL::NormalizedCellType result=INTERP_KERNEL::NORM_ERROR; + for(int i=0; i); +} + +std::vector MEDFileJoint::getDirectChildrenWithNull() const +{ + return std::vector(); +} + +MEDFileJoint *MEDFileJoint::New() +{ + return new MEDFileJoint(); +} + +MEDFileJoint *MEDFileJoint::New(const std::string& fileName, const std::string& mName, int curJoint) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(), MED_ACC_RDONLY); + return new MEDFileJoint(fid,mName,curJoint); +} + +MEDFileJoint *MEDFileJoint::New(med_idt fid, const std::string& mName, int curJoint) +{ + return new MEDFileJoint(fid,mName,curJoint); +} + +MEDFileJoint *MEDFileJoint::New(const std::string& jointName, const std::string& locMeshName, const std::string& remoteMeshName, int remoteMeshNum) +{ + MEDFileJoint* j = new MEDFileJoint(); + j->setJointName( jointName ); + j->setLocalMeshName( locMeshName ); + j->setRemoteMeshName( remoteMeshName ); + j->setDomainNumber( remoteMeshNum ); + return j; +} + +MEDFileJoint::MEDFileJoint() +{ +} + +/*! + * Returns a new MEDFileJoint holding the mesh data that has been read from a given MED + * file. The Joint to load is specified by mesh name and a Joint iteration. + * \param [in] fileName - the name of MED file to read. + * \param [in] mName - the name of the mesh to read. + * \param [in] curJoint - the iteration number of current joint. + * \return MEDFileJoint * - a new instance of MEDFileJoint. + * \throw If the file is not readable. + * \throw If there is no mesh with given attributes in the file. + */ +MEDFileJoint::MEDFileJoint(med_idt fid, const std::string& mName, int curJoint) +{ + INTERP_KERNEL::AutoPtr joint_name=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); + INTERP_KERNEL::AutoPtr desc_name=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE); + INTERP_KERNEL::AutoPtr rem_mesh_name=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE); + int domain_number=0, nstep=0, nocstpncorrespondence=0; + MEDsubdomainJointInfo(fid,mName.c_str(), curJoint, joint_name, desc_name, &domain_number,rem_mesh_name, + &nstep, &nocstpncorrespondence); + setLocalMeshName(mName); + setRemoteMeshName(MEDLoaderBase::buildStringFromFortran(rem_mesh_name,MED_NAME_SIZE)); + setDescription(MEDLoaderBase::buildStringFromFortran(desc_name,MED_COMMENT_SIZE)); + setJointName(MEDLoaderBase::buildStringFromFortran(joint_name,MED_NAME_SIZE)); + setDomainNumber(domain_number); + for(int cur_step=1; cur_step <= nstep; ++cur_step) + { + MEDFileJointOneStep *cor=MEDFileJointOneStep::New(fid, mName.c_str(), getJointName(), cur_step); + _joint.push_back(cor); + } +} + +/*! + * Writes \a this joint into a MED file specified by its name. + * \param [in] fileName - the MED file name. + * \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics. + * - 2 - erase; an existing file is removed. + * - 1 - append; same data should not be present in an existing file. + * - 0 - overwrite; same data present in an existing file is overwritten. + * \throw If the mesh name is not set. + * \throw If \a mode == 1 and the same data is present in an existing file. + */ +void MEDFileJoint::write(const std::string& fileName, int mode) const +{ + med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod); + std::ostringstream oss; oss << "MEDFileJoint : error on attempt to write in file : \"" << fileName << "\""; + MEDFileUtilities::CheckMEDCode(fid,fid,oss.str()); + write(fid); +} + +void MEDFileJoint::write(med_idt fid) const +{ + // if ( _loc_mesh_name.empty() ) + // throw INTERP_KERNEL::Exception("MEDFileJoint::write : name of a local mesh not defined!"); + MEDsubdomainJointCr(fid,getLocalMeshName().c_str(),getJointName().c_str(),getDescription().c_str(),getDomainNumber(),getRemoteMeshName().c_str()); + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_joint.begin();it!=_joint.end();it++) { + (*it)->writeLL(fid, getLocalMeshName(),getJointName()); + } +} + +void MEDFileJoint::pushStep(MEDFileJointOneStep* step) +{ + if(!step) + throw INTERP_KERNEL::Exception("MEDFileJoint::pushStep : invalid input pointer ! should be different from 0 !"); + _joint.push_back(step); + step->incrRef(); +} + +int MEDFileJoint::getNumberOfSteps() const +{ + return _joint.size(); +} + +/** Return a borrowed reference (caller is not responsible) */ +MEDFileJointOneStep *MEDFileJoint::getStepAtPos(int i) const +{ + if(i<0 || i>=(int)_joint.size()) + { + std::ostringstream oss; oss << "MEDFileJoint::getStepAtPos : invalid step id given in parameter ! Should be in [0;" << _joint.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + const MEDFileJointOneStep* ret = _joint[i]; + return const_cast( ret ); +} + +/*! + * Checks if \a this and another Joint are equal. + * \param [in] other - the Joint to compare with. + * \return bool - \c true if the Joints are equal, \c false, else. + */ +bool MEDFileJoint::isEqual(const MEDFileJoint *other) const +{ + if(_loc_mesh_name!=other->_loc_mesh_name) + return false; + if(_joint_name!=other->_joint_name) + return false; + if(_desc_name!=other->_desc_name) + return false; + if(_rem_mesh_name!=other->_rem_mesh_name) + return false; + if(_domain_number!=other->_domain_number) + return false; + std::vector found( getNumberOfSteps(), false ); + for(int i=0; iisEqual(other->getStepAtPos(j))) + { + found[ j ] = true; + break; + } + } + if ( j == getNumberOfSteps() ) + return false; + } + return true; +} + +MEDFileJoint *MEDFileJoint::deepCpy() const +{ + std::vector< MEDCouplingAutoRefCountObjectPtr > joint(_joint.size()); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_joint.begin();it!=_joint.end();it++,i++) + if((const MEDFileJointOneStep *)*it) + joint[i]=(*it)->deepCpy(); + MEDCouplingAutoRefCountObjectPtr ret=MEDFileJoint::New(); + ret->_joint=joint; + return ret.retn(); +} + +MEDFileJoint *MEDFileJoint::shallowCpy() const +{ + MEDCouplingAutoRefCountObjectPtr ret=new MEDFileJoint(*this); + return ret.retn(); +} + +bool MEDFileJoint::changeJointNames(const std::vector< std::pair >& modifTab) +{ + for(std::vector< std::pair >::const_iterator it=modifTab.begin();it!=modifTab.end();it++) + { + if((*it).first==_joint_name) + { + _joint_name=(*it).second; + return true; + } + } + return false; +} + +/*! + * Returns a string describing \a this mesh. This description includes the correspondence and + * the number correspondence. + * \return std::string - the joint information string. + */ +std::string MEDFileJoint::simpleRepr() const +{ + std::ostringstream oss; + oss << "(*************************************)\n(* JOINT INFORMATION: *)\n(*************************************)\n"; + oss << "- Local Mesh name : <<" << getLocalMeshName() << ">>\n"; + oss << "- Remote Mesh name : <<" << getRemoteMeshName() << ">>\n"; + oss << "- Description : <<" << getDescription() << ">>\n"; + oss << "- Joint name : <<" << getJointName() << ">>\n"; + oss << "- Domain number : " << getDomainNumber() << "\n"; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_joint.begin();it!=_joint.end();it++) + { + oss << (*it)->simpleRepr(); + } + return oss.str(); +} + +MEDFileJoints *MEDFileJoints::New() +{ + return new MEDFileJoints; +} + +MEDFileJoints *MEDFileJoints::New(const std::string& fileName, const std::string& meshName) +{ + MEDFileUtilities::CheckFileForRead(fileName); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(), MED_ACC_RDONLY); + return new MEDFileJoints( fid, meshName ); +} + +MEDFileJoints *MEDFileJoints::New(med_idt fid, const std::string& meshName) +{ + return new MEDFileJoints( fid, meshName ); +} + +void MEDFileJoints::write(med_idt fid) const +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_joints.begin();it!=_joints.end();it++) + { + (*it)->write(fid); + } +} + +void MEDFileJoints::write(const std::string& fileName, int mode) const +{ + med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode); + MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod); + std::ostringstream oss; oss << "MEDFileJoints : error on attempt to write in file : \"" << fileName << "\""; + MEDFileUtilities::CheckMEDCode(fid,fid,oss.str()); + write(fid); +} + +std::string MEDFileJoints::getMeshName() const +{ + for ( size_t i = 0; i <= _joints.size(); ++i ) + if ( (const MEDFileJoint*) _joints[i] ) + return _joints[i]->getLocalMeshName(); + + return ""; +} + +int MEDFileJoints::getNumberOfJoints() const +{ + return _joints.size(); +} + +/** Return a borrowed reference (caller is not responsible) */ +MEDFileJoint *MEDFileJoints::getJointAtPos(int i) const +{ + if(i<0 || i>=(int)_joints.size()) + { + std::ostringstream oss; oss << "MEDFileJoints::getJointAtPos : invalid joint id given in parameter ! Should be in [0;" << _joints.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + const MEDFileJoint* ret = _joints[i]; + return const_cast( ret ); +} + + +/** Return a borrowed reference (caller is not responsible) */ +MEDFileJoint *MEDFileJoints::getJointWithName(const std::string& jname) const +{ + std::vector js=getJointsNames(); + std::vector::iterator it=std::find(js.begin(),js.end(),jname); + if(it==js.end()) + { + std::ostringstream oss; oss << "MEDFileJoints::getJointWithName : Joint \"" << jname << "\" does not exist in this ! Existing are : "; + std::copy(js.begin(),js.end(),std::ostream_iterator(oss," ")); + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + return getJointAtPos((int)std::distance(js.begin(),it)); +} + +std::vector MEDFileJoints::getJointsNames() const +{ + std::vector ret(_joints.size()); + int i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_joints.begin();it!=_joints.end();it++,i++) + { + const MEDFileJoint *f=(*it); + if(f) + { + ret[i]=f->getJointName(); + } + else + { + std::ostringstream oss; oss << "MEDFileJoints::getJointsNames : At rank #" << i << " joint is not defined !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + } + return ret; +} + +bool MEDFileJoints::changeJointNames(const std::vector< std::pair >& modifTab) +{ + bool ret=false; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_joints.begin();it!=_joints.end();it++) + { + MEDFileJoint *cur(*it); + if(cur) + ret=cur->changeJointNames(modifTab) || ret; + } + return ret; +} + +void MEDFileJoints::resize(int newSize) +{ + _joints.resize(newSize); +} + +void MEDFileJoints::pushJoint(MEDFileJoint *joint) +{ + if(!joint) + throw INTERP_KERNEL::Exception("MEDFileJoints::pushJoint() : invalid input pointer ! should be different from 0 !"); + if ( !_joints.empty() && + _joints[0]->getLocalMeshName() != joint->getLocalMeshName() ) + throw INTERP_KERNEL::Exception("MEDFileJoints::pushJoint() : different names of local meshes ! should be equal !"); + + _joints.push_back(joint); + joint->incrRef(); +} + +void MEDFileJoints::setJointAtPos(int i, MEDFileJoint *joint) +{ + if(!joint) + throw INTERP_KERNEL::Exception("MEDFileJoints::setJointAtPos : invalid input pointer ! should be different from 0 !"); + if(i>=(int)_joints.size()) + _joints.resize(i+1); + _joints[i]=joint; + joint->incrRef(); +} + +void MEDFileJoints::destroyJointAtPos(int i) +{ + if(i<0 || i>=(int)_joints.size()) + { + std::ostringstream oss; oss << "MEDFileJoints::destroyJointAtPos : Invalid given id in input (" << i << ") should be in [0," << _joints.size() << ") !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + _joints.erase(_joints.begin()+i); +} + +MEDFileJoints::MEDFileJoints() +{ +} + +MEDFileJoints::MEDFileJoints(med_idt fid, const std::string& meshName) +{ + int num_joint=MEDnSubdomainJoint(fid, meshName.c_str() ); + for(int i = 1; i <= num_joint; i++) + _joints.push_back(MEDFileJoint::New(fid,meshName,i)); +} + +MEDFileJoints *MEDFileJoints::deepCpy() const +{ + std::vector< MEDCouplingAutoRefCountObjectPtr > joints(_joints.size()); + std::size_t i=0; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_joints.begin();it!=_joints.end();it++,i++) + if((const MEDFileJoint *)*it) + joints[i]=(*it)->deepCpy(); + MEDCouplingAutoRefCountObjectPtr ret=MEDFileJoints::New(); + ret->_joints=joints; + return ret.retn(); +} + +std::size_t MEDFileJoints::getHeapMemorySizeWithoutChildren() const +{ + return _joints.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr)); +} + +std::vector MEDFileJoints::getDirectChildrenWithNull() const +{ + std::vector ret; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_joints.begin();it!=_joints.end();it++) + ret.push_back((const MEDFileJoint *)*it); + return ret; +} + +std::string MEDFileJoints::simpleRepr() const +{ + std::ostringstream oss; + oss << "(*****************)\n(* MEDFileJoints *)\n(*****************)\n\n"; + simpleReprWithoutHeader(oss); + return oss.str(); +} + +void MEDFileJoints::simpleReprWithoutHeader(std::ostream& oss) const +{ + int nbOfJoints=getNumberOfJoints(); + oss << "There are " << nbOfJoints << " joints with the following names : \n"; + std::vector jns=getJointsNames(); + for(int i=0;i >::const_iterator it=_joints.begin();it!=_joints.end();it++) + { + oss << (*it)->simpleRepr(); + } +} diff --git a/src/MEDLoader/MEDFileJoint.hxx b/src/MEDLoader/MEDFileJoint.hxx new file mode 100644 index 000000000..1d32312f8 --- /dev/null +++ b/src/MEDLoader/MEDFileJoint.hxx @@ -0,0 +1,194 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef __MEDFILEJOINT_HXX__ +#define __MEDFILEJOINT_HXX__ + +#include "MEDLoaderDefines.hxx" +#include "MEDFileUtilities.hxx" +#include "MEDCouplingMemArray.hxx" +#include "MEDCouplingAutoRefCountObjectPtr.hxx" + +namespace ParaMEDMEM +{ +/*! + * \brief Joint Correspondence enumerates pairs of corresponding entities of a + * certain geometrical type in adjacent mesh domains. + * Correspondence of nodes is constructed when you specify no cell type, + * else Correspondence of cells is constructed. + */ +class MEDFileJointCorrespondence : public RefCountObject, public MEDFileWritable +{ +public: + MEDLOADER_EXPORT static MEDFileJointCorrespondence *New(); + MEDLOADER_EXPORT static MEDFileJointCorrespondence *New(DataArrayInt* correspondence); // nodes + MEDLOADER_EXPORT static MEDFileJointCorrespondence *New(DataArrayInt* correspondence, // cells + INTERP_KERNEL::NormalizedCellType loc_geo_type, + INTERP_KERNEL::NormalizedCellType rem_geo_type); + MEDLOADER_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const; + MEDLOADER_EXPORT std::vector getDirectChildrenWithNull() const; + MEDLOADER_EXPORT MEDFileJointCorrespondence *deepCpy() const; + MEDLOADER_EXPORT MEDFileJointCorrespondence *shallowCpy() const; + MEDLOADER_EXPORT bool isEqual(const MEDFileJointCorrespondence *other) const; + MEDLOADER_EXPORT void setIsNodal(bool isNodal) { _is_nodal = isNodal; } + MEDLOADER_EXPORT bool getIsNodal() const { return _is_nodal; } + MEDLOADER_EXPORT void setLocalGeometryType(INTERP_KERNEL::NormalizedCellType type) { _loc_geo_type=type; } + MEDLOADER_EXPORT INTERP_KERNEL::NormalizedCellType getLocalGeometryType() const { return _loc_geo_type; } + MEDLOADER_EXPORT void setRemoteGeometryType(INTERP_KERNEL::NormalizedCellType type) { _rem_geo_type=type; } + MEDLOADER_EXPORT INTERP_KERNEL::NormalizedCellType getRemoteGeometryType() const { return _rem_geo_type; } + MEDLOADER_EXPORT void setCorrespondence(DataArrayInt *corr); + MEDLOADER_EXPORT const DataArrayInt *getCorrespondence() const { return _correspondence; } + MEDLOADER_EXPORT void write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName, int order, int iteration) const; + + MEDLOADER_EXPORT std::string simpleRepr() const; + MEDLOADER_EXPORT void writeLL(med_idt fid, const std::string& localMeshName, const std::string& jointName, int order, int iteration) const; +private: + MEDFileJointCorrespondence(); + MEDFileJointCorrespondence(DataArrayInt* correspondence, + bool is_nodal = true, + INTERP_KERNEL::NormalizedCellType loc_geo_type = INTERP_KERNEL::NORM_ERROR, + INTERP_KERNEL::NormalizedCellType rem_geo_type = INTERP_KERNEL::NORM_ERROR); +private: + bool _is_nodal; + INTERP_KERNEL::NormalizedCellType _loc_geo_type; + INTERP_KERNEL::NormalizedCellType _rem_geo_type; + MEDCouplingAutoRefCountObjectPtr _correspondence; +}; + +/*! + * \brief Joint of one iteration holds correspondences of entities of all types + */ +class MEDFileJointOneStep : public RefCountObject, public MEDFileWritable +{ +public: + MEDLOADER_EXPORT static MEDFileJointOneStep *New(int dt=-1, int it=-1); + MEDLOADER_EXPORT static MEDFileJointOneStep *New(const std::string& fileName, const std::string& mName, const std::string& jointName, int number=1); + MEDLOADER_EXPORT static MEDFileJointOneStep *New(med_idt fid, const std::string& mName, const std::string& jointName, int number=1); + MEDLOADER_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const; + MEDLOADER_EXPORT std::vector getDirectChildrenWithNull() const; + MEDLOADER_EXPORT MEDFileJointOneStep *deepCpy() const; + MEDLOADER_EXPORT MEDFileJointOneStep *shallowCpy() const; + MEDLOADER_EXPORT bool isEqual(const MEDFileJointOneStep *other) const; + MEDLOADER_EXPORT void setOrder(int order) { _order=order; } + MEDLOADER_EXPORT int getOrder() const { return _order; } + MEDLOADER_EXPORT void setIteration(int it) { _iteration=it; } + MEDLOADER_EXPORT int getIteration() const { return _iteration; } + MEDLOADER_EXPORT void pushCorrespondence(MEDFileJointCorrespondence* correspondence); + MEDLOADER_EXPORT int getNumberOfCorrespondences() const; + MEDLOADER_EXPORT MEDFileJointCorrespondence *getCorrespondenceAtPos(int i) const; + + MEDLOADER_EXPORT void write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName) const; + + MEDLOADER_EXPORT std::string simpleRepr() const; + MEDLOADER_EXPORT void writeLL(med_idt fid, const std::string& localMeshName, const std::string& jointName) const; +private: + MEDFileJointOneStep(); + MEDFileJointOneStep(med_idt fid, const std::string& mName, const std::string& jointName, int number); + MEDLOADER_EXPORT INTERP_KERNEL::NormalizedCellType convertGeometryType(med_geometry_type geotype); +protected: + int _order; + int _iteration; +private: + std::vector > _correspondences; +}; + +/*! + * \brief Joint holds a sequence of joints of different iterations relating to + * a pair of mesh domains: a local one and a distant one + */ +class MEDFileJoint : public RefCountObject, public MEDFileWritable +{ +public: + MEDLOADER_EXPORT static MEDFileJoint *New(); + MEDLOADER_EXPORT static MEDFileJoint *New(const std::string& fileName, const std::string& mName, int num); + MEDLOADER_EXPORT static MEDFileJoint *New(med_idt fid, const std::string& mName, int num); + MEDLOADER_EXPORT static MEDFileJoint *New(const std::string& jointName, const std::string& locMeshName, const std::string& remoteMeshName, int remoteMeshNum ); + MEDLOADER_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const; + MEDLOADER_EXPORT std::vector getDirectChildrenWithNull() const; + MEDLOADER_EXPORT MEDFileJoint *deepCpy() const; + MEDLOADER_EXPORT MEDFileJoint *shallowCpy() const; + MEDLOADER_EXPORT bool isEqual(const MEDFileJoint *other) const; + MEDLOADER_EXPORT void setLocalMeshName(const std::string& name) { _loc_mesh_name=name; } + MEDLOADER_EXPORT std::string getLocalMeshName() const { return _loc_mesh_name; } + MEDLOADER_EXPORT void setRemoteMeshName(const std::string& name) { _rem_mesh_name=name; } + MEDLOADER_EXPORT std::string getRemoteMeshName() const { return _rem_mesh_name; } + MEDLOADER_EXPORT void setDescription(const std::string& name) { _desc_name=name; } + MEDLOADER_EXPORT std::string getDescription() const { return _desc_name; } + MEDLOADER_EXPORT void setJointName(const std::string& name) { _joint_name=name; } + MEDLOADER_EXPORT std::string getJointName() const { return _joint_name; } + MEDLOADER_EXPORT bool changeJointNames(const std::vector< std::pair >& modifTab); + MEDLOADER_EXPORT void setDomainNumber(const int& number) { _domain_number=number; } + MEDLOADER_EXPORT int getDomainNumber() const { return _domain_number; } + MEDLOADER_EXPORT void pushStep(MEDFileJointOneStep* step); + MEDLOADER_EXPORT int getNumberOfSteps() const; + MEDLOADER_EXPORT MEDFileJointOneStep *getStepAtPos(int i) const; + + MEDLOADER_EXPORT void write(const std::string& fileName, int mode) const; + MEDLOADER_EXPORT void write(med_idt fid) const; + + MEDLOADER_EXPORT std::string simpleRepr() const; + private: + MEDFileJoint(); + MEDFileJoint(med_idt fid, const std::string& mName, int num); + private: + std::string _loc_mesh_name; + std::string _joint_name; + std::string _desc_name; + int _domain_number; + std::string _rem_mesh_name; + std::vector< MEDCouplingAutoRefCountObjectPtr > _joint; + }; + + /*! + * \brief Joints of a mesh domain relating to all other mesh domains + */ + class MEDFileJoints : public RefCountObject, public MEDFileWritable + { + public: + MEDLOADER_EXPORT static MEDFileJoints *New(); + MEDLOADER_EXPORT static MEDFileJoints *New(const std::string& fileName, const std::string& meshName); + MEDLOADER_EXPORT static MEDFileJoints *New(med_idt fid, const std::string& meshName); + MEDLOADER_EXPORT MEDFileJoints *deepCpy() const; + MEDLOADER_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const; + MEDLOADER_EXPORT std::vector getDirectChildrenWithNull() const; + MEDLOADER_EXPORT std::string simpleRepr() const; + MEDLOADER_EXPORT void simpleReprWithoutHeader(std::ostream& oss) const; + MEDLOADER_EXPORT void write(const std::string& fileName, int mode) const; + MEDLOADER_EXPORT void write(med_idt fid) const; + MEDLOADER_EXPORT std::string getMeshName() const; + MEDLOADER_EXPORT int getNumberOfJoints() const; + MEDLOADER_EXPORT MEDFileJoint *getJointAtPos(int i) const; + MEDLOADER_EXPORT MEDFileJoint *getJointWithName(const std::string& jname) const; + MEDLOADER_EXPORT std::vector getJointsNames() const; + MEDLOADER_EXPORT bool changeJointNames(const std::vector< std::pair >& modifTab); + // + MEDLOADER_EXPORT void resize(int newSize); + MEDLOADER_EXPORT void pushJoint(MEDFileJoint *joint); + MEDLOADER_EXPORT void setJointAtPos(int i, MEDFileJoint *joint); + MEDLOADER_EXPORT void destroyJointAtPos(int i); + private: + ~MEDFileJoints() { } + MEDFileJoints(); + MEDFileJoints(med_idt fid, const std::string& meshName); + private: + std::vector< MEDCouplingAutoRefCountObjectPtr > _joints; + }; +} + +#endif diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index 83599d14f..5ce3bfee0 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -91,18 +91,21 @@ MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelect { MEDCouplingAutoRefCountObjectPtr ret=MEDFileUMesh::New(); ret->loadUMeshFromFile(fid,ms.front(),dt,it,mrs); + ret->loadJointsFromFile(fid); return (MEDFileUMesh *)ret.retn(); } case CARTESIAN: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCMesh::New(); ret->loadCMeshFromFile(fid,ms.front(),dt,it,mrs); + ret->loadJointsFromFile(fid); return (MEDFileCMesh *)ret.retn(); } case CURVE_LINEAR: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCurveLinearMesh::New(); ret->loadCLMeshFromFile(fid,ms.front(),dt,it,mrs); + ret->loadJointsFromFile(fid); return (MEDFileCurveLinearMesh *)ret.retn(); } default: @@ -121,13 +124,16 @@ MEDFileMesh *MEDFileMesh::New(const std::string& fileName, MEDFileMeshReadSelect * \param [in] mName - the name of the mesh to read. * \param [in] dt - the number of a time step. * \param [in] it - the number of an iteration. + * \param [in] joints - the sub-domain joints to use instead of those that can be read + * from the MED file. Usually this joints are those just read by another iteration + * of mName mesh, when this method is called by MEDFileMeshMultiTS::New() * \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this * mesh using decrRef() as it is no more needed. * \throw If the file is not readable. * \throw If there is no mesh with given attributes in the file. * \throw If the mesh in the file is of a not supported type. */ -MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) +MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs, MEDFileJoints* joints) { MEDFileUtilities::CheckFileForRead(fileName); ParaMEDMEM::MEDCouplingMeshType meshType; @@ -141,18 +147,21 @@ MEDFileMesh *MEDFileMesh::New(const std::string& fileName, const std::string& mN { MEDCouplingAutoRefCountObjectPtr ret=MEDFileUMesh::New(); ret->loadUMeshFromFile(fid,mName,dt,it,mrs); + ret->loadJointsFromFile(fid,joints); return (MEDFileUMesh *)ret.retn(); } case CARTESIAN: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCMesh::New(); ret->loadCMeshFromFile(fid,mName,dt,it,mrs); + ret->loadJointsFromFile(fid,joints); return (MEDFileCMesh *)ret.retn(); } case CURVE_LINEAR: { MEDCouplingAutoRefCountObjectPtr ret=MEDFileCurveLinearMesh::New(); ret->loadCLMeshFromFile(fid,mName,dt,it,mrs); + ret->loadJointsFromFile(fid,joints); return (MEDFileCurveLinearMesh *)ret.retn(); } default: @@ -2401,7 +2410,8 @@ MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it try { loadUMeshFromFile(fid,mName,dt,it,mrs); -} + loadJointsFromFile(fid); + } catch(INTERP_KERNEL::Exception& e) { throw e; @@ -2429,6 +2439,62 @@ void MEDFileUMesh::loadPartUMeshFromFile(med_idt fid, const std::string& mName, dispatchLoadedPart(fid,loaderl2,mName,mrs); } +/*! + * \brief Write joints in a file + */ +void MEDFileMesh::writeJoints(med_idt fid) const +{ + if ( (const MEDFileJoints*) _joints ) + _joints->write(fid); +} + +/*! + * \brief Load joints in a file or use provided ones + */ +//================================================================================ +/*! + * \brief Load joints in a file or use provided ones + * \param [in] fid - MED file descriptor + * \param [in] toUseInstedOfReading - optional joints to use instead of reading, + * Usually this joints are those just read by another iteration + * of namesake mesh, when this method is called by MEDFileMeshMultiTS::New() + */ +//================================================================================ + +void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading) +{ + if ( toUseInstedOfReading ) + setJoints( toUseInstedOfReading ); + else + _joints = MEDFileJoints::New( fid, _name ); +} + +/*! + * \brief Return number of joints, which is equal to number of adjacent mesh domains + */ +int MEDFileMesh::getNumberOfJoints() +{ + return ( (MEDFileJoints*) _joints ) ? _joints->getNumberOfJoints() : 0; +} + +/*! + * \brief Return joints with all adjacent mesh domains + */ +MEDFileJoints * MEDFileMesh::getJoints() const +{ + return (MEDFileJoints*) & (*_joints); +} + +void MEDFileMesh::setJoints( MEDFileJoints* joints ) +{ + if ( joints != _joints ) + { + _joints = joints; + if ( joints ) + joints->incrRef(); + } +} + /*! * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor. * @@ -2448,7 +2514,6 @@ void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int } loaderl2.loadAll(fid,mid,mName,dt,it,mrs); dispatchLoadedPart(fid,loaderl2,mName,mrs); - } void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs) @@ -2515,6 +2580,8 @@ void MEDFileUMesh::writeLL(med_idt fid) const if((const MEDFileUMeshSplitL1 *)(*it)!=0) (*it)->write(fid,meshName,mdim); MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str); + + writeJoints(fid); } /*! @@ -5924,6 +5991,7 @@ MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it try { loadCMeshFromFile(fid,mName,dt,it,mrs); + loadJointsFromFile(fid); } catch(INTERP_KERNEL::Exception& e) { @@ -6009,6 +6077,8 @@ void MEDFileCMesh::writeLL(med_idt fid) const // std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE)); MEDFileStructuredMesh::writeStructuredLL(fid,meshName); + + writeJoints(fid); } void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const @@ -6176,6 +6246,7 @@ MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& m try { loadCLMeshFromFile(fid,mName,dt,it,mrs); + loadJointsFromFile(fid); } catch(INTERP_KERNEL::Exception& e) { @@ -6215,6 +6286,8 @@ void MEDFileCurveLinearMesh::writeLL(med_idt fid) const // std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE)); MEDFileStructuredMesh::writeStructuredLL(fid,meshName); + + writeJoints(fid); } void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs) @@ -6320,13 +6393,41 @@ void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) _mesh_one_ts[0]=mesh1TimeStep; } +MEDFileJoints * MEDFileMeshMultiTS::getJoints() const +{ + if ( MEDFileMesh* m = getOneTimeStep() ) + return m->getJoints(); + return 0; +} + +/*! + * \brief Set Joints that are common to all time-stamps + */ +void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints ) +{ + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) + { + (*it)->setJoints( joints ); + } +} + void MEDFileMeshMultiTS::write(med_idt fid) const { + MEDFileJoints * joints = getJoints(); + bool jointsWritten = false; + for(std::vector< MEDCouplingAutoRefCountObjectPtr >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++) { + if ( jointsWritten ) + const_cast(**it).setJoints( 0 ); + else + jointsWritten = true; + (*it)->copyOptionsFrom(*this); (*it)->write(fid); } + + ((MEDFileMeshMultiTS*)this)->setJoints( joints ); // restore joints } void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const @@ -6339,9 +6440,16 @@ void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const } void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName) -{//for the moment to be improved - _mesh_one_ts.resize(1); - _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1); +{ + MEDFileJoints* joints = 0; + if ( !_mesh_one_ts.empty() && getOneTimeStep() ) + { + // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading + joints = getOneTimeStep()->getJoints(); + } + + _mesh_one_ts.clear(); //for the moment to be improved + _mesh_one_ts.push_back( MEDFileMesh::New(fileName,mName,-1,-1,0, joints )); } MEDFileMeshMultiTS::MEDFileMeshMultiTS() @@ -6464,6 +6572,16 @@ std::vector MEDFileMeshes::getMeshesNames() const } return ret; } +/*const MEDFileJoints* MEDFileMeshes::getJoints() const +{ + const MEDFileJoints *ret=_joints; + if(!ret) + { + std::ostringstream oss; oss << "MEDFileMeshes::getJoints : joints is not defined !"; + throw INTERP_KERNEL::Exception(oss.str().c_str()); + } + return ret; +}*/ bool MEDFileMeshes::changeNames(const std::vector< std::pair >& modifTab) { diff --git a/src/MEDLoader/MEDFileMesh.hxx b/src/MEDLoader/MEDFileMesh.hxx index 1f3defa38..2bb997d34 100644 --- a/src/MEDLoader/MEDFileMesh.hxx +++ b/src/MEDLoader/MEDFileMesh.hxx @@ -26,6 +26,7 @@ #include "MEDFileUtilities.hxx" #include "MEDCouplingPartDefinition.hxx" #include "MEDFileMeshReadSelector.hxx" +#include "MEDFileJoint.hxx" #include #include @@ -39,7 +40,7 @@ namespace ParaMEDMEM { public: MEDLOADER_EXPORT static MEDFileMesh *New(const std::string& fileName, MEDFileMeshReadSelector *mrs=0); - MEDLOADER_EXPORT static MEDFileMesh *New(const std::string& fileName, const std::string& mName, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0); + MEDLOADER_EXPORT static MEDFileMesh *New(const std::string& fileName, const std::string& mName, int dt=-1, int it=-1, MEDFileMeshReadSelector *mrs=0, MEDFileJoints* joints=0); MEDLOADER_EXPORT std::size_t getHeapMemorySizeWithoutChildren() const; MEDLOADER_EXPORT std::vector getDirectChildrenWithNull() const; MEDLOADER_EXPORT virtual MEDFileMesh *createNewEmpty() const = 0; @@ -169,6 +170,9 @@ namespace ParaMEDMEM MEDLOADER_EXPORT virtual DataArrayInt *getNodeFamiliesArr(const std::vector& fams, bool renum=false) const; // tools MEDLOADER_EXPORT virtual bool unPolyze(std::vector& oldCode, std::vector& newCode, DataArrayInt *& o2nRenumCell) = 0; + MEDLOADER_EXPORT int getNumberOfJoints(); + MEDLOADER_EXPORT MEDFileJoints *getJoints() const; + MEDLOADER_EXPORT void setJoints( MEDFileJoints* joints ); protected: MEDFileMesh(); //! protected because no way in MED file API to specify this name @@ -187,6 +191,8 @@ namespace ParaMEDMEM static std::string FindOrCreateAndGiveFamilyWithId(std::map& families, int id, bool& created); static std::string CreateNameNotIn(const std::string& nameTry, const std::vector& namesToAvoid); static int PutInThirdComponentOfCodeOffset(std::vector& code, int strt); + void writeJoints(med_idt fid) const; + void loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading=0); protected: int _order; int _iteration; @@ -197,6 +203,7 @@ namespace ParaMEDMEM mutable std::string _univ_name; bool _univ_wr_status; std::string _desc_name; + MEDCouplingAutoRefCountObjectPtr _joints; protected: std::map > _groups; std::map _families; @@ -478,6 +485,8 @@ namespace ParaMEDMEM MEDLOADER_EXPORT void write(med_idt fid) const; MEDLOADER_EXPORT void write(const std::string& fileName, int mode) const; MEDLOADER_EXPORT void setOneTimeStep(MEDFileMesh *mesh1TimeStep); + MEDLOADER_EXPORT MEDFileJoints *getJoints() const; + MEDLOADER_EXPORT void setJoints( MEDFileJoints* joints ); private: ~MEDFileMeshMultiTS() { } void loadFromFile(const std::string& fileName, const std::string& mName); diff --git a/src/MEDLoader/Swig/MEDLoaderCommon.i b/src/MEDLoader/Swig/MEDLoaderCommon.i index 901bea448..b4132f8ca 100644 --- a/src/MEDLoader/Swig/MEDLoaderCommon.i +++ b/src/MEDLoader/Swig/MEDLoaderCommon.i @@ -27,6 +27,7 @@ %{ #include "MEDLoader.hxx" +#include "MEDFileJoint.hxx" #include "MEDFileMesh.hxx" #include "MEDFileField.hxx" #include "MEDFileParameter.hxx" @@ -93,6 +94,7 @@ using namespace ParaMEDMEM; %newobject ParaMEDMEM::MEDFileMesh::getNodeFamiliesArr; %newobject ParaMEDMEM::MEDFileMesh::getAllFamiliesIdsReferenced; %newobject ParaMEDMEM::MEDFileMesh::computeAllFamilyIdsInUse; +%newobject ParaMEDMEM::MEDFileData::getJoints; %newobject ParaMEDMEM::MEDFileStructuredMesh::getImplicitFaceMesh; %newobject ParaMEDMEM::MEDFileUMesh::New; %newobject ParaMEDMEM::MEDFileUMesh::LoadPartOf; @@ -191,6 +193,21 @@ using namespace ParaMEDMEM; %newobject ParaMEDMEM::MEDFileParameters::getParamWithName; %newobject ParaMEDMEM::MEDFileParameters::__getitem__; +%newobject ParaMEDMEM::MEDFileJointCorrespondence::New; +%newobject ParaMEDMEM::MEDFileJointCorrespondence::deepCpy; +%newobject ParaMEDMEM::MEDFileJointCorrespondence::shallowCpy; +%newobject ParaMEDMEM::MEDFileJointOneStep::New; +%newobject ParaMEDMEM::MEDFileJointOneStep::deepCpy; +%newobject ParaMEDMEM::MEDFileJointOneStep::shallowCpy; +%newobject ParaMEDMEM::MEDFileJoint::New; +%newobject ParaMEDMEM::MEDFileJoint::deepCpy; +%newobject ParaMEDMEM::MEDFileJoint::shallowCpy; +%newobject ParaMEDMEM::MEDFileJoints::New; +%newobject ParaMEDMEM::MEDFileJoints::deepCpy; +%newobject ParaMEDMEM::MEDFileJoints::getJointAtPos; +%newobject ParaMEDMEM::MEDFileJoints::getJointWithName; +%newobject ParaMEDMEM::MEDFileJoints::__getitem__; + %newobject ParaMEDMEM::SauvWriter::New; %newobject ParaMEDMEM::SauvReader::New; %newobject ParaMEDMEM::SauvReader::loadInMEDFileDS; @@ -219,6 +236,10 @@ using namespace ParaMEDMEM; %feature("unref") MEDFileParameterDouble1TS "$this->decrRef();" %feature("unref") MEDFileParameterMultiTS "$this->decrRef();" %feature("unref") MEDFileParameters "$this->decrRef();" +%feature("unref") MEDFileJointCorrespondence "$this->decrRef();" +%feature("unref") MEDFileJointOneStep "$this->decrRef();" +%feature("unref") MEDFileJoint "$this->decrRef();" +%feature("unref") MEDFileJoints "$this->decrRef();" %feature("unref") MEDFileData "$this->decrRef();" %feature("unref") SauvReader "$this->decrRef();" %feature("unref") SauvWriter "$this->decrRef();" @@ -476,6 +497,208 @@ namespace ParaMEDMEM } } }; + class MEDFileJointCorrespondence : public RefCountObject, public MEDFileWritable + { + public: + static MEDFileJointCorrespondence *New() throw(INTERP_KERNEL::Exception); + static MEDFileJointCorrespondence *New(DataArrayInt* correspondence) // nodes + throw(INTERP_KERNEL::Exception); + static MEDFileJointCorrespondence *New(DataArrayInt* correspondence, // cells + INTERP_KERNEL::NormalizedCellType loc_geo_type, + INTERP_KERNEL::NormalizedCellType rem_geo_type) + throw(INTERP_KERNEL::Exception); + std::vector getDirectChildrenWithNull() const; + MEDFileJointCorrespondence *deepCpy() const; + MEDFileJointCorrespondence *shallowCpy() const; + void setIsNodal(bool isNodal); + bool getIsNodal() const; + bool isEqual(const MEDFileJointCorrespondence *other) const; + void setLocalGeometryType(INTERP_KERNEL::NormalizedCellType type); + INTERP_KERNEL::NormalizedCellType getLocalGeometryType() const; + void setRemoteGeometryType(INTERP_KERNEL::NormalizedCellType type); + INTERP_KERNEL::NormalizedCellType getRemoteGeometryType() const; + void setCorrespondence(DataArrayInt *corr) throw(INTERP_KERNEL::Exception); + const DataArrayInt *getCorrespondence() const throw(INTERP_KERNEL::Exception); + void write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName, int order, int iteration) const throw(INTERP_KERNEL::Exception); + std::string simpleRepr() const throw(INTERP_KERNEL::Exception); + %extend + { + MEDFileJointCorrespondence() + { + return MEDFileJointCorrespondence::New(); + } + MEDFileJointCorrespondence(DataArrayInt* correspondence) throw(INTERP_KERNEL::Exception) + { + return MEDFileJointCorrespondence::New(correspondence); + } + MEDFileJointCorrespondence(DataArrayInt* correspondence, // cells + INTERP_KERNEL::NormalizedCellType loc_geo_type, + INTERP_KERNEL::NormalizedCellType rem_geo_type) throw(INTERP_KERNEL::Exception) + { + return MEDFileJointCorrespondence::New(correspondence, loc_geo_type, rem_geo_type); + } + + std::string __str__() const throw(INTERP_KERNEL::Exception) + { + return self->simpleRepr(); + } + } + }; + + class MEDFileJointOneStep : public RefCountObject, public MEDFileWritable + { + public: + static MEDFileJointOneStep *New(int dt=-1, int it=-1) throw(INTERP_KERNEL::Exception); + static MEDFileJointOneStep *New(const std::string& fileName, const std::string& mName, const std::string& jointName, int number=1) throw(INTERP_KERNEL::Exception); + MEDFileJointOneStep *deepCpy() const; + MEDFileJointOneStep *shallowCpy() const; + bool isEqual(const MEDFileJointOneStep *other) const; + void setOrder(int order); + int getOrder() const; + void setIteration(int it); + int getIteration() const; + void pushCorrespondence(MEDFileJointCorrespondence* correspondence); + int getNumberOfCorrespondences() const; + MEDFileJointCorrespondence *getCorrespondenceAtPos(int i) const; + void write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName) const throw(INTERP_KERNEL::Exception); + std::string simpleRepr() const throw(INTERP_KERNEL::Exception); + %extend + { + MEDFileJointOneStep() + { + return MEDFileJointOneStep::New(); + } + + MEDFileJointOneStep(const std::string& fileName, const std::string& mName, const std::string& jointName, int number) throw(INTERP_KERNEL::Exception) + { + return MEDFileJointOneStep::New(fileName,mName,jointName,number); + } + + std::string __str__() const throw(INTERP_KERNEL::Exception) + { + return self->simpleRepr(); + } + } + }; + class MEDFileJoint : public RefCountObject, public MEDFileWritable + { + public: + static MEDFileJoint *New() throw(INTERP_KERNEL::Exception); + static MEDFileJoint *New(const std::string& fileName, const std::string& mName, int num) throw(INTERP_KERNEL::Exception); + static MEDFileJoint *New(const std::string& jointName, const std::string& locMeshName, const std::string& remoteMeshName, int remoteMeshNum ) throw(INTERP_KERNEL::Exception); + MEDFileJoint *deepCpy() const; + MEDFileJoint *shallowCpy() const; + bool isEqual(const MEDFileJoint *other) const; + void setLocalMeshName(const std::string& name); + std::string getLocalMeshName() const; + void setRemoteMeshName(const std::string& name); + std::string getRemoteMeshName() const; + void setDescription(const std::string& name); + std::string getDescription() const; + void setJointName(const std::string& name); + std::string getJointName() const; + bool changeJointNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); + void setDomainNumber(const int& number); + int getDomainNumber() const; + void pushStep(MEDFileJointOneStep* step); + int getNumberOfSteps() const; + MEDFileJointOneStep *getStepAtPos(int i) const; + void write(const std::string& fileName, int mode) const throw(INTERP_KERNEL::Exception); + std::string simpleRepr() const; + %extend + { + MEDFileJoint() + { + return MEDFileJoint::New(); + } + + MEDFileJoint(const std::string& fileName, const std::string& mName, int num) throw(INTERP_KERNEL::Exception) + { + return MEDFileJoint::New(fileName,mName,num); + } + + std::string __str__() const throw(INTERP_KERNEL::Exception) + { + return self->simpleRepr(); + } + } + }; + + class MEDFileJoints : public RefCountObject, public MEDFileWritable + { + public: + static MEDFileJoints *New() throw(INTERP_KERNEL::Exception); + static MEDFileJoints *New(const std::string& fileName, const std::string& meshName) throw(INTERP_KERNEL::Exception); + MEDFileJoints *deepCpy() const; + std::string simpleRepr() const; + void write(const std::string& fileName, int mode) const throw(INTERP_KERNEL::Exception); + std::string getMeshName() const; + int getNumberOfJoints() const; + std::vector getJointsNames() const; + bool changeJointNames(const std::vector< std::pair >& modifTab) throw(INTERP_KERNEL::Exception); + void resize(int newSize) throw(INTERP_KERNEL::Exception); + void pushJoint(MEDFileJoint *joint); + void setJointAtPos(int i, MEDFileJoint *joint) throw(INTERP_KERNEL::Exception); + void destroyJointAtPos(int i) throw(INTERP_KERNEL::Exception); + %extend + { + MEDFileJoints() + { + return MEDFileJoints::New(); + } + + MEDFileJoints(const std::string& fileName, const std::string& meshName) throw(INTERP_KERNEL::Exception) + { + return MEDFileJoints::New(fileName,meshName); + } + + std::string __str__() const throw(INTERP_KERNEL::Exception) + { + return self->simpleRepr(); + } + + MEDFileJoint *__getitem__(PyObject *obj) throw(INTERP_KERNEL::Exception) + { + if(PyInt_Check(obj)) + { + MEDFileJoint *ret=self->getJointAtPos(InterpreteNegativeInt((int)PyInt_AS_LONG(obj),self->getNumberOfJoints())); + if(ret) + ret->incrRef(); + return ret; + } + else if(PyString_Check(obj)) + { + MEDFileJoint *ret=self->getJointWithName(PyString_AsString(obj)); + if(ret) + ret->incrRef(); + return ret; + } + else + throw INTERP_KERNEL::Exception("MEDFileJoints::__getitem__ : only integer or string with meshname supported !"); + } + + int __len__() const throw(INTERP_KERNEL::Exception) + { + return self->getNumberOfJoints(); + } + + MEDFileJoint *getJointAtPos(int i) const throw(INTERP_KERNEL::Exception) + { + MEDFileJoint *ret=self->getJointAtPos(i); + if(ret) + ret->incrRef(); + return ret; + } + + MEDFileJoint *getJointWithName(const std::string& paramName) const throw(INTERP_KERNEL::Exception) + { + MEDFileJoint *ret=self->getJointWithName(paramName); + if(ret) + ret->incrRef(); + return ret; + } + } + }; class MEDFileMesh : public RefCountObject, public MEDFileWritable { @@ -590,6 +813,9 @@ namespace ParaMEDMEM virtual DataArrayInt *getNodeGroupsArr(const std::vector& grps, bool renum=false) const throw(INTERP_KERNEL::Exception); virtual DataArrayInt *getNodeFamilyArr(const std::string& fam, bool renum=false) const throw(INTERP_KERNEL::Exception); virtual DataArrayInt *getNodeFamiliesArr(const std::vector& fams, bool renum=false) const throw(INTERP_KERNEL::Exception); + int getNumberOfJoints(); + MEDFileJoints *getJoints(); + void setJoints( MEDFileJoints* joints ); %extend { std::string __str__() const throw(INTERP_KERNEL::Exception) diff --git a/src/MEDLoader/Swig/MEDLoaderTest3.py b/src/MEDLoader/Swig/MEDLoaderTest3.py index 2682b2dd9..bb5ec84d4 100644 --- a/src/MEDLoader/Swig/MEDLoaderTest3.py +++ b/src/MEDLoader/Swig/MEDLoaderTest3.py @@ -4360,5 +4360,131 @@ class MEDLoaderTest(unittest.TestCase): pass pass + def testMEDFileJoint1(self): + fileName="Pyfile88.med" + coo=DataArrayDouble([(0,0,0),(1,0,0),(2,0,0)]) + coo.setInfoOnComponents(["x [cm]","y [cm]","z [cm]"]) + mm=MEDFileUMesh() + mm.setCoords(coo) + mm.setName("maa1") + mm.setDescription("un maillage") + mm.write(fileName,2) + node_correspond=MEDFileJointCorrespondence(DataArrayInt([1,2,3,4,5,6,7,8])) + cell_correspond=MEDFileJointCorrespondence(DataArrayInt([9,10,11,12]),NORM_TRI3,NORM_TRI3) + one_step_joint=MEDFileJointOneStep() + one_step_joint.pushCorrespondence(cell_correspond) + one_step_joint.pushCorrespondence(node_correspond) + one_joint=MEDFileJoint() + one_joint.pushStep(one_step_joint) + one_joint.setLocalMeshName("maa1") + one_joint.setRemoteMeshName("maa1") + one_joint.setDescription("joint_description") + one_joint.setJointName("joint_1") + one_joint.setDomainNumber(1) + self.assertEqual( one_joint.getLocalMeshName(), "maa1") + self.assertEqual( one_joint.getRemoteMeshName(), "maa1") + self.assertEqual( one_joint.getDescription(), "joint_description") + self.assertEqual( one_joint.getJointName(), "joint_1") + self.assertEqual( one_joint.getDomainNumber(), 1) + joints=MEDFileJoints() + joints.pushJoint(one_joint); + joints.write(fileName,0) + # read back + jointsR=MEDFileJoints(fileName,mm.getName()) + self.assertEqual( jointsR.getNumberOfJoints(), 1 ) + jR = jointsR.getJointAtPos(0) + self.assertTrue( jR.isEqual( one_joint )) + self.assertRaises( InterpKernelException, jointsR.getJointAtPos,1) + self.assertRaises( InterpKernelException, jointsR.destroyJointAtPos,1) + jointsR.destroyJointAtPos(0) + + pass + def testMEDFileJoint2(self): + fileNameWr="Pyfile89.med" + coo=DataArrayDouble([(0,0,0),(1,0,0),(2,0,0)]) + coo.setInfoOnComponents(["x [cm]","y [cm]","z [cm]"]) + mm=MEDFileUMesh() + mm.setCoords(coo) + mm.setName("maa1") + mm.setDescription("un maillage") + node_correspond=MEDFileJointCorrespondence(DataArrayInt([13,14,15,16])) + cell_correspond=MEDFileJointCorrespondence(DataArrayInt([17,18]),NORM_TETRA4,NORM_PENTA6) + one_step_joint=MEDFileJointOneStep() + two_step_joint=MEDFileJointOneStep() + one_joint=MEDFileJoint() + two_joint=MEDFileJoint() + one_step_joint.pushCorrespondence(node_correspond) + one_joint.pushStep(one_step_joint) + two_step_joint.pushCorrespondence(cell_correspond) + two_step_joint.pushCorrespondence(node_correspond) + two_joint.pushStep(two_step_joint) + one_joint.setLocalMeshName("maa1") + one_joint.setRemoteMeshName("maa1") + one_joint.setDescription("joint_description_1") + one_joint.setJointName("joint_1") + one_joint.setDomainNumber(1) + two_joint.setLocalMeshName("maa1") + two_joint.setRemoteMeshName("maa1") + two_joint.setDescription("joint_description_2") + two_joint.setJointName("joint_2") + two_joint.setDomainNumber(2) + joints=MEDFileJoints() + joints.pushJoint(one_joint) + joints.pushJoint(two_joint) + mm.setJoints( joints ) + mm.write(fileNameWr,2) + # + mm=MEDFileMesh.New(fileNameWr) + self.assertEqual( mm.getNumberOfJoints(), 2) + jointsR = mm.getJoints(); + self.assertEqual( jointsR.getMeshName(), mm.getName() ) + self.assertEqual( len( jointsR ), 2 ) + jointR1 = jointsR[0] + jointR2 = jointsR[1] + self.assertFalse( jointR1 is None ) + self.assertFalse( jointR2 is None ) + self.assertTrue( jointR1.isEqual( one_joint )) + self.assertTrue( jointR2.isEqual( two_joint )) + pass + + def testMEDFileJoint1(self): + node_correspond=MEDFileJointCorrespondence(DataArrayInt([1,2,3,4,5,6,7,8])) + cell_correspond=MEDFileJointCorrespondence(DataArrayInt([9,10,11,12]),NORM_TRI3,NORM_TRI3) + cell_correspon2=MEDFileJointCorrespondence(DataArrayInt([9,10,11]),NORM_TRI3,NORM_TRI3) + cell_correspon3=MEDFileJointCorrespondence(DataArrayInt([9,10,11,12]),NORM_TRI3,NORM_QUAD4) + joint1st_1=MEDFileJointOneStep() + joint1st_1.pushCorrespondence(cell_correspond) + joint1st_1.pushCorrespondence(node_correspond) + joint1st_2=MEDFileJointOneStep() + joint1st_2.pushCorrespondence(cell_correspond) + joint1st_2.pushCorrespondence(node_correspond) + joint1st_3=MEDFileJointOneStep() + joint1st_3.pushCorrespondence(node_correspond) + joint1st_3.pushCorrespondence(cell_correspond) + joint1st_4=MEDFileJointOneStep() + joint1st_4.pushCorrespondence(cell_correspond) + joint1st_5=MEDFileJointOneStep() + joint1st_5.pushCorrespondence(cell_correspon2) + joint1st_6=MEDFileJointOneStep() + joint1st_6.pushCorrespondence(cell_correspon3) + self.assertTrue( joint1st_1.isEqual( joint1st_2 )) + self.assertTrue( joint1st_1.isEqual( joint1st_3 )) + self.assertFalse( joint1st_1.isEqual( joint1st_4 )) + self.assertFalse( joint1st_4.isEqual( joint1st_5 )) + self.assertFalse( joint1st_4.isEqual( joint1st_6 )) + one_joint=MEDFileJoint() + one_joint.pushStep(joint1st_1) + one_joint.setLocalMeshName("maa1") + one_joint.setRemoteMeshName("maa2") + one_joint.setDescription("joint_description") + one_joint.setJointName("joint_1") + one_joint.setDomainNumber(1) + self.assertEqual( "maa1", one_joint.getLocalMeshName()) + self.assertEqual( "maa2", one_joint.getRemoteMeshName()) + self.assertEqual( "joint_description", one_joint.getDescription()) + self.assertEqual( 1, one_joint.getDomainNumber()) + self.assertEqual( "joint_1", one_joint.getJointName()) + pass + pass unittest.main() diff --git a/src/MEDPartitioner/CMakeLists.txt b/src/MEDPartitioner/CMakeLists.txt index d6003437c..2404e49f9 100644 --- a/src/MEDPartitioner/CMakeLists.txt +++ b/src/MEDPartitioner/CMakeLists.txt @@ -78,8 +78,8 @@ SET(medpartitionercpp_HEADERS_HXX MEDPARTITIONER.hxx MEDPARTITIONER_ParaDomainSelector.hxx MEDPARTITIONER_ConnectZone.hxx - MEDPARTITIONER_SkyLineArray.hxx MEDPARTITIONER_Topology.hxx + MEDPARTITIONER_MEDPartitioner.hxx ) SET(medpartitionercpp_SOURCES @@ -93,8 +93,8 @@ SET(medpartitionercpp_SOURCES MEDPARTITIONER_Utils.cxx MEDPARTITIONER_ParaDomainSelector.cxx MEDPARTITIONER_ConnectZone.cxx - MEDPARTITIONER_SkyLineArray.cxx MEDPARTITIONER_metis.c + MEDPARTITIONER_MEDPartitioner.cxx ) SET(medpartitionercpp_LDFLAGS diff --git a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx index 155526dbf..78fd1a0f4 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx @@ -21,6 +21,8 @@ #include +using namespace ParaMEDMEM; + MEDPARTITIONER::ConnectZone::ConnectZone(): _name("") ,_description("") @@ -35,7 +37,7 @@ MEDPARTITIONER::ConnectZone::~ConnectZone() { delete _node_corresp; delete _face_corresp; - for(std::map < std::pair ,SkyLineArray * >::iterator iter=_entity_corresp.begin(); iter!=_entity_corresp.end();iter++) + for(std::map < std::pair ,MEDCouplingSkyLineArray * >::iterator iter=_entity_corresp.begin(); iter!=_entity_corresp.end();iter++) { delete iter->second; } @@ -84,7 +86,7 @@ ParaMEDMEM::MEDCouplingUMesh *MEDPARTITIONER::ConnectZone::getDistantMesh() cons bool MEDPARTITIONER::ConnectZone::isEntityCorrespPresent(int localEntity, int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for(map_iter iter=_entity_corresp.begin(); iter != _entity_corresp.end(); iter++) { if ((iter->first).first==localEntity && (iter->first).second==distantEntity) @@ -108,6 +110,11 @@ int MEDPARTITIONER::ConnectZone::getNodeNumber() const return _node_corresp->getNumberOf(); } +const ParaMEDMEM::MEDCouplingSkyLineArray * MEDPARTITIONER::ConnectZone::getNodeCorresp() const +{ + return _node_corresp; +} + const int *MEDPARTITIONER::ConnectZone::getFaceCorrespIndex() const { return _face_corresp->getIndex(); @@ -123,56 +130,88 @@ int MEDPARTITIONER::ConnectZone::getFaceNumber() const return _face_corresp->getNumberOf(); } +const ParaMEDMEM::MEDCouplingSkyLineArray * MEDPARTITIONER::ConnectZone::getFaceCorresp() const +{ + return _face_corresp; +} + const int *MEDPARTITIONER::ConnectZone::getEntityCorrespIndex(int localEntity, - int distantEntity) const + int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for(map_iter iter=_entity_corresp.begin();iter!=_entity_corresp.end();iter++) - { - if ((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getIndex(); - } + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getIndex(); + } return 0; } const int *MEDPARTITIONER::ConnectZone::getEntityCorrespValue(int localEntity, - int distantEntity) const + int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for (map_iter iter=_entity_corresp.begin();iter!=_entity_corresp.end();iter++) - { - if ((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getValue(); - } + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getValue(); + } return 0; } int MEDPARTITIONER::ConnectZone::getEntityCorrespNumber(int localEntity, - int distantEntity) const + int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for(map_iter iter=_entity_corresp.begin();iter!=_entity_corresp.end();iter++) - { - if((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getNumberOf(); - } + { + if((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getNumberOf(); + } return 0; } int MEDPARTITIONER::ConnectZone::getEntityCorrespLength(int localEntity, - int distantEntity) const + int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; - + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; + for (map_iter iter=_entity_corresp.begin(); iter != _entity_corresp.end(); iter++) + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getLength(); + } + return 0; +} + +const ParaMEDMEM::MEDCouplingSkyLineArray * +MEDPARTITIONER::ConnectZone::getEntityCorresp(int localEntity, int distantEntity) const +{ + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; + + for (map_iter iter=_entity_corresp.begin(); iter != _entity_corresp.end(); iter++) + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second; + } + return 0; +} + +std::vector< std::pair< int,int > > MEDPARTITIONER::ConnectZone::getEntities() const +{ + std::vector< std::pair< int,int > > types; + + std::map, MEDCouplingSkyLineArray*>::const_iterator + iter = _entity_corresp.begin(); + for ( ; iter != _entity_corresp.end(); iter++) { - if ((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getLength(); + types.push_back( iter->first ); } - return 0; + + return types; } void MEDPARTITIONER::ConnectZone::setName(const std::string& name) @@ -207,33 +246,44 @@ void MEDPARTITIONER::ConnectZone::setDistantMesh(ParaMEDMEM::MEDCouplingUMesh * /*! transforms an int array containing * the node-node connections - * to a SkyLineArray + * to a MEDCouplingSkyLineArray */ -void MEDPARTITIONER::ConnectZone::setNodeCorresp(int * nodeCorresp, int nbnode) +void MEDPARTITIONER::ConnectZone::setNodeCorresp(const int * nodeCorresp, int nbnode) { - std::vector index(nbnode+1),value(2*nbnode); + MEDCouplingAutoRefCountObjectPtr indexArr( DataArrayInt::New() ); + MEDCouplingAutoRefCountObjectPtr valueArr( DataArrayInt::New() ); + indexArr->alloc( nbnode+1 ); + valueArr->alloc( 2*nbnode ); + int * index = indexArr->getPointer(); + int * value = valueArr->getPointer(); for (int i=0; i index(nbface+1),value(2*nbface); + MEDCouplingAutoRefCountObjectPtr indexArr( DataArrayInt::New() ); + MEDCouplingAutoRefCountObjectPtr valueArr( DataArrayInt::New() ); + indexArr->alloc( nbface+1 ); + valueArr->alloc( 2*nbface ); + int * index = indexArr->getPointer(); + int * value = valueArr->getPointer(); for (int i=0; i index(nbentity+1),value(2*nbentity); + MEDCouplingAutoRefCountObjectPtr indexArr( DataArrayInt::New() ); + MEDCouplingAutoRefCountObjectPtr valueArr( DataArrayInt::New() ); + indexArr->alloc( nbentity+1 ); + valueArr->alloc( 2*nbentity ); + int * index = indexArr->getPointer(); + int * value = valueArr->getPointer(); for (int i=0; i, ParaMEDMEM::MEDCouplingSkyLineArray * >::iterator it; + it = _entity_corresp.insert + ( std::make_pair( std::make_pair(localEntity,distantEntity), nullArray )).first; + if ( it->second != nullArray ) delete it->second; + it->second = array; } - - - - - - - diff --git a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx index 83190cbee..8c1626dfd 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx @@ -22,9 +22,10 @@ #include "MEDPARTITIONER.hxx" #include "MEDCouplingUMesh.hxx" -#include "MEDPARTITIONER_SkyLineArray.hxx" +#include "MEDCouplingSkyLineArray.hxx" #include +#include #include namespace MEDPARTITIONER @@ -47,9 +48,11 @@ namespace MEDPARTITIONER const int *getNodeCorrespIndex() const; const int *getNodeCorrespValue() const; int getNodeNumber() const; + const ParaMEDMEM::MEDCouplingSkyLineArray * getNodeCorresp() const; const int *getFaceCorrespIndex() const; const int *getFaceCorrespValue() const; int getFaceNumber() const; + const ParaMEDMEM::MEDCouplingSkyLineArray * getFaceCorresp() const; const int *getEntityCorrespIndex(int localEntity, int distantEntity) const; const int *getEntityCorrespValue(int localEntity, @@ -58,6 +61,10 @@ namespace MEDPARTITIONER int distantEntity) const; int getEntityCorrespLength(int localEntity, int distantEntity) const; + const ParaMEDMEM::MEDCouplingSkyLineArray * getEntityCorresp(int localEntity, + int distantEntity) const; + std::vector< std::pair< int,int > > getEntities() const; + void setName(const std::string& name) ; void setDescription(const std::string& description) ; void setDistantDomainNumber(int distantDomainNumber) ; @@ -65,14 +72,14 @@ namespace MEDPARTITIONER void setLocalMesh(ParaMEDMEM::MEDCouplingUMesh * localMesh) ; void setDistantMesh(ParaMEDMEM::MEDCouplingUMesh * distantMesh) ; - void setNodeCorresp(int * nodeCorresp, int nbnode); - void setNodeCorresp(MEDPARTITIONER::SkyLineArray* array); - void setFaceCorresp(int * faceCorresp, int nbface); - void setFaceCorresp(MEDPARTITIONER::SkyLineArray* array); + void setNodeCorresp(const int * nodeCorresp, int nbnode); + void setNodeCorresp(ParaMEDMEM::MEDCouplingSkyLineArray* array); + void setFaceCorresp(const int * faceCorresp, int nbface); + void setFaceCorresp(ParaMEDMEM::MEDCouplingSkyLineArray* array); void setEntityCorresp(int localEntity, int distantEntity, - int * entityCorresp, int nbentity); + const int * entityCorresp, int nbentity); void setEntityCorresp(int localEntity, int distantEntity, - MEDPARTITIONER::SkyLineArray *array); + ParaMEDMEM::MEDCouplingSkyLineArray *array); private : std::string _name; std::string _description; @@ -82,10 +89,10 @@ namespace MEDPARTITIONER ParaMEDMEM::MEDCouplingUMesh * _local_mesh; ParaMEDMEM::MEDCouplingUMesh * _distant_mesh; - SkyLineArray * _node_corresp; - SkyLineArray * _face_corresp; + ParaMEDMEM::MEDCouplingSkyLineArray * _node_corresp; + ParaMEDMEM::MEDCouplingSkyLineArray * _face_corresp; - std::map < std::pair , SkyLineArray * > _entity_corresp; + std::map < std::pair , ParaMEDMEM::MEDCouplingSkyLineArray * > _entity_corresp; }; } # endif diff --git a/src/MEDPartitioner/MEDPARTITIONER_Graph.cxx b/src/MEDPartitioner/MEDPARTITIONER_Graph.cxx index a2a4b2feb..62a273a6a 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_Graph.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_Graph.cxx @@ -19,7 +19,9 @@ #include "MEDPARTITIONER_Graph.hxx" -MEDPARTITIONER::Graph::Graph(MEDPARTITIONER::SkyLineArray *array, int *edgeweight):_graph(array),_partition(0),_edge_weight(edgeweight),_cell_weight(0) +#include + +MEDPARTITIONER::Graph::Graph(ParaMEDMEM::MEDCouplingSkyLineArray *array, int *edgeweight):_graph(array),_partition(0),_edge_weight(edgeweight),_cell_weight(0) { } @@ -28,3 +30,15 @@ MEDPARTITIONER::Graph::~Graph() delete _partition; delete _graph; } + +int MEDPARTITIONER::Graph::nbDomains() const +{ + std::set domains; + if ( _partition ) + if ( ParaMEDMEM::DataArrayInt* array = _partition->getValueArray() ) + { + for ( const int * dom = array->begin(); dom != array->end(); ++dom ) + domains.insert( *dom ); + } + return domains.size(); +} diff --git a/src/MEDPartitioner/MEDPARTITIONER_Graph.hxx b/src/MEDPartitioner/MEDPARTITIONER_Graph.hxx index 6aaef4ba7..33ea67601 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_Graph.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_Graph.hxx @@ -21,10 +21,15 @@ #define __MEDPARTITIONER_GRAPH_HXX__ #include "MEDPARTITIONER.hxx" -#include "MEDPARTITIONER_SkyLineArray.hxx" +#include "MEDCouplingSkyLineArray.hxx" #include +namespace ParaMEDMEM +{ + class MEDCouplingSkyLineArray; +} + namespace MEDPARTITIONER { class ParaDomainSelector; @@ -33,28 +38,32 @@ namespace MEDPARTITIONER public: typedef enum {METIS,SCOTCH} splitter_type; - Graph() { } + Graph(){}; //creates a graph from a SKYLINEARRAY - Graph(MEDPARTITIONER::SkyLineArray* graph, int* edgeweight=0); + Graph(ParaMEDMEM::MEDCouplingSkyLineArray* graph, int* edgeweight=0); virtual ~Graph(); void setEdgesWeights(int *edgeweight) { _edge_weight=edgeweight; } void setVerticesWeights(int *cellweight) { _cell_weight=cellweight; } //computes partitioning of the graph - virtual void partGraph(int ndomain, const std::string&, ParaDomainSelector *sel=0) = 0; + virtual void partGraph(int ndomain, const std::string& options_string="", ParaDomainSelector *sel=0) = 0; //returns the partitioning const int *getPart() const { return _partition->getValue(); } //returns the number of graph vertices (which can correspond to the cells in the mesh!) int nbVertices() const { return _graph->getNumberOf(); } + + // returns nb of domains in _partition + int nbDomains() const; - const SkyLineArray *getGraph() const { return _graph; } + const ParaMEDMEM::MEDCouplingSkyLineArray *getGraph() const { return _graph; } + const ParaMEDMEM::MEDCouplingSkyLineArray *getPartition() const { return _partition; } protected: - SkyLineArray* _graph; - SkyLineArray* _partition; + ParaMEDMEM::MEDCouplingSkyLineArray* _graph; + ParaMEDMEM::MEDCouplingSkyLineArray* _partition; int* _edge_weight; int* _cell_weight; }; diff --git a/src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.cxx b/src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.cxx new file mode 100644 index 000000000..4ecca4e64 --- /dev/null +++ b/src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.cxx @@ -0,0 +1,159 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "MEDPARTITIONER_MEDPartitioner.hxx" +#include "MEDPARTITIONER_MeshCollection.hxx" +#include "MEDPARTITIONER_Topology.hxx" +#include "MEDPARTITIONER_ParaDomainSelector.hxx" +#include "MEDPARTITIONER_ParallelTopology.hxx" +#include "MEDPARTITIONER_Utils.hxx" +#include "MEDPARTITIONER_Graph.hxx" +#include "MEDPARTITIONER_MetisGraph.hxx" +#include "MEDPARTITIONER_ScotchGraph.hxx" +#include "MEDPARTITIONER_MeshCollectionDriver.hxx" +#include "MEDCouplingUMesh.hxx" + +#include +#include + +MEDPARTITIONER::MEDPartitioner::MEDPartitioner(const std::string& filename, int ndomains, const std::string& library,bool creates_boundary_faces, bool create_joints, bool mesure_memory): + _input_collection( 0 ), _output_collection( 0 ), _new_topology( 0 ) +{ + MyGlobals::_World_Size = 1; + MyGlobals::_Rank = 0; + MyGlobals::_Creates_Boundary_Faces = creates_boundary_faces; + MyGlobals::_Create_Joints = create_joints; + + ParaDomainSelector parallelizer(mesure_memory); + _input_collection=new MeshCollection(filename,parallelizer); + _input_collection->setParaDomainSelector( ¶llelizer ); + + MEDPARTITIONER::ParallelTopology* aPT = + (MEDPARTITIONER::ParallelTopology*) _input_collection->getTopology(); + aPT->setGlobalNumerotationDefault( _input_collection->getParaDomainSelector() ); + _input_collection->prepareFieldDescriptions(); + createPartitionCollection(ndomains, library, creates_boundary_faces, create_joints, mesure_memory); + + parallelizer.evaluateMemory(); +} + +MEDPARTITIONER::MEDPartitioner::MEDPartitioner(const ParaMEDMEM::MEDFileData* filedata, int ndomains, const std::string& library,bool creates_boundary_faces, bool create_joints, bool mesure_memory): + _input_collection( 0 ), _output_collection( 0 ), _new_topology( 0 ) +{ + MyGlobals::_World_Size = 1; + MyGlobals::_Rank = 0; + MyGlobals::_Creates_Boundary_Faces = creates_boundary_faces; + MyGlobals::_Create_Joints = create_joints; + + ParaDomainSelector parallelizer(mesure_memory); + _input_collection=new MeshCollection(); + _input_collection->setParaDomainSelector( ¶llelizer ); + _input_collection->retrieveDriver()->readMEDFileData(filedata); + + MEDPARTITIONER::ParallelTopology* aPT = + (MEDPARTITIONER::ParallelTopology*) _input_collection->getTopology(); + aPT->setGlobalNumerotationDefault( _input_collection->getParaDomainSelector() ); + _input_collection->prepareFieldDescriptions(); + createPartitionCollection(ndomains, library, creates_boundary_faces, create_joints, mesure_memory); + + parallelizer.evaluateMemory(); +} + +MEDPARTITIONER::MEDPartitioner::MEDPartitioner(const ParaMEDMEM::MEDFileData* filedata, MEDPARTITIONER ::Graph* graph, bool creates_boundary_faces, bool create_joints, bool mesure_memory): + _input_collection( 0 ), _output_collection( 0 ), _new_topology( 0 ) +{ + MyGlobals::_World_Size = 1; + MyGlobals::_Rank = 0; + MyGlobals::_Creates_Boundary_Faces = creates_boundary_faces; + MyGlobals::_Create_Joints = create_joints; + + ParaDomainSelector parallelizer(mesure_memory); + _input_collection=new MeshCollection(); + _input_collection->setParaDomainSelector( ¶llelizer ); + _input_collection->retrieveDriver()->readMEDFileData(filedata); + + MEDPARTITIONER::ParallelTopology* aPT = + (MEDPARTITIONER::ParallelTopology*) _input_collection->getTopology(); + aPT->setGlobalNumerotationDefault( _input_collection->getParaDomainSelector() ); + _input_collection->prepareFieldDescriptions(); + + _new_topology = new MEDPARTITIONER::ParallelTopology( graph, aPT, graph->nbDomains(), _input_collection->getMeshDimension() ); + _output_collection=new MeshCollection(*_input_collection,_new_topology,false,false); + _output_collection->filterFaceOnCell(); + + parallelizer.evaluateMemory(); +} + +MEDPARTITIONER::MEDPartitioner::~MEDPartitioner() +{ + delete _input_collection; _input_collection = 0; + delete _output_collection; _output_collection = 0; + delete _new_topology; _new_topology = 0; +} + +void MEDPARTITIONER::MEDPartitioner::createPartitionCollection(int ndomains, const std::string& library,bool creates_boundary_faces, bool create_joints, bool mesure_memory) +{ + //ParallelTopology* aPT = (ParallelTopology*) _input_collection->getTopology(); + if (library == "metis") + _new_topology = _input_collection->createPartition(ndomains,MEDPARTITIONER::Graph::METIS); + else + _new_topology = _input_collection->createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH); + _output_collection=new MeshCollection(*_input_collection,_new_topology,false,false); + _output_collection->filterFaceOnCell(); +} + +void MEDPARTITIONER::MEDPartitioner::write(const std::string& filename) +{ + ParaDomainSelector parallelizer(false); + _output_collection->setParaDomainSelector( ¶llelizer ); + _output_collection->write(filename); + parallelizer.evaluateMemory(); +} + +ParaMEDMEM::MEDFileData* MEDPARTITIONER::MEDPartitioner::getMEDFileData() +{ + return _output_collection->retrieveDriver()->getMEDFileData(); +} + +MEDPARTITIONER::Graph* MEDPARTITIONER::MEDPartitioner::Graph(ParaMEDMEM::MEDCouplingSkyLineArray* graph, Graph::splitter_type split, int* edgeweight) +{ + MEDPARTITIONER::Graph* cellGraph=0; + ParaMEDMEM::MEDCouplingSkyLineArray* arr = new ParaMEDMEM::MEDCouplingSkyLineArray(graph->getIndexArray(), graph->getValueArray()); + switch (split) + { + case Graph::METIS: + if ( !cellGraph ) + { +#ifdef MED_ENABLE_METIS + cellGraph=new METISGraph(arr,edgeweight); +#endif + } + if ( !cellGraph ) + throw INTERP_KERNEL::Exception("MEDPartitioner::Graph : PARMETIS/METIS is not available. Check your products, please."); + break; + case Graph::SCOTCH: +#ifdef MED_ENABLE_SCOTCH + cellGraph=new SCOTCHGraph(arr,edgeweight); +#else + throw INTERP_KERNEL::Exception("MEDPartitioner::Graph : SCOTCH is not available. Check your products, please."); +#endif + break; + } + return cellGraph; +} diff --git a/src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.hxx b/src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.hxx new file mode 100644 index 000000000..d7c31ffda --- /dev/null +++ b/src/MEDPartitioner/MEDPARTITIONER_MEDPartitioner.hxx @@ -0,0 +1,62 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef __MEDPARTITIONER_MEDPARTITIONER_HXX__ +#define __MEDPARTITIONER_MEDPARTITIONER_HXX__ + +#include "MEDPARTITIONER_Graph.hxx" + +#include +#include + +namespace ParaMEDMEM +{ + class DataArrayInt; + class MEDFileData; + class MEDCouplingSkyLineArray; +} + +namespace MEDPARTITIONER +{ + class Topology; + class MeshCollection; + class ParaDomainSelector; + class Graph; + + class MEDPartitioner + { + public: + MEDPartitioner(const std::string& filename, int ndomains=1, const std::string& library="metis",bool creates_boundary_faces=false, bool create_joints=false, bool mesure_memory=false); + MEDPartitioner(const ParaMEDMEM::MEDFileData* fileData, int ndomains=1, const std::string& library="metis",bool creates_boundary_faces=false, bool create_joints=false, bool mesure_memory=false); + MEDPartitioner(const ParaMEDMEM::MEDFileData* fileData, Graph* graph, bool creates_boundary_faces=false, bool create_joints=false, bool mesure_memory=false); + static MEDPARTITIONER::Graph* Graph(ParaMEDMEM::MEDCouplingSkyLineArray* graph, Graph::splitter_type split=Graph::METIS, int* edgeweight=0); + void write(const std::string& filename); + ParaMEDMEM::MEDFileData* getMEDFileData(); + ~MEDPartitioner(); + + ParaMEDMEM::MEDFileData *convertToMEDFileData(MeshCollection* meshcollection); + void createPartitionCollection(int ndomains, const std::string& library,bool creates_boundary_faces, bool create_joints, bool mesure_memory); + + private: + MeshCollection* _input_collection; + MeshCollection* _output_collection; + Topology* _new_topology; + }; +} +#endif diff --git a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx index 8678cf786..ec806a93b 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx @@ -18,30 +18,29 @@ // #include "MEDPARTITIONER_MeshCollection.hxx" + +#include "MEDPARTITIONER_ConnectZone.hxx" +#include "MEDPARTITIONER_Graph.hxx" #include "MEDPARTITIONER_MeshCollectionDriver.hxx" -#include "MEDPARTITIONER_MeshCollectionMedXmlDriver.hxx" #include "MEDPARTITIONER_MeshCollectionMedAsciiDriver.hxx" +#include "MEDPARTITIONER_MeshCollectionMedXmlDriver.hxx" #include "MEDPARTITIONER_ParaDomainSelector.hxx" -#include "MEDPARTITIONER_Topology.hxx" #include "MEDPARTITIONER_ParallelTopology.hxx" +#include "MEDPARTITIONER_Topology.hxx" +#include "MEDPARTITIONER_UserGraph.hxx" +#include "MEDPARTITIONER_Utils.hxx" #ifdef HAVE_MPI #include "MEDPARTITIONER_JointFinder.hxx" #endif -#include "MEDPARTITIONER_Graph.hxx" -#include "MEDPARTITIONER_UserGraph.hxx" -#include "MEDPARTITIONER_Utils.hxx" - -#include "MEDLoaderBase.hxx" -#include "MEDLoader.hxx" +#include "MEDCouplingAutoRefCountObjectPtr.hxx" +#include "MEDCouplingFieldDouble.hxx" #include "MEDCouplingMemArray.hxx" -#include "MEDCouplingUMesh.hxx" #include "MEDCouplingNormalizedUnstructuredMesh.hxx" -#include "MEDCouplingFieldDouble.hxx" -#include "PointLocator3DIntersectorP0P0.hxx" - -#include "MEDCouplingAutoRefCountObjectPtr.hxx" +#include "MEDCouplingUMesh.hxx" +#include "MEDLoader.hxx" +#include "MEDLoaderBase.hxx" #ifdef HAVE_MPI #include @@ -106,7 +105,9 @@ MEDPARTITIONER::MeshCollection::MeshCollection(MeshCollection& initialCollection _joint_finder(0) { std::vector > > new2oldIds(initialCollection.getTopology()->nbDomain()); - castCellMeshes(initialCollection, new2oldIds); + std::vector o2nRenumber; + + castCellMeshes(initialCollection, new2oldIds, o2nRenumber ); //defining the name for the collection and the underlying meshes setName(initialCollection.getName()); @@ -163,7 +164,7 @@ MEDPARTITIONER::MeshCollection::MeshCollection(MeshCollection& initialCollection std::cout << "treating groups" << std::endl; _family_info=initialCollection.getFamilyInfo(); _group_info=initialCollection.getGroupInfo(); - + #ifdef HAVE_MPI if (MyGlobals::_Verbose>0 && MyGlobals::_World_Size>1) MPI_Barrier(MPI_COMM_WORLD); //synchronize verbose messages @@ -173,7 +174,7 @@ MEDPARTITIONER::MeshCollection::MeshCollection(MeshCollection& initialCollection castAllFields(initialCollection,"cellFieldDouble"); if (_i_non_empty_mesh<0) { - for (int i=0; i<_mesh.size(); i++) + for (size_t i=0; i<_mesh.size(); i++) { if (_mesh[i]) { @@ -183,16 +184,28 @@ MEDPARTITIONER::MeshCollection::MeshCollection(MeshCollection& initialCollection } } + // find faces common with neighbor domains and put them in groups + buildBoundaryFaces(); + + //building the connect zones necessary for writing joints + buildConnectZones( nodeMapping, o2nRenumber, initialCollection.getTopology()->nbDomain() ); + + // delete o2nRenumber + for ( size_t i = 0; i < o2nRenumber.size(); ++i ) + if ( o2nRenumber[i] ) + o2nRenumber[i]->decrRef(); } /*! - Creates the meshes using the topology underlying he mesh collection and the mesh data + Creates the meshes using the topology underlying he mesh collection and the mesh data coming from the ancient collection \param initialCollection collection from which the data is extracted to create the new meshes + \param [out] o2nRenumber returns for each new domain a permutation array returned by sortCellsInMEDFileFrmt() */ void MEDPARTITIONER::MeshCollection::castCellMeshes(MeshCollection& initialCollection, - std::vector > >& new2oldIds) + std::vector > >& new2oldIds, + std::vector & o2nRenumber) { if (MyGlobals::_Verbose>10) std::cout << "proc " << MyGlobals::_Rank << " : castCellMeshes" << std::endl; @@ -203,6 +216,7 @@ void MEDPARTITIONER::MeshCollection::castCellMeshes(MeshCollection& initialColle int nbOldDomain=initialCollection.getTopology()->nbDomain(); _mesh.resize(nbNewDomain); + o2nRenumber.resize(nbNewDomain,0); int rank=MyGlobals::_Rank; //splitting the initial domains into smaller bits std::vector > splitMeshes; @@ -266,22 +280,23 @@ void MEDPARTITIONER::MeshCollection::castCellMeshes(MeshCollection& initialColle for (int inew=0; inew meshes; - + for (int i=0; i<(int)splitMeshes[inew].size(); i++) - if (splitMeshes[inew][i]!=0) + if (splitMeshes[inew][i]!=0) if (splitMeshes[inew][i]->getNumberOfCells()>0) meshes.push_back(splitMeshes[inew][i]); - if (!isParallelMode()||_domain_selector->isMyDomain(inew)) + if (!isParallelMode()||_domain_selector->isMyDomain(inew)) + { + if (meshes.size()==0) { - if (meshes.size()==0) - { _mesh[inew]=CreateEmptyMEDCouplingUMesh(); std::cout << "WARNING : castCellMeshes fusing : no meshes try another number of processors" << std::endl; } else { _mesh[inew]=ParaMEDMEM::MEDCouplingUMesh::MergeUMeshes(meshes); + o2nRenumber[inew]=_mesh[inew]->sortCellsInMEDFileFrmt(); bool areNodesMerged; int nbNodesMerged; if (meshes.size()>1) @@ -290,7 +305,6 @@ void MEDPARTITIONER::MeshCollection::castCellMeshes(MeshCollection& initialColle array->decrRef(); // array is not used in this case } _mesh[inew]->zipCoords(); - } } for (int i=0;i<(int)splitMeshes[inew].size();i++) @@ -302,7 +316,7 @@ void MEDPARTITIONER::MeshCollection::castCellMeshes(MeshCollection& initialColle } /*! - \param initialCollection source mesh collection + \param initialCollection source mesh collection \param nodeMapping structure containing the correspondency between nodes in the initial collection and the node(s) in the new collection */ void MEDPARTITIONER::MeshCollection::createNodeMapping( MeshCollection& initialCollection, NodeMapping& nodeMapping) @@ -936,6 +950,323 @@ void MEDPARTITIONER::MeshCollection::remapDoubleField(int inew, int iold, } } +namespace +{ + using namespace ParaMEDMEM; + //================================================================================ + /*! + * \brief Sort correspondence ids of one domain and permute ids of the other accordingly + * \param [in,out] ids1 - ids of one domain + * \param [in,out] ids2 - ids of another domain + * \param [in] delta - a delta to change all ids + * \param [in] removeEqual - to remove equal ids + * \return DataArrayInt* - array of ids joined back + */ + //================================================================================ + + DataArrayInt* sortCorrespondences( DataArrayInt* ids1, + DataArrayInt* ids2, + int delta, + bool removeEqual = false) + { + // sort + MEDCouplingAutoRefCountObjectPtr< DataArrayInt > renumN2O = ids1->buildPermArrPerLevel(); + ids1->renumberInPlaceR( renumN2O->begin() ); + ids2->renumberInPlaceR( renumN2O->begin() ); + + if ( removeEqual ) + { + ids1 = ids1->buildUnique(); + ids2 = ids2->buildUnique(); + } + if ( delta != 0 ) + { + int * id = ids1->getPointer(); + for ( ; id < ids1->end(); ++id ) + ++(*id); + id = ids2->getPointer(); + for ( ; id < ids2->end(); ++id ) + ++(*id); + } + + // join + DataArrayInt* ids12 = DataArrayInt::Meld( ids1, ids2 ); // two components + ids12->rearrange( 1 ); // make one component + return ids12; + } + + //================================================================================ + /*! + * \brief Renumber ids according to mesh->sortCellsInMEDFileFrmt() + * \param [in,out] ids - cell ids to renumber + * \param [in] o2nRenumber - renumbering array in "Old to New" mode + */ + //================================================================================ + + void renumber( DataArrayInt* ids, const DataArrayInt* o2nRenumber ) + { + if ( !ids || !o2nRenumber ) + return; + int * id = ids->getPointer(); + const int * o2n = o2nRenumber->getConstPointer(); + for ( ; id < ids->end(); ++id ) + { + *id = o2n[ *id ]; + } + } +} + +//================================================================================ +/*! + * \brief Fill up ConnectZone's stored in _topology with nodal correspondences + * \param [in] nodeMapping - mapping between old nodes and new nodes + * (iolddomain,ioldnode)->(inewdomain,inewnode) + * \param [in] o2nRenumber - renumbering array returned by mesh->sortCellsInMEDFileFrmt() + * per a new domain + * \param [in] nbInitialDomains - nb of old domains + */ +//================================================================================ + +void MEDPARTITIONER::MeshCollection::buildConnectZones( const NodeMapping& nodeMapping, + const std::vector & o2nRenumber, + int nbInitialDomains) +{ + if ( !MyGlobals::_Create_Joints || _topology->nbDomain() < 2 ) + return; + + if ( MyGlobals::_World_Size > 1 ) + { + _topology->getCZ().clear(); + return; // not implemented for parallel mode + } + + // at construction, _topology creates cell correspondences basing on Graph information, + // and here we + // 1) add node correspondences, + // 2) split cell correspondences by cell geometry types + // 3) sort ids to be in ascending order + + const int nb_domains = _topology->nbDomain(); + + // ================================== + // 1) add node correspondences + // ================================== + + std::vector< std::vector< std::vector< int > > > nodeCorresp( nb_domains ); + for ( int idomain = 0; idomain < nb_domains; ++idomain ) + { + nodeCorresp[ idomain ].resize( nb_domains ); + } + + NodeMapping::const_iterator nmIt1, nmIt2 = nodeMapping.begin(); + for ( nmIt1 = nmIt2; nmIt1 != nodeMapping.end(); nmIt1 = nmIt2 ) + { + // look for an "old" node mapped into several "new" nodes in different domains + int nbSameOld = 0; + while ( ++nmIt2 != nodeMapping.end() && nmIt2->first == nmIt1->first ) + nbSameOld += ( nmIt2->second != nmIt1->second ); + + if ( nbSameOld > 0 ) + { + NodeMapping::const_iterator nmEnd = nmIt2; + for ( ; true; ++nmIt1 ) + { + nmIt2 = nmIt1; + if ( ++nmIt2 == nmEnd ) + break; + int dom1 = nmIt1->second.first; + int node1 = nmIt1->second.second; + for ( ; nmIt2 != nmEnd; ++nmIt2 ) + { + int dom2 = nmIt2->second.first; + int node2 = nmIt2->second.second; + if ( dom1 != dom2 ) + { + nodeCorresp[ dom1 ][ dom2 ].push_back( node1 ); + nodeCorresp[ dom1 ][ dom2 ].push_back( node2 ); + nodeCorresp[ dom2 ][ dom1 ].push_back( node2 ); + nodeCorresp[ dom2 ][ dom1 ].push_back( node1 ); + } + } + } + } + } + + // add nodeCorresp to czVec + + std::vector& czVec = _topology->getCZ(); + + for ( int idomain = 0; idomain < nb_domains; ++idomain ) + { + for ( int idomainNear = 0; idomainNear < nb_domains; ++idomainNear ) + { + std::vector< int > & corresp = nodeCorresp[ idomain ][ idomainNear ]; + if ( corresp.empty() ) + continue; + + MEDPARTITIONER::ConnectZone* cz = 0; + for ( size_t i = 0; i < czVec.size() && !cz; ++i ) + if ( czVec[i] && + czVec[i]->getLocalDomainNumber () == idomain && + czVec[i]->getDistantDomainNumber() == idomainNear ) + cz = czVec[i]; + + if ( !cz ) + { + cz = new MEDPARTITIONER::ConnectZone(); + cz->setName( "Nodal Connect Zone defined by MEDPARTITIONER" ); + cz->setLocalDomainNumber ( idomain ); + cz->setDistantDomainNumber( idomainNear ); + czVec.push_back(cz); + } + + cz->setNodeCorresp( &corresp[0], corresp.size()/2 ); + } + } + + // ========================================================== + // 2) split cell correspondences by cell geometry types + // ========================================================== + + for ( size_t i = 0; i < czVec.size(); ++i ) + { + MEDPARTITIONER::ConnectZone* cz = czVec[i]; + if ( !cz || + cz->getEntityCorrespNumber( 0,0 ) == 0 || + cz->getLocalDomainNumber () > (int)_mesh.size() || + cz->getDistantDomainNumber() > (int)_mesh.size() ) + continue; + ParaMEDMEM::MEDCouplingUMesh* mesh1 = _mesh[ cz->getLocalDomainNumber () ]; + ParaMEDMEM::MEDCouplingUMesh* mesh2 = _mesh[ cz->getDistantDomainNumber() ]; + + // separate ids of two domains + const ParaMEDMEM::MEDCouplingSkyLineArray *corrArray = cz->getEntityCorresp( 0, 0 ); + const DataArrayInt* ids12 = corrArray->getValueArray(); + MEDCouplingAutoRefCountObjectPtr ids1, ids2, ids12Sorted; + ids1 = ids12->selectByTupleId2( 0, corrArray->getLength(), 2 ); + ids2 = ids12->selectByTupleId2( 1, corrArray->getLength(), 2 ); + + // renumber cells according to mesh->sortCellsInMEDFileFrmt() + renumber( ids1, o2nRenumber[ cz->getLocalDomainNumber() ]); + renumber( ids2, o2nRenumber[ cz->getDistantDomainNumber() ]); + + // check nb cell types + std::set types1, types2; + types1 = mesh1->getTypesOfPart( ids1->begin(), ids1->end() ); + types2 = mesh2->getTypesOfPart( ids2->begin(), ids2->end() ); + if ( types1.size() < 1 || types2.size() < 1 ) + continue; // parallel mode? + + MEDPARTITIONER::ConnectZone* cz21 = 0; // zone 2 -> 1 + for ( size_t j = 0; j < czVec.size() && !cz21; ++j ) + if ( czVec[j] && + czVec[j]->getLocalDomainNumber () == cz->getDistantDomainNumber() && + czVec[j]->getDistantDomainNumber() == cz->getLocalDomainNumber() ) + cz21 = czVec[j]; + + if ( types1.size() == 1 && types2.size() == 1 ) // split not needed, only sort + { + ids12Sorted = sortCorrespondences( ids1, ids2, /*delta=*/1 ); + cz->setEntityCorresp( *types1.begin(), *types2.begin(), + ids12Sorted->begin(), ids12Sorted->getNbOfElems() / 2 ); + + if ( cz21 )// set 2->1 correspondence + { + ids12Sorted = sortCorrespondences( ids2, ids1, /*delta=*/0 ); + cz21->setEntityCorresp( *types2.begin(), *types1.begin(), + ids12Sorted->begin(), ids12Sorted->getNbOfElems() / 2 ); + } + } + else // split and sort + { + typedef std::pair< std::vector< int >, std::vector< int > > T2Vecs; + T2Vecs idsByType[ INTERP_KERNEL::NORM_MAXTYPE ][ INTERP_KERNEL::NORM_MAXTYPE ]; + int t1, t2; + + const int nbIds = ids1->getNbOfElems(); + const int * p1 = ids1->begin(), * p2 = ids2->begin(); + for ( int i = 0; i < nbIds; ++i ) + { + t1 = mesh1->getTypeOfCell( p1[ i ]); + t2 = mesh2->getTypeOfCell( p2[ i ]); + T2Vecs & ids = idsByType[ t1 ][ t2 ]; + ids.first .push_back( p1[ i ]); + ids.second.push_back( p1[ i ]); + } + + const int maxType = int( INTERP_KERNEL::NORM_MAXTYPE ); + for ( t1 = 0; t1 < maxType; ++t1 ) + for ( t2 = 0; t2 < maxType; ++t2 ) + { + T2Vecs & ids = idsByType[ t1 ][ t2 ]; + if ( ids.first.empty() ) continue; + p1 = & ids.first[0]; + p2 = & ids.second[0]; + ids1->desallocate(); + ids1->pushBackValsSilent( p1, p1+ids.first.size() ); + ids2->desallocate(); + ids2->pushBackValsSilent( p2, p2+ids.first.size() ); + ids12Sorted = sortCorrespondences( ids1, ids2, /*delta=*/1 ); + + cz->setEntityCorresp( t1, t2, + ids12Sorted->begin(), ids12Sorted->getNbOfElems() / 2 ); + + if ( cz21 )// set 2->1 correspondence + { + ids12Sorted = sortCorrespondences( ids2, ids1, /*delta=*/0 ); + cz21->setEntityCorresp( t2, t1, + ids12Sorted->begin(), ids12Sorted->getNbOfElems() / 2 ); + break; + } + } + }// split and sort + + cz->setEntityCorresp( 0, 0, 0, 0 ); // erase ids computed by _topology + if ( cz21 ) + cz21->setEntityCorresp( 0, 0, 0, 0 ); + + } // loop on czVec + + + // ========================================== + // 3) sort node ids to be in ascending order + // ========================================== + + const bool removeEqual = ( nbInitialDomains > 1 ); + + for ( size_t i = 0; i < czVec.size(); ++i ) + { + MEDPARTITIONER::ConnectZone* cz = czVec[i]; + if ( !cz || cz->getNodeNumber() < 1 ) + continue; + if ( cz->getDistantDomainNumber() < cz->getLocalDomainNumber() ) + continue; // treat a pair of domains once + + MEDPARTITIONER::ConnectZone* cz21 = 0; // zone 2 -> 1 + for ( size_t j = 0; j < czVec.size() && !cz21; ++j ) + if ( czVec[j] && + czVec[j]->getLocalDomainNumber () == cz->getDistantDomainNumber() && + czVec[j]->getDistantDomainNumber() == cz->getLocalDomainNumber() ) + cz21 = czVec[j]; + + // separate ids of two domains + const ParaMEDMEM::MEDCouplingSkyLineArray *corrArray = cz->getNodeCorresp(); + const DataArrayInt *ids12 = corrArray->getValueArray(); + MEDCouplingAutoRefCountObjectPtr ids1, ids2, ids12Sorted; + ids1 = ids12->selectByTupleId2( 0, corrArray->getLength(), 2 ); + ids2 = ids12->selectByTupleId2( 1, corrArray->getLength(), 2 ); + + ids12Sorted = sortCorrespondences( ids1, ids2, /*delta=*/0, removeEqual ); + cz->setNodeCorresp( ids12Sorted->begin(), ids12Sorted->getNbOfElems() / 2 ); + + if ( cz21 )// set 2->1 correspondence + { + ids12Sorted = sortCorrespondences( ids2, ids1, /*delta=*/0, false ); + cz->setNodeCorresp( ids12Sorted->begin(), ids12Sorted->getNbOfElems() / 2 ); + } + } +} + //================================================================================ /*! * \brief Find faces common with neighbor domains and put them in "JOINT_n_p_Faces" @@ -943,8 +1274,11 @@ void MEDPARTITIONER::MeshCollection::remapDoubleField(int inew, int iold, */ //================================================================================ -void MEDPARTITIONER::MeshCollection::buildConnectZones() +void MEDPARTITIONER::MeshCollection::buildBoundaryFaces() { + if (_topology->nbDomain() < 2 || !_subdomain_boundary_creates ) + return; + if ( getMeshDimension() < 2 ) return; @@ -1129,7 +1463,7 @@ void MEDPARTITIONER::MeshCollection::createJointGroup( const std::vector< int >& // remove faces from the familyID-the family if ( familyID != 0 && famIDs ) - for ( size_t i = 0; i < totalNbFaces; ++i ) + for ( int i = 0; i < totalNbFaces; ++i ) if ( famIDs[i] == familyID ) famIDs[i] = 0; @@ -1441,9 +1775,6 @@ MEDPARTITIONER::MeshCollection::~MeshCollection() */ void MEDPARTITIONER::MeshCollection::write(const std::string& filename) { - //building the connect zones necessary for writing joints - if (_topology->nbDomain()>1 && _subdomain_boundary_creates ) - buildConnectZones(); //suppresses link with driver so that it can be changed for writing delete _driver; _driver=0; @@ -1491,7 +1822,7 @@ int MEDPARTITIONER::MeshCollection::getMeshDimension() const int MEDPARTITIONER::MeshCollection::getNbOfLocalMeshes() const { int nb=0; - for (int i=0; i<_mesh.size(); i++) + for (size_t i=0; i<_mesh.size(); i++) { if (_mesh[i]) nb++; } @@ -1501,7 +1832,7 @@ int MEDPARTITIONER::MeshCollection::getNbOfLocalMeshes() const int MEDPARTITIONER::MeshCollection::getNbOfLocalCells() const { int nb=0; - for (int i=0; i<_mesh.size(); i++) + for (size_t i=0; i<_mesh.size(); i++) { if (_mesh[i]) nb=nb+_mesh[i]->getNumberOfCells(); } @@ -1511,7 +1842,7 @@ int MEDPARTITIONER::MeshCollection::getNbOfLocalCells() const int MEDPARTITIONER::MeshCollection::getNbOfLocalFaces() const { int nb=0; - for (int i=0; i<_face_mesh.size(); i++) + for (size_t i=0; i<_face_mesh.size(); i++) { if (_face_mesh[i]) nb=nb+_face_mesh[i]->getNumberOfCells(); } @@ -1540,7 +1871,11 @@ ParaMEDMEM::MEDCouplingUMesh* MEDPARTITIONER::MeshCollection::getFaceMesh(int id std::vector& MEDPARTITIONER::MeshCollection::getCZ() { - return _connect_zones; + if ( _topology ) + return _topology->getCZ(); + + static std::vector noCZ; + return noCZ; } MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::getTopology() const @@ -1548,23 +1883,26 @@ MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::getTopology() const return _topology; } -void MEDPARTITIONER::MeshCollection::setTopology(Topology* topo) +void MEDPARTITIONER::MeshCollection::setTopology(Topology* topo, bool takeOwneship) { if (_topology!=0) { throw INTERP_KERNEL::Exception("topology is already set"); } else - _topology = topo; + { + _topology = topo; + _owns_topology = takeOwneship; + } } -/*! Method creating the cell graph in serial mode - * - * \param array returns the pointer to the structure that contains the graph +/*! Method creating the cell graph in serial mode + * + * \param array returns the pointer to the structure that contains the graph * \param edgeweight returns the pointer to the table that contains the edgeweights * (only used if indivisible regions are required) */ -void MEDPARTITIONER::MeshCollection::buildCellGraph(MEDPARTITIONER::SkyLineArray* & array, int *& edgeweights ) +void MEDPARTITIONER::MeshCollection::buildCellGraph(ParaMEDMEM::MEDCouplingSkyLineArray* & array, int *& edgeweights ) { using std::map; @@ -1583,106 +1921,10 @@ void MEDPARTITIONER::MeshCollection::buildCellGraph(MEDPARTITIONER::SkyLineArray vector value; vector index(1,0); - array=new MEDPARTITIONER::SkyLineArray(index,value); + array=new ParaMEDMEM::MEDCouplingSkyLineArray(index,value); return; } - - int meshDim = mesh->getMeshDimension(); - - ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New(); - ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New(); - int nbNodes=mesh->getNumberOfNodes(); - mesh->getReverseNodalConnectivity(revConn,indexr); - //problem saturation over 1 000 000 nodes for 1 proc - if (MyGlobals::_Verbose>100) - std::cout << "proc " << MyGlobals::_Rank << " : getReverseNodalConnectivity done on " << nbNodes << " nodes" << std::endl; - const int* indexr_ptr=indexr->getConstPointer(); - const int* revConn_ptr=revConn->getConstPointer(); - - const ParaMEDMEM::DataArrayInt* index; - const ParaMEDMEM::DataArrayInt* conn; - conn=mesh->getNodalConnectivity(); - index=mesh->getNodalConnectivityIndex(); - int nbCells=mesh->getNumberOfCells(); - - if (MyGlobals::_Verbose>100) - std::cout << "proc " << MyGlobals::_Rank << " : getNodalConnectivity done on " << nbNodes << " nodes" << std::endl; - const int* index_ptr=index->getConstPointer(); - const int* conn_ptr=conn->getConstPointer(); - - //creating graph arcs (cell to cell relations) - //arcs are stored in terms of (index,value) notation - // 0 3 5 6 6 - // 1 2 3 2 3 3 - // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3) - // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell - - //warning here one node have less than or equal effective number of cell with it - //but cell could have more than effective nodes - //because other equals nodes in other domain (with other global inode) - if (MyGlobals::_Verbose>50) - std::cout<< "proc " << MyGlobals::_Rank << " : creating graph arcs on nbNodes " << _topology->nbNodes() << std::endl; - - vector cell2cell_index(nbCells+1,0); - vector cell2cell; - cell2cell.reserve(3*nbCells); - - for (int icell=0; icell counter; - for (int iconn=index_ptr[icell]; iconn::iterator iter=counter.find(icell2); - if (iter!=counter.end()) (iter->second)++; - else counter.insert(make_pair(icell2,1)); - } - } - for (map::const_iterator iter=counter.begin(); - iter!=counter.end(); - iter++) - if (iter->second >= meshDim) - { - cell2cell_index[icell+1]++; - cell2cell.push_back(iter->first); - } - - - } - indexr->decrRef(); - revConn->decrRef(); - - cell2cell_index[0]=0; - for (int icell=0; icell50) - std::cout << "proc " << MyGlobals::_Rank << " : create skylinearray" << std::endl; - - //filling up index and value to create skylinearray structure - array=new MEDPARTITIONER::SkyLineArray(cell2cell_index,cell2cell); - - if (MyGlobals::_Verbose>100) - { - std::cout << "\nproc " << _domain_selector->rank() << " : end MeshCollection::buildCellGraph " << - cell2cell_index.size()-1 << " " << cell2cell.size() << std::endl; - int max=cell2cell_index.size()>15?15:cell2cell_index.size(); - if (cell2cell_index.size()>1) - { - for (int i=0; igenerateGraph(); } /*! Method creating the cell graph in multidomain mode * @@ -1690,7 +1932,7 @@ void MEDPARTITIONER::MeshCollection::buildCellGraph(MEDPARTITIONER::SkyLineArray * \param edgeweight returns the pointer to the table that contains the edgeweights * (only used if indivisible regions are required) */ -void MEDPARTITIONER::MeshCollection::buildParallelCellGraph(MEDPARTITIONER::SkyLineArray* & array, int *& edgeweights ) +void MEDPARTITIONER::MeshCollection::buildParallelCellGraph(ParaMEDMEM::MEDCouplingSkyLineArray* & array, int *& edgeweights ) { using std::multimap; using std::vector; @@ -1858,7 +2100,7 @@ void MEDPARTITIONER::MeshCollection::buildParallelCellGraph(MEDPARTITIONER::SkyL } } - array=new MEDPARTITIONER::SkyLineArray(index,value); + array=new ParaMEDMEM::MEDCouplingSkyLineArray(index,value); if (MyGlobals::_Verbose>100) { @@ -1887,44 +2129,44 @@ void MEDPARTITIONER::MeshCollection::buildParallelCellGraph(MEDPARTITIONER::SkyL * returns a topology based on the new graph */ MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::createPartition(int nbdomain, - Graph::splitter_type split, + Graph::splitter_type split, const std::string& options_string, int *user_edge_weights, int *user_vertices_weights) { if (MyGlobals::_Verbose>10) std::cout << "proc " << MyGlobals::_Rank << " : MeshCollection::createPartition : Building cell graph" << std::endl; - + if (nbdomain <1) throw INTERP_KERNEL::Exception("Number of subdomains must be > 0"); - MEDPARTITIONER::SkyLineArray* array=0; + ParaMEDMEM::MEDCouplingSkyLineArray* array=0; int* edgeweights=0; if (_topology->nbDomain()>1 || isParallelMode()) buildParallelCellGraph(array,edgeweights); else buildCellGraph(array,edgeweights); - + Graph* cellGraph = 0; switch (split) { case Graph::METIS: if ( isParallelMode() && MyGlobals::_World_Size > 1 ) - { + { #ifdef MED_ENABLE_PARMETIS - if (MyGlobals::_Verbose>10) - std::cout << "ParMETISGraph" << std::endl; - cellGraph=new ParMETISGraph(array,edgeweights); + if (MyGlobals::_Verbose>10) + std::cout << "ParMETISGraph" << std::endl; + cellGraph=new ParMETISGraph(array,edgeweights); #endif - } + } if ( !cellGraph ) - { + { #ifdef MED_ENABLE_METIS - if (MyGlobals::_Verbose>10) - std::cout << "METISGraph" << std::endl; - cellGraph=new METISGraph(array,edgeweights); + if (MyGlobals::_Verbose>10) + std::cout << "METISGraph" << std::endl; + cellGraph=new METISGraph(array,edgeweights); #endif - } + } if ( !cellGraph ) throw INTERP_KERNEL::Exception("MeshCollection::createPartition : PARMETIS/METIS is not available. Check your products, please."); break; @@ -1971,7 +2213,7 @@ MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::createPartition(int nb */ MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::createPartition(const int* partition) { - MEDPARTITIONER::SkyLineArray* array=0; + ParaMEDMEM::MEDCouplingSkyLineArray* array=0; int* edgeweights=0; if ( _topology->nbDomain()>1) @@ -2052,6 +2294,10 @@ void MEDPARTITIONER::MeshCollection::prepareFieldDescriptions() //filter _field_descriptions to be in all procs compliant and equal { int nbfiles=MyGlobals::_File_Names.size(); //nb domains + if (nbfiles==0) + { + nbfiles=_topology->nbDomain(); + } std::vector r2; //from allgatherv then vector(procs) of serialised vector(fields) of vector(description) data for (int i=0; i<(int)_field_descriptions.size(); i++) diff --git a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx index 04a7083b2..a4eec9a4c 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx @@ -36,6 +36,7 @@ namespace ParaMEDMEM { class MEDCouplingUMesh; class DataArrayInt; + class MEDCouplingSkyLineArray; } namespace MEDPARTITIONER @@ -43,7 +44,6 @@ namespace MEDPARTITIONER class Topology; class MeshCollectionDriver; class ParaDomainSelector; - class SkyLineArray; class ConnectZone; class JointFinder; @@ -75,9 +75,9 @@ namespace MEDPARTITIONER void setDriverType(MEDPARTITIONER::DriverType type) { _driver_type=type; } //creation of the cell graph - void buildCellGraph(MEDPARTITIONER::SkyLineArray* & array,int *& edgeweights ); + void buildCellGraph(ParaMEDMEM::MEDCouplingSkyLineArray* & array,int *& edgeweights ); //creation of the cell graph - void buildParallelCellGraph(MEDPARTITIONER::SkyLineArray* & array,int *& edgeweights ); + void buildParallelCellGraph(ParaMEDMEM::MEDCouplingSkyLineArray* & array,int *& edgeweights ); //creation and partition of the associated graph Topology* createPartition(int nbdomain, Graph::splitter_type type = Graph::METIS, @@ -122,8 +122,9 @@ namespace MEDPARTITIONER //getting a pointer to topology Topology* getTopology() const ; ParaDomainSelector* getParaDomainSelector() const { return _domain_selector; } + void setParaDomainSelector(ParaDomainSelector* pds) { _domain_selector = pds; } //setting a new topology - void setTopology(Topology* topology); + void setTopology(Topology* topology, bool takeOwneship); //getting/setting the name of the global mesh (as opposed //to the name of a subdomain \a nn, which is name_nn) @@ -131,6 +132,8 @@ namespace MEDPARTITIONER void setName(const std::string& name) { _name=name; } void setDomainNames(const std::string& name); + void setNonEmptyMesh(int number) { _i_non_empty_mesh=number;} + //getting/setting the description of the global mesh std::string getDescription() const { return _description; } void setDescription(const std::string& name) { _description=name; } @@ -140,7 +143,8 @@ namespace MEDPARTITIONER std::multimap,std::pair >& nodeMapping); void castCellMeshes(MeshCollection& initialCollection, - std::vector > >& new2oldIds); + std::vector > >& new2oldIds, + std::vector & o2nRenumber); //creates faces on the new collection void castFaceMeshes(MeshCollection& initialCollection, @@ -148,7 +152,12 @@ namespace MEDPARTITIONER std::vector > >& new2oldIds); //constructing connect zones - void buildConnectZones(); + void buildConnectZones( const NodeMapping& nodeMapping, + const std::vector & o2nRenumber, + int nbInitialDomains ); + + // Find faces common with neighbor domains and put them in groups + void buildBoundaryFaces(); private: void castIntField(std::vector& meshesCastFrom, @@ -199,9 +208,6 @@ namespace MEDPARTITIONER //index of a non empty mesh within _mesh (in parallel mode all of meshes can be empty) int _i_non_empty_mesh; - //links to connectzones - std::vector _connect_zones; - //family ids storages std::vector _cell_family_ids; std::vector _face_family_ids; diff --git a/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.cxx b/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.cxx index 7c0358e56..f13015f77 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.cxx @@ -17,16 +17,21 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -#include "MEDPARTITIONER_ParallelTopology.hxx" #include "MEDPARTITIONER_MeshCollectionDriver.hxx" + +#include "MEDPARTITIONER_ConnectZone.hxx" #include "MEDPARTITIONER_MeshCollection.hxx" #include "MEDPARTITIONER_ParaDomainSelector.hxx" +#include "MEDPARTITIONER_ParallelTopology.hxx" #include "MEDPARTITIONER_Utils.hxx" -#include "MEDCouplingUMesh.hxx" #include "MEDCouplingFieldDouble.hxx" -#include "MEDLoader.hxx" +#include "MEDCouplingRefCountObject.hxx" +#include "MEDCouplingUMesh.hxx" +#include "MEDFileField.hxx" +#include "MEDFileJoint.hxx" #include "MEDFileMesh.hxx" +#include "MEDLoader.hxx" #include #include @@ -77,112 +82,71 @@ int MeshCollectionDriver::readSeq(const char* filename, const char* meshname) (_collection->getCZ()).clear(); ParallelTopology* aPT = new ParallelTopology((_collection->getMesh())); - _collection->setTopology(aPT); + _collection->setTopology(aPT, true); _collection->setName(meshname); _collection->setDomainNames(meshname); return 0; } -//================================================================================ -/*! - * \brief Return mesh dimension from distributed med file had being read - */ -//================================================================================ - -void MeshCollectionDriver::readSubdomain(std::vector& cellglobal, - std::vector& faceglobal, - std::vector& nodeglobal, int idomain) +void MeshCollectionDriver::readMEDFileData(const ParaMEDMEM::MEDFileData* filedata) { - std::string meshname=MyGlobals::_Mesh_Names[idomain]; - std::string file=MyGlobals::_File_Names[idomain]; + const int nbDomains = filedata->getMeshes()->getNumberOfMeshes(); + _collection->getMesh() .resize( nbDomains, 0 ); + _collection->getFaceMesh() .resize( nbDomains, 0 ); + _collection->getCellFamilyIds().resize( nbDomains, 0 ); + _collection->getFaceFamilyIds().resize( nbDomains, 0 ); - ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(file,meshname); - std::vector nonEmpty=mfm->getNonEmptyLevels(); - - try - { - (_collection->getMesh())[idomain]=mfm->getLevel0Mesh(false); - //reading families groups - ParaMEDMEM::DataArrayInt* cellIds(mfm->getFamilyFieldAtLevel(0)->deepCpy()); - (_collection->getCellFamilyIds())[idomain]=cellIds; - } - catch(...) - { - (_collection->getMesh())[idomain]=CreateEmptyMEDCouplingUMesh(); // or 0 if you want tests; - ParaMEDMEM::DataArrayInt* empty=ParaMEDMEM::DataArrayInt::New(); - empty->alloc(0,1); - (_collection->getCellFamilyIds())[idomain]=empty; - std::cout << "\nNO Level0Mesh (Cells)\n"; + for (int i=0; i(filedata->getMeshes()->getMeshAtPos(i)); + readData(mfm,i); + if ( mfm && mfm->getMeshDimension() > 0 ) + _collection->setNonEmptyMesh( i ); } - try - { - if (nonEmpty.size()>1 && nonEmpty[1]==-1) - { - (_collection->getFaceMesh())[idomain]=mfm->getLevelM1Mesh(false); - //reading families groups - ParaMEDMEM::DataArrayInt* faceIds(mfm->getFamilyFieldAtLevel(-1)->deepCpy()); - (_collection->getFaceFamilyIds())[idomain]=faceIds; - if (MyGlobals::_Verbose>10) - std::cout << "proc " << MyGlobals::_Rank << " : WITH Faces\n"; - } - else - { - throw INTERP_KERNEL::Exception("no faces"); - } - } - catch(...) + ParallelTopology* aPT = new ParallelTopology(_collection->getMesh()); + _collection->setTopology(aPT, true); + if ( nbDomains > 0 ) { - (_collection->getFaceMesh())[idomain]=CreateEmptyMEDCouplingUMesh(); // or 0 if you want test; - ParaMEDMEM::DataArrayInt* empty=ParaMEDMEM::DataArrayInt::New(); - (_collection->getFaceFamilyIds())[idomain]=empty; - if (MyGlobals::_Verbose>10) - std::cout << "proc " << MyGlobals::_Rank << " : WITHOUT Faces\n"; + _collection->setName( filedata->getMeshes()->getMeshAtPos(0)->getName() ); + _collection->setDomainNames( _collection->getName() ); } - - //reading groups - _collection->getFamilyInfo()=mfm->getFamilyInfo(); - _collection->getGroupInfo()=mfm->getGroupInfo(); + if ( ParaDomainSelector* domainSelector = _collection->getParaDomainSelector() ) + if ( _collection->isParallelMode() ) + { + //to know nb of cells on each proc to compute global cell ids from locally global + domainSelector->gatherNbOf(_collection->getMesh()); + } +} +void MeshCollectionDriver::readFileData(std::string file,std::string meshname,int idomain) const +{ + ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(file,meshname); + readData(mfm,idomain); mfm->decrRef(); - - std::vector localInformation; - std::string str; - localInformation.push_back(str+"ioldDomain="+IntToStr(idomain)); - localInformation.push_back(str+"meshName="+meshname); - MyGlobals::_General_Informations.push_back(SerializeFromVectorOfString(localInformation)); - std::vector localFields=BrowseAllFieldsOnMesh(file, meshname, idomain); - if (localFields.size()>0) - MyGlobals::_Field_Descriptions.push_back(SerializeFromVectorOfString(localFields)); } - -void MeshCollectionDriver::readSubdomain(int idomain) +void MeshCollectionDriver::readData(ParaMEDMEM::MEDFileUMesh* mfm, int idomain) const { - std::string meshname=MyGlobals::_Mesh_Names[idomain]; - std::string file=MyGlobals::_File_Names[idomain]; - - ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(file,meshname); std::vector nonEmpty=mfm->getNonEmptyLevels(); - - try - { - (_collection->getMesh())[idomain]=mfm->getLevel0Mesh(false); + try + { + (_collection->getMesh())[idomain]=mfm->getLevel0Mesh(false); //reading families groups ParaMEDMEM::DataArrayInt* cellIds(mfm->getFamilyFieldAtLevel(0)->deepCpy()); (_collection->getCellFamilyIds())[idomain]=cellIds; } catch(...) - { + { (_collection->getMesh())[idomain]=CreateEmptyMEDCouplingUMesh(); // or 0 if you want tests; ParaMEDMEM::DataArrayInt* empty=ParaMEDMEM::DataArrayInt::New(); empty->alloc(0,1); (_collection->getCellFamilyIds())[idomain]=empty; std::cout<<"\nNO Level0Mesh (Cells)\n"; } - try - { + try + { if (nonEmpty.size()>1 && nonEmpty[1]==-1) { (_collection->getFaceMesh())[idomain]=mfm->getLevelM1Mesh(false); @@ -205,12 +169,16 @@ void MeshCollectionDriver::readSubdomain(int idomain) if (MyGlobals::_Verbose>10) std::cout << "proc " << MyGlobals::_Rank << " : WITHOUT Faces\n"; } - //reading groups _collection->getFamilyInfo()=mfm->getFamilyInfo(); _collection->getGroupInfo()=mfm->getGroupInfo(); +} - mfm->decrRef(); +void MeshCollectionDriver::readSubdomain(int idomain) +{ + std::string meshname=MyGlobals::_Mesh_Names[idomain]; + std::string file=MyGlobals::_File_Names[idomain]; + readFileData(file,meshname,idomain); std::vector localInformation; std::string str; @@ -218,19 +186,16 @@ void MeshCollectionDriver::readSubdomain(int idomain) localInformation.push_back(str+"meshName="+meshname); MyGlobals::_General_Informations.push_back(SerializeFromVectorOfString(localInformation)); std::vector localFields=BrowseAllFieldsOnMesh(file, meshname, idomain); - if (localFields.size()>0) + if (localFields.size()>0) MyGlobals::_Field_Descriptions.push_back(SerializeFromVectorOfString(localFields)); } - -void MeshCollectionDriver::writeMedFile(int idomain, const std::string& distfilename) const +ParaMEDMEM::MEDFileMesh* MeshCollectionDriver::getMesh(int idomain) const { - std::vector meshes; + ParaMEDMEM::MEDFileUMesh* mfm = ParaMEDMEM::MEDFileUMesh::New(); + ParaMEDMEM::MEDCouplingUMesh* cellMesh=_collection->getMesh(idomain); ParaMEDMEM::MEDCouplingUMesh* faceMesh=_collection->getFaceMesh(idomain); - //ParaMEDMEM::MEDCouplingUMesh* faceMeshFilter=0; - - std::string finalMeshName=ExtractFromDescription(MyGlobals::_General_Informations[0], "finalMeshName="); // std::string cleFilter=Cle1ToStr("filterFaceOnCell",idomain); // ParaMEDMEM::DataArrayInt* filter=0; // if (_collection->getMapDataArrayInt().find(cleFilter)!=_collection->getMapDataArrayInt().end()) @@ -240,97 +205,160 @@ void MeshCollectionDriver::writeMedFile(int idomain, const std::string& distfile // faceMeshFilter=(ParaMEDMEM::MEDCouplingUMesh *) faceMesh->buildPartOfMySelf(index,index+filter->getNbOfElems(),true); // faceMesh=faceMeshFilter; // } + // if (faceMeshFilter!=0) + // faceMeshFilter->decrRef(); + std::string finalMeshName=""; + if (MyGlobals::_General_Informations.size()!=0) + { + std::size_t found=MyGlobals::_General_Informations[0].find("finalMeshName="); + if ((found!=std::string::npos) && (found>0)) + { + finalMeshName=ExtractFromDescription(MyGlobals::_General_Informations[0], "finalMeshName="); + } + } + if (finalMeshName.empty()) + { + finalMeshName=_collection->getName(); + } cellMesh->setName(finalMeshName); - meshes.push_back(cellMesh); - + mfm->setMeshAtLevel( 0, cellMesh ); + faceMesh->checkCoherency(); if (faceMesh->getNumberOfCells()>0) { faceMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-10); - meshes.push_back(faceMesh); + faceMesh->setName(finalMeshName); + mfm->setMeshAtLevel( -1, faceMesh ); } - - //ParaMEDMEM::MEDCouplingUMesh* boundaryMesh=0; + + // ParaMEDMEM::MEDCouplingUMesh* boundaryMesh=0; // if (MyGlobals::_Creates_Boundary_Faces>0) // { // //try to write Boundary meshes // bool keepCoords=false; //TODO or true // boundaryMesh=(ParaMEDMEM::MEDCouplingUMesh *) cellMesh->buildBoundaryMesh(keepCoords); // boundaryMesh->setName("boundaryMesh"); - // } - - MEDLoader::WriteUMeshes(distfilename, meshes, true); - // if (faceMeshFilter!=0) - // faceMeshFilter->decrRef(); - // if (boundaryMesh!=0) // { // //doing that testMesh becomes second mesh sorted by alphabetical order of name // MEDLoader::WriteUMesh(distfilename, boundaryMesh, false); // boundaryMesh->decrRef(); // } - ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(distfilename, _collection->getMesh(idomain)->getName()); mfm->setFamilyInfo(_collection->getFamilyInfo()); mfm->setGroupInfo(_collection->getGroupInfo()); - std::string key=Cle1ToStr("faceFamily_toArray",idomain); - if ( meshes.size() == 2 && - _collection->getMapDataArrayInt().find(key)!=_collection->getMapDataArrayInt().end()) - { - ParaMEDMEM::DataArrayInt *fam=_collection->getMapDataArrayInt().find(key)->second; - mfm->setFamilyFieldArr(-1,fam); - } - + if ( faceMesh->getNumberOfCells()>0 && _collection->getMapDataArrayInt().find(key)!=_collection->getMapDataArrayInt().end()) + mfm->setFamilyFieldArr(-1,_collection->getMapDataArrayInt().find(key)->second); key=Cle1ToStr("cellFamily_toArray",idomain); if (_collection->getMapDataArrayInt().find(key)!=_collection->getMapDataArrayInt().end()) mfm->setFamilyFieldArr(0,_collection->getMapDataArrayInt().find(key)->second); - mfm->write(distfilename,0); - key="/inewFieldDouble="+IntToStr(idomain)+"/"; + // add joints - std::map::iterator it; - int nbfFieldFound=0; - for (it=_collection->getMapDataArrayDouble().begin() ; it!=_collection->getMapDataArrayDouble().end(); it++) + using ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr; + using ParaMEDMEM::MEDCouplingSkyLineArray; + using ParaMEDMEM::MEDFileJoint; + using ParaMEDMEM::MEDFileJointCorrespondence; + using ParaMEDMEM::MEDFileJointOneStep; + using ParaMEDMEM::MEDFileJoints; + using ParaMEDMEM::MEDFileJoints; + + if ( _collection->getCZ().size() > 0 ) { - std::string desc=(*it).first; - size_t found=desc.find(key); - if (found==std::string::npos) - continue; - if (MyGlobals::_Verbose>20) - std::cout << "proc " << MyGlobals::_Rank << " : write field " << desc << std::endl; - std::string meshName, fieldName; - int typeField, DT, IT, entity; - FieldShortDescriptionToData(desc, fieldName, typeField, entity, DT, IT); - double time=StrToDouble(ExtractFromDescription(desc, "time=")); - int typeData=StrToInt(ExtractFromDescription(desc, "typeData=")); - std::string entityName=ExtractFromDescription(desc, "entityName="); - ParaMEDMEM::MEDCouplingFieldDouble* field=0; - if (typeData!=6) - { - std::cout << "WARNING : writeMedFile : typeData " << typeData << " not implemented for fields\n"; - continue; - } - if (entityName=="MED_CELL") - { - //there is a field of idomain to write - field=ParaMEDMEM::MEDCouplingFieldDouble::New(ParaMEDMEM::ON_CELLS,ParaMEDMEM::ONE_TIME); - } - if (entityName=="MED_NODE_ELEMENT") - { - //there is a field of idomain to write - field=ParaMEDMEM::MEDCouplingFieldDouble::New(ParaMEDMEM::ON_GAUSS_NE,ParaMEDMEM::ONE_TIME); - } - if (!field) + MEDCouplingAutoRefCountObjectPtr< MEDFileJoints > joints = MEDFileJoints::New(); + + for ( size_t i = 0; i < _collection->getCZ().size(); ++i ) { - std::cout << "WARNING : writeMedFile : entityName " << entityName << " not implemented for fields\n"; - continue; + ConnectZone* cz = _collection->getCZ()[i]; + if ( !cz || + cz->getLocalDomainNumber() != idomain ) + continue; + { + std::ostringstream oss; + oss << "joint_" << cz->getDistantDomainNumber(); + cz->setName( oss.str() ); + } + { + std::ostringstream oss; + oss << "connect_zone_" << i; + cz->setDescription( oss.str() ); + } + + MEDCouplingAutoRefCountObjectPtr< MEDFileJoint> + joint = MEDFileJoint::New( cz->getName(), finalMeshName, + finalMeshName, cz->getDistantDomainNumber() ); + joint->setDescription( cz->getDescription() ); + joints->pushJoint( joint ); + + MEDCouplingAutoRefCountObjectPtr< MEDFileJointOneStep> j1st = MEDFileJointOneStep::New(); + joint->pushStep( j1st ); + + const MEDCouplingSkyLineArray * nodeCorr = cz->getNodeCorresp(); + if ( nodeCorr ) + { + MEDCouplingAutoRefCountObjectPtr< MEDFileJointCorrespondence > + corr = MEDFileJointCorrespondence::New( nodeCorr->getValueArray() ); + j1st->pushCorrespondence( corr ); + } + + std::vector< std::pair< int,int > > types = cz->getEntities(); + INTERP_KERNEL::NormalizedCellType t1, t2; + for ( size_t it = 0; it < types.size(); ++it ) + { + const MEDCouplingSkyLineArray * cellCorr = + cz->getEntityCorresp( types[it].first, types[it].second ); + if ( cellCorr && cellCorr->getNumberOf() > 0 ) + { + t1 = INTERP_KERNEL::NormalizedCellType( types[it].first ); + t2 = INTERP_KERNEL::NormalizedCellType( types[it].second ); + MEDCouplingAutoRefCountObjectPtr< MEDFileJointCorrespondence> + corr = MEDFileJointCorrespondence::New( cellCorr->getValueArray(), t1, t2 ); + j1st->pushCorrespondence( corr ); + } + } } - nbfFieldFound++; + mfm->setJoints( joints ); + } + + return mfm; +} + +ParaMEDMEM::MEDCouplingFieldDouble* MeshCollectionDriver::getField(std::string key, std::string description, ParaMEDMEM::DataArrayDouble* data, ParaMEDMEM::MEDFileMesh* mfm, int idomain) const +{ + std::string desc=description; + if (MyGlobals::_Verbose>20) + std::cout << "proc " << MyGlobals::_Rank << " : write field " << desc << std::endl; + std::string meshName, fieldName; + int typeField, DT, IT, entity; + FieldShortDescriptionToData(desc, fieldName, typeField, entity, DT, IT); + double time=StrToDouble(ExtractFromDescription(desc, "time=")); + int typeData=StrToInt(ExtractFromDescription(desc, "typeData=")); + std::string entityName=ExtractFromDescription(desc, "entityName="); + ParaMEDMEM::MEDCouplingFieldDouble* field=0; + if (typeData!=6) + { + std::cout << "WARNING : writeMedFile : typeData " << typeData << " not implemented for fields\n"; + } + if (entityName=="MED_CELL") + { + //there is a field of idomain to write + field=ParaMEDMEM::MEDCouplingFieldDouble::New(ParaMEDMEM::ON_CELLS,ParaMEDMEM::ONE_TIME); + } + if (entityName=="MED_NODE_ELEMENT") + { + //there is a field of idomain to write + field=ParaMEDMEM::MEDCouplingFieldDouble::New(ParaMEDMEM::ON_GAUSS_NE,ParaMEDMEM::ONE_TIME); + } + if (!field) + { + std::cout << "WARNING : writeMedFile : entityName " << entityName << " not implemented for fields\n"; + } + if (field && typeData==6) + { field->setName(fieldName); - field->setMesh(mfm->getLevel0Mesh(false)); - ParaMEDMEM::DataArrayDouble *da=(*it).second; - + field->setMesh(mfm->getGenMeshAtLevel(0)); + ParaMEDMEM::DataArrayDouble *da=data; //get information for components etc.. std::vector r1; r1=SelectTagsInVectorOfString(MyGlobals::_General_Informations,"fieldName="+fieldName); @@ -341,17 +369,36 @@ void MeshCollectionDriver::writeMedFile(int idomain, const std::string& distfile int nbc=StrToInt(ExtractFromDescription(r1[0], "nbComponents=")); if (nbc==da->getNumberOfComponents()) { - for (int i=0; isetInfoOnComponent(i,ExtractFromDescription(r1[0], "componentInfo"+IntToStr(i)+"=")); } else { std::cerr << "Problem On field " << fieldName << " : number of components unexpected " << da->getNumberOfComponents() << std::endl; } - field->setArray(da); field->setTime(time,DT,IT); field->checkCoherency(); + } + return field; +} + +void MeshCollectionDriver::writeMedFile(int idomain, const std::string& distfilename) const +{ + ParaMEDMEM::MEDFileMesh* mfm = getMesh( idomain ); + mfm->write(distfilename,2); + + std::string key="/inewFieldDouble="+IntToStr(idomain)+"/"; + std::map::iterator it; + int nbfFieldFound=0; + for (it=_collection->getMapDataArrayDouble().begin() ; it!=_collection->getMapDataArrayDouble().end(); it++) + { + size_t found=(*it).first.find(key); + if (found==std::string::npos) + continue; + ParaMEDMEM::MEDCouplingFieldDouble* field=0; + field = getField(key, (*it).first, (*it).second, mfm, idomain); + nbfFieldFound++; try { MEDLoader::WriteField(distfilename,field,false); @@ -360,6 +407,8 @@ void MeshCollectionDriver::writeMedFile(int idomain, const std::string& distfile { //cout trying rewrite all data, only one field defined std::string tmp,newName=distfilename; + std::string fieldName; + fieldName=field->getName(); tmp+="_"+fieldName+"_"+IntToStr(nbfFieldFound)+".med"; newName.replace(newName.find(".med"),4,tmp); std::cout << "WARNING : writeMedFile : create a new file name with only one field because MEDLoader::WriteField throw:" << newName << std::endl; @@ -368,3 +417,44 @@ void MeshCollectionDriver::writeMedFile(int idomain, const std::string& distfile } mfm->decrRef(); } + +ParaMEDMEM::MEDFileData* MeshCollectionDriver::getMEDFileData() +{ + ParaMEDMEM::MEDFileData* newdata = ParaMEDMEM::MEDFileData::New(); + + ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr meshes; + ParaMEDMEM::MEDCouplingAutoRefCountObjectPtr fields; + meshes = ParaMEDMEM::MEDFileMeshes::New(); + fields = ParaMEDMEM::MEDFileFields::New(); + + for (size_t i=0; i<_collection->getMesh().size(); i++) + { + ParaMEDMEM::MEDFileMesh* mfm = getMesh( i ); + meshes->pushMesh(mfm); + + std::string key="/inewFieldDouble="+IntToStr(i)+"/"; + std::map::iterator it; + ParaMEDMEM::MEDFileFieldMultiTS* fieldsMTS = ParaMEDMEM::MEDFileFieldMultiTS::New(); + for (it=_collection->getMapDataArrayDouble().begin() ; it!=_collection->getMapDataArrayDouble().end(); it++) + { + size_t found=(*it).first.find(key); + if (found==std::string::npos) + continue; + ParaMEDMEM::MEDCouplingFieldDouble* field=0; + field=getField(key, (*it).first, (*it).second, mfm, i); + ParaMEDMEM::MEDFileField1TS* f1ts = ParaMEDMEM::MEDFileField1TS::New(); + f1ts->setFieldNoProfileSBT(field); + fieldsMTS->pushBackTimeStep(f1ts); + + field->decrRef(); + f1ts->decrRef(); + } + fields->pushField(fieldsMTS); + + fieldsMTS->decrRef(); + mfm->decrRef(); + } + newdata->setMeshes(meshes); + newdata->setFields(fields); + return newdata; +} diff --git a/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.hxx b/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.hxx index d4d3a41e2..d179d17ac 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionDriver.hxx @@ -21,10 +21,15 @@ #define __MEDPARTITIONER_MESHCOLLECTIONDRIVER_HXX__ #include "MEDPARTITIONER.hxx" - +#include "MEDFileData.hxx" #include #include +namespace ParaMEDMEM +{ + class MEDFileData; +} + namespace MEDPARTITIONER { class MeshCollection; @@ -37,12 +42,15 @@ namespace MEDPARTITIONER virtual ~MeshCollectionDriver() { } virtual int read(const char*, ParaDomainSelector* sel=0) = 0; int readSeq(const char*,const char*); + ParaMEDMEM::MEDFileData *getMEDFileData(); virtual void write(const char*, ParaDomainSelector* sel=0) const = 0; + void readMEDFileData(const ParaMEDMEM::MEDFileData* filedata); protected: - void readSubdomain(std::vector& cellglobal, - std::vector& faceglobal, - std::vector& nodeglobal, int idomain); void readSubdomain(int idomain); + void readData(ParaMEDMEM::MEDFileUMesh* mfm, int idomain) const; + void readFileData(std::string file,std::string meshname,int idomain) const; + ParaMEDMEM::MEDFileMesh* getMesh(int idomain) const; + ParaMEDMEM::MEDCouplingFieldDouble* getField(std::string key, std::string description, ParaMEDMEM::DataArrayDouble* data, ParaMEDMEM::MEDFileMesh* mfm, int idomain) const; void writeMedFile(int idomain, const std::string& distfilename) const; protected: MeshCollection* _collection; diff --git a/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionMedAsciiDriver.cxx b/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionMedAsciiDriver.cxx index b1ab04cd8..4eb8360cb 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionMedAsciiDriver.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MeshCollectionMedAsciiDriver.cxx @@ -52,6 +52,40 @@ MeshCollectionMedAsciiDriver::MeshCollectionMedAsciiDriver(MeshCollection* colle *\param filename ascii file containing the list of MED v2.3 files * */ +int MeshCollectionMedAsciiDriver::read(ParaMEDMEM::MEDFileData* filedata) +{ + readMEDFileData(filedata); + + std::vector cz; // to fill from filedata + std::vector cellglobal; + std::vector nodeglobal; + std::vector faceglobal; + int size = (_collection->getMesh()).size(); + cellglobal.resize(size); + nodeglobal.resize(size); + faceglobal.resize(size); + for ( int idomain = 0; idomain < size; ++idomain ) + { + cellglobal[idomain]=0; + faceglobal[idomain]=0; + nodeglobal[idomain]=0; + if ( (_collection->getMesh())[idomain] && (_collection->getMesh())[idomain]->getNumberOfNodes() > 0 ) + _collection->setNonEmptyMesh(idomain); + } + //creation of topology from mesh and connect zones + ParallelTopology* aPT = new ParallelTopology((_collection->getMesh()), cz, cellglobal, nodeglobal, faceglobal); + _collection->setTopology(aPT,true); + + return 0; +} + +/*!reads a MED File v>=2.3 + * and mounts the corresponding meshes in memory + * the connect zones are created from the joints + * + *\param filename ascii file containing the list of MED v2.3 files + * */ + int MeshCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector* domainSelector) { //distributed meshes @@ -105,7 +139,7 @@ int MeshCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector* throw INTERP_KERNEL::Exception("domain must be written from 1 to N in ASCII file descriptor"); } if ( !domainSelector || domainSelector->isMyDomain(i)) - readSubdomain(cellglobal,faceglobal,nodeglobal, i); + readSubdomain(i); } //loop on domains } //of try @@ -116,7 +150,7 @@ int MeshCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector* //creation of topology from mesh and connect zones ParallelTopology* aPT = new ParallelTopology((_collection->getMesh()), (_collection->getCZ()), cellglobal, nodeglobal, faceglobal); - _collection->setTopology(aPT); + _collection->setTopology(aPT, true); for (int i=0; igatherNbOf(_collection->getMesh()); } - _collection->setTopology(aPT); + _collection->setTopology(aPT, true); _collection->setDomainNames(_collection->getName()); return 0; } @@ -245,7 +245,19 @@ void MeshCollectionMedXmlDriver::write(const char* filename, ParaDomainSelector* int nbdomains= _collection->getMesh().size(); //loop on the domains - std::string finalMeshName=ExtractFromDescription(MyGlobals::_General_Informations[0], "finalMeshName="); + std::string finalMeshName=""; + if (MyGlobals::_General_Informations.size()!=0) + { + std::size_t found=MyGlobals::_General_Informations[0].find("finalMeshName="); + if ((found!=std::string::npos) && (found>0)) + { + finalMeshName=ExtractFromDescription(MyGlobals::_General_Informations[0], "finalMeshName="); + } + } + if (finalMeshName.empty()) + { + finalMeshName=_collection->getName(); + } for (int idomain=nbdomains-1; idomain>=0;idomain--) { std::string distfilename; @@ -277,7 +289,7 @@ void MeshCollectionMedXmlDriver::write(const char* filename, ParaDomainSelector* node = xmlNewChild(mesh_node,0, BAD_CAST "chunk",0); xmlNewProp(node, BAD_CAST "subdomain", BAD_CAST buff); xmlNewChild(node,0,BAD_CAST "name", BAD_CAST finalMeshName.c_str()); - //xmlNewChild(node,0,BAD_CAST "name", BAD_CAST (_collection->getMesh())[idomain]->getName()); + //xmlNewChild(node,0,BAD_CAST "name", BAD_CAST ((_collection->getMesh())[idomain]->getName()).c_str()); } } diff --git a/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.cxx b/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.cxx index 1acf1bbd9..d91ceda7f 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.cxx @@ -36,7 +36,7 @@ METISGraph::METISGraph():Graph() { } -METISGraph::METISGraph(MEDPARTITIONER::SkyLineArray* graph, int* edgeweight) +METISGraph::METISGraph(ParaMEDMEM::MEDCouplingSkyLineArray* graph, int* edgeweight) :Graph(graph,edgeweight) { } @@ -112,7 +112,7 @@ void METISGraph::partGraph(int ndomain, //creating a skylinearray with no copy of the index and partition array //the fifth argument true specifies that only the pointers are passed //to the object - _partition = new MEDPARTITIONER::SkyLineArray(index,value); + _partition = new ParaMEDMEM::MEDCouplingSkyLineArray(index,value); #endif } diff --git a/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.hxx b/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.hxx index 75d6af14e..46bea277e 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MetisGraph.hxx @@ -30,7 +30,7 @@ namespace MEDPARTITIONER { public: METISGraph(); - METISGraph(MEDPARTITIONER::SkyLineArray*, int *edgeweight=0); + METISGraph(ParaMEDMEM::MEDCouplingSkyLineArray*, int *edgeweight=0); virtual ~METISGraph(); void partGraph(int ndomain, const std::string& options_string="", ParaDomainSelector *sel=0); }; diff --git a/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.cxx b/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.cxx index ab1c1b426..18ca26082 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.cxx @@ -38,7 +38,7 @@ ParMETISGraph::ParMETISGraph():Graph() { } -ParMETISGraph::ParMETISGraph(MEDPARTITIONER::SkyLineArray* graph, int* edgeweight) +ParMETISGraph::ParMETISGraph(MEDCouplingSkyLineArray* graph, int* edgeweight) :Graph(graph,edgeweight) { } @@ -136,7 +136,7 @@ void ParMETISGraph::partGraph(int ndomain, //the fifth argument true specifies that only the pointers are passed //to the object - _partition = new MEDPARTITIONER::SkyLineArray(index,value); + _partition = new MEDCouplingSkyLineArray(index,value); #endif } diff --git a/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.hxx b/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.hxx index 178683eb3..8b71b2833 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ParMetisGraph.hxx @@ -30,7 +30,7 @@ namespace MEDPARTITIONER { public: ParMETISGraph(); - ParMETISGraph(MEDPARTITIONER::SkyLineArray*, int *edgeweight=0); + ParMETISGraph(MEDCouplingSkyLineArray*, int *edgeweight=0); virtual ~ParMETISGraph(); void partGraph(int ndomain, const std::string& options_string="", ParaDomainSelector *sel=0); }; diff --git a/src/MEDPartitioner/MEDPARTITIONER_ParaDomainSelector.cxx b/src/MEDPartitioner/MEDPARTITIONER_ParaDomainSelector.cxx index a5b8257c3..cf65b32e3 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ParaDomainSelector.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ParaDomainSelector.cxx @@ -370,8 +370,8 @@ std::auto_ptr MEDPARTITIONER::ParaDomainSelector::gatherG // Make graph // ----------- - // MEDPARTITIONER::SkyLineArray* array = - // new MEDPARTITIONER::SkyLineArray( index_size-1, value_size, graph_index, graph_value, true ); + // MEDCouplingSkyLineArray* array = + // new MEDCouplingSkyLineArray( index_size-1, value_size, graph_index, graph_value, true ); // glob_graph = new UserGraph( array, partition, index_size-1 ); diff --git a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx index 658379ac2..a8a4ab5bf 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx @@ -278,7 +278,7 @@ ParallelTopology::ParallelTopology(Graph* graph, Topology* oldTopology, int nb_d _nb_domain=nb_domain; _mesh_dimension=mesh_dimension; - + if (MyGlobals::_Verbose>200) std::cout << "proc " << MyGlobals::_Rank << " : new topology oldNbDomain " << oldTopology->nbDomain() << " newNbDomain " << _nb_domain << std::endl; @@ -316,22 +316,79 @@ ParallelTopology::ParallelTopology(Graph* graph, Topology* oldTopology, int nb_d if (MyGlobals::_Verbose>300) for (int idomain=0; idomain<_nb_domain; idomain++) - std::cout << "proc " << MyGlobals::_Rank << " : nbCells in new domain " << idomain << " : " << _nb_cells[idomain] << std::endl; + std::cout << "proc " << MyGlobals::_Rank << " : nbCells in new domain " << idomain << " : " << _nb_cells[idomain] << std::endl; + + // JOINTs + + if ( MyGlobals::_Create_Joints && nb_domain > 1 ) + { + std::vector< std::vector< std::vector< int > > > cellCorresp( nb_domain ); + for ( int idomain = 0; idomain < nb_domain; ++idomain ) + { + cellCorresp[ idomain ].resize( nb_domain ); + } + const ParaMEDMEM::MEDCouplingSkyLineArray* skylinegraph = graph->getGraph(); + const int* index = skylinegraph->getIndex(); + const int* value = skylinegraph->getValue(); + const int nbCells = skylinegraph->getNumberOf(); + + for ( int iGlob = 0; iGlob < nbCells; ++iGlob ) + { + int iGlobDom = part[ iGlob ]; + for ( int i = index[ iGlob ]; i < index[ iGlob+1 ]; i++ ) + { + int iGlobNear = value[ i ]; + if ( iGlob > iGlobNear ) + continue; // treat ( iGlob, iGlobNear ) pair once + int iGlobNearDom = part[ iGlobNear ]; + if ( iGlobDom != iGlobNearDom ) + { + int iLoc = convertGlobalCell( iGlob ).second - 1; // to MEDCoupling fmt + int iLocNear = convertGlobalCell( iGlobNear ).second - 1; + cellCorresp[ iGlobDom ][ iGlobNearDom ].push_back( iLoc ); + cellCorresp[ iGlobDom ][ iGlobNearDom ].push_back( iLocNear ); + cellCorresp[ iGlobNearDom ][ iGlobDom ].push_back( iLocNear ); + cellCorresp[ iGlobNearDom ][ iGlobDom ].push_back( iLoc ); + } + } + } + for ( int idomain = 0; idomain < nb_domain; ++idomain ) + { + for ( int idomainNear = 0; idomainNear < nb_domain; ++idomainNear ) + { + std::vector< int > & corresp = cellCorresp[ idomain ][ idomainNear ]; + if ( corresp.empty() ) + continue; + MEDPARTITIONER::ConnectZone* cz = new MEDPARTITIONER::ConnectZone(); + cz->setName( "Connect Zone defined by MEDPARTITIONER" ); + cz->setDistantDomainNumber( idomainNear ); + cz->setLocalDomainNumber ( idomain ); + cz->setEntityCorresp( 0,0, &corresp[0], corresp.size()/2 ); + _connect_zones.push_back( cz ); + } + } + } } ParallelTopology::~ParallelTopology() { -} + for ( size_t i = 0; i < _connect_zones.size(); ++i ) + { + delete _connect_zones[i]; + _connect_zones[i] = 0; + } + _connect_zones.clear(); +} /*!Converts a list of global node numbers * to a distributed array with local cell numbers. - * + * * If a node in the list is represented on several domains, * only the first value is returned * */ void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, int* local, int* ip) { - if (_node_glob_to_loc.empty()) + if (_node_glob_to_loc.empty()) throw INTERP_KERNEL::Exception("Node mapping has not yet been built"); for (int i=0; i< nbnode; i++) { @@ -600,6 +657,11 @@ int ParallelTopology::convertGlobalNode(int iglobal, int idomain) return -1; } +std::vector& ParallelTopology::getCZ() +{ + return _connect_zones; +} + /*! * adding a face to the topology */ diff --git a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx index bc81aa8a4..5de3f4820 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx @@ -147,6 +147,8 @@ namespace MEDPARTITIONER int convertGlobalNode(int iglobal, int idomain); + std::vector& getCZ(); + //adding a face to the topology void appendFace(int idomain, int ilocal, int iglobal); @@ -161,10 +163,10 @@ namespace MEDPARTITIONER typedef INTERP_KERNEL::HashMultiMap > TGlob2DomainLoc; TGlob2DomainLoc _glob_to_loc; - std::vector > _loc_to_glob; - INTERP_KERNEL::HashMultiMap > _node_glob_to_loc; + TGlob2DomainLoc _node_glob_to_loc; //mapping local -> global + std::vector > _loc_to_glob; std::vector > _node_loc_to_glob; // global numbers in parallel mode @@ -185,6 +187,10 @@ namespace MEDPARTITIONER int _nb_total_faces; int _nb_domain; int _mesh_dimension; + + //links to connectzones + std::vector _connect_zones; + }; } #endif diff --git a/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.cxx b/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.cxx index 73fdd8265..c8b9f5e76 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.cxx @@ -37,7 +37,7 @@ SCOTCHGraph::SCOTCHGraph():Graph() { } -SCOTCHGraph::SCOTCHGraph(MEDPARTITIONER::SkyLineArray* graph, int* edgeweight):Graph(graph,edgeweight) +SCOTCHGraph::SCOTCHGraph(ParaMEDMEM::MEDCouplingSkyLineArray* graph, int* edgeweight):Graph(graph,edgeweight) { } @@ -110,6 +110,6 @@ void SCOTCHGraph::partGraph(int ndomain, const std::string& options_string, Para //creating a skylinearray with no copy of the index and partition array //the fifth argument true specifies that only the pointers are passed //to the object - _partition = new MEDPARTITIONER::SkyLineArray(index,value); + _partition = new ParaMEDMEM::MEDCouplingSkyLineArray(index,value); #endif } diff --git a/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.hxx b/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.hxx index 39c6f964f..ea6510b7d 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ScotchGraph.hxx @@ -26,12 +26,11 @@ namespace MEDPARTITIONER { - class SkyLineArray; class MEDPARTITIONER_EXPORT SCOTCHGraph : public Graph { public: SCOTCHGraph(); - SCOTCHGraph(MEDPARTITIONER::SkyLineArray*, int* edgeweight=0); + SCOTCHGraph(ParaMEDMEM::MEDCouplingSkyLineArray*, int* edgeweight=0); virtual ~SCOTCHGraph(); void partGraph(int ndomain, const std::string& options_string="", ParaDomainSelector* sel=0); }; diff --git a/src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.cxx b/src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.cxx deleted file mode 100644 index d53de21be..000000000 --- a/src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.cxx +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2007-2015 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. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// 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 -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -#include "MEDPARTITIONER_SkyLineArray.hxx" - -#include - -MEDPARTITIONER::SkyLineArray::SkyLineArray() -{ -} - -MEDPARTITIONER::SkyLineArray::SkyLineArray(const SkyLineArray &myArray) -{ - _index=myArray._index; - _value=myArray._value; -} - -MEDPARTITIONER::SkyLineArray::~SkyLineArray() -{ -} - - -MEDPARTITIONER::SkyLineArray::SkyLineArray(const std::vector& index, const std::vector& value) -{ - _value=value; - _index=index; -} - - diff --git a/src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.hxx b/src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.hxx deleted file mode 100644 index 561081869..000000000 --- a/src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.hxx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2007-2015 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. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// 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 -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -#ifndef __MEDPARTITIONER_MEDSKYLINEARRAY_H__ -#define __MEDPARTITIONER_MEDSKYLINEARRAY_H__ - -#include "MEDPARTITIONER.hxx" - -#include - -namespace MEDPARTITIONER -{ - class MEDPARTITIONER_EXPORT SkyLineArray - { - private: - std::vector _index; - std::vector _value; - public: - /*! if used SkyLineArray will keep empty */ - SkyLineArray(); - SkyLineArray( const SkyLineArray &myArray ); - SkyLineArray( const std::vector& index, const std::vector& value ); - ~SkyLineArray(); - - int getNumberOf() const { return _index.size()-1; } - int getLength() const { return _value.size() ; } - const int* getIndex() const { return (const int*)(&_index[0]); } - const int* getValue() const { return (const int*)(&_value[0]); } - }; -} -# endif diff --git a/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx b/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx index 9ea47e889..018388c62 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx @@ -34,7 +34,6 @@ namespace MEDPARTITIONER { class Graph; class ConnectZone; - class SkyLineArray; class MeshCollection; class MEDPARTITIONER_FaceModel; @@ -105,6 +104,8 @@ namespace MEDPARTITIONER virtual int convertGlobalFace(int iglobal, int idomain) = 0; /*! converting a global node number to a local representation */ virtual int convertGlobalNode(int iglobal, int idomain) = 0; + /*! getting a reference to connect zones vector */ + virtual std::vector& getCZ() = 0; }; } diff --git a/src/MEDPartitioner/MEDPARTITIONER_UserGraph.cxx b/src/MEDPartitioner/MEDPARTITIONER_UserGraph.cxx index 81d1fc66c..a6070f245 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_UserGraph.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_UserGraph.cxx @@ -30,7 +30,7 @@ using namespace MEDPARTITIONER; * (domain numbers range from 0 to ndomain-1 * \param n number of cells in the mesh */ -UserGraph::UserGraph(MEDPARTITIONER::SkyLineArray *array, const int *partition, int n):Graph(array,0) +UserGraph::UserGraph(ParaMEDMEM::MEDCouplingSkyLineArray *array, const int *partition, int n):Graph(array,0) { std::vector index(n+1),value(n); @@ -42,7 +42,7 @@ UserGraph::UserGraph(MEDPARTITIONER::SkyLineArray *array, const int *partition, value[i]=partition[i]; } - _partition = new MEDPARTITIONER::SkyLineArray(index,value); + _partition = new ParaMEDMEM::MEDCouplingSkyLineArray(index,value); } diff --git a/src/MEDPartitioner/MEDPARTITIONER_UserGraph.hxx b/src/MEDPartitioner/MEDPARTITIONER_UserGraph.hxx index 9fac944b1..a6fc144a5 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_UserGraph.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_UserGraph.hxx @@ -27,12 +27,12 @@ namespace MEDPARTITIONER { - class SkyLineArray; + class MEDCouplingSkyLineArray; class ParaDomainSelector; class MEDPARTITIONER_EXPORT UserGraph : public Graph { public: - UserGraph(MEDPARTITIONER::SkyLineArray*, const int*, int); + UserGraph(ParaMEDMEM::MEDCouplingSkyLineArray*, const int*, int); virtual ~UserGraph(); void partGraph(int, const std::string& options=std::string(""), ParaDomainSelector *sel=0); }; diff --git a/src/MEDPartitioner/MEDPARTITIONER_Utils.cxx b/src/MEDPartitioner/MEDPARTITIONER_Utils.cxx index ae6174557..861da009d 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_Utils.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_Utils.cxx @@ -45,6 +45,7 @@ int MEDPARTITIONER::MyGlobals::_World_Size=-1; int MEDPARTITIONER::MyGlobals::_Randomize=0; int MEDPARTITIONER::MyGlobals::_Atomize=0; int MEDPARTITIONER::MyGlobals::_Creates_Boundary_Faces=0; +int MEDPARTITIONER::MyGlobals::_Create_Joints=0; std::vector MEDPARTITIONER::MyGlobals::_File_Names; std::vector MEDPARTITIONER::MyGlobals::_Mesh_Names; std::vector MEDPARTITIONER::MyGlobals::_Field_Descriptions; diff --git a/src/MEDPartitioner/MEDPARTITIONER_Utils.hxx b/src/MEDPartitioner/MEDPARTITIONER_Utils.hxx index f0a1b8270..64fc0c2b9 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_Utils.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_Utils.hxx @@ -127,6 +127,7 @@ namespace MEDPARTITIONER static int _Randomize; static int _Atomize; static int _Creates_Boundary_Faces; + static int _Create_Joints; static int _Is0verbose; //trace cout if rank 0 and verbose static std::vector _File_Names; //on [iold] static std::vector _Mesh_Names; //on [iold] diff --git a/src/MEDPartitioner/medpartitioner.cxx b/src/MEDPartitioner/medpartitioner.cxx index cb6452057..48b90a7d4 100644 --- a/src/MEDPartitioner/medpartitioner.cxx +++ b/src/MEDPartitioner/medpartitioner.cxx @@ -73,6 +73,7 @@ int main(int argc, char** argv) MyGlobals::_World_Size=1; MyGlobals::_Rank=0; MyGlobals::_Creates_Boundary_Faces=0; + MyGlobals::_Create_Joints=0; // Primitive parsing of command-line options string desc ("Available options of medpartitioner V1.0:\n" @@ -86,6 +87,7 @@ int main(int argc, char** argv) "\t--split-method= : name of the splitting library (metis/scotch), default is metis\n" #endif "\t--creates-boundary-faces : creates boundary faces mesh in the output files\n" + "\t--creates-joints : creates joints in the output files\n" "\t--dump-cpu-memory : dumps passed CPU time and maximal increase of used memory\n" ); @@ -111,6 +113,7 @@ int main(int argc, char** argv) else if (TestArg(argv[i],"--split-method",value)) library=value; else if (TestArg(argv[i],"--ndomains",value)) ndomains=atoi(value.c_str()); else if (TestArg(argv[i],"--creates-boundary-faces",value)) MyGlobals::_Creates_Boundary_Faces=1; + else if (TestArg(argv[i],"--create-joints",value)) MyGlobals::_Create_Joints=1; else if (TestArg(argv[i],"--dump-cpu-memory",value)) mesure_memory=true; else { @@ -151,6 +154,7 @@ int main(int argc, char** argv) cout << " split-method = " << library << endl; cout << " ndomains = " << ndomains << endl; cout << " creates_boundary_faces = " << MyGlobals::_Creates_Boundary_Faces << endl; + cout << " create-joints = " << MyGlobals::_Create_Joints<< endl; cout << " dump-cpu-memory = " << mesure_memory<< endl; cout << " verbose = " << MyGlobals::_Verbose << endl; } diff --git a/src/MEDPartitioner_Swig/CMakeLists.txt b/src/MEDPartitioner_Swig/CMakeLists.txt new file mode 100644 index 000000000..05c8140f0 --- /dev/null +++ b/src/MEDPartitioner_Swig/CMakeLists.txt @@ -0,0 +1,76 @@ +# Copyright (C) 2012-2015 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. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +INCLUDE(${SWIG_USE_FILE}) + +ADD_DEFINITIONS(${PYTHON_DEFINITIONS}) + +SET_SOURCE_FILES_PROPERTIES(MEDPartitioner.i PROPERTIES CPLUSPLUS ON) +SET_SOURCE_FILES_PROPERTIES(MEDPartitioner.i PROPERTIES SWIG_DEFINITIONS "-shadow") +SET(SWIG_MODULE_MEDPartitioner_EXTRA_FLAGS "${SWIG_EXTRA_FLAGS_FOR_NUMPYANDSCIPY};-DWITHOUT_AUTOFIELD") + +SET (MEDPartitioner_SWIG_DPYS_FILES + MEDPartitionerCommon.i) + +INCLUDE_DIRECTORIES( + ${PYTHON_INCLUDE_DIRS} + ${PTHREAD_INCLUDE_DIR} # pthread dependancy due to python2.7 library + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${MEDFILE_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR}/../MEDPartitioner + ${CMAKE_CURRENT_SOURCE_DIR}/../MEDCoupling_Swig + ${CMAKE_CURRENT_SOURCE_DIR}/../MEDCoupling + ${CMAKE_CURRENT_SOURCE_DIR}/../MEDLoader + ${CMAKE_CURRENT_SOURCE_DIR}/../MEDLoader/Swig + ${CMAKE_CURRENT_SOURCE_DIR}/../INTERP_KERNEL + ${CMAKE_CURRENT_SOURCE_DIR}/../INTERP_KERNEL/Bases + ${CMAKE_CURRENT_SOURCE_DIR}/../INTERP_KERNEL/Geometric2D + ${CMAKE_CURRENT_SOURCE_DIR}/../INTERP_KERNEL/ExprEval + ${CMAKE_CURRENT_SOURCE_DIR}/../INTERP_KERNEL/GaussPoints + ) + +SWIG_ADD_MODULE(MEDPartitioner python MEDPartitioner.i) +SWIG_LINK_LIBRARIES(MEDPartitioner ${PYTHON_LIBRARIES} ${PLATFORM_LIBS} medpartitionercpp) + +IF(WIN32) + SET_TARGET_PROPERTIES(_MEDPartitioner PROPERTIES DEBUG_OUTPUT_NAME _MEDPartitioner_d) +ENDIF(WIN32) +INSTALL(TARGETS ${SWIG_MODULE_MEDPartitioner_REAL_NAME} DESTINATION ${SALOME_INSTALL_PYTHON}) + +SET(PYFILES_TO_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/MEDPartitioner.py) +INSTALL_AND_COMPILE_PYTHON_FILE("${PYFILES_TO_INSTALL}" ${SALOME_INSTALL_SCRIPT_PYTHON}) + +INSTALL(FILES MEDPartitioner.i MEDPartitionerCommon.i DESTINATION ${SALOME_INSTALL_HEADERS}) +INSTALL(FILES MEDPartitionerTest.py DESTINATION ${SALOME_INSTALL_SCRIPT_PYTHON}) + +SALOME_GENERATE_TESTS_ENVIRONMENT(tests_env) +ADD_TEST(MEDPartitionerTest ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/MEDPartitionerTest.py) +SET_TESTS_PROPERTIES(MEDPartitionerTest PROPERTIES ENVIRONMENT "${tests_env}") + +# Application tests + +SET(TEST_INSTALL_DIRECTORY ${SALOME_INSTALL_SCRIPT_SCRIPTS}/test/MEDCoupling/MEDPartitioner_Swig) +INSTALL(FILES MEDPartitionerTest.py DESTINATION ${TEST_INSTALL_DIRECTORY}) + +INSTALL(FILES CTestTestfileInstall.cmake + DESTINATION ${TEST_INSTALL_DIRECTORY} + RENAME CTestTestfile.cmake) + + diff --git a/src/MEDPartitioner_Swig/CTestTestfileInstall.cmake b/src/MEDPartitioner_Swig/CTestTestfileInstall.cmake new file mode 100644 index 000000000..2100e6bf0 --- /dev/null +++ b/src/MEDPartitioner_Swig/CTestTestfileInstall.cmake @@ -0,0 +1,21 @@ +# Copyright (C) 2015 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. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +ADD_TEST(MEDPartitionerTest python MEDPartitionerTest.py) +SET_TESTS_PROPERTIES(MEDPartitionerTest PROPERTIES LABELS "${COMPONENT_NAME}") diff --git a/src/MEDPartitioner_Swig/MEDPartitioner.i b/src/MEDPartitioner_Swig/MEDPartitioner.i new file mode 100644 index 000000000..13f6d9ca9 --- /dev/null +++ b/src/MEDPartitioner_Swig/MEDPartitioner.i @@ -0,0 +1,140 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +%include "MEDPartitionerCommon.i" + + +// %pythoncode %{ +// def ParaMEDMEMDataArrayDoublenew(cls,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDouble____new___(cls,args) +// def ParaMEDMEMDataArrayDoubleIadd(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDouble____iadd___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleIsub(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDouble____isub___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleImul(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDouble____imul___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleIdiv(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDouble____idiv___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleIpow(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDouble____ipow___(self, self, *args) +// def ParaMEDMEMDataArrayIntnew(cls,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayInt____new___(cls,args) +// def ParaMEDMEMDataArrayIntIadd(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayInt____iadd___(self, self, *args) +// def ParaMEDMEMDataArrayIntIsub(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayInt____isub___(self, self, *args) +// def ParaMEDMEMDataArrayIntImul(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayInt____imul___(self, self, *args) +// def ParaMEDMEMDataArrayIntIdiv(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayInt____idiv___(self, self, *args) +// def ParaMEDMEMDataArrayIntImod(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayInt____imod___(self, self, *args) +// def ParaMEDMEMDataArrayIntIpow(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayInt____ipow___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleTupleIadd(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDoubleTuple____iadd___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleTupleIsub(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDoubleTuple____isub___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleTupleImul(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDoubleTuple____imul___(self, self, *args) +// def ParaMEDMEMDataArrayDoubleTupleIdiv(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayDoubleTuple____idiv___(self, self, *args) +// def ParaMEDMEMDataArrayIntTupleIadd(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayIntTuple____iadd___(self, self, *args) +// def ParaMEDMEMDataArrayIntTupleIsub(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayIntTuple____isub___(self, self, *args) +// def ParaMEDMEMDataArrayIntTupleImul(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayIntTuple____imul___(self, self, *args) +// def ParaMEDMEMDataArrayIntTupleIdiv(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayIntTuple____idiv___(self, self, *args) +// def ParaMEDMEMDataArrayIntTupleImod(self,*args): +// import _MEDPartitioner +// return _MEDPartitioner.DataArrayIntTuple____imod___(self, self, *args) +// %} + + +// %pythoncode %{ +// DataArrayDouble.__new__=classmethod(ParaMEDMEMDataArrayDoublenew) +// DataArrayDouble.__iadd__=ParaMEDMEMDataArrayDoubleIadd +// DataArrayDouble.__isub__=ParaMEDMEMDataArrayDoubleIsub +// DataArrayDouble.__imul__=ParaMEDMEMDataArrayDoubleImul +// DataArrayDouble.__idiv__=ParaMEDMEMDataArrayDoubleIdiv +// DataArrayDouble.__ipow__=ParaMEDMEMDataArrayDoubleIpow + +// DataArrayInt.__new__=classmethod(ParaMEDMEMDataArrayIntnew) +// DataArrayInt.__iadd__=ParaMEDMEMDataArrayIntIadd +// DataArrayInt.__isub__=ParaMEDMEMDataArrayIntIsub +// DataArrayInt.__imul__=ParaMEDMEMDataArrayIntImul +// DataArrayInt.__idiv__=ParaMEDMEMDataArrayIntIdiv +// DataArrayInt.__imod__=ParaMEDMEMDataArrayIntImod +// DataArrayInt.__ipow__=ParaMEDMEMDataArrayIntIpow + +// DataArrayDoubleTuple.__iadd__=ParaMEDMEMDataArrayDoubleTupleIadd +// DataArrayDoubleTuple.__isub__=ParaMEDMEMDataArrayDoubleTupleIsub +// DataArrayDoubleTuple.__imul__=ParaMEDMEMDataArrayDoubleTupleImul +// DataArrayDoubleTuple.__idiv__=ParaMEDMEMDataArrayDoubleTupleIdiv + +// DataArrayIntTuple.__iadd__=ParaMEDMEMDataArrayIntTupleIadd +// DataArrayIntTuple.__isub__=ParaMEDMEMDataArrayIntTupleIsub +// DataArrayIntTuple.__imul__=ParaMEDMEMDataArrayIntTupleImul +// DataArrayIntTuple.__idiv__=ParaMEDMEMDataArrayIntTupleIdiv +// DataArrayIntTuple.__imod__=ParaMEDMEMDataArrayIntTupleImod + +// del ParaMEDMEMDataArrayDoublenew +// del ParaMEDMEMDataArrayDoubleIadd +// del ParaMEDMEMDataArrayDoubleIsub +// del ParaMEDMEMDataArrayDoubleImul +// del ParaMEDMEMDataArrayDoubleIdiv +// del ParaMEDMEMDataArrayIntnew +// del ParaMEDMEMDataArrayIntIadd +// del ParaMEDMEMDataArrayIntIsub +// del ParaMEDMEMDataArrayIntImul +// del ParaMEDMEMDataArrayIntIdiv +// del ParaMEDMEMDataArrayIntImod +// del ParaMEDMEMDataArrayDoubleTupleIadd +// del ParaMEDMEMDataArrayDoubleTupleIsub +// del ParaMEDMEMDataArrayDoubleTupleImul +// del ParaMEDMEMDataArrayDoubleTupleIdiv +// del ParaMEDMEMDataArrayIntTupleIadd +// del ParaMEDMEMDataArrayIntTupleIsub +// del ParaMEDMEMDataArrayIntTupleImul +// del ParaMEDMEMDataArrayIntTupleIdiv +// del ParaMEDMEMDataArrayIntTupleImod +// %} diff --git a/src/MEDPartitioner_Swig/MEDPartitionerCommon.i b/src/MEDPartitioner_Swig/MEDPartitionerCommon.i new file mode 100644 index 000000000..93a390a81 --- /dev/null +++ b/src/MEDPartitioner_Swig/MEDPartitionerCommon.i @@ -0,0 +1,70 @@ +// Copyright (C) 2007-2015 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. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +%module MEDPartitioner + +%include std_string.i + +%{ +#include "MEDFileData.hxx" + +#include "MEDPARTITIONER_MEDPartitioner.hxx" +#include "MEDPARTITIONER.hxx" +#include "MEDPARTITIONER_Graph.hxx" + +using namespace ParaMEDMEM; +using namespace INTERP_KERNEL; +using namespace MEDPARTITIONER; +%} + +%feature("autodoc", "1"); +%feature("docstring"); + +%newobject MEDPARTITIONER::MEDPartitioner::New; +%newobject MEDPARTITIONER::MEDPartitioner::Graph; +%newobject MEDPARTITIONER::MEDPartitioner::getMEDFileData; +%feature("unref") ParaMEDMEM::MEDFileData "$this->decrRef();" + +%nodefaultctor; + +%rename (InterpKernelException) INTERP_KERNEL::Exception; + +namespace MEDPARTITIONER +{ + class Graph + { + public: + virtual void partGraph(int ndomain, const std::string& options_string="", ParaDomainSelector *sel=0) throw(INTERP_KERNEL::Exception); + const ParaMEDMEM::MEDCouplingSkyLineArray *getGraph() const; + const ParaMEDMEM::MEDCouplingSkyLineArray *getPartition() const; + int nbVertices() const; + }; + + class MEDPartitioner + { + public: + MEDPartitioner(const std::string& filename, int ndomains=1, const std::string& library="metis",bool creates_boundary_faces=false, bool create_joints=false, bool mesure_memory=false) throw(INTERP_KERNEL::Exception); + MEDPartitioner(const ParaMEDMEM::MEDFileData* fileData, int ndomains=1, const std::string& library="metis",bool creates_boundary_faces=false, bool create_joints=false, bool mesure_memory=false) throw(INTERP_KERNEL::Exception); + MEDPartitioner(const ParaMEDMEM::MEDFileData* fileData, Graph* graph, bool creates_boundary_faces=false, bool create_joints=false, bool mesure_memory=false) throw(INTERP_KERNEL::Exception); + static MEDPARTITIONER::Graph* Graph(ParaMEDMEM::MEDCouplingSkyLineArray* graph, Graph::splitter_type split=Graph::METIS, int* edgeweight=0) throw(INTERP_KERNEL::Exception); + ParaMEDMEM::MEDFileData* getMEDFileData() throw(INTERP_KERNEL::Exception); + void write(const std::string& filename) throw(INTERP_KERNEL::Exception); + }; +} + diff --git a/src/MEDPartitioner_Swig/MEDPartitionerTest.py b/src/MEDPartitioner_Swig/MEDPartitionerTest.py new file mode 100644 index 000000000..8ad3c3064 --- /dev/null +++ b/src/MEDPartitioner_Swig/MEDPartitionerTest.py @@ -0,0 +1,100 @@ +# Copyright (C) 2012-2015 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. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# 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 +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from MEDPartitioner import * +from MEDLoader import * +import unittest +from MEDLoaderDataForTest import MEDLoaderDataForTest + +class MEDPartitionerTest(unittest.TestCase): + def testPartition(self): + fname="PyPartitionTest.med" + data=MEDLoaderDataForTest.buildACompleteMEDDataStructureWithFieldsOnCells_1() + data.write(fname,2) + part_file=MEDPartitioner(fname,2) + part_data=MEDPartitioner(data,2) + part_file.write("splitted_PyPartitionTest_1") + part_data.write("splitted_PyPartitionTest_2") + part_file_xml=MEDPartitioner("splitted_PyPartitionTest_1.xml") + part_data_xml=MEDPartitioner("splitted_PyPartitionTest_2.xml") + data1=part_file_xml.getMEDFileData() + data2=part_data_xml.getMEDFileData() + m1d=data1.getMeshes().getMeshAtPos(0) + m2d=data2.getMeshes().getMeshAtPos(0) + self.assertTrue(m1d.isEqual(m2d,1e-12)) + pass + def testPartitionGraph(self): + data=MEDLoaderDataForTest.buildACompleteMEDDataStructureWithFieldsOnCells_1() + m=data.getMeshes().getMeshAtPos(0) + graph=MEDPartitioner.Graph(m.getLevel0Mesh().generateGraph()) + graph.partGraph(2) + tool=MEDPartitioner(data,graph) + data2=tool.getMEDFileData() + self.assertEqual( 2, data2.getMeshes().getNumberOfMeshes() ) + pass + def testPartitionWithJoints(self): + # cartesian mesh 4x4 + arr=DataArrayDouble(5) ; arr.iota() + c=MEDCouplingCMesh() ; c.setCoords(arr,arr) + m=c.buildUnstructured() + m.setName("mesh") + mm=MEDFileUMesh() + mm.setMeshAtLevel(0,m) + ms=MEDFileMeshes() ; ms.pushMesh(mm) + data=MEDFileData() + data.setMeshes(ms) + part_file=MEDPartitioner(data,4,"metis",True,True,True) + data_file=part_file.getMEDFileData() + meshes=data_file.getMeshes() + self.assertEqual( 4, meshes.getNumberOfMeshes()) + self.assertEqual( 3, meshes.getMeshAtPos(0).getJoints().getNumberOfJoints()) + self.assertEqual( 3, meshes.getMeshAtPos(1).getJoints().getNumberOfJoints()) + self.assertEqual( 3, meshes.getMeshAtPos(2).getJoints().getNumberOfJoints()) + self.assertEqual( 3, meshes.getMeshAtPos(3).getJoints().getNumberOfJoints()) + joints=meshes.getMeshAtPos(0).getJoints() + self.assertEqual( 1, joints.getJointAtPos(0).getDomainNumber(), 1) + self.assertEqual( 2, joints.getJointAtPos(1).getDomainNumber(), 2) + self.assertEqual( 3, joints.getJointAtPos(2).getDomainNumber(), 3) + self.assertEqual( 2, joints.getJointAtPos(0).getStepAtPos(0).getNumberOfCorrespondences()) + self.assertEqual( 2, joints.getJointAtPos(1).getStepAtPos(0).getNumberOfCorrespondences()) + self.assertEqual( 1, joints.getJointAtPos(2).getStepAtPos(0).getNumberOfCorrespondences()) + found=0 + for ii in xrange(joints.getJointAtPos(0).getStepAtPos(0).getNumberOfCorrespondences()): + correspond=joints.getJointAtPos(0).getStepAtPos(0).getCorrespondenceAtPos(ii) + if correspond.getCorrespondence().isEqual(DataArrayInt([1,3,2,4])): + found+=1 + self.assertEqual(NORM_QUAD4, correspond.getLocalGeometryType()) + self.assertEqual(NORM_QUAD4, correspond.getRemoteGeometryType()) + pass + pass + self.assertEqual(1,found) + pass + def testPartitionPartGraph(self): + arr=DataArrayDouble(5) ; arr.iota() + c=MEDCouplingCMesh() ; c.setCoords(arr,arr) + m=c.buildUnstructured() + part=MEDPartitioner.Graph(m.generateGraph()) + part.partGraph(2) + a=part.getGraph() + p=part.getPartition() + self.assertTrue(isinstance(a,MEDCouplingSkyLineArray)) + self.assertTrue(isinstance(p,MEDCouplingSkyLineArray)) + self.assertTrue(part.nbVertices() > 0 ) + pass +unittest.main() -- 2.30.2