Salome HOME
71a7e65c8f244bed9270e3fd55c253d6c24b2bc0
[modules/med.git] / src / MEDCoupling / MEDCouplingExtrudedMesh.cxx
1 // Copyright (C) 2007-2012  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.
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 "MEDCouplingExtrudedMesh.hxx"
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingMemArray.hxx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
25 #include "CellModel.hxx"
26
27 #include "InterpolationUtils.hxx"
28
29 #include <limits>
30 #include <algorithm>
31 #include <functional>
32 #include <iterator>
33 #include <sstream>
34 #include <cmath>
35 #include <list>
36 #include <set>
37
38 using namespace ParaMEDMEM;
39
40 /*!
41  * Build an extruded mesh instance from 3D and 2D unstructured mesh lying on the \b same \b coords.
42  * @param mesh3D 3D unstructured mesh.
43  * @param mesh2D 2D unstructured mesh lying on the same coordinates than mesh3D. \b Warning mesh2D is \b not \b const
44  * because the mesh is aggregated and potentially modified by rotate or translate method.
45  * @param cell2DId Id of cell in mesh2D mesh where the computation of 1D mesh will be done.
46  */
47 MEDCouplingExtrudedMesh *MEDCouplingExtrudedMesh::New(const MEDCouplingUMesh *mesh3D, const MEDCouplingUMesh *mesh2D, int cell2DId) throw(INTERP_KERNEL::Exception)
48 {
49   return new MEDCouplingExtrudedMesh(mesh3D,mesh2D,cell2DId);
50 }
51
52 /*!
53  * This constructor is here only for unserialisation process.
54  * This constructor is normally completely useless for end user.
55  */
56 MEDCouplingExtrudedMesh *MEDCouplingExtrudedMesh::New()
57 {
58   return new MEDCouplingExtrudedMesh;
59 }
60
61 MEDCouplingMeshType MEDCouplingExtrudedMesh::getType() const
62 {
63   return EXTRUDED;
64 }
65
66 /*!
67  * This method copyies all tiny strings from other (name and components name).
68  * @throw if other and this have not same mesh type.
69  */
70 void MEDCouplingExtrudedMesh::copyTinyStringsFrom(const MEDCouplingMesh *other) throw(INTERP_KERNEL::Exception)
71 {
72   const MEDCouplingExtrudedMesh *otherC=dynamic_cast<const MEDCouplingExtrudedMesh *>(other);
73   if(!otherC)
74     throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::copyTinyStringsFrom : meshes have not same type !");
75   MEDCouplingMesh::copyTinyStringsFrom(other);
76   _mesh2D->copyTinyStringsFrom(otherC->_mesh2D);
77   _mesh1D->copyTinyStringsFrom(otherC->_mesh1D);
78 }
79
80 MEDCouplingExtrudedMesh::MEDCouplingExtrudedMesh(const MEDCouplingUMesh *mesh3D, const MEDCouplingUMesh *mesh2D, int cell2DId) throw(INTERP_KERNEL::Exception)
81 try:_mesh2D(const_cast<MEDCouplingUMesh *>(mesh2D)),_mesh1D(MEDCouplingUMesh::New()),_mesh3D_ids(0),_cell_2D_id(cell2DId)
82 {
83   if(_mesh2D!=0)
84     _mesh2D->incrRef();
85   computeExtrusion(mesh3D);
86   setName(mesh3D->getName());
87 }
88 catch(INTERP_KERNEL::Exception& e)
89   {
90     if(_mesh2D)
91       _mesh2D->decrRef();
92     if(_mesh1D)
93       _mesh1D->decrRef();
94     if(_mesh3D_ids)
95       _mesh3D_ids->decrRef();
96     throw e;
97   }
98
99 MEDCouplingExtrudedMesh::MEDCouplingExtrudedMesh():_mesh2D(0),_mesh1D(0),_mesh3D_ids(0),_cell_2D_id(-1)
100 {
101 }
102
103 MEDCouplingExtrudedMesh::MEDCouplingExtrudedMesh(const MEDCouplingExtrudedMesh& other, bool deepCopy):MEDCouplingMesh(other),_cell_2D_id(other._cell_2D_id)
104 {
105   if(deepCopy)
106     {
107       _mesh2D=other._mesh2D->clone(true);
108       _mesh1D=other._mesh1D->clone(true);
109       _mesh3D_ids=other._mesh3D_ids->deepCpy();
110     }
111   else
112     {
113       _mesh2D=other._mesh2D;
114       if(_mesh2D)
115         _mesh2D->incrRef();
116       _mesh1D=other._mesh1D;
117       if(_mesh1D)
118         _mesh1D->incrRef();
119       _mesh3D_ids=other._mesh3D_ids;
120       if(_mesh3D_ids)
121         _mesh3D_ids->incrRef();
122     }
123 }
124
125 int MEDCouplingExtrudedMesh::getNumberOfCells() const
126 {
127   return _mesh2D->getNumberOfCells()*_mesh1D->getNumberOfCells();
128 }
129
130 int MEDCouplingExtrudedMesh::getNumberOfNodes() const
131 {
132   return _mesh2D->getNumberOfNodes();
133 }
134
135 int MEDCouplingExtrudedMesh::getSpaceDimension() const
136 {
137   return 3;
138 }
139
140 int MEDCouplingExtrudedMesh::getMeshDimension() const
141 {
142   return 3;
143 }
144
145 MEDCouplingMesh *MEDCouplingExtrudedMesh::deepCpy() const
146 {
147   return clone(true);
148 }
149
150 MEDCouplingExtrudedMesh *MEDCouplingExtrudedMesh::clone(bool recDeepCpy) const
151 {
152   return new MEDCouplingExtrudedMesh(*this,recDeepCpy);
153 }
154
155 bool MEDCouplingExtrudedMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
156 {
157   if(!other)
158     throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::isEqualIfNotWhy : input other pointer is null !");
159   const MEDCouplingExtrudedMesh *otherC=dynamic_cast<const MEDCouplingExtrudedMesh *>(other);
160   std::ostringstream oss;
161   if(!otherC)
162     {
163       reason="mesh given in input is not castable in MEDCouplingExtrudedMesh !";
164       return false;
165     }
166   if(!MEDCouplingMesh::isEqualIfNotWhy(other,prec,reason))
167     return false;
168   if(!_mesh2D->isEqualIfNotWhy(otherC->_mesh2D,prec,reason))
169     {
170       reason.insert(0,"Mesh2D unstructured meshes differ : ");
171       return false;
172     }
173   if(!_mesh1D->isEqualIfNotWhy(otherC->_mesh1D,prec,reason))
174     {
175       reason.insert(0,"Mesh1D unstructured meshes differ : ");
176       return false;
177     }
178   if(!_mesh3D_ids->isEqualIfNotWhy(*otherC->_mesh3D_ids,reason))
179     {
180       reason.insert(0,"Mesh3D ids DataArrayInt instances differ : ");
181       return false;
182     }
183   if(_cell_2D_id!=otherC->_cell_2D_id)
184     {
185       oss << "Cell 2D id of the two extruded mesh differ : this = " << _cell_2D_id << " other = " <<  otherC->_cell_2D_id;
186       reason=oss.str();
187       return false;
188     }
189   return true;
190 }
191
192 bool MEDCouplingExtrudedMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
193 {
194   const MEDCouplingExtrudedMesh *otherC=dynamic_cast<const MEDCouplingExtrudedMesh *>(other);
195   if(!otherC)
196     return false;
197   if(!_mesh2D->isEqualWithoutConsideringStr(otherC->_mesh2D,prec))
198     return false;
199   if(!_mesh1D->isEqualWithoutConsideringStr(otherC->_mesh1D,prec))
200     return false;
201   if(!_mesh3D_ids->isEqualWithoutConsideringStr(*otherC->_mesh3D_ids))
202     return false;
203   if(_cell_2D_id!=otherC->_cell_2D_id)
204     return false;
205   return true;
206 }
207
208 void MEDCouplingExtrudedMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
209                                                    DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
210 {
211   throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::checkDeepEquivalWith : not implemented yet !");
212 }
213
214 void MEDCouplingExtrudedMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
215                                                               DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
216 {
217   throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::checkDeepEquivalOnSameNodesWith : not implemented yet !");
218 }
219
220 INTERP_KERNEL::NormalizedCellType MEDCouplingExtrudedMesh::getTypeOfCell(int cellId) const
221 {
222   const int *ids=_mesh3D_ids->getConstPointer();
223   int nbOf3DCells=_mesh3D_ids->getNumberOfTuples();
224   const int *where=std::find(ids,ids+nbOf3DCells,cellId);
225   if(where==ids+nbOf3DCells)
226     throw INTERP_KERNEL::Exception("Invalid cellId specified >= getNumberOfCells() !");
227   int nbOfCells2D=_mesh2D->getNumberOfCells();
228   int locId=((int)std::distance(ids,where))%nbOfCells2D;
229   INTERP_KERNEL::NormalizedCellType tmp=_mesh2D->getTypeOfCell(locId);
230   return INTERP_KERNEL::CellModel::GetCellModel(tmp).getExtrudedType();
231 }
232
233 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingExtrudedMesh::getAllGeoTypes() const
234 {
235   const std::set<INTERP_KERNEL::NormalizedCellType>& ret2D=_mesh2D->getAllTypes();
236   std::set<INTERP_KERNEL::NormalizedCellType> ret;
237   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=ret2D.begin();it!=ret2D.end();it++)
238     ret.insert(INTERP_KERNEL::CellModel::GetCellModel(*it).getExtrudedType());
239   return ret;
240 }
241
242 int MEDCouplingExtrudedMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
243 {
244   int ret=0;
245   int nbOfCells2D=_mesh2D->getNumberOfCells();
246   for(int i=0;i<nbOfCells2D;i++)
247     {
248       INTERP_KERNEL::NormalizedCellType t=_mesh2D->getTypeOfCell(i);
249       if(INTERP_KERNEL::CellModel::GetCellModel(t).getExtrudedType()==type)
250         ret++;
251     }
252   return ret*_mesh1D->getNumberOfCells();
253 }
254
255 void MEDCouplingExtrudedMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
256 {
257   int nbOfCells2D=_mesh2D->getNumberOfCells();
258   int nbOfNodes2D=_mesh2D->getNumberOfNodes();
259   int locId=cellId%nbOfCells2D;
260   int lev=cellId/nbOfCells2D;
261   std::vector<int> tmp,tmp2;
262   _mesh2D->getNodeIdsOfCell(locId,tmp);
263   tmp2=tmp;
264   std::transform(tmp.begin(),tmp.end(),tmp.begin(),std::bind2nd(std::plus<int>(),nbOfNodes2D*lev));
265   std::transform(tmp2.begin(),tmp2.end(),tmp2.begin(),std::bind2nd(std::plus<int>(),nbOfNodes2D*(lev+1)));
266   conn.insert(conn.end(),tmp.begin(),tmp.end());
267   conn.insert(conn.end(),tmp2.begin(),tmp2.end());
268 }
269
270 void MEDCouplingExtrudedMesh::getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const throw(INTERP_KERNEL::Exception)
271 {
272   int nbOfNodes2D=_mesh2D->getNumberOfNodes();
273   int locId=nodeId%nbOfNodes2D;
274   int lev=nodeId/nbOfNodes2D;
275   std::vector<double> tmp,tmp2;
276   _mesh2D->getCoordinatesOfNode(locId,tmp);
277   tmp2=tmp;
278   int spaceDim=_mesh1D->getSpaceDimension();
279   const double *z=_mesh1D->getCoords()->getConstPointer();
280   std::transform(tmp.begin(),tmp.end(),z+lev*spaceDim,tmp.begin(),std::plus<double>());
281   std::transform(tmp2.begin(),tmp2.end(),z+(lev+1)*spaceDim,tmp2.begin(),std::plus<double>());
282   coo.insert(coo.end(),tmp.begin(),tmp.end());
283   coo.insert(coo.end(),tmp2.begin(),tmp2.end());
284 }
285
286 std::string MEDCouplingExtrudedMesh::simpleRepr() const
287 {
288   std::ostringstream ret;
289   ret << "3D Extruded mesh from a 2D Surf Mesh with name : \"" << getName() << "\"\n";
290   ret << "Description of mesh : \"" << getDescription() << "\"\n";
291   int tmpp1,tmpp2;
292   double tt=getTime(tmpp1,tmpp2);
293   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
294   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
295   ret << "Cell id where 1D mesh has been deduced : " << _cell_2D_id << "\n";
296   ret << "Number of cells : " << getNumberOfCells() << "(" << _mesh2D->getNumberOfCells() << "x" << _mesh1D->getNumberOfCells() << ")\n";
297   ret << "1D Mesh info : _____________________\n\n\n";
298   ret << _mesh1D->simpleRepr();
299   ret << "\n\n\n2D Mesh info : _____________________\n\n\n" << _mesh2D->simpleRepr() << "\n\n\n";
300   return ret.str();
301 }
302
303 std::string MEDCouplingExtrudedMesh::advancedRepr() const
304 {
305   std::ostringstream ret;
306   ret << "3D Extruded mesh from a 2D Surf Mesh with name : \"" << getName() << "\"\n";
307   ret << "Description of mesh : \"" << getDescription() << "\"\n";
308   int tmpp1,tmpp2;
309   double tt=getTime(tmpp1,tmpp2);
310   ret << "Time attached to the mesh (unit) : " << tt << " (" << getTimeUnit() << ")\n";
311   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
312   ret << "Cell id where 1D mesh has been deduced : " << _cell_2D_id << "\n";
313   ret << "Number of cells : " << getNumberOfCells() << "(" << _mesh2D->getNumberOfCells() << "x" << _mesh1D->getNumberOfCells() << ")\n";
314   ret << "1D Mesh info : _____________________\n\n\n";
315   ret << _mesh1D->advancedRepr();
316   ret << "\n\n\n2D Mesh info : _____________________\n\n\n" << _mesh2D->advancedRepr() << "\n\n\n";
317   ret << "3D cell ids per level :\n";
318   return ret.str();
319 }
320
321 void MEDCouplingExtrudedMesh::checkCoherency() const throw (INTERP_KERNEL::Exception)
322 {
323 }
324
325 void MEDCouplingExtrudedMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
326 {
327   checkCoherency();
328 }
329
330 void MEDCouplingExtrudedMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
331 {
332   checkCoherency1(eps);
333 }
334
335 void MEDCouplingExtrudedMesh::getBoundingBox(double *bbox) const
336 {
337   double bbox2D[6];
338   _mesh2D->getBoundingBox(bbox2D);
339   const double *nodes1D=_mesh1D->getCoords()->getConstPointer();
340   int nbOfNodes1D=_mesh1D->getNumberOfNodes();
341   double bbox1DMin[3],bbox1DMax[3],tmp[3];
342   std::fill(bbox1DMin,bbox1DMin+3,std::numeric_limits<double>::max());
343   std::fill(bbox1DMax,bbox1DMax+3,-(std::numeric_limits<double>::max()));
344   for(int i=0;i<nbOfNodes1D;i++)
345     {
346       std::transform(nodes1D+3*i,nodes1D+3*(i+1),bbox1DMin,bbox1DMin,static_cast<const double& (*)(const double&, const double&)>(std::min<double>));
347       std::transform(nodes1D+3*i,nodes1D+3*(i+1),bbox1DMax,bbox1DMax,static_cast<const double& (*)(const double&, const double&)>(std::max<double>));
348     }
349   std::transform(bbox1DMax,bbox1DMax+3,bbox1DMin,tmp,std::minus<double>());
350   int id=(int)std::distance(tmp,std::max_element(tmp,tmp+3));
351   bbox[0]=bbox1DMin[0]; bbox[1]=bbox1DMax[0];
352   bbox[2]=bbox1DMin[1]; bbox[3]=bbox1DMax[1];
353   bbox[4]=bbox1DMin[2]; bbox[5]=bbox1DMax[2];
354   bbox[2*id+1]+=tmp[id];
355 }
356
357 void MEDCouplingExtrudedMesh::updateTime() const
358 {
359   if(_mesh2D)
360     {
361       updateTimeWith(*_mesh2D);
362     }
363   if(_mesh1D)
364     {
365       updateTimeWith(*_mesh1D);
366     }
367 }
368
369 void MEDCouplingExtrudedMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
370 {
371   throw INTERP_KERNEL::Exception("Functionnality of renumbering cells unavailable for ExtrudedMesh");
372 }
373
374 MEDCouplingUMesh *MEDCouplingExtrudedMesh::build3DUnstructuredMesh() const
375 {
376   MEDCouplingUMesh *ret=_mesh2D->buildExtrudedMesh(_mesh1D,0);
377   const int *renum=_mesh3D_ids->getConstPointer();
378   ret->renumberCells(renum,false);
379   ret->setName(getName());
380   return ret;
381 }
382
383 MEDCouplingUMesh *MEDCouplingExtrudedMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
384 {
385   return build3DUnstructuredMesh();
386 }
387
388 MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureField(bool) const
389 {
390   std::string name="MeasureOfMesh_";
391   name+=getName();
392   MEDCouplingFieldDouble *ret2D=_mesh2D->getMeasureField(true);
393   MEDCouplingFieldDouble *ret1D=_mesh1D->getMeasureField(true);
394   const double *ret2DPtr=ret2D->getArray()->getConstPointer();
395   const double *ret1DPtr=ret1D->getArray()->getConstPointer();
396   int nbOf2DCells=_mesh2D->getNumberOfCells();
397   int nbOf1DCells=_mesh1D->getNumberOfCells();
398   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
399   const int *renum=_mesh3D_ids->getConstPointer();
400   MEDCouplingFieldDouble *ret=MEDCouplingFieldDouble::New(ON_CELLS,NO_TIME);
401   ret->setMesh(this);
402   DataArrayDouble *da=DataArrayDouble::New();
403   da->alloc(nbOf3DCells,1);
404   double *retPtr=da->getPointer();
405   for(int i=0;i<nbOf1DCells;i++)
406     for(int j=0;j<nbOf2DCells;j++)
407       retPtr[renum[i*nbOf2DCells+j]]=ret2DPtr[j]*ret1DPtr[i];
408   ret->setArray(da);
409   da->decrRef();
410   ret->setName(name.c_str());
411   ret2D->decrRef();
412   ret1D->decrRef();
413   return ret;
414 }
415
416 MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::getMeasureFieldOnNode(bool isAbs) const
417 {
418   //not implemented yet
419   return 0;
420 }
421
422 MEDCouplingFieldDouble *MEDCouplingExtrudedMesh::buildOrthogonalField() const
423 {
424   throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::buildOrthogonalField : This method has no sense for MEDCouplingExtrudedMesh that is 3D !");
425 }
426
427 int MEDCouplingExtrudedMesh::getCellContainingPoint(const double *pos, double eps) const
428 {
429   throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::getCellContainingPoint : not implemented yet !");
430 }
431
432 MEDCouplingExtrudedMesh::~MEDCouplingExtrudedMesh()
433 {
434   if(_mesh2D)
435     _mesh2D->decrRef();
436   if(_mesh1D)
437     _mesh1D->decrRef();
438   if(_mesh3D_ids)
439     _mesh3D_ids->decrRef();
440 }
441
442 void MEDCouplingExtrudedMesh::computeExtrusion(const MEDCouplingUMesh *mesh3D) throw(INTERP_KERNEL::Exception)
443 {
444   const char errMsg1[]="2D mesh is empty unable to compute extrusion !";
445   const char errMsg2[]="Coords between 2D and 3D meshes are not the same ! Try MEDCouplingPointSet::tryToShareSameCoords method";
446   const char errMsg3[]="No chance to find extrusion pattern in mesh3D,mesh2D couple because nbCells3D%nbCells2D!=0 !";
447   if(_mesh2D==0 || mesh3D==0)
448     throw INTERP_KERNEL::Exception(errMsg1);
449   if(_mesh2D->getCoords()!=mesh3D->getCoords())
450     throw INTERP_KERNEL::Exception(errMsg2);
451   if(mesh3D->getNumberOfCells()%_mesh2D->getNumberOfCells()!=0)
452     throw INTERP_KERNEL::Exception(errMsg3);
453   if(!_mesh3D_ids)
454     _mesh3D_ids=DataArrayInt::New();
455   if(!_mesh1D)
456     _mesh1D=MEDCouplingUMesh::New();
457   computeExtrusionAlg(mesh3D);
458 }
459
460 void MEDCouplingExtrudedMesh::build1DExtrusion(int idIn3DDesc, int newId, int nbOf1DLev, MEDCouplingUMesh *subMesh,
461                                                const int *desc3D, const int *descIndx3D,
462                                                const int *revDesc3D, const int *revDescIndx3D,
463                                                bool computeMesh1D) throw(INTERP_KERNEL::Exception)
464 {
465   int nbOf2DCells=_mesh2D->getNumberOfCells();
466   int start=revDescIndx3D[idIn3DDesc];
467   int end=revDescIndx3D[idIn3DDesc+1];
468   if(end-start!=1)
469     {
470       std::ostringstream ost; ost << "Invalid bases 2D mesh specified : 2D cell # " <<  idIn3DDesc;
471       ost << " shared by more than 1 3D cell !!!";
472       throw INTERP_KERNEL::Exception(ost.str().c_str());
473     }
474   int current3DCell=revDesc3D[start];
475   int current2DCell=idIn3DDesc;
476   int *mesh3DIDs=_mesh3D_ids->getPointer();
477   mesh3DIDs[newId]=current3DCell;
478   const int *conn2D=subMesh->getNodalConnectivity()->getConstPointer();
479   const int *conn2DIndx=subMesh->getNodalConnectivityIndex()->getConstPointer();
480   for(int i=1;i<nbOf1DLev;i++)
481     {
482       std::vector<int> conn(conn2D+conn2DIndx[current2DCell]+1,conn2D+conn2DIndx[current2DCell+1]);
483       std::sort(conn.begin(),conn.end());
484       if(computeMesh1D)
485         computeBaryCenterOfFace(conn,i-1);
486       current2DCell=findOppositeFaceOf(current2DCell,current3DCell,conn,
487                                        desc3D,descIndx3D,conn2D,conn2DIndx);
488       start=revDescIndx3D[current2DCell];
489       end=revDescIndx3D[current2DCell+1];
490       if(end-start!=2)
491         {
492           std::ostringstream ost; ost << "Expecting to have 2 3D cells attached to 2D cell " << current2DCell << "!";
493           ost << " : Impossible or call tryToShareSameCoords method !";
494           throw INTERP_KERNEL::Exception(ost.str().c_str());
495         }
496       if(revDesc3D[start]!=current3DCell)
497         current3DCell=revDesc3D[start];
498       else
499         current3DCell=revDesc3D[start+1];
500       mesh3DIDs[i*nbOf2DCells+newId]=current3DCell;
501     }
502   if(computeMesh1D)
503     {
504       std::vector<int> conn(conn2D+conn2DIndx[current2DCell]+1,conn2D+conn2DIndx[current2DCell+1]);
505       std::sort(conn.begin(),conn.end());
506       computeBaryCenterOfFace(conn,nbOf1DLev-1);
507       current2DCell=findOppositeFaceOf(current2DCell,current3DCell,conn,
508                                        desc3D,descIndx3D,conn2D,conn2DIndx);
509       conn.clear();
510       conn.insert(conn.end(),conn2D+conn2DIndx[current2DCell]+1,conn2D+conn2DIndx[current2DCell+1]);
511       std::sort(conn.begin(),conn.end());
512       computeBaryCenterOfFace(conn,nbOf1DLev);
513     }
514 }
515
516 int MEDCouplingExtrudedMesh::findOppositeFaceOf(int current2DCell, int current3DCell, const std::vector<int>& connSorted,
517                                                 const int *desc3D, const int *descIndx3D,
518                                                 const int *conn2D, const int *conn2DIndx) throw(INTERP_KERNEL::Exception)
519 {
520   int start=descIndx3D[current3DCell];
521   int end=descIndx3D[current3DCell+1];
522   bool found=false;
523   for(const int *candidate2D=desc3D+start;candidate2D!=desc3D+end && !found;candidate2D++)
524     {
525       if(*candidate2D!=current2DCell)
526         {
527           std::vector<int> conn2(conn2D+conn2DIndx[*candidate2D]+1,conn2D+conn2DIndx[*candidate2D+1]);
528           std::sort(conn2.begin(),conn2.end());
529           std::list<int> intersect;
530           std::set_intersection(connSorted.begin(),connSorted.end(),conn2.begin(),conn2.end(),
531                                 std::insert_iterator< std::list<int> >(intersect,intersect.begin()));
532           if(intersect.empty())
533             return *candidate2D;
534         }
535     }
536   std::ostringstream ost; ost << "Impossible to find an opposite 2D face of face # " <<  current2DCell;
537   ost << " in 3D cell # " << current3DCell << " : Impossible or call tryToShareSameCoords method !";
538   throw INTERP_KERNEL::Exception(ost.str().c_str());
539 }
540
541 void MEDCouplingExtrudedMesh::computeBaryCenterOfFace(const std::vector<int>& nodalConnec, int lev1DId)
542 {
543   double *zoneToUpdate=_mesh1D->getCoords()->getPointer()+lev1DId*3;
544   std::fill(zoneToUpdate,zoneToUpdate+3,0.);
545   const double *coords=_mesh2D->getCoords()->getConstPointer();
546   for(std::vector<int>::const_iterator iter=nodalConnec.begin();iter!=nodalConnec.end();iter++)
547     std::transform(zoneToUpdate,zoneToUpdate+3,coords+3*(*iter),zoneToUpdate,std::plus<double>());
548   std::transform(zoneToUpdate,zoneToUpdate+3,zoneToUpdate,std::bind2nd(std::multiplies<double>(),(double)(1./(int)nodalConnec.size())));
549 }
550
551 int MEDCouplingExtrudedMesh::FindCorrespCellByNodalConn(const std::vector<int>& nodalConnec, const int *revNodalPtr, const int *revNodalIndxPtr) throw(INTERP_KERNEL::Exception)
552 {
553   std::vector<int>::const_iterator iter=nodalConnec.begin();
554   std::set<int> s1(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1]);
555   iter++;
556   for(;iter!=nodalConnec.end();iter++)
557     {
558       std::set<int> s2(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1]);
559       std::set<int> s3;
560       std::set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),std::insert_iterator< std::set<int> >(s3,s3.end()));
561       s1=s3;
562     }
563   if(s1.size()==1)
564     return *(s1.begin());
565   std::ostringstream ostr;
566   ostr << "Cell with nodal connec : ";
567   std::copy(nodalConnec.begin(),nodalConnec.end(),std::ostream_iterator<int>(ostr," "));
568   ostr << " is not part of mesh";
569   throw INTERP_KERNEL::Exception(ostr.str().c_str());
570 }
571
572 /*!
573  * This method is callable on 1Dmeshes (meshDim==1 && spaceDim==3) returned by MEDCouplingExtrudedMesh::getMesh1D typically.
574  * These 1Dmeshes (meshDim==1 && spaceDim==3) have a special semantic because these meshes do not specify a static location but a translation along a path.
575  * This method checks that 'm1' and 'm2' are compatible, if not an exception is thrown. In case these meshes ('m1' and 'm2') are compatible 2 corresponding meshes
576  * are created ('m1r' and 'm2r') that can be used for interpolation.
577  * @param m1 input mesh with meshDim==1 and spaceDim==3
578  * @param m2 input mesh with meshDim==1 and spaceDim==3
579  * @param eps tolerance acceptable to determine compatibility
580  * @param m1r output mesh with ref count equal to 1 with meshDim==1 and spaceDim==1
581  * @param m2r output mesh with ref count equal to 1 with meshDim==1 and spaceDim==1
582  * @param v is the output normalized vector of the common direction of 'm1' and 'm2'  
583  * @throw in case that m1 and m2 are not compatible each other.
584  */
585 void MEDCouplingExtrudedMesh::Project1DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
586                                               MEDCouplingUMesh *&m1r, MEDCouplingUMesh *&m2r, double *v) throw(INTERP_KERNEL::Exception)
587 {
588   if(m1->getSpaceDimension()!=3 || m1->getSpaceDimension()!=3)
589     throw INTERP_KERNEL::Exception("Input meshes are expected to have a spaceDim==3 for Projec1D !");
590   m1r=m1->clone(true);
591   m2r=m2->clone(true);
592   m1r->changeSpaceDimension(1);
593   m2r->changeSpaceDimension(1);
594   std::vector<int> c;
595   std::vector<double> ref,ref2;
596   m1->getNodeIdsOfCell(0,c);
597   m1->getCoordinatesOfNode(c[0],ref);
598   m1->getCoordinatesOfNode(c[1],ref2);
599   std::transform(ref2.begin(),ref2.end(),ref.begin(),v,std::minus<double>());
600   double n=INTERP_KERNEL::norm<3>(v);
601   std::transform(v,v+3,v,std::bind2nd(std::multiplies<double>(),1/n));
602   m1->project1D(&ref[0],v,eps,m1r->getCoords()->getPointer());
603   m2->project1D(&ref[0],v,eps,m2r->getCoords()->getPointer());
604   
605 }
606
607 void MEDCouplingExtrudedMesh::rotate(const double *center, const double *vector, double angle)
608 {
609   _mesh2D->rotate(center,vector,angle);
610   _mesh1D->rotate(center,vector,angle);
611 }
612
613 void MEDCouplingExtrudedMesh::translate(const double *vector)
614 {
615   _mesh2D->translate(vector);
616   _mesh1D->translate(vector);
617 }
618
619 void MEDCouplingExtrudedMesh::scale(const double *point, double factor)
620 {
621   _mesh2D->scale(point,factor);
622   _mesh1D->scale(point,factor);
623 }
624
625 std::vector<int> MEDCouplingExtrudedMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
626 {
627   throw INTERP_KERNEL::Exception("Not implemented yet !");
628 }
629
630 DataArrayInt *MEDCouplingExtrudedMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
631 {
632   throw INTERP_KERNEL::Exception("Not implemented yet !");
633 }
634
635 void MEDCouplingExtrudedMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
636 {
637   throw INTERP_KERNEL::Exception("Not implemented yet !");
638 }
639
640 MEDCouplingMesh *MEDCouplingExtrudedMesh::buildPart(const int *start, const int *end) const
641 {
642   // not implemented yet !
643   return 0;
644 }
645
646 MEDCouplingMesh *MEDCouplingExtrudedMesh::buildPartAndReduceNodes(const int *start, const int *end, DataArrayInt*& arr) const
647 {
648   // not implemented yet !
649   return 0;
650 }
651
652 DataArrayInt *MEDCouplingExtrudedMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
653 {
654   throw INTERP_KERNEL::Exception("MEDCouplingExtrudedMesh::simplexize : unavailable for such a type of mesh : Extruded !");
655 }
656
657 MEDCouplingMesh *MEDCouplingExtrudedMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
658 {
659   // not implemented yet !
660   return 0;
661 }
662
663 DataArrayDouble *MEDCouplingExtrudedMesh::getCoordinatesAndOwner() const
664 {
665   DataArrayDouble *arr2D=_mesh2D->getCoords();
666   DataArrayDouble *arr1D=_mesh1D->getCoords();
667   DataArrayDouble *ret=DataArrayDouble::New();
668   ret->alloc(getNumberOfNodes(),3);
669   int nbOf1DLev=_mesh1D->getNumberOfNodes();
670   int nbOf2DNodes=_mesh2D->getNumberOfNodes();
671   const double *ptSrc=arr2D->getConstPointer();
672   double *pt=ret->getPointer();
673   std::copy(ptSrc,ptSrc+3*nbOf2DNodes,pt);
674   for(int i=1;i<nbOf1DLev;i++)
675     {
676       std::copy(ptSrc,ptSrc+3*nbOf2DNodes,pt+3*i*nbOf2DNodes);
677       double vec[3];
678       std::copy(arr1D->getConstPointer()+3*i,arr1D->getConstPointer()+3*(i+1),vec);
679       std::transform(arr1D->getConstPointer()+3*(i-1),arr1D->getConstPointer()+3*i,vec,vec,std::minus<double>());
680       for(int j=0;j<nbOf2DNodes;j++)
681         std::transform(vec,vec+3,pt+3*(i*nbOf2DNodes+j),pt+3*(i*nbOf2DNodes+j),std::plus<double>());
682     }
683   return ret;
684 }
685
686 DataArrayDouble *MEDCouplingExtrudedMesh::getBarycenterAndOwner() const
687 {
688   //not yet implemented
689   return 0;
690 }
691
692 void MEDCouplingExtrudedMesh::computeExtrusionAlg(const MEDCouplingUMesh *mesh3D) throw(INTERP_KERNEL::Exception)
693 {
694   _mesh3D_ids->alloc(mesh3D->getNumberOfCells(),1);
695   int nbOf1DLev=mesh3D->getNumberOfCells()/_mesh2D->getNumberOfCells();
696   _mesh1D->setMeshDimension(1);
697   _mesh1D->allocateCells(nbOf1DLev);
698   int tmpConn[2];
699   for(int i=0;i<nbOf1DLev;i++)
700     {
701       tmpConn[0]=i;
702       tmpConn[1]=i+1;
703       _mesh1D->insertNextCell(INTERP_KERNEL::NORM_SEG2,2,tmpConn);
704     }
705   _mesh1D->finishInsertingCells();
706   DataArrayDouble *myCoords=DataArrayDouble::New();
707   myCoords->alloc(nbOf1DLev+1,3);
708   _mesh1D->setCoords(myCoords);
709   myCoords->decrRef();
710   DataArrayInt *desc,*descIndx,*revDesc,*revDescIndx;
711   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
712   MEDCouplingUMesh *subMesh=mesh3D->buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
713   DataArrayInt *revNodal2D,*revNodalIndx2D;
714   revNodal2D=DataArrayInt::New(); revNodalIndx2D=DataArrayInt::New();
715   subMesh->getReverseNodalConnectivity(revNodal2D,revNodalIndx2D);
716   const int *nodal2D=_mesh2D->getNodalConnectivity()->getConstPointer();
717   const int *nodal2DIndx=_mesh2D->getNodalConnectivityIndex()->getConstPointer();
718   const int *revNodal2DPtr=revNodal2D->getConstPointer();
719   const int *revNodalIndx2DPtr=revNodalIndx2D->getConstPointer();
720   const int *descP=desc->getConstPointer();
721   const int *descIndxP=descIndx->getConstPointer();
722   const int *revDescP=revDesc->getConstPointer();
723   const int *revDescIndxP=revDescIndx->getConstPointer();
724   //
725   int nbOf2DCells=_mesh2D->getNumberOfCells();
726   for(int i=0;i<nbOf2DCells;i++)
727     {
728       int idInSubMesh;
729        std::vector<int> nodalConnec(nodal2D+nodal2DIndx[i]+1,nodal2D+nodal2DIndx[i+1]);
730        try
731         {
732           idInSubMesh=FindCorrespCellByNodalConn(nodalConnec,revNodal2DPtr,revNodalIndx2DPtr);
733         }
734        catch(INTERP_KERNEL::Exception& e)
735          {
736            std::ostringstream ostr; ostr << "mesh2D cell # " << i << " is not part of any cell of 3D mesh !\n";
737            ostr << e.what();
738            throw INTERP_KERNEL::Exception(ostr.str().c_str());
739          }
740        build1DExtrusion(idInSubMesh,i,nbOf1DLev,subMesh,descP,descIndxP,revDescP,revDescIndxP,i==_cell_2D_id);
741     }
742   //
743   revNodal2D->decrRef();
744   revNodalIndx2D->decrRef();
745   subMesh->decrRef();
746   desc->decrRef();
747   descIndx->decrRef();
748   revDesc->decrRef();
749   revDescIndx->decrRef();
750 }
751
752 void MEDCouplingExtrudedMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
753 {
754   std::vector<int> tinyInfo1;
755   std::vector<std::string> ls1;
756   std::vector<double> ls3;
757   _mesh2D->getTinySerializationInformation(ls3,tinyInfo1,ls1);
758   std::vector<int> tinyInfo2;
759   std::vector<std::string> ls2;
760   std::vector<double> ls4;
761   _mesh1D->getTinySerializationInformation(ls4,tinyInfo2,ls2);
762   tinyInfo.clear(); littleStrings.clear();
763   tinyInfo.insert(tinyInfo.end(),tinyInfo1.begin(),tinyInfo1.end());
764   littleStrings.insert(littleStrings.end(),ls1.begin(),ls1.end());
765   tinyInfo.insert(tinyInfo.end(),tinyInfo2.begin(),tinyInfo2.end());
766   littleStrings.insert(littleStrings.end(),ls2.begin(),ls2.end());
767   tinyInfo.push_back(_cell_2D_id);
768   tinyInfo.push_back((int)tinyInfo1.size());
769   tinyInfo.push_back(_mesh3D_ids->getNbOfElems());
770   littleStrings.push_back(getName());
771   littleStrings.push_back(getDescription());
772 }
773
774 void MEDCouplingExtrudedMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
775 {
776   std::size_t sz=tinyInfo.size();
777   int sz1=tinyInfo[sz-2];
778   std::vector<int> ti1(tinyInfo.begin(),tinyInfo.begin()+sz1);
779   std::vector<int> ti2(tinyInfo.begin()+sz1,tinyInfo.end()-3);
780   MEDCouplingUMesh *um=MEDCouplingUMesh::New();
781   DataArrayInt *a1tmp=DataArrayInt::New();
782   DataArrayDouble *a2tmp=DataArrayDouble::New();
783   int la1=0,la2=0;
784   std::vector<std::string> ls1,ls2;
785   um->resizeForUnserialization(ti1,a1tmp,a2tmp,ls1);
786   la1+=a1tmp->getNbOfElems(); la2+=a2tmp->getNbOfElems();
787   a1tmp->decrRef(); a2tmp->decrRef();
788   a1tmp=DataArrayInt::New(); a2tmp=DataArrayDouble::New();
789   um->resizeForUnserialization(ti2,a1tmp,a2tmp,ls2);
790   la1+=a1tmp->getNbOfElems(); la2+=a2tmp->getNbOfElems();
791   a1tmp->decrRef(); a2tmp->decrRef();
792   um->decrRef();
793   //
794   a1->alloc(la1+tinyInfo[sz-1],1);
795   a2->alloc(la2,1);
796   littleStrings.resize(ls1.size()+ls2.size()+2);
797 }
798
799 void MEDCouplingExtrudedMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
800 {
801   a1=DataArrayInt::New(); a2=DataArrayDouble::New();
802   DataArrayInt *a1_1=0,*a1_2=0;
803   DataArrayDouble *a2_1=0,*a2_2=0;
804   _mesh2D->serialize(a1_1,a2_1);
805   _mesh1D->serialize(a1_2,a2_2);
806   a1->alloc(a1_1->getNbOfElems()+a1_2->getNbOfElems()+_mesh3D_ids->getNbOfElems(),1);
807   int *ptri=a1->getPointer();
808   ptri=std::copy(a1_1->getConstPointer(),a1_1->getConstPointer()+a1_1->getNbOfElems(),ptri);
809   a1_1->decrRef();
810   ptri=std::copy(a1_2->getConstPointer(),a1_2->getConstPointer()+a1_2->getNbOfElems(),ptri);
811   a1_2->decrRef();
812   std::copy(_mesh3D_ids->getConstPointer(),_mesh3D_ids->getConstPointer()+_mesh3D_ids->getNbOfElems(),ptri);
813   a2->alloc(a2_1->getNbOfElems()+a2_2->getNbOfElems(),1);
814   double *ptrd=a2->getPointer();
815   ptrd=std::copy(a2_1->getConstPointer(),a2_1->getConstPointer()+a2_1->getNbOfElems(),ptrd);
816   a2_1->decrRef();
817   std::copy(a2_2->getConstPointer(),a2_2->getConstPointer()+a2_2->getNbOfElems(),ptrd);
818   a2_2->decrRef();
819 }
820
821 void MEDCouplingExtrudedMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
822 {
823   setName(littleStrings[littleStrings.size()-2].c_str());
824   setDescription(littleStrings.back().c_str());
825   std::size_t sz=tinyInfo.size();
826   int sz1=tinyInfo[sz-2];
827   _cell_2D_id=tinyInfo[sz-3];
828   std::vector<int> ti1(tinyInfo.begin(),tinyInfo.begin()+sz1);
829   std::vector<int> ti2(tinyInfo.begin()+sz1,tinyInfo.end()-3);
830   DataArrayInt *a1tmp=DataArrayInt::New();
831   DataArrayDouble *a2tmp=DataArrayDouble::New();
832   const int *a1Ptr=a1->getConstPointer();
833   const double *a2Ptr=a2->getConstPointer();
834   _mesh2D=MEDCouplingUMesh::New();
835   std::vector<std::string> ls1,ls2;
836   _mesh2D->resizeForUnserialization(ti1,a1tmp,a2tmp,ls1);
837   std::copy(a2Ptr,a2Ptr+a2tmp->getNbOfElems(),a2tmp->getPointer());
838   std::copy(a1Ptr,a1Ptr+a1tmp->getNbOfElems(),a1tmp->getPointer());
839   a2Ptr+=a2tmp->getNbOfElems();
840   a1Ptr+=a1tmp->getNbOfElems();
841   ls2.insert(ls2.end(),littleStrings.begin(),littleStrings.begin()+ls1.size());
842   std::vector<double> d1(1);
843   _mesh2D->unserialization(d1,ti1,a1tmp,a2tmp,ls2);
844   a1tmp->decrRef(); a2tmp->decrRef();
845   //
846   ls2.clear();
847   ls2.insert(ls2.end(),littleStrings.begin()+ls1.size(),littleStrings.end()-2);
848   _mesh1D=MEDCouplingUMesh::New();
849   a1tmp=DataArrayInt::New(); a2tmp=DataArrayDouble::New();
850   _mesh1D->resizeForUnserialization(ti2,a1tmp,a2tmp,ls1);
851   std::copy(a2Ptr,a2Ptr+a2tmp->getNbOfElems(),a2tmp->getPointer());
852   std::copy(a1Ptr,a1Ptr+a1tmp->getNbOfElems(),a1tmp->getPointer());
853   a1Ptr+=a1tmp->getNbOfElems();
854   _mesh1D->unserialization(d1,ti2,a1tmp,a2tmp,ls2);
855   a1tmp->decrRef(); a2tmp->decrRef();
856   //
857   _mesh3D_ids=DataArrayInt::New();
858   int szIds=(int)std::distance(a1Ptr,a1->getConstPointer()+a1->getNbOfElems());
859   _mesh3D_ids->alloc(szIds,1);
860   std::copy(a1Ptr,a1Ptr+szIds,_mesh3D_ids->getPointer());
861 }
862
863 void MEDCouplingExtrudedMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
864 {
865   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=buildUnstructured();
866   m->writeVTKLL(ofs,cellData,pointData);
867 }
868
869 std::string MEDCouplingExtrudedMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
870 {
871   return _mesh2D->getVTKDataSetType();
872 }