00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef DRIVERTOOLS_HXX
00024 #define DRIVERTOOLS_HXX
00025
00026 #include <MEDMEM.hxx>
00027
00028 #include "MEDMEM_define.hxx"
00029 #include "MEDMEM_Exception.hxx"
00030 #include "MEDMEM_FieldForward.hxx"
00031 #include "MEDMEM_ArrayInterface.hxx"
00032 #include "MEDMEM_Group.hxx"
00033 #include "MEDMEM_GaussLocalization.hxx"
00034
00035 #include <string>
00036 #include <vector>
00037 #include <set>
00038 #include <list>
00039 #include <map>
00040 #include <iostream>
00041 #include <iomanip>
00042 #include <algorithm>
00043
00044
00045
00046
00047 #define CASTEM_FULL_INTERLACE
00048
00049
00050 namespace MEDMEM {
00051 class MESH;
00052 class CONNECTIVITY;
00053 class COORDINATE;
00054 class GROUP;
00055 class FAMILY;
00056 class FIELD_;
00057 class _intermediateMED;
00058
00059
00060 struct MEDMEM_EXPORT _noeud
00061 {
00062 mutable int number;
00063 std::vector<double> coord;
00064 };
00065
00066
00067 typedef pair<int,int> _link;
00068
00069
00070 struct MEDMEM_EXPORT _maille
00071 {
00072 typedef std::map<int,_noeud>::iterator TNoeud;
00073 std::vector< TNoeud > sommets;
00074 MED_EN::medGeometryElement geometricType;
00075 mutable bool reverse;
00076 mutable int* sortedNodeIDs;
00077
00078
00079 _maille(MED_EN::medGeometryElement type=MED_EN::MED_NONE, size_t nelem=0)
00080 : geometricType(type),reverse(false),sortedNodeIDs(0),_ordre(0) { sommets.reserve(nelem); }
00081
00082 _maille(const _maille& ma);
00083 void init() const { if ( sortedNodeIDs ) delete [] sortedNodeIDs; sortedNodeIDs = 0; }
00084 ~_maille() { init(); }
00085
00086 int dimension() const
00087 { return geometricType/100; }
00088
00089 int dimensionWithPoly() const
00090 { return geometricType >= MED_EN::MED_POLYGON ? dimension()-2 : dimension(); }
00091
00092 const int* getSortedNodes() const;
00093 bool operator < (const _maille& ma) const;
00094 MED_EN::medEntityMesh getEntity(const int meshDimension) const throw (MEDEXCEPTION);
00095 _link link(int i) const;
00096
00097
00098 int nodeNum(int i) const { return abs( sommets[i]->second.number ); }
00099 int nodeID (int i) const { return sommets[i]->first; }
00100
00101 unsigned ordre() const { return abs( _ordre ); }
00102 bool isMerged() const { return _ordre < 0; }
00103 void setMergedOrdre(unsigned o) const { _ordre = -o; }
00104 void setOrdre(int o) const { _ordre = o; }
00105
00106 private:
00107 mutable int _ordre;
00108 _maille& operator=(const _maille& ma);
00109 };
00110
00111
00112 struct MEDMEM_EXPORT _mailleIteratorCompare
00113 {
00114
00115
00116
00117 bool operator () (std::set<_maille>::iterator i1, std::set<_maille>::iterator i2)
00118 {
00119
00120 return i1->ordre() < i2->ordre();
00121 }
00122 };
00123
00124
00125 struct MEDMEM_EXPORT _groupe
00126 {
00127 typedef std::set<_maille>::iterator TMaille;
00128 typedef std::vector< TMaille >::const_iterator TMailleIter;
00129 std::string nom;
00130 std::vector< TMaille > mailles;
00131 std::vector<int> groupes;
00132 std::map<unsigned,int> relocMap;
00133 GROUP* medGroup;
00134
00135 const _maille& maille(int index) { return *mailles[index]; }
00136 bool empty() const { return mailles.empty() && groupes.empty(); }
00137 #ifdef WNT
00138 int size() const { return (mailles.size()>relocMap.size())?mailles.size():relocMap.size(); }
00139 #else
00140 int size() const { return std::max( mailles.size(), relocMap.size() ); }
00141 #endif
00142 _groupe():medGroup(0) {}
00143 };
00144
00145
00146 struct MEDMEM_EXPORT _fieldBase {
00147
00148
00149
00150 struct _sub_data
00151
00152 {
00153 int _supp_id;
00154 std::vector<std::string> _comp_names;
00155 std::vector<int> _nb_gauss;
00156
00157 void setData( int nb_comp, int supp_id )
00158 { _supp_id = supp_id - 1; _comp_names.resize(nb_comp); _nb_gauss.resize(nb_comp,1); }
00159 int nbComponents() const { return _comp_names.size(); }
00160 std::string & compName( int i_comp ) { return _comp_names[ i_comp ]; }
00161 bool isValidNbGauss() const { return *std::max_element( _nb_gauss.begin(), _nb_gauss.end() ) ==
00162 *std::min_element( _nb_gauss.begin(), _nb_gauss.end() ); }
00163 #ifdef WNT
00164 int nbGauss() const { return (1>_nb_gauss[0])?1:_nb_gauss[0]; }
00165 #else
00166 int nbGauss() const { return std::max( 1, _nb_gauss[0] ); }
00167 #endif
00168 bool hasGauss() const { return nbGauss() > 1; }
00169 };
00170
00171 std::vector< _sub_data > _sub;
00172 int _group_id;
00173
00174
00175
00176 MED_EN::med_type_champ _type;
00177 std::string _name;
00178 std::string _description;
00179
00180 _fieldBase( MED_EN::med_type_champ theType, int nb_sub )
00181 : _group_id(-1),_type(theType) { _sub.resize( nb_sub ); }
00182 virtual std::list<std::pair< FIELD_*, int> > getField(std::vector<_groupe>& groupes) const = 0;
00183 void getGroupIds( std::set<int> & ids, bool all ) const;
00184 bool hasCommonSupport() const { return _group_id >= 0; }
00185 bool hasSameComponentsBySupport() const;
00186 virtual void dump(std::ostream&) const;
00187 virtual ~_fieldBase() {}
00188 };
00189
00190
00191 template< class T > class _field: public _fieldBase
00192 {
00193 std::vector< std::vector< T > > comp_values;
00194 public:
00195 _field< T > ( MED_EN::med_type_champ theType, int nb_sub, int total_nb_comp )
00196 : _fieldBase( theType, nb_sub ) { comp_values.reserve( total_nb_comp ); }
00197 std::vector< T >& addComponent( int nb_values );
00198 std::list<std::pair< FIELD_*, int> > getField(std::vector<_groupe>& groupes) const;
00199 virtual void dump(std::ostream&) const;
00200 };
00201
00202
00208 class MEDMEM_EXPORT _maillageByDimIterator
00209 {
00210 public:
00211
00212 _maillageByDimIterator( const _intermediateMED & medi,
00213 const int dim=-1,
00214 const bool convertPoly = false )
00215 { myImed = & medi; init( dim, convertPoly ); }
00216
00217
00218 void init(const int dim=-1,
00219 const bool convertPoly = false );
00220
00222 const std::set<_maille > * nextType() {
00223 while ( myIt != myEnd )
00224 if ( !myIt->second.empty() && ( myDim < 0 || dim(false) == myDim ))
00225 return & (myIt++)->second;
00226 else
00227 ++myIt;
00228 return 0;
00229 }
00231 int dim(const bool last=true) const {
00232 iterator it = myIt;
00233 if ( last ) --it;
00234 return myConvertPoly ?
00235 it->second.begin()->dimensionWithPoly() :
00236 it->second.begin()->dimension();
00237 }
00239 MED_EN::medGeometryElement type() const { iterator it = myIt; return (--it)->first; }
00240
00242 int sizeWithoutMerged() const {
00243 iterator it = myIt;
00244 removed::const_iterator tNb = nbRemovedByType->find( (--it)->first );
00245 return it->second.size() - ( tNb == nbRemovedByType->end() ? 0 : tNb->second );
00246 }
00247 private:
00248 typedef std::map<MED_EN::medGeometryElement, int > removed;
00249 typedef std::map<MED_EN::medGeometryElement, std::set<_maille > > TMaillageByType;
00250 typedef TMaillageByType::const_iterator iterator;
00251
00252 const _intermediateMED* myImed;
00253 iterator myIt, myEnd;
00254 int myDim, myConvertPoly;
00255 const removed * nbRemovedByType;
00256 };
00257
00258
00269 struct MEDMEM_EXPORT _intermediateMED
00270 {
00271 typedef std::map<MED_EN::medGeometryElement, std::set<_maille > > TMaillageByType;
00272 typedef std::map<MED_EN::medGeometryElement, int > TNbByType;
00273 typedef std::map< const _maille*, std::vector<int> > TPolyherdalNbFaceNodes;
00274
00275 TNbByType nbRemovedByType;
00276 std::vector<_groupe> groupes;
00277
00278 std::map< int, _noeud > points;
00279 std::list< _fieldBase* > fields;
00280 bool hasMixedCells;
00281 TPolyherdalNbFaceNodes polyherdalNbFaceNodes;
00282
00283 inline _groupe::TMaille insert(const _maille& ma);
00284
00285 int getMeshDimension() const;
00286 void mergeNodesAndElements(double tolerance);
00287 CONNECTIVITY * getConnectivity();
00288 COORDINATE * getCoordinate(const string & coordinateSystem="CARTESIAN");
00289
00290
00291
00292 void getGroups(std::vector<GROUP *> & _groupCell, std::vector<GROUP *> & _groupFace,
00293 std::vector<GROUP *> & _groupEdge, std::vector<GROUP *> & _groupNode,
00294 MESH * _ptrMesh);
00295
00296
00297 void getFields(std::list< FIELD_* >& fields);
00298
00299
00300 bool myGroupsTreated;
00301 void treatGroupes();
00302 void numerotationMaillage();
00303 bool numerotationPoints();
00304 int nbMerged(int geoType) const;
00305
00306 _intermediateMED()
00307 { myNodesNumerated = myMaillesNumerated = myGroupsTreated = false; currentTypeMailles = 0; }
00308 ~_intermediateMED();
00309
00310 private:
00311
00312 bool myNodesNumerated, myMaillesNumerated;
00313
00314
00315
00316 TMaillageByType maillageByType;
00317 TMaillageByType::value_type* currentTypeMailles;
00318 friend class _maillageByDimIterator;
00319 };
00320
00321 _groupe::TMaille _intermediateMED::insert(const _maille& ma)
00322 {
00323 if ( !currentTypeMailles || currentTypeMailles->first != ma.geometricType )
00324 currentTypeMailles = & *maillageByType.insert
00325 ( make_pair( ma.geometricType, std::set<_maille >())).first;
00326
00327 _groupe::TMaille res = currentTypeMailles->second.insert( ma ).first;
00328
00329 ((_maille&)ma).init();
00330
00331
00332 return res;
00333 }
00334
00335
00336
00337 std::ostream& operator << (std::ostream& , const _maille& );
00338 std::ostream& operator << (std::ostream& , const _groupe& );
00339 std::ostream& operator << (std::ostream& , const _noeud& );
00340 std::ostream& operator << (std::ostream& , const _intermediateMED& );
00341 std::ostream& operator << (std::ostream& , const _fieldBase* );
00342
00343
00344
00345
00346
00347 template <class T>
00348 std::vector< T >& _field< T >::addComponent( int nb_values )
00349 {
00350 comp_values.push_back( std::vector< T >() );
00351 std::vector< T >& res = comp_values.back();
00352 res.resize( nb_values );
00353 return res;
00354 }
00355
00356
00357
00358
00359
00360
00361 template <class T>
00362 std::list<std::pair< FIELD_*, int> > _field< T >::getField(std::vector<_groupe> & groupes) const
00363 {
00364 const char* LOC = "_field< T >::getField()";
00365
00366 std::list<std::pair< FIELD_*, int> > res;
00367
00368
00369 int nbtypegeo = 0;
00370 vector<int> nbelgeoc(2,0), nbgaussgeo(2,0);
00371
00372 int i_comp_tot = 0, nb_fields = 0;
00373 std::set<int> supp_id_set;
00374 std::vector< _sub_data >::const_iterator sub_data, sub_end = _sub.end();
00375
00376 _groupe* grp = 0;
00377 GROUP* medGrp = 0;
00378 if ( hasCommonSupport() )
00379 {
00380 grp = & groupes[ _group_id ];
00381 medGrp = grp->medGroup;
00382 if ( !grp || grp->empty() || !medGrp || !medGrp->getNumberOfTypes())
00383 return res;
00384
00385
00386 nbtypegeo = medGrp->getNumberOfTypes();
00387 nbelgeoc .resize( nbtypegeo + 1, 0 );
00388 nbgaussgeo.resize( nbtypegeo + 1, 0 );
00389 const int * nbElemByType = medGrp->getNumberOfElements();
00390 const MED_EN::medGeometryElement* types = medGrp->getTypes();
00391 for (int iType = 0; iType < nbtypegeo; ++iType) {
00392
00393 nbelgeoc [ iType+1 ] = nbelgeoc[ iType ] + nbElemByType[ iType ];
00394
00395 for ( sub_data = _sub.begin(); sub_data != sub_end; ++sub_data ) {
00396 _groupe & sub_grp = groupes[ sub_data->_supp_id ];
00397 if ( !sub_grp.empty() && sub_grp.mailles[0]->geometricType == types[ iType ])
00398 break;
00399 }
00400 ASSERT_MED( sub_data != sub_end );
00401 nbgaussgeo[ iType+1 ] = sub_data->nbGauss();
00402 }
00403 }
00404 typedef typename MEDMEM_ArrayInterface<T,FullInterlace,NoGauss>::Array TArrayNoGauss;
00405 typedef typename MEDMEM_ArrayInterface<T,FullInterlace,Gauss>::Array TArrayGauss;
00406 FIELD< T, FullInterlace > * f = 0;
00407 TArrayNoGauss * arrayNoGauss = 0;
00408 TArrayGauss * arrayGauss = 0;
00409
00410
00411 int i_sub = 1;
00412 for ( sub_data = _sub.begin(); sub_data != sub_end; ++sub_data, ++i_sub )
00413 {
00414
00415 if ( !hasCommonSupport() ) {
00416 grp = & groupes[ sub_data->_supp_id ];
00417 medGrp = grp->medGroup;
00418 }
00419 int nb_val = grp->size();
00420
00421
00422 bool validSub = true;
00423 if ( !nb_val ) {
00424 INFOS_MED("Skip field <" << _name << ">: invalid supporting group "
00425 << (hasCommonSupport() ? _group_id : sub_data->_supp_id )
00426 << " of " << i_sub << "-th subcomponent" );
00427 validSub = false;
00428 }
00429 if ( !sub_data->isValidNbGauss() ) {
00430 INFOS_MED("Skip field <" << _name << ">: different nb of gauss points in components ");
00431 validSub = false;
00432 }
00433 if ( !validSub ) {
00434 if ( hasCommonSupport() ) {
00435 if ( !res.empty() ) {
00436 if(f)
00437 f->removeReference();
00438 res.clear();
00439 }
00440 return res;
00441 }
00442 i_comp_tot += sub_data->nbComponents();
00443 continue;
00444 }
00445
00446
00447
00448 if ( !f || !hasCommonSupport() || !supp_id_set.insert( sub_data->_supp_id ).second )
00449 {
00450 ++nb_fields;
00451 supp_id_set.clear();
00452 arrayNoGauss = 0;
00453 arrayGauss = 0;
00454
00455 f = new FIELD< T, FullInterlace >();
00456
00457 f->setNumberOfComponents( sub_data->nbComponents() );
00458 f->setComponentsNames( & sub_data->_comp_names[ 0 ] );
00459 f->setNumberOfValues ( nb_val );
00460 f->setName( _name );
00461 f->setDescription( _description );
00462 vector<string> str( sub_data->nbComponents() );
00463 f->setComponentsDescriptions( &str[0] );
00464 f->setMEDComponentsUnits( &str[0] );
00465 if ( !hasCommonSupport() && nb_fields > 1 )
00466 {
00467 f->setName( MEDMEM::STRING(_name) << "_Sub_" << nb_fields );
00468 INFOS_MED("Warning: field |" <<_name<<"| is incompatible with MED format (has "
00469 "sub-fields of different nature), so we map its sub-field #"<< nb_fields <<
00470 " into a separate field |"<<f->getName() << "|");
00471 }
00472 res.push_back( make_pair( f , hasCommonSupport() ? _group_id : sub_data->_supp_id ));
00473 MESSAGE_MED(" MAKE " << nb_fields << "-th field <" << _name << "> on group_id " << _group_id );
00474
00475
00476 if ( !sub_data->hasGauss() ) {
00477 arrayNoGauss = new TArrayNoGauss( sub_data->nbComponents(), nb_val );
00478 f->setArray( arrayNoGauss );
00479 }
00480 else {
00481 if ( !hasCommonSupport() ) {
00482 nbtypegeo = 1;
00483 nbelgeoc [1] = nb_val;
00484 nbgaussgeo[1] = sub_data->nbGauss();
00485 }
00486 arrayGauss = new TArrayGauss(sub_data->nbComponents(), nb_val,
00487 nbtypegeo, & nbelgeoc[0], & nbgaussgeo[0]);
00488 f->setArray( arrayGauss );
00489
00490
00491 const MED_EN::medGeometryElement* types = medGrp->getTypes();
00492 for (int iGeom = 0; iGeom < nbtypegeo; ++iGeom) {
00493 ostringstream name;
00494 name << "Gauss_" << nbgaussgeo[iGeom+1] << "points_on" << types[iGeom] << "geom";
00495 GAUSS_LOCALIZATION_* loc = GAUSS_LOCALIZATION_::makeDefaultLocalization
00496 (name.str(), types[iGeom], nbgaussgeo[iGeom+1]);
00497 f->setGaussLocalization( types[iGeom], loc );
00498 }
00499 }
00500 }
00501
00502
00503
00504
00505 _groupe & sub_grp = groupes[ sub_data->_supp_id ];
00506 int nb_supp_elems = sub_grp.mailles.size();
00507 int nb_gauss = sub_data->nbGauss();
00508 MESSAGE_MED("insert sub data, group_id: " << sub_data->_supp_id <<
00509 ", nb values: " << comp_values[ i_comp_tot ].size() <<
00510 ", relocMap size: " << sub_grp.relocMap.size() <<
00511 ", nb mailles: " << nb_supp_elems);
00512
00513 #ifdef CASTEM_FULL_INTERLACE
00514 const int gauss_step = 1;
00515 const int elem_step = nb_gauss;
00516 #else
00517 const int gauss_step = nb_supp_elems;
00518 const int elem_step = 1;
00519 #endif
00520 int i;
00521
00522 for ( int i_comp = 1; i_comp <= sub_data->nbComponents(); ++i_comp )
00523 {
00524
00525 const std::vector< T > & values = comp_values[ i_comp_tot++ ];
00526 bool oneValue = ( values.size() == 1 );
00527 ASSERT_MED( oneValue || (int)values.size() == nb_supp_elems * nb_gauss );
00528 for ( int k = 0; k < nb_supp_elems; ++k )
00529 {
00530 const T& val = oneValue ? values[ 0 ] : values[ k * elem_step ];
00531 const _maille& ma = sub_grp.maille( k );
00532 if ( medGrp->isOnAllElements() ) {
00533 i = ma.ordre();
00534 }
00535 else {
00536 std::map<unsigned,int>::const_iterator ordre_i = grp->relocMap.find( ma.ordre() );
00537 if ( ordre_i == grp->relocMap.end() )
00538 throw MEDEXCEPTION (LOCALIZED(STRING(LOC) << ", cant find elem index. "
00539 << k << "-th elem: " << ma));
00540 i = ordre_i->second;
00541 }
00542 if ( arrayNoGauss ) {
00543 arrayNoGauss->setIJ( i, i_comp, val );
00544 }
00545 else {
00546 const T* pVal = & val;
00547 for ( int iGauss = 1; iGauss <= nb_gauss; ++iGauss, pVal += gauss_step )
00548 arrayGauss->setIJK( i, i_comp, iGauss, *pVal);
00549 }
00550 }
00551 }
00552 }
00553
00554 return res;
00555 }
00556
00557
00558
00559 template <class T> void _field< T >::dump(std::ostream& os) const
00560
00561 {
00562 _fieldBase::dump(os);
00563 os << endl;
00564 for ( int i = 0 ; i < (int)comp_values.size(); ++i )
00565 {
00566 os << " " << i+1 << "-th component, nb values: " << comp_values[ i ].size() << endl;
00567 }
00568 }
00569
00570 }
00571
00572 #endif