Salome HOME
fix: replace unordered_set/map with set/map
[tools/medcoupling.git] / src / MEDLoader / MEDFileJoint.cxx
1 // Copyright (C) 2007-2024  CEA, EDF
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "MEDFileJoint.hxx"
21 #include "MEDFileBasis.hxx"
22 #include "MEDLoader.hxx"
23 #include "MEDLoaderBase.hxx"
24 #include "MEDFileSafeCaller.txx"
25
26 #include "CellModel.hxx"
27 #include "InterpKernelAutoPtr.hxx"
28
29 // From MEDLOader.cxx TU
30 extern med_geometry_type                 typmai[MED_N_CELL_FIXED_GEO];
31 extern INTERP_KERNEL::NormalizedCellType typmai2[MED_N_CELL_FIXED_GEO];
32 extern med_geometry_type                 typmai3[INTERP_KERNEL::NORM_MAXTYPE];
33
34 using namespace MEDCoupling;
35
36 std::size_t MEDFileJointCorrespondence::getHeapMemorySizeWithoutChildren() const
37 {
38   return sizeof(MCAuto<DataArrayIdType>);
39 }
40
41 std::vector<const BigMemoryObject *> MEDFileJointCorrespondence::getDirectChildrenWithNull() const
42 {
43   return std::vector<const BigMemoryObject *>();
44 }
45
46 MEDFileJointCorrespondence::MEDFileJointCorrespondence():
47   _is_nodal( true ),
48   _loc_geo_type( INTERP_KERNEL::NORM_ERROR ),
49   _rem_geo_type( INTERP_KERNEL::NORM_ERROR )
50 {
51 }
52
53 /*!
54  * Constructor.
55  *  \param [in] correspondence - correspondence.
56  *  \param [in] isNodal - is the correspondence of cells or nodes.
57  *  \param [in] loc_geo_type - the local geometry type of correspondence.
58  *  \param [in] rem_geo_type - the remote geometry type of correspondence.
59  */
60 MEDFileJointCorrespondence::MEDFileJointCorrespondence(DataArrayIdType* correspondence,
61                                                        bool          isNodal,
62                                                        INTERP_KERNEL::NormalizedCellType loc_geo_type,
63                                                        INTERP_KERNEL::NormalizedCellType rem_geo_type):
64   _is_nodal( isNodal ),
65   _loc_geo_type( loc_geo_type ),
66   _rem_geo_type( rem_geo_type )
67 {
68   MEDFileJointCorrespondence::setCorrespondence( correspondence );
69 }
70
71 MEDFileJointCorrespondence* MEDFileJointCorrespondence::New(DataArrayIdType* correspondence,
72                                                             INTERP_KERNEL::NormalizedCellType loc_geo_type,
73                                                             INTERP_KERNEL::NormalizedCellType rem_geo_type)
74 {
75   return new MEDFileJointCorrespondence(correspondence, /*isNodal=*/false, loc_geo_type, rem_geo_type );
76 }
77
78 /*!
79  * Returns a new MEDFileJointCorrespondence of nodes
80  */
81 MEDFileJointCorrespondence *MEDFileJointCorrespondence::New(DataArrayIdType* correspondence)
82 {
83   return new MEDFileJointCorrespondence(correspondence);
84 }
85
86 /*!
87  * Returns a new undefined MEDFileJointCorrespondence
88  */
89
90 MEDFileJointCorrespondence *MEDFileJointCorrespondence::New()
91 {
92   return new MEDFileJointCorrespondence();
93 }
94
95 /*!
96  * Writes \a this joint into a MED file specified by its name.
97  *  \param [in] fileName - the MED file name.
98  *  \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics.
99  *          - 2 - erase; an existing file is removed.
100  *          - 1 - append; same data should not be present in an existing file.
101  *          - 0 - overwrite; same data present in an existing file is overwritten.
102  *  \param [in] order - order.
103  *  \param [in] iteration - iteration.
104  *  \throw If the mesh name is not set.
105  *  \throw If \a mode == 1 and the same data is present in an existing file.
106  */
107 void MEDFileJointCorrespondence::write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName, int order, int iteration) const
108 {
109   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
110   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
111
112   std::ostringstream oss; oss << "MEDFileJointCorrespondence : error on attempt to write in file : \"" << fileName << "\"";
113   MEDFileUtilities::CheckMEDCode((int)fid,fid,oss.str());
114
115   if (( !_is_nodal ) &&
116       ( _loc_geo_type == INTERP_KERNEL::NORM_ERROR ||
117         _rem_geo_type == INTERP_KERNEL::NORM_ERROR ))
118     {
119       throw INTERP_KERNEL::Exception( "Geometric type not specified for a cell Joint" );
120     }
121
122   if ( (const DataArrayIdType *)_correspondence )
123     {
124       writeLL(fid, localMeshName, jointName, order, iteration);
125     }
126   else
127     {
128       throw INTERP_KERNEL::Exception("MEDFileJointCorrespondence::write : correspondence array not defined");
129     }
130 }
131
132 void MEDFileJointCorrespondence::writeLL(med_idt fid, const std::string& localMeshName, const std::string& jointName, int order, int iteration) const
133 {
134   if ( _is_nodal )
135     {
136       MEDFILESAFECALLERWR0(MEDsubdomainCorrespondenceWr,(fid, localMeshName.c_str(), jointName.c_str(),
137                                                          order, iteration,
138                                                          MED_NODE, MED_NONE,
139                                                          MED_NODE, MED_NONE,
140                                                          ToMedInt(_correspondence->getNbOfElems()/2),
141                                                          ToMedIntArray(_correspondence)->getConstPointer()));
142     }
143   else
144     {
145       MEDFILESAFECALLERWR0(MEDsubdomainCorrespondenceWr,(fid, localMeshName.c_str(), jointName.c_str(),
146                                                          order, iteration,
147                                                          MED_CELL, typmai3[ _loc_geo_type ],
148                                                          MED_CELL, typmai3[ _rem_geo_type ],
149                                                          ToMedInt(_correspondence->getNbOfElems()/2),
150                                                          ToMedIntArray(_correspondence)->getConstPointer()));
151     }
152 }
153
154 void MEDFileJointCorrespondence::setCorrespondence(DataArrayIdType *corr)
155 {
156   _correspondence=corr;
157   if ( corr )
158     corr->incrRef();
159 }
160
161 /*!
162  * Checks if \a this and another mesh are equal.
163  *  \param [in] other - the mesh to compare with.
164  *  \return bool - \c true if the meshes are equal, \c false, else.
165  */
166 bool MEDFileJointCorrespondence::isEqual(const MEDFileJointCorrespondence *other) const
167 {
168   if(_is_nodal!=other->_is_nodal)
169     return false;
170   if(_loc_geo_type!=other->_loc_geo_type)
171     return false;
172   if(_rem_geo_type!=other->_rem_geo_type)
173     return false;
174   if(!_correspondence->isEqual(*other->_correspondence))
175     return false;
176   return true;
177 }
178
179 MEDFileJointCorrespondence *MEDFileJointCorrespondence::deepCopy() const
180 {
181   MCAuto<MEDFileJointCorrespondence> ret=new MEDFileJointCorrespondence(*this);
182   return ret.retn();
183 }
184
185 MEDFileJointCorrespondence *MEDFileJointCorrespondence::shallowCpy() const
186 {
187   MCAuto<MEDFileJointCorrespondence> ret=new MEDFileJointCorrespondence(*this);
188   return ret.retn();
189 }
190
191 /*!
192  * Returns a string describing \a this mesh. This description includes the correspondence and
193  * the number correspondence.
194  *  \return std::string - the joint information string.
195  */
196 std::string MEDFileJointCorrespondence::simpleRepr() const
197 {
198   std::ostringstream oss;
199   oss << "(*************************************)\n(* JOINT_CORRESPOND INFORMATION: *)\n(*************************************)\n";
200   oss << "- entity type of the correspondence : " << ( getIsNodal() ? "NODE" : "CELL" ) << "\n";
201   oss << "- Local geometry type of the correspondence : " << INTERP_KERNEL::CellModel::GetCellModel( _loc_geo_type ).getRepr() << "\n";
202   oss << "- Remote geometry type of the correspondence : " << INTERP_KERNEL::CellModel::GetCellModel( _rem_geo_type ).getRepr() << "\n";
203   if ( (const DataArrayIdType *)_correspondence )
204     {
205       oss << "- Number entity of the correspondence : " << getCorrespondence()->getNumberOfTuples() << "\n";
206
207       const DataArrayIdType* tmp=getCorrespondence();
208       oss << "- Correspondence : <<";
209       for(const mcIdType *it=tmp->begin();it!=tmp->end();it++)
210         oss<< *it << " ";
211     }
212   else
213     {
214       oss << "- Number entity of the correspondence : 0\n";
215     }
216   oss << std::endl;
217   return oss.str();
218 }
219
220
221 MEDFileJointOneStep::MEDFileJointOneStep():_order(-1),_iteration(-1)
222 {
223 }
224
225 std::size_t MEDFileJointOneStep::getHeapMemorySizeWithoutChildren() const
226 {
227   return _correspondences.capacity()*sizeof(MCAuto<DataArrayIdType>);
228 }
229
230 std::vector<const BigMemoryObject *> MEDFileJointOneStep::getDirectChildrenWithNull() const
231 {
232   return std::vector<const BigMemoryObject *>();
233 }
234
235 MEDFileJointOneStep *MEDFileJointOneStep::New(int dt, int it)
236 {
237   MEDFileJointOneStep* j = new MEDFileJointOneStep();
238   j->setOrder( dt );
239   j->setIteration( it );
240   return j;
241 }
242
243 /*!
244  * Returns a new MEDFileJointOneStep.
245  *  \param [in] fileName - the name of MED file to read.
246  *  \param [in] mName - the name of the mesh to read.
247  *  \param [in] jointName - the joint name.
248  *  \param [in] num - the number of an iteration.
249  *  \return MEDFileMesh * - a new instance of MEDFileJointOneStep.
250  *  \throw If the file is not readable.
251  *  \throw If there is no mesh with given attributes in the file.
252  */
253 MEDFileJointOneStep *MEDFileJointOneStep::New(const std::string& fileName, const std::string& mName, const std::string& jointName, int num)
254 {
255   MEDFileUtilities::CheckFileForRead(fileName);
256   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(), MED_ACC_RDONLY);
257   return new MEDFileJointOneStep(fid, mName, jointName, num);
258 }
259
260 MEDFileJointOneStep* MEDFileJointOneStep::New(med_idt fid, const std::string& mName, const std::string& jointName, int num)
261 {
262   return new MEDFileJointOneStep( fid, mName, jointName, num);
263 }
264
265 MEDFileJointOneStep::MEDFileJointOneStep(med_idt fid, const std::string& mName, const std::string& jointName, int num)
266 {
267   med_int order, iteration, ncorrespondence;
268   MEDFILESAFECALLERRD0(MEDsubdomainComputingStepInfo,(fid, mName.c_str(), jointName.c_str(), num, &order, &iteration, &ncorrespondence));
269   MEDFileJointOneStep::setOrder(FromMedInt<int>(order));
270   MEDFileJointOneStep::setIteration(FromMedInt<int>(iteration));
271   for ( int cur_it = 1; cur_it <= ncorrespondence; ++cur_it )
272     {
273       med_int num_entity;
274       med_entity_type loc_ent_type, rem_ent_type;
275       med_geometry_type loc_geo_type, rem_geo_type;
276       MEDFILESAFECALLERRD0(MEDsubdomainCorrespondenceSizeInfo,(fid, mName.c_str(), jointName.c_str(), order, iteration, cur_it,
277                                                                &loc_ent_type, &loc_geo_type, &rem_ent_type, &rem_geo_type, &num_entity));
278       if ( num_entity > 0 )
279         {
280           MCAuto<DataArrayMedInt> correspondence=DataArrayMedInt::New();
281           correspondence->alloc(num_entity*2, 1);
282           MEDFILESAFECALLERRD0(MEDsubdomainCorrespondenceRd,(fid, mName.c_str(), jointName.c_str(), order, iteration, loc_ent_type,
283                                                              loc_geo_type, rem_ent_type, rem_geo_type, correspondence->getPointer()));
284           MEDFileJointCorrespondence *cor=MEDFileJointCorrespondence::New();
285           cor->setIsNodal( loc_ent_type == MED_NODE );
286           cor->setLocalGeometryType ( convertGeometryType( loc_geo_type ));
287           cor->setRemoteGeometryType( convertGeometryType( rem_geo_type ));
288           cor->setCorrespondence( FromMedIntArray<mcIdType>(correspondence ));
289           _correspondences.push_back(cor);
290         }
291     }
292 }
293
294 /*!
295  * Writes \a this joint into a MED file specified by its name.
296  *  \param [in] fileName - the MED file name.
297  *  \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics.
298  * - 2 - erase; an existing file is removed.
299  * - 1 - append; same data should not be present in an existing file.
300  * - 0 - overwrite; same data present in an existing file is overwritten.
301  *  \throw If the mesh name is not set.
302  *  \throw If \a mode == 1 and the same data is present in an existing file.
303  */
304 void MEDFileJointOneStep::write(const std::string& fileName, int mode, const std::string& localMeshName, const std::string& jointName) const
305 {
306   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
307   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
308   std::ostringstream oss; oss << "MEDFileJointOneStep : error on attempt to write in file : \"" << fileName << "\"";
309   MEDFileUtilities::CheckMEDCode((int)fid,fid,oss.str());
310   if ( _correspondences.empty() )
311     throw INTERP_KERNEL::Exception("MEDFileJointOneStep::write : no correspondences defined !");
312   writeLL(fid, localMeshName, jointName);
313 }
314
315 void MEDFileJointOneStep::writeLL(med_idt fid, const std::string& localMeshName, const std::string& jointName) const
316 {
317   for(std::vector< MCAuto<MEDFileJointCorrespondence> >::const_iterator it=_correspondences.begin();it!=_correspondences.end();it++)
318     {
319       (*it)->writeLL(fid, localMeshName, jointName, getOrder(), getIteration());
320     }
321 }
322
323 void MEDFileJointOneStep::pushCorrespondence(MEDFileJointCorrespondence* correspondence)
324 {
325   if(!correspondence)
326     throw INTERP_KERNEL::Exception("MEDFileJointCorrespondence::pushCorrespondence : invalid input pointer ! should be different from 0 !");
327   _correspondences.push_back(correspondence);
328   correspondence->incrRef();
329 }
330
331 void MEDFileJointOneStep::clearCorrespondences()
332 {
333   _correspondences.clear();
334 }
335
336 int MEDFileJointOneStep::getNumberOfCorrespondences() const
337 {
338   return (int)_correspondences.size();
339 }
340
341 /** Return a borrowed reference (caller is not responsible) */
342 MEDFileJointCorrespondence *MEDFileJointOneStep::getCorrespondenceAtPos(int i) const
343 {
344   if(i<0 || i>=(int)_correspondences.size())
345     {
346       std::ostringstream oss; oss << "MEDFileJointOneStep::getCorrespondenceAtPos : invalid correspondence id given in parameter ! Should be in [0;" << _correspondences.size() << ") !";
347       throw INTERP_KERNEL::Exception(oss.str().c_str());
348     }
349   const MEDFileJointCorrespondence* ret = _correspondences[i];
350   return const_cast<MEDFileJointCorrespondence *>( ret );
351 }
352
353 /*!
354  * Checks if \a this and another Joint are equal.
355  *  \param [in] other - the Joint to compare with.
356  *  \return bool - \c true if the Joints are equal, \c false, else.
357  */
358 bool MEDFileJointOneStep::isEqual(const MEDFileJointOneStep *other) const
359 {
360   if(_order!=other->_order)
361     return false;
362   if(_iteration!=other->_iteration)
363     return false;
364   if ( getNumberOfCorrespondences() != other->getNumberOfCorrespondences() )
365     return false;
366
367   std::vector<bool> found( getNumberOfCorrespondences(), false );
368   for(int i=0; i<getNumberOfCorrespondences(); i++)
369     {
370       int j;
371       for(j=0; j<getNumberOfCorrespondences(); j++)
372         {
373           if ( !found[ j ] &&
374                getCorrespondenceAtPos(i)->isEqual(other->getCorrespondenceAtPos(j)))
375             {
376               found[ j ] = true;
377               break;
378             }
379         }
380       if ( j == getNumberOfCorrespondences() )
381         return false;
382     }
383   return true;
384 }
385
386 MEDFileJointOneStep *MEDFileJointOneStep::deepCopy() const
387 {
388   std::vector< MCAuto<MEDFileJointCorrespondence> > correspondences(_correspondences.size());
389   std::size_t i=0;
390   for(std::vector< MCAuto<MEDFileJointCorrespondence> >::const_iterator it=_correspondences.begin();it!=_correspondences.end();it++,i++)
391     if((const MEDFileJointCorrespondence *)*it)
392       correspondences[i]=(*it)->deepCopy();
393   MCAuto<MEDFileJointOneStep> ret= new MEDFileJointOneStep;
394   ret->_correspondences=correspondences;
395   return ret.retn();
396 }
397
398 MEDFileJointOneStep *MEDFileJointOneStep::shallowCpy() const
399 {
400   MCAuto<MEDFileJointOneStep> ret=new MEDFileJointOneStep(*this);
401   return ret.retn();
402 }
403
404 /*!
405  * Returns a string describing \a this Joint. This description includes the correspondence and
406  * the number of correspondences.
407  *  \return std::string - the joint information string.
408  */
409 std::string MEDFileJointOneStep::simpleRepr() const
410 {
411   std::ostringstream oss;
412   oss << "(*************************************)\n(* JOINT_ONE_STEP INFORMATION: *)\n(*************************************)\n";
413   oss << "- Number of the correspondences : <<" << _correspondences.size() << ">>\n";
414   for(std::vector< MCAuto<MEDFileJointCorrespondence> >::const_iterator it=_correspondences.begin();it!=_correspondences.end();it++)
415     {
416       oss << (*it)->simpleRepr();
417     }
418   return oss.str();
419 }
420
421 INTERP_KERNEL::NormalizedCellType MEDFileJointOneStep::convertGeometryType(med_geometry_type geotype)
422 {
423   INTERP_KERNEL::NormalizedCellType result=INTERP_KERNEL::NORM_ERROR;
424   for(int i=0; i<MED_N_CELL_FIXED_GEO; i++)
425     {
426       if (typmai[i]==geotype)
427         {
428           result=typmai2[i];
429           break;
430         }
431     }
432   return result;
433 }
434
435 std::size_t MEDFileJoint::getHeapMemorySizeWithoutChildren() const
436 {
437   return _joint.capacity()*sizeof(MCAuto<MEDFileJointOneStep>);
438 }
439
440 std::vector<const BigMemoryObject *> MEDFileJoint::getDirectChildrenWithNull() const
441 {
442   return std::vector<const BigMemoryObject *>();
443 }
444
445 MEDFileJoint *MEDFileJoint::New()
446 {
447   return new MEDFileJoint();
448 }
449
450 MEDFileJoint *MEDFileJoint::New(const std::string& fileName, const std::string& mName, int curJoint)
451 {
452   MEDFileUtilities::CheckFileForRead(fileName);
453   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(), MED_ACC_RDONLY);
454   return new MEDFileJoint(fid,mName,curJoint);
455 }
456
457 MEDFileJoint *MEDFileJoint::New(med_idt fid, const std::string& mName, int curJoint)
458 {
459   return new MEDFileJoint(fid,mName,curJoint);
460 }
461
462 MEDFileJoint *MEDFileJoint::New(const std::string& jointName, const std::string& locMeshName, const std::string& remoteMeshName, int remoteMeshNum)
463 {
464   MEDFileJoint* j = new MEDFileJoint();
465   j->setJointName( jointName );
466   j->setLocalMeshName( locMeshName );
467   j->setRemoteMeshName( remoteMeshName );
468   j->setDomainNumber( remoteMeshNum );
469   return j;
470 }
471
472 MEDFileJoint::MEDFileJoint()
473 {
474 }
475
476 /*!
477  * Returns a new MEDFileJoint holding the mesh data that has been read from a given MED
478  * file. The Joint to load is specified by mesh name and a Joint iteration.
479  *  \param [in] fid - the handler ID of MED file to read.
480  *  \param [in] mName - the name of the mesh to read.
481  *  \param [in] curJoint - the iteration number of current joint.
482  *  \throw If the file is not readable.
483  *  \throw If there is no mesh with given attributes in the file.
484  */
485 MEDFileJoint::MEDFileJoint(med_idt fid, const std::string& mName, int curJoint)
486 {
487   INTERP_KERNEL::AutoPtr<char> joint_name=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
488   INTERP_KERNEL::AutoPtr<char> desc_name=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
489   INTERP_KERNEL::AutoPtr<char> rem_mesh_name=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
490   med_int domain_number=0, nstep=0, nocstpncorrespondence=0;
491   MEDFILESAFECALLERRD0(MEDsubdomainJointInfo,(fid,mName.c_str(), curJoint, joint_name, desc_name, &domain_number,rem_mesh_name,
492                                               &nstep, &nocstpncorrespondence));
493   setLocalMeshName(mName);
494   setRemoteMeshName(MEDLoaderBase::buildStringFromFortran(rem_mesh_name,MED_NAME_SIZE));
495   setDescription(MEDLoaderBase::buildStringFromFortran(desc_name,MED_COMMENT_SIZE));
496   setJointName(MEDLoaderBase::buildStringFromFortran(joint_name,MED_NAME_SIZE));
497   setDomainNumber(FromMedInt<int>(domain_number));
498   for(int cur_step=1; cur_step <= nstep; ++cur_step)
499     {
500       MEDFileJointOneStep *cor=MEDFileJointOneStep::New(fid, mName.c_str(), getJointName(), cur_step);
501       _joint.push_back(cor);
502     }
503 }
504
505 void MEDFileJoint::writeLL(med_idt fid) const
506 {
507   // if ( _loc_mesh_name.empty() )
508   //   throw INTERP_KERNEL::Exception("MEDFileJoint::write : name of a local mesh not defined!");
509   MEDFILESAFECALLERWR0(MEDsubdomainJointCr,(fid,getLocalMeshName().c_str(),getJointName().c_str(),getDescription().c_str(),getDomainNumber(),getRemoteMeshName().c_str()));
510   for(std::vector< MCAuto<MEDFileJointOneStep> >::const_iterator it=_joint.begin();it!=_joint.end();it++)
511     (*it)->writeLL(fid, getLocalMeshName(),getJointName());
512 }
513
514 void MEDFileJoint::pushStep(MEDFileJointOneStep* step)
515 {
516   if(!step)
517     throw INTERP_KERNEL::Exception("MEDFileJoint::pushStep : invalid input pointer ! should be different from 0 !");
518   _joint.push_back(step);
519   step->incrRef();
520 }
521
522 int MEDFileJoint::getNumberOfSteps() const
523 {
524   return (int)_joint.size();
525 }
526
527 /** Return a borrowed reference (caller is not responsible) */
528 MEDFileJointOneStep *MEDFileJoint::getStepAtPos(int i) const
529 {
530   if(i<0 || i>=(int)_joint.size())
531     {
532       std::ostringstream oss; oss << "MEDFileJoint::getStepAtPos : invalid step id given in parameter ! Should be in [0;" << _joint.size() << ") !";
533       throw INTERP_KERNEL::Exception(oss.str().c_str());
534     }
535   const MEDFileJointOneStep* ret = _joint[i];
536   return const_cast<MEDFileJointOneStep *>( ret );
537 }
538
539 /*!
540  * Checks if \a this and another Joint are equal.
541  *  \param [in] other - the Joint to compare with.
542  *  \return bool - \c true if the Joints are equal, \c false, else.
543  */
544 bool MEDFileJoint::isEqual(const MEDFileJoint *other) const
545 {
546   if(_loc_mesh_name!=other->_loc_mesh_name)
547     return false;
548   if(_joint_name!=other->_joint_name)
549     return false;
550   if(_desc_name!=other->_desc_name)
551       return false;
552   if(_rem_mesh_name!=other->_rem_mesh_name)
553     return false;
554   if(_domain_number!=other->_domain_number)
555     return false;
556   int nbTS(getNumberOfSteps());
557   if(nbTS!=other->getNumberOfSteps())
558     return false;
559   std::vector<bool> found(nbTS,false);
560   for(int i=0;i<nbTS;i++)
561     {
562       int j;
563       for(j=0;j<nbTS;j++)
564         {
565           if(!found[j] && getStepAtPos(i)->isEqual(other->getStepAtPos(j)))
566             {
567               found[j]=true;
568               break;
569             }
570         }
571       if(j==nbTS)
572         return false;
573     }
574   return true;
575 }
576
577 MEDFileJoint *MEDFileJoint::deepCopy() const
578 {
579   std::vector< MCAuto<MEDFileJointOneStep> > joint(_joint.size());
580   std::size_t i=0;
581   for(std::vector< MCAuto<MEDFileJointOneStep> >::const_iterator it=_joint.begin();it!=_joint.end();it++,i++)
582     if((const MEDFileJointOneStep *)*it)
583       joint[i]=(*it)->deepCopy();
584   MCAuto<MEDFileJoint> ret=new MEDFileJoint(*this);
585   ret->_joint=joint;
586   return ret.retn();
587 }
588
589 MEDFileJoint *MEDFileJoint::shallowCpy() const
590 {
591   MCAuto<MEDFileJoint> ret=new MEDFileJoint(*this);
592   return ret.retn();
593 }
594
595 bool MEDFileJoint::changeJointNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
596 {
597   for(std::vector< std::pair<std::string,std::string> >::const_iterator it=modifTab.begin();it!=modifTab.end();it++)
598     {
599       if((*it).first==_joint_name)
600         {
601           _joint_name=(*it).second;
602           return true;
603         }
604     }
605   return false;
606 }
607
608 /*!
609  * Returns a string describing \a this mesh. This description includes the correspondence and
610  * the number correspondence.
611  *  \return std::string - the joint information string.
612  */
613 std::string MEDFileJoint::simpleRepr() const
614 {
615   std::ostringstream oss;
616   oss << "(*************************************)\n(* JOINT INFORMATION: *)\n(*************************************)\n";
617   oss << "- Local Mesh name : <<" << getLocalMeshName() << ">>\n";
618   oss << "- Remote Mesh name : <<" << getRemoteMeshName() << ">>\n";
619   oss << "- Description : <<" << getDescription() << ">>\n";
620   oss << "- Joint name : <<" << getJointName() << ">>\n";
621   oss << "- Domain number : " << getDomainNumber() << "\n";
622   for(std::vector< MCAuto<MEDFileJointOneStep> >::const_iterator it=_joint.begin();it!=_joint.end();it++)
623     {
624       oss << (*it)->simpleRepr();
625     }
626   return oss.str();
627 }
628
629 MEDFileJoints *MEDFileJoints::New()
630 {
631   return new MEDFileJoints;
632 }
633
634 MEDFileJoints *MEDFileJoints::New(const std::string& fileName, const std::string& meshName)
635 {
636   MEDFileUtilities::CheckFileForRead(fileName);
637   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(), MED_ACC_RDONLY);
638   return new MEDFileJoints( fid, meshName );
639 }
640
641 MEDFileJoints *MEDFileJoints::New(med_idt fid, const std::string& meshName)
642 {
643   return new MEDFileJoints( fid, meshName );
644 }
645
646 void MEDFileJoints::writeLL(med_idt fid) const
647 {
648   for(std::vector< MCAuto<MEDFileJoint> >::const_iterator it=_joints.begin();it!=_joints.end();it++)
649     (*it)->writeLL(fid);
650 }
651
652 std::string MEDFileJoints::getMeshName() const
653 {
654   for ( size_t i = 0; i <= _joints.size(); ++i )
655     if ( (const MEDFileJoint*) _joints[i] )
656       return _joints[i]->getLocalMeshName();
657
658   return "";
659 }
660
661 int MEDFileJoints::getNumberOfJoints() const
662 {
663   return (int)_joints.size();
664 }
665
666 /** Return a borrowed reference (caller is not responsible) */
667 MEDFileJoint *MEDFileJoints::getJointAtPos(int i) const
668 {
669   if(i<0 || i>=(int)_joints.size())
670     {
671       std::ostringstream oss; oss << "MEDFileJoints::getJointAtPos : invalid joint id given in parameter ! Should be in [0;" << _joints.size() << ") !";
672       throw INTERP_KERNEL::Exception(oss.str().c_str());
673     }
674   const MEDFileJoint* ret = _joints[i];
675   return const_cast<MEDFileJoint *>( ret );
676 }
677
678
679 /** Return a borrowed reference (caller is not responsible) */
680 MEDFileJoint *MEDFileJoints::getJointWithName(const std::string& jname) const
681 {
682   std::vector<std::string> js=getJointsNames();
683   std::vector<std::string>::iterator it=std::find(js.begin(),js.end(),jname);
684   if(it==js.end())
685     {
686       std::ostringstream oss; oss << "MEDFileJoints::getJointWithName : Joint  \"" << jname << "\" does not exist in this ! Existing are : ";
687       std::copy(js.begin(),js.end(),std::ostream_iterator<std::string>(oss," "));
688       throw INTERP_KERNEL::Exception(oss.str().c_str());
689     }
690   return getJointAtPos((int)std::distance(js.begin(),it));
691 }
692
693 std::vector<std::string> MEDFileJoints::getJointsNames() const
694 {
695   std::vector<std::string> ret(_joints.size());
696   int i=0;
697   for(std::vector< MCAuto<MEDFileJoint> >::const_iterator it=_joints.begin();it!=_joints.end();it++,i++)
698     {
699       const MEDFileJoint *f=(*it);
700       if(f)
701         {
702           ret[i]=f->getJointName();
703         }
704       else
705         {
706           std::ostringstream oss; oss << "MEDFileJoints::getJointsNames : At rank #" << i << " joint is not defined !";
707           throw INTERP_KERNEL::Exception(oss.str().c_str());
708         }
709     }
710   return ret;
711 }
712
713 bool MEDFileJoints::changeJointNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
714 {
715   bool ret=false;
716   for(std::vector< MCAuto<MEDFileJoint> >::iterator it=_joints.begin();it!=_joints.end();it++)
717     {
718       MEDFileJoint *cur(*it);
719       if(cur)
720         ret=cur->changeJointNames(modifTab) || ret;
721     }
722   return ret;
723 }
724
725 void MEDFileJoints::resize(int newSize)
726 {
727   _joints.resize(newSize);
728 }
729
730 void MEDFileJoints::pushJoint(MEDFileJoint *joint)
731 {
732   if(!joint)
733     throw INTERP_KERNEL::Exception("MEDFileJoints::pushJoint() : invalid input pointer ! should be different from 0 !");
734   if ( !_joints.empty() &&
735        _joints[0]->getLocalMeshName() != joint->getLocalMeshName() )
736     throw INTERP_KERNEL::Exception("MEDFileJoints::pushJoint() : different names of local meshes ! should be equal !");
737
738   _joints.push_back(joint);
739   joint->incrRef();
740 }
741
742 void MEDFileJoints::setJointAtPos(int i, MEDFileJoint *joint)
743 {
744   if(!joint)
745     throw INTERP_KERNEL::Exception("MEDFileJoints::setJointAtPos : invalid input pointer ! should be different from 0 !");
746   if(i>=(int)_joints.size())
747     _joints.resize(i+1);
748   _joints[i]=joint;
749   joint->incrRef();
750 }
751
752 void MEDFileJoints::destroyJointAtPos(int i)
753 {
754   if(i<0 || i>=(int)_joints.size())
755     {
756       std::ostringstream oss; oss << "MEDFileJoints::destroyJointAtPos : Invalid given id in input (" << i << ") should be in [0," << _joints.size() << ") !";
757       throw INTERP_KERNEL::Exception(oss.str().c_str());
758     }
759   _joints.erase(_joints.begin()+i);
760 }
761
762 MEDFileJoints::MEDFileJoints()
763 {
764 }
765
766 MEDFileJoints::MEDFileJoints(med_idt fid, const std::string& meshName)
767 {
768   med_int num_joint=MEDnSubdomainJoint(fid, meshName.c_str() );
769   for(int i = 1; i <= num_joint; i++)
770     _joints.push_back(MEDFileJoint::New(fid,meshName,i));
771 }
772
773 MEDFileJoints *MEDFileJoints::deepCopy() const
774 {
775   std::vector< MCAuto<MEDFileJoint> > joints(_joints.size());
776   std::size_t i=0;
777   for(std::vector< MCAuto<MEDFileJoint> >::const_iterator it=_joints.begin();it!=_joints.end();it++,i++)
778     if((const MEDFileJoint *)*it)
779       joints[i]=(*it)->deepCopy();
780   MCAuto<MEDFileJoints> ret=MEDFileJoints::New();
781   ret->_joints=joints;
782   return ret.retn();
783 }
784
785 std::size_t MEDFileJoints::getHeapMemorySizeWithoutChildren() const
786 {
787   return _joints.capacity()*(sizeof(MCAuto<MEDFileJoint>));
788 }
789
790 std::vector<const BigMemoryObject *> MEDFileJoints::getDirectChildrenWithNull() const
791 {
792   std::vector<const BigMemoryObject *> ret;
793   for(std::vector< MCAuto<MEDFileJoint> >::const_iterator it=_joints.begin();it!=_joints.end();it++)
794     ret.push_back((const MEDFileJoint *)*it);
795   return ret;
796 }
797
798 std::string MEDFileJoints::simpleRepr() const
799 {
800   std::ostringstream oss;
801   oss << "(*****************)\n(* MEDFileJoints *)\n(*****************)\n\n";
802   simpleReprWithoutHeader(oss);
803   return oss.str();
804 }
805
806 void MEDFileJoints::simpleReprWithoutHeader(std::ostream& oss) const
807 {
808   int nbOfJoints=getNumberOfJoints();
809   oss << "There are " << nbOfJoints << " joints with the following names : \n";
810   std::vector<std::string> jns=getJointsNames();
811   for(int i=0;i<nbOfJoints;i++)
812     oss << "  - #" << i << " \"" << jns[i] << "\"\n";
813   for(std::vector< MCAuto<MEDFileJoint> >::const_iterator it=_joints.begin();it!=_joints.end();it++)
814     {
815       oss << (*it)->simpleRepr();
816     }
817 }