]> SALOME platform Git repositories - modules/med.git/blob - src/MEDCoupling/MEDCouplingIMesh.cxx
Salome HOME
First test OK with createPatchesFromCriterion
[modules/med.git] / src / MEDCoupling / MEDCouplingIMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
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 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingIMesh.hxx"
22 #include "MEDCouplingCMesh.hxx"
23 #include "MEDCouplingMemArray.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25
26 #include <functional>
27 #include <algorithm>
28 #include <sstream>
29 #include <numeric>
30
31 using namespace ParaMEDMEM;
32
33 MEDCouplingIMesh::MEDCouplingIMesh():_space_dim(-1)
34 {
35   _origin[0]=0.; _origin[1]=0.; _origin[2]=0.;
36   _dxyz[0]=0.; _dxyz[1]=0.; _dxyz[2]=0.;
37   _structure[0]=0; _structure[1]=0; _structure[2]=0;
38 }
39
40 MEDCouplingIMesh::MEDCouplingIMesh(const MEDCouplingIMesh& other, bool deepCopy):MEDCouplingStructuredMesh(other,deepCopy),_space_dim(other._space_dim),_axis_unit(other._axis_unit)
41 {
42   _origin[0]=other._origin[0]; _origin[1]=other._origin[1]; _origin[2]=other._origin[2];
43   _dxyz[0]=other._dxyz[0]; _dxyz[1]=other._dxyz[1]; _dxyz[2]=other._dxyz[2];
44   _structure[0]=other._structure[0]; _structure[1]=other._structure[1]; _structure[2]=other._structure[2];
45 }
46
47 MEDCouplingIMesh::~MEDCouplingIMesh()
48 {
49 }
50
51 MEDCouplingIMesh *MEDCouplingIMesh::New()
52 {
53   return new MEDCouplingIMesh;
54 }
55
56 MEDCouplingIMesh *MEDCouplingIMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
57                                         const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
58 {
59   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> ret(new MEDCouplingIMesh);
60   ret->setName(meshName);
61   ret->setSpaceDimension(spaceDim);
62   ret->setNodeStruct(nodeStrctStart,nodeStrctStop);
63   ret->setOrigin(originStart,originStop);
64   ret->setDXYZ(dxyzStart,dxyzStop);
65   return ret.retn();
66 }
67
68 MEDCouplingMesh *MEDCouplingIMesh::deepCpy() const
69 {
70   return clone(true);
71 }
72
73 MEDCouplingIMesh *MEDCouplingIMesh::clone(bool recDeepCpy) const
74 {
75   return new MEDCouplingIMesh(*this,recDeepCpy);
76 }
77
78 void MEDCouplingIMesh::setNodeStruct(const int *nodeStrctStart, const int *nodeStrctStop)
79 {
80   checkSpaceDimension();
81   int sz((int)std::distance(nodeStrctStart,nodeStrctStop));
82   if(sz!=_space_dim)
83     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::setNodeStruct : input vector of node structure has not the right size ! Or change space dimension before calling it !");
84   std::copy(nodeStrctStart,nodeStrctStop,_structure);
85   declareAsNew();
86 }
87
88 std::vector<int> MEDCouplingIMesh::getNodeStruct() const
89 {
90   checkSpaceDimension();
91   return std::vector<int>(_structure,_structure+_space_dim);
92 }
93
94 void MEDCouplingIMesh::setOrigin(const double *originStart, const double *originStop)
95 {
96   checkSpaceDimension();
97   int sz((int)std::distance(originStart,originStop));
98   if(sz!=_space_dim)
99     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::setOrigin : input vector of origin vector has not the right size ! Or change space dimension before calling it !");
100   std::copy(originStart,originStop,_origin);
101   declareAsNew();
102 }
103
104 std::vector<double> MEDCouplingIMesh::getOrigin() const
105 {
106   checkSpaceDimension();
107   return std::vector<double>(_origin,_origin+_space_dim);
108 }
109
110 void MEDCouplingIMesh::setDXYZ(const double *dxyzStart, const double *dxyzStop)
111 {
112   checkSpaceDimension();
113   int sz((int)std::distance(dxyzStart,dxyzStop));
114   if(sz!=_space_dim)
115     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::setDXYZ : input vector of dxyz vector has not the right size ! Or change space dimension before calling it !");
116   std::copy(dxyzStart,dxyzStop,_dxyz);
117   declareAsNew();
118 }
119
120 std::vector<double> MEDCouplingIMesh::getDXYZ() const
121 {
122   checkSpaceDimension();
123   return std::vector<double>(_dxyz,_dxyz+_space_dim);
124 }
125
126 void MEDCouplingIMesh::setAxisUnit(const std::string& unitName)
127 {
128   _axis_unit=unitName;
129   declareAsNew();
130 }
131
132 std::string MEDCouplingIMesh::getAxisUnit() const
133 {
134   return _axis_unit;
135 }
136
137 /*!
138  * This method returns the measure of any cell in \a this.
139  * This specific method of image grid mesh utilizes the fact that any cell in \a this have the same measure.
140  * The value returned by this method is those used to feed the returned field in the MEDCouplingIMesh::getMeasureField.
141  *
142  * \sa getMeasureField
143  */
144 double MEDCouplingIMesh::getMeasureOfAnyCell() const
145 {
146   checkCoherency();
147   int dim(getSpaceDimension());
148   double ret(1.);
149   for(int i=0;i<dim;i++)
150     ret*=fabs(_dxyz[i]);
151   return ret;
152 }
153
154 /*!
155  * This method is allows to convert \a this into MEDCouplingCMesh instance.
156  * This method is the middle level between MEDCouplingIMesh and the most general MEDCouplingUMesh.
157  * This method is useful for MED writers that do not have still the image grid support.
158  *
159  * \sa MEDCouplingMesh::buildUnstructured
160  */
161 MEDCouplingCMesh *MEDCouplingIMesh::convertToCartesian() const
162 {
163   checkCoherency();
164   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCMesh> ret(MEDCouplingCMesh::New());
165   try
166   { ret->copyTinyInfoFrom(this); }
167   catch(INTERP_KERNEL::Exception& ) { }
168   int spaceDim(getSpaceDimension());
169   std::vector<std::string> infos(buildInfoOnComponents());
170   for(int i=0;i<spaceDim;i++)
171     {
172       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New()); arr->alloc(_structure[i],1); arr->setInfoOnComponent(0,infos[i]);
173       arr->iota(); arr->applyLin(_dxyz[i],_origin[i]);
174       ret->setCoordsAt(i,arr);
175     }
176   return ret.retn();
177 }
178
179 /*!
180  * This method refines \a this uniformaly along all of its dimensions. In case of success the space covered by \a this will remain
181  * the same before the invocation except that the number of cells will be multiplied by \a factor ^ this->getMeshDimension().
182  * The origin of \a this will be not touched only spacing and node structure will be changed.
183  * This method can be useful for AMR users.
184  */
185 void MEDCouplingIMesh::refineWithFactor(const std::vector<int>& factors)
186 {
187   if((int)factors.size()!=_space_dim)
188     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::refineWithFactor : refinement factors must have size equal to spaceDim !");
189   checkCoherency();
190   std::vector<int> structure(_structure,_structure+3);
191   std::vector<double> dxyz(_dxyz,_dxyz+3);
192   for(int i=0;i<_space_dim;i++)
193     {
194       if(factors[i]<=0)
195         {
196           std::ostringstream oss; oss << "MEDCouplingIMesh::refineWithFactor : factor for axis #" << i << " (" << factors[i] << ")is invalid ! Must be > 0 !";
197           throw INTERP_KERNEL::Exception(oss.str().c_str());
198         }
199       int factAbs(std::abs(factors[i]));
200       double fact2(1./(double)factors[i]);
201       structure[i]=(_structure[i]-1)*factAbs+1;
202       dxyz[i]=fact2*_dxyz[i];
203     }
204   std::copy(structure.begin(),structure.end(),_structure);
205   std::copy(dxyz.begin(),dxyz.end(),_dxyz);
206   declareAsNew();
207 }
208
209 /*!
210  * This method returns a newly created mesh containing a single cell in it. This returned cell covers exactly the space covered by \a this.
211  *
212  * \return MEDCouplingIMesh * - A newly created object (to be managed by the caller with decrRef) containing simply one cell.
213  *
214  * \throw if \a this does not pass the \c checkCoherency test.
215  */
216 MEDCouplingIMesh *MEDCouplingIMesh::asSingleCell() const
217 {
218   checkCoherency();
219   int spaceDim(getSpaceDimension()),nodeSt[3];
220   double dxyz[3];
221   for(int i=0;i<spaceDim;i++)
222     {
223       if(_structure[i]>=2)
224         {
225           nodeSt[i]=2;
226           dxyz[i]=(_structure[i]-1)*_dxyz[i];
227         }
228       else
229         {
230           nodeSt[i]=_structure[i];
231           dxyz[i]=_dxyz[i];
232         }
233     }
234   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> ret(MEDCouplingIMesh::New(getName(),getSpaceDimension(),nodeSt,nodeSt+spaceDim,_origin,_origin+spaceDim,dxyz,dxyz+spaceDim));
235   ret->copyTinyInfoFrom(this);
236   return ret.retn();
237 }
238
239 /*!
240  * This static method is useful to condense field on cells of a MEDCouplingIMesh instance coming from a refinement ( MEDCouplingIMesh::refineWithFactor for example)
241  * to a coarse MEDCouplingIMesh instance. So this method can be seen as a specialization in P0P0 conservative interpolation non overlaping from fine image mesh
242  * to a coarse image mesh. Only tuples ( deduced from \a fineLocInCoarse ) of \a coarseDA will be modified. Other tuples of \a coarseDA will be let unchanged.
243  *
244  * \param [in,out] coarseDA The DataArrayDouble corresponding to the a cell field of a coarse mesh whose cell structure is defined by \a coarseSt.
245  * \param [in] coarseSt The cell structure of coarse mesh.
246  * \param [in] fineDA The DataArray containing the cell field on uniformly refined mesh
247  * \param [in] fineLocInCoarse The cell localization of refined mesh into the coarse one.
248  * \param [in] facts The refinement coefficient per axis.
249  * \sa SpreadCoarseToFine
250  */
251 void MEDCouplingIMesh::CondenseFineToCoarse(DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, const DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts)
252 {
253   if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated())
254     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the parameters 1 or 3 are NULL or not allocated !");
255   int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseSt)),nbOfTuplesInFineExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(fineLocInCoarse));
256   int nbCompo(fineDA->getNumberOfComponents());
257   if(coarseDA->getNumberOfComponents()!=nbCompo)
258     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the number of components of fine DA and coarse one mismatches !");
259   if(meshDim!=(int)fineLocInCoarse.size() || meshDim!=(int)facts.size())
260     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : the size of fineLocInCoarse (4th param) and facts (5th param) must be equal to the sier of coarseSt (2nd param) !");
261   if(coarseDA->getNumberOfTuples()!=nbOfTuplesInCoarseExp)
262     {
263       std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarse : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !";
264       throw INTERP_KERNEL::Exception(oss.str().c_str());
265     }
266   int nbTuplesFine(fineDA->getNumberOfTuples());
267   if(nbTuplesFine%nbOfTuplesInFineExp!=0)
268     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : Invalid nb of tuples in fine DataArray regarding its structure !");
269   int fact(std::accumulate(facts.begin(),facts.end(),1,std::multiplies<int>()));
270   if(nbTuplesFine!=fact*nbOfTuplesInFineExp)
271     {
272       std::ostringstream oss; oss << "MEDCouplingIMesh::CondenseFineToCoarse : Invalid number of tuples ("  << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!";
273       throw INTERP_KERNEL::Exception(oss.str().c_str());
274     }
275   // to improve use jump-iterator. Factorizes with SwitchOnIdsFrom BuildExplicitIdsFrom
276   double *outPtr(coarseDA->getPointer());
277   const double *inPtr(fineDA->begin());
278   //
279   std::vector<int> dims(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse));
280   switch(meshDim)
281   {
282     case 1:
283       {
284         int offset(fineLocInCoarse[0].first),fact0(facts[0]);
285         for(int i=0;i<dims[0];i++)
286           {
287             double *loc(outPtr+(offset+i)*nbCompo);
288             for(int ifact=0;ifact<fact0;ifact++,inPtr+=nbCompo)
289               {
290                 if(ifact!=0)
291                   std::transform(inPtr,inPtr+nbCompo,loc,loc,std::plus<double>());
292                 else
293                   std::copy(inPtr,inPtr+nbCompo,loc);
294               }
295           }
296         break;
297       }
298     case 2:
299       {
300         int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first),fact1(facts[1]),fact0(facts[0]);
301         for(int j=0;j<dims[1];j++)
302           {
303             for(int jfact=0;jfact<fact1;jfact++)
304               {
305                 for(int i=0;i<dims[0];i++)
306                   {
307                     double *loc(outPtr+(kk+i)*nbCompo);
308                     for(int ifact=0;ifact<fact0;ifact++,inPtr+=nbCompo)
309                       {
310                         if(jfact!=0 || ifact!=0)
311                           std::transform(inPtr,inPtr+nbCompo,loc,loc,std::plus<double>());
312                         else
313                           std::copy(inPtr,inPtr+nbCompo,loc);
314                       }
315                   }
316               }
317             kk+=coarseSt[0];
318           }
319         break;
320       }
321     case 3:
322       {
323         int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first+coarseSt[0]*coarseSt[1]*fineLocInCoarse[2].first),fact2(facts[2]),fact1(facts[1]),fact0(facts[0]);
324         for(int k=0;k<dims[2];k++)
325           {
326             for(int kfact=0;kfact<fact2;kfact++)
327               {
328                 for(int j=0;j<dims[1];j++)
329                   {
330                     for(int jfact=0;jfact<fact1;jfact++)
331                       {
332                         for(int i=0;i<dims[0];i++)
333                           {
334                             double *loc(outPtr+(kk+i+j*coarseSt[0])*nbCompo);
335                             for(int ifact=0;ifact<fact0;ifact++,inPtr+=nbCompo)
336                               {
337                                 if(kfact!=0 || jfact!=0 || ifact!=0)
338                                   std::transform(inPtr,inPtr+nbCompo,loc,loc,std::plus<double>());
339                                 else
340                                   std::copy(inPtr,inPtr+nbCompo,loc);
341                               }
342                           }
343                       }
344                   }
345               }
346             kk+=coarseSt[0]*coarseSt[1];
347           }
348         break;
349       }
350     default:
351       throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CondenseFineToCoarse : only dimensions 1, 2 and 3 supported !");
352   }
353 }
354
355 /*!
356  * This method spreads the values of coarse data \a coarseDA into \a fineDA.
357  *
358  * \param [in] coarseDA The DataArrayDouble corresponding to the a cell field of a coarse mesh whose cell structure is defined by \a coarseSt.
359  * \param [in] coarseSt The cell structure of coarse mesh.
360  * \param [in,out] fineDA The DataArray containing the cell field on uniformly refined mesh
361  * \param [in] fineLocInCoarse The cell localization of refined mesh into the coarse one.
362  * \param [in] facts The refinement coefficient per axis.
363  * \sa CondenseFineToCoarse
364  */
365 void MEDCouplingIMesh::SpreadCoarseToFine(const DataArrayDouble *coarseDA, const std::vector<int>& coarseSt, DataArrayDouble *fineDA, const std::vector< std::pair<int,int> >& fineLocInCoarse, const std::vector<int>& facts)
366 {
367   if(!coarseDA || !coarseDA->isAllocated() || !fineDA || !fineDA->isAllocated())
368     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : the parameters 1 or 3 are NULL or not allocated !");
369   int meshDim((int)coarseSt.size()),nbOfTuplesInCoarseExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(coarseSt)),nbOfTuplesInFineExp(MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(fineLocInCoarse));
370   int nbCompo(fineDA->getNumberOfComponents());
371   if(coarseDA->getNumberOfComponents()!=nbCompo)
372     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : the number of components of fine DA and coarse one mismatches !");
373   if(meshDim!=(int)fineLocInCoarse.size() || meshDim!=(int)facts.size())
374     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : the size of fineLocInCoarse (4th param) and facts (5th param) must be equal to the sier of coarseSt (2nd param) !");
375   if(coarseDA->getNumberOfTuples()!=nbOfTuplesInCoarseExp)
376     {
377       std::ostringstream oss; oss << "MEDCouplingIMesh::SpreadCoarseToFine : Expecting " << nbOfTuplesInCoarseExp << " tuples having " << coarseDA->getNumberOfTuples() << " !";
378       throw INTERP_KERNEL::Exception(oss.str().c_str());
379     }
380   int nbTuplesFine(fineDA->getNumberOfTuples());
381   if(nbTuplesFine%nbOfTuplesInFineExp!=0)
382     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : Invalid nb of tuples in fine DataArray regarding its structure !");
383   int fact(std::accumulate(facts.begin(),facts.end(),1,std::multiplies<int>()));
384   if(nbTuplesFine!=fact*nbOfTuplesInFineExp)
385     {
386       std::ostringstream oss; oss << "MEDCouplingIMesh::SpreadCoarseToFine : Invalid number of tuples ("  << nbTuplesFine << ") of fine dataarray is invalid ! Must be " << fact*nbOfTuplesInFineExp << "!";
387       throw INTERP_KERNEL::Exception(oss.str().c_str());
388     }
389   // to improve use jump-iterator. Factorizes with SwitchOnIdsFrom BuildExplicitIdsFrom
390   double *outPtr(fineDA->getPointer());
391   const double *inPtr(coarseDA->begin());
392   //
393   std::vector<int> dims(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(fineLocInCoarse));
394   switch(meshDim)
395   {
396     case 1:
397       {
398         int offset(fineLocInCoarse[0].first),fact0(facts[0]);
399         for(int i=0;i<dims[0];i++)
400           {
401             const double *loc(inPtr+(offset+i)*nbCompo);
402             for(int ifact=0;ifact<fact0;ifact++)
403               outPtr=std::copy(loc,loc+nbCompo,outPtr);
404           }
405         break;
406       }
407     case 2:
408       {
409         int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first),fact0(facts[0]),fact1(facts[1]);
410         for(int j=0;j<dims[1];j++)
411           {
412             for(int jfact=0;jfact<fact1;jfact++)
413               {
414                 for(int i=0;i<dims[0];i++)
415                   {
416                     const double *loc(inPtr+(kk+i)*nbCompo);
417                     for(int ifact=0;ifact<fact0;ifact++)
418                       outPtr=std::copy(loc,loc+nbCompo,outPtr);
419                   }
420               }
421             kk+=coarseSt[0];
422           }
423         break;
424       }
425     case 3:
426       {
427         int kk(fineLocInCoarse[0].first+coarseSt[0]*fineLocInCoarse[1].first+coarseSt[0]*coarseSt[1]*fineLocInCoarse[2].first),fact0(facts[0]),fact1(facts[2]),fact2(facts[2]);
428         for(int k=0;k<dims[2];k++)
429           {
430             for(int kfact=0;kfact<fact2;kfact++)
431               {
432                 for(int j=0;j<dims[1];j++)
433                   {
434                     for(int jfact=0;jfact<fact1;jfact++)
435                       {
436                         for(int i=0;i<dims[0];i++)
437                           {
438                             const double *loc(inPtr+(kk+i+j*coarseSt[0])*nbCompo);
439                             for(int ifact=0;ifact<fact0;ifact++)
440                               outPtr=std::copy(loc,loc+nbCompo,outPtr);
441                           }
442                       }
443                   }
444               }
445             kk+=coarseSt[0]*coarseSt[1];
446           }
447         break;
448       }
449     default:
450       throw INTERP_KERNEL::Exception("MEDCouplingIMesh::SpreadCoarseToFine : only dimensions 1, 2 and 3 supported !");
451   }
452 }
453
454 void MEDCouplingIMesh::setSpaceDimension(int spaceDim)
455 {
456   if(spaceDim==_space_dim)
457     return ;
458   CheckSpaceDimension(spaceDim);
459   _space_dim=spaceDim;
460   declareAsNew();
461 }
462
463 void MEDCouplingIMesh::updateTime() const
464 {
465 }
466
467 std::size_t MEDCouplingIMesh::getHeapMemorySizeWithoutChildren() const
468 {
469   return MEDCouplingStructuredMesh::getHeapMemorySizeWithoutChildren();
470 }
471
472 std::vector<const BigMemoryObject *> MEDCouplingIMesh::getDirectChildren() const
473 {
474   return std::vector<const BigMemoryObject *>();
475 }
476
477 /*!
478  * This method copyies all tiny strings from other (name and components name).
479  * @throw if other and this have not same mesh type.
480  */
481 void MEDCouplingIMesh::copyTinyStringsFrom(const MEDCouplingMesh *other)
482
483   const MEDCouplingIMesh *otherC=dynamic_cast<const MEDCouplingIMesh *>(other);
484   if(!otherC)
485     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::copyTinyStringsFrom : meshes have not same type !");
486   MEDCouplingStructuredMesh::copyTinyStringsFrom(other);
487   declareAsNew();
488 }
489
490 bool MEDCouplingIMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
491 {
492   if(!other)
493     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::isEqualIfNotWhy : input other pointer is null !");
494   const MEDCouplingIMesh *otherC(dynamic_cast<const MEDCouplingIMesh *>(other));
495   if(!otherC)
496     {
497       reason="mesh given in input is not castable in MEDCouplingIMesh !";
498       return false;
499     }
500   if(!MEDCouplingStructuredMesh::isEqualIfNotWhy(other,prec,reason))
501     return false;
502   if(!isEqualWithoutConsideringStrInternal(otherC,prec,reason))
503     return false;
504   if(_axis_unit!=otherC->_axis_unit)
505     {
506       reason="The units of axis are not the same !";
507       return false;
508     }
509   return true;
510 }
511
512 bool MEDCouplingIMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
513 {
514   const MEDCouplingIMesh *otherC=dynamic_cast<const MEDCouplingIMesh *>(other);
515   if(!otherC)
516     return false;
517   std::string tmp;
518   return isEqualWithoutConsideringStrInternal(other,prec,tmp);
519 }
520
521 bool MEDCouplingIMesh::isEqualWithoutConsideringStrInternal(const MEDCouplingMesh *other, double prec, std::string& reason) const
522 {
523   const MEDCouplingIMesh *otherC=dynamic_cast<const MEDCouplingIMesh *>(other);
524   if(!otherC)
525     return false;
526   if(_space_dim!=otherC->_space_dim)
527     {
528       std::ostringstream oss;
529       oss << "The spaceDimension of this (" << _space_dim << ") is not equal to those of other (" << otherC->_space_dim << ") !";
530       return false;
531     }
532   checkSpaceDimension();
533   for(int i=0;i<_space_dim;i++)
534     {
535       if(fabs(_origin[i]-otherC->_origin[i])>prec)
536         {
537           std::ostringstream oss;
538           oss << "The origin of this and other differs at " << i << " !";
539           reason=oss.str();
540           return false;
541         }
542     }
543   for(int i=0;i<_space_dim;i++)
544     {
545       if(fabs(_dxyz[i]-otherC->_dxyz[i])>prec)
546         {
547           std::ostringstream oss;
548           oss << "The delta of this and other differs at " << i << " !";
549           reason=oss.str();
550           return false;
551         }
552     }
553   for(int i=0;i<_space_dim;i++)
554     {
555       if(_structure[i]!=otherC->_structure[i])
556         {
557           std::ostringstream oss;
558           oss << "The structure of this and other differs at " << i << " !";
559           reason=oss.str();
560           return false;
561         }
562     }
563   return true;
564 }
565
566 void MEDCouplingIMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
567                                             DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const
568 {
569   if(!isEqualWithoutConsideringStr(other,prec))
570     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::checkDeepEquivalWith : Meshes are not the same !");
571 }
572
573 /*!
574  * Nothing is done here (except to check that the other is a ParaMEDMEM::MEDCouplingIMesh instance too).
575  * The user intend that the nodes are the same, so by construction of ParaMEDMEM::MEDCouplingIMesh, \a this and \a other are the same !
576  */
577 void MEDCouplingIMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
578                                                        DataArrayInt *&cellCor) const
579 {
580   if(!isEqualWithoutConsideringStr(other,prec))
581     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::checkDeepEquivalOnSameNodesWith : Meshes are not the same !");
582 }
583
584 void MEDCouplingIMesh::checkCoherency() const
585 {
586   checkSpaceDimension();
587   for(int i=0;i<_space_dim;i++)
588     if(_structure[i]<1)
589       {
590         std::ostringstream oss; oss << "MEDCouplingIMesh::checkCoherency : On axis " << i << "/" << _space_dim << ", number of nodes is equal to " << _structure[i] << " ! must be >=1 !";
591         throw INTERP_KERNEL::Exception(oss.str().c_str());
592       }
593 }
594
595 void MEDCouplingIMesh::checkCoherency1(double eps) const
596 {
597   checkCoherency();
598 }
599
600 void MEDCouplingIMesh::checkCoherency2(double eps) const
601 {
602   checkCoherency1(eps);
603 }
604
605 void MEDCouplingIMesh::getNodeGridStructure(int *res) const
606 {
607   checkSpaceDimension();
608   std::copy(_structure,_structure+_space_dim,res);
609 }
610
611 std::vector<int> MEDCouplingIMesh::getNodeGridStructure() const
612 {
613   checkSpaceDimension();
614   std::vector<int> ret(_structure,_structure+_space_dim);
615   return ret;
616 }
617
618 MEDCouplingStructuredMesh *MEDCouplingIMesh::buildStructuredSubPart(const std::vector< std::pair<int,int> >& cellPart) const
619 {
620   checkCoherency();
621   int dim(getSpaceDimension());
622   if(dim!=(int)cellPart.size())
623     {
624       std::ostringstream oss; oss << "MEDCouplingIMesh::buildStructuredSubPart : the space dimension is " << dim << " and cell part size is " << cellPart.size() << " !";
625       throw INTERP_KERNEL::Exception(oss.str().c_str());
626     }
627   double retOrigin[3]={0.,0.,0.};
628   int retStruct[3]={0,0,0};
629   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> ret(dynamic_cast<MEDCouplingIMesh *>(deepCpy()));
630   for(int i=0;i<dim;i++)
631     {
632       int startNode(cellPart[i].first),endNode(cellPart[i].second+1);
633       int myDelta(endNode-startNode);
634       if(startNode<0 || startNode>=_structure[i])
635         {
636           std::ostringstream oss; oss << "MEDCouplingIMesh::buildStructuredSubPart : At dimension #" << i << " the start node id is " << startNode << " it should be in [0," << _structure[i] << ") !";
637           throw INTERP_KERNEL::Exception(oss.str().c_str());
638         }
639       if(myDelta<0 || myDelta>_structure[i])
640         {
641           std::ostringstream oss; oss << "MEDCouplingIMesh::buildStructuredSubPart : Along dimension #" << i << " the number of nodes is " << _structure[i] << ", and you are requesting for " << myDelta << " nodes wide range !" << std::endl;
642           throw INTERP_KERNEL::Exception(oss.str().c_str());
643         }
644       retOrigin[i]=_origin[i]+startNode*_dxyz[i];
645       retStruct[i]=myDelta;
646     }
647   ret->setNodeStruct(retStruct,retStruct+dim);
648   ret->setOrigin(retOrigin,retOrigin+dim);
649   ret->checkCoherency();
650   return ret.retn();
651 }
652
653 /*!
654  * Return the space dimension of \a this.
655  */
656 int MEDCouplingIMesh::getSpaceDimension() const
657 {
658   return _space_dim;
659 }
660
661 void MEDCouplingIMesh::getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const
662 {
663   int tmp[3];
664   int spaceDim(getSpaceDimension());
665   getSplitNodeValues(tmp);
666   int tmp2[3];
667   GetPosFromId(nodeId,spaceDim,tmp,tmp2);
668   for(int j=0;j<spaceDim;j++)
669     coo.push_back(_origin[j]+_dxyz[j]*tmp2[j]);
670 }
671
672 std::string MEDCouplingIMesh::simpleRepr() const
673 {
674   std::ostringstream ret;
675   ret << "Image grid with name : \"" << getName() << "\"\n";
676   ret << "Description of mesh : \"" << getDescription() << "\"\n";
677   int tmpp1,tmpp2;
678   double tt(getTime(tmpp1,tmpp2));
679   int spaceDim(_space_dim);
680   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
681   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
682   ret << "Space dimension : " << spaceDim << "\n";
683   if(spaceDim<0 || spaceDim>3)
684     return ret.str();
685   ret << "The nodal structure is : "; std::copy(_structure,_structure+spaceDim,std::ostream_iterator<int>(ret," ")); ret << "\n";
686   ret << "The origin position is [" << _axis_unit << "]: ";
687   std::copy(_origin,_origin+spaceDim,std::ostream_iterator<double>(ret," ")); ret << "\n";
688   ret << "The intervals along axis are : ";
689   std::copy(_dxyz,_dxyz+spaceDim,std::ostream_iterator<double>(ret," ")); ret << "\n";
690   return ret.str();
691 }
692
693 std::string MEDCouplingIMesh::advancedRepr() const
694 {
695   return simpleRepr();
696 }
697
698 void MEDCouplingIMesh::getBoundingBox(double *bbox) const
699 {
700   checkCoherency();
701   int dim(getSpaceDimension());
702   for(int idim=0; idim<dim; idim++)
703     {
704       bbox[2*idim]=_origin[idim];
705       bbox[2*idim+1]=_origin[idim]+_dxyz[idim]*_structure[idim];
706     }
707 }
708
709 /*!
710  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
711  * mesh.<br>
712  * For 1D cells, the returned field contains lengths.<br>
713  * For 2D cells, the returned field contains areas.<br>
714  * For 3D cells, the returned field contains volumes.
715  *  \param [in] isAbs - a not used parameter.
716  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
717  *         and one time . The caller is to delete this field using decrRef() as it is no
718  *         more needed.
719  */
720 MEDCouplingFieldDouble *MEDCouplingIMesh::getMeasureField(bool isAbs) const
721 {
722   checkCoherency();
723   std::string name="MeasureOfMesh_";
724   name+=getName();
725   int nbelem(getNumberOfCells());
726   MEDCouplingFieldDouble *field(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
727   field->setName(name);
728   DataArrayDouble* array(DataArrayDouble::New());
729   array->alloc(nbelem,1);
730   array->fillWithValue(getMeasureOfAnyCell());
731   field->setArray(array) ;
732   array->decrRef();
733   field->setMesh(const_cast<MEDCouplingIMesh *>(this));
734   field->synchronizeTimeWithMesh();
735   return field;
736 }
737
738 /*!
739  * not implemented yet !
740  */
741 MEDCouplingFieldDouble *MEDCouplingIMesh::getMeasureFieldOnNode(bool isAbs) const
742 {
743   throw INTERP_KERNEL::Exception("MEDCouplingIMesh::getMeasureFieldOnNode : not implemented yet !");
744   //return 0;
745 }
746
747 int MEDCouplingIMesh::getCellContainingPoint(const double *pos, double eps) const
748 {
749   int dim(getSpaceDimension()),ret(0),coeff(1);
750   for(int i=0;i<dim;i++)
751     {
752       int nbOfCells(_structure[i]-1);
753       double ref(pos[i]);
754       int tmp((int)((ref-_origin[i])/_dxyz[i]));
755       if(tmp>=0 && tmp<nbOfCells)
756         {
757           ret+=coeff*tmp;
758           coeff*=nbOfCells;
759         }
760       else
761         return -1;
762     }
763   return ret;
764 }
765
766 void MEDCouplingIMesh::rotate(const double *center, const double *vector, double angle)
767 {
768   throw INTERP_KERNEL::Exception("No rotation available on IMesh : Traduce it to unstructured mesh to apply it !");
769 }
770
771 /*!
772  * Translates all nodes of \a this mesh by a given vector. Actually, it adds each
773  * component of the \a vector to all node coordinates of a corresponding axis.
774  *  \param [in] vector - the translation vector whose size must be not less than \a
775  *         this->getSpaceDimension().
776  */
777 void MEDCouplingIMesh::translate(const double *vector)
778 {
779   checkSpaceDimension();
780   int dim(getSpaceDimension());
781   std::transform(_origin,_origin+dim,vector,_origin,std::plus<double>());
782   declareAsNew();
783 }
784
785 /*!
786  * Applies scaling transformation to all nodes of \a this mesh.
787  *  \param [in] point - coordinates of a scaling center. This array is to be of
788  *         size \a this->getSpaceDimension() at least.
789  *  \param [in] factor - a scale factor.
790  */
791 void MEDCouplingIMesh::scale(const double *point, double factor)
792 {
793   checkSpaceDimension();
794   int dim(getSpaceDimension());
795   std::transform(_origin,_origin+dim,point,_origin,std::minus<double>());
796   std::transform(_origin,_origin+dim,_origin,std::bind2nd(std::multiplies<double>(),factor));
797   std::transform(_dxyz,_dxyz+dim,_dxyz,std::bind2nd(std::multiplies<double>(),factor));
798   std::transform(_origin,_origin+dim,point,_origin,std::plus<double>());
799   declareAsNew();
800 }
801
802 MEDCouplingMesh *MEDCouplingIMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
803 {
804   //not implemented yet !
805   return 0;
806 }
807
808 /*!
809  * Returns a new DataArrayDouble holding coordinates of all nodes of \a this mesh.
810  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
811  *          this->getNumberOfNodes() tuples per \a this->getSpaceDimension()
812  *          components. The caller is to delete this array using decrRef() as it is
813  *          no more needed.
814  */
815 DataArrayDouble *MEDCouplingIMesh::getCoordinatesAndOwner() const
816 {
817   checkCoherency();
818   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
819   int spaceDim(getSpaceDimension()),nbNodes(getNumberOfNodes());
820   ret->alloc(nbNodes,spaceDim);
821   double *pt(ret->getPointer());
822   ret->setInfoOnComponents(buildInfoOnComponents());
823   int tmp2[3],tmp[3];
824   getSplitNodeValues(tmp);
825   for(int i=0;i<nbNodes;i++)
826     {
827       GetPosFromId(i,spaceDim,tmp,tmp2);
828       for(int j=0;j<spaceDim;j++)
829         pt[i*spaceDim+j]=_dxyz[j]*tmp2[j]+_origin[j];
830     }
831   return ret.retn();
832 }
833
834 /*!
835  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
836  * computed by averaging coordinates of cell nodes.
837  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
838  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
839  *          components. The caller is to delete this array using decrRef() as it is
840  *          no more needed.
841  */
842 DataArrayDouble *MEDCouplingIMesh::getBarycenterAndOwner() const
843 {
844   checkCoherency();
845   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
846   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells()),tmp[3],tmp2[3];
847   ret->alloc(nbCells,spaceDim);
848   double *pt(ret->getPointer()),shiftOrigin[3];
849   std::transform(_dxyz,_dxyz+spaceDim,shiftOrigin,std::bind2nd(std::multiplies<double>(),0.5));
850   std::transform(_origin,_origin+spaceDim,shiftOrigin,shiftOrigin,std::plus<double>());
851   getSplitCellValues(tmp);
852   ret->setInfoOnComponents(buildInfoOnComponents());
853   for(int i=0;i<nbCells;i++)
854     {
855       GetPosFromId(i,spaceDim,tmp,tmp2);
856       for(int j=0;j<spaceDim;j++)
857         pt[i*spaceDim+j]=_dxyz[j]*tmp2[j]+shiftOrigin[j];
858     }
859   return ret.retn();
860 }
861
862 DataArrayDouble *MEDCouplingIMesh::computeIsoBarycenterOfNodesPerCell() const
863 {
864   return MEDCouplingIMesh::getBarycenterAndOwner();
865 }
866
867 void MEDCouplingIMesh::renumberCells(const int *old2NewBg, bool check)
868 {
869   throw INTERP_KERNEL::Exception("Functionnality of renumbering cell not available for IMesh !");
870 }
871
872 void MEDCouplingIMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
873 {
874   int it,order;
875   double time(getTime(it,order));
876   tinyInfo.clear();
877   tinyInfoD.clear();
878   littleStrings.clear();
879   littleStrings.push_back(getName());
880   littleStrings.push_back(getDescription());
881   littleStrings.push_back(getTimeUnit());
882   littleStrings.push_back(getAxisUnit());
883   tinyInfo.push_back(it);
884   tinyInfo.push_back(order);
885   tinyInfo.push_back(_space_dim);
886   tinyInfo.insert(tinyInfo.end(),_structure,_structure+3);
887   tinyInfoD.push_back(time);
888   tinyInfoD.insert(tinyInfoD.end(),_dxyz,_dxyz+3);
889   tinyInfoD.insert(tinyInfoD.end(),_origin,_origin+3);
890 }
891
892 void MEDCouplingIMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
893 {
894   a1->alloc(0,1);
895   a2->alloc(0,1);
896 }
897
898 void MEDCouplingIMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
899 {
900   a1=DataArrayInt::New();
901   a1->alloc(0,1);
902   a2=DataArrayDouble::New();
903   a2->alloc(0,1);
904 }
905
906 void MEDCouplingIMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2,
907                                        const std::vector<std::string>& littleStrings)
908 {
909   setName(littleStrings[0]);
910   setDescription(littleStrings[1]);
911   setTimeUnit(littleStrings[2]);
912   setAxisUnit(littleStrings[3]);
913   setTime(tinyInfoD[0],tinyInfo[0],tinyInfo[1]);
914   _space_dim=tinyInfo[2];
915   _structure[0]=tinyInfo[3]; _structure[1]=tinyInfo[4]; _structure[2]=tinyInfo[5];
916   _dxyz[0]=tinyInfoD[1]; _dxyz[1]=tinyInfoD[2]; _dxyz[2]=tinyInfoD[3];
917   _origin[0]=tinyInfoD[4]; _origin[1]=tinyInfoD[5]; _origin[2]=tinyInfoD[6];
918   declareAsNew();
919 }
920
921 void MEDCouplingIMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
922 {
923   checkCoherency();
924   std::ostringstream extent,origin,spacing;
925   for(int i=0;i<3;i++)
926     {
927       if(i<_space_dim)
928         { extent << "0 " <<  _structure[i]-1 << " "; origin << _origin[i] << " "; spacing << _dxyz[i] << " "; }
929       else
930         { extent << "0 0 "; origin << "0 "; spacing << "0 "; }
931     }
932   ofs << "  <" << getVTKDataSetType() << " WholeExtent=\"" << extent.str() << "\" Origin=\"" << origin.str() << "\" Spacing=\"" << spacing.str() << "\">\n";
933   ofs << "    <Piece Extent=\"" << extent.str() << "\">\n";
934   ofs << "      <PointData>\n" << pointData << std::endl;
935   ofs << "      </PointData>\n";
936   ofs << "      <CellData>\n" << cellData << std::endl;
937   ofs << "      </CellData>\n";
938   ofs << "      <Coordinates>\n";
939   ofs << "      </Coordinates>\n";
940   ofs << "    </Piece>\n";
941   ofs << "  </" << getVTKDataSetType() << ">\n";
942 }
943
944 void MEDCouplingIMesh::reprQuickOverview(std::ostream& stream) const
945 {
946   stream << "MEDCouplingIMesh C++ instance at " << this << ". Name : \"" << getName() << "\". Space dimension : " << _space_dim << ".";
947   if(_space_dim<0 || _space_dim>3)
948     return ;
949   stream << "\n";
950   std::ostringstream stream0,stream1;
951   int nbNodes(1),nbCells(0);
952   bool isPb(false);
953   for(int i=0;i<_space_dim;i++)
954     {
955       char tmp('X'+i);
956       int tmpNodes(_structure[i]);
957       stream1 << "- Axis " << tmp << " : " << tmpNodes << " nodes (orig=" << _origin[i] << ", inter=" << _dxyz[i] << ").";
958       if(i!=_space_dim-1)
959         stream1 << std::endl;
960       if(tmpNodes>=1)
961         nbNodes*=tmpNodes;
962       else
963         isPb=true;
964       if(tmpNodes>=2)
965         nbCells=nbCells==0?tmpNodes-1:nbCells*(tmpNodes-1);
966     }
967   if(!isPb)
968     {
969       stream0 << "Number of cells : " << nbCells << ", Number of nodes : " << nbNodes;
970       stream << stream0.str();
971       if(_space_dim>0)
972         stream << std::endl;
973     }
974   stream << stream1.str();
975 }
976
977 std::string MEDCouplingIMesh::getVTKDataSetType() const
978 {
979   return std::string("ImageData");
980 }
981
982 std::vector<std::string> MEDCouplingIMesh::buildInfoOnComponents() const
983 {
984   checkSpaceDimension();
985   int dim(getSpaceDimension());
986   std::vector<std::string> ret(dim);
987   for(int i=0;i<dim;i++)
988     {
989       std::ostringstream oss;
990       char tmp('X'+i); oss << tmp;
991       ret[i]=DataArray::BuildInfoFromVarAndUnit(oss.str(),_axis_unit);
992     }
993   return ret;
994 }
995
996 void MEDCouplingIMesh::checkSpaceDimension() const
997 {
998   CheckSpaceDimension(_space_dim);
999 }
1000
1001 void MEDCouplingIMesh::CheckSpaceDimension(int spaceDim)
1002 {
1003   if(spaceDim<0 || spaceDim>3)
1004     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CheckSpaceDimension : input spaceDim must be in [0,1,2,3] !");
1005 }
1006
1007 int MEDCouplingIMesh::FindIntRoot(int val, int order)
1008 {
1009   if(order==0)
1010     return 1;
1011   if(val<0)
1012     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::FindIntRoot : input val is < 0 ! Not possible to compute a root !");
1013   if(order==1)
1014     return val;
1015   if(order!=2 && order!=3)
1016     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::FindIntRoot : the order available are 0,1,2 or 3 !");
1017   double valf((double)val);
1018   if(order==2)
1019     {
1020       double retf(sqrt(valf));
1021       int ret((int)retf);
1022       if(ret*ret!=val)
1023         throw INTERP_KERNEL::Exception("MEDCouplingIMesh::FindIntRoot : the input val is not a perfect square root !");
1024       return ret;
1025     }
1026   else//order==3
1027     {
1028       double retf(std::pow(val,0.3333333333333333));
1029       int ret((int)retf),ret2(ret+1);
1030       if(ret*ret*ret!=val && ret2*ret2*ret2!=val)
1031         throw INTERP_KERNEL::Exception("MEDCouplingIMesh::FindIntRoot : the input val is not a perfect cublic root !");
1032       if(ret*ret*ret==val)
1033         return ret;
1034       else
1035         return ret2;
1036     }
1037 }