Salome HOME
31988e3e0789833975299db2fd75be962261693d
[modules/med.git] / src / INTERP_KERNEL / VolSurfUser.txx
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 #ifndef __VOLSURFUSER_TXX__
20 #define __VOLSURFUSER_TXX__
21
22 #include "VolSurfUser.hxx"
23 #include "VolSurfFormulae.hxx"
24 #include "InterpolationUtils.hxx"
25
26 #include <algorithm>
27
28 namespace INTERP_KERNEL
29 {
30   template<class ConnType, NumberingPolicy numPol, int SPACEDIM>
31   double computeVolSurfOfCell(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords)
32   {
33     switch(type)
34       {
35       case INTERP_KERNEL::NORM_SEG2 :
36       case INTERP_KERNEL::NORM_SEG3 :
37       case INTERP_KERNEL::NORM_SEG4 :
38         {
39           int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
40           int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
41           return INTERP_KERNEL::calculateLgthForSeg2(coords+(SPACEDIM*N1),coords+(SPACEDIM*N2),SPACEDIM);
42         }
43       case INTERP_KERNEL::NORM_TRI3 :
44       case INTERP_KERNEL::NORM_TRI6 :
45       case INTERP_KERNEL::NORM_TRI7 :
46         {
47           int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
48           int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
49           int N3 = OTT<ConnType,numPol>::coo2C(connec[2]);
50               
51           return INTERP_KERNEL::calculateAreaForTria(coords+(SPACEDIM*N1),
52                                                      coords+(SPACEDIM*N2),
53                                                      coords+(SPACEDIM*N3),
54                                                      SPACEDIM);
55         }
56         break;
57             
58       case INTERP_KERNEL::NORM_QUAD4 :
59       case INTERP_KERNEL::NORM_QUAD8 :
60       case INTERP_KERNEL::NORM_QUAD9 :
61         {
62           int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
63           int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
64           int N3 = OTT<ConnType,numPol>::coo2C(connec[2]);
65           int N4 = OTT<ConnType,numPol>::coo2C(connec[3]);
66               
67           return INTERP_KERNEL::calculateAreaForQuad(coords+SPACEDIM*N1,
68                                                      coords+SPACEDIM*N2,
69                                                      coords+SPACEDIM*N3,
70                                                      coords+SPACEDIM*N4,
71                                                      SPACEDIM);
72         }
73         break;
74             
75       case INTERP_KERNEL::NORM_POLYGON :
76         {          
77           const double **pts=new const double *[lgth];
78           for(int inod=0;inod<lgth;inod++)
79             pts[inod] = coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[inod]);
80           double val=INTERP_KERNEL::calculateAreaForPolyg(pts,lgth,SPACEDIM);
81           delete [] pts;
82           return val;
83         }
84         break;
85       case INTERP_KERNEL::NORM_TETRA4 :
86       case INTERP_KERNEL::NORM_TETRA10 :
87         {
88           int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
89           int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
90           int N3 = OTT<ConnType,numPol>::coo2C(connec[2]);
91           int N4 = OTT<ConnType,numPol>::coo2C(connec[3]);
92               
93           return INTERP_KERNEL::calculateVolumeForTetra(coords+SPACEDIM*N1,
94                                                         coords+SPACEDIM*N2,
95                                                         coords+SPACEDIM*N3,
96                                                         coords+SPACEDIM*N4);
97         }
98         break;
99             
100       case INTERP_KERNEL::NORM_PYRA5 :
101       case INTERP_KERNEL::NORM_PYRA13 :
102         {
103           int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
104           int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
105           int N3 = OTT<ConnType,numPol>::coo2C(connec[2]);
106           int N4 = OTT<ConnType,numPol>::coo2C(connec[3]);
107           int N5 = OTT<ConnType,numPol>::coo2C(connec[4]);
108               
109           return INTERP_KERNEL::calculateVolumeForPyra(coords+SPACEDIM*N1,
110                                                        coords+SPACEDIM*N2,
111                                                        coords+SPACEDIM*N3,
112                                                        coords+SPACEDIM*N4,
113                                                        coords+SPACEDIM*N5);
114         }
115         break;
116             
117       case INTERP_KERNEL::NORM_PENTA6 :
118       case INTERP_KERNEL::NORM_PENTA15 :
119         {
120           int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
121           int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
122           int N3 = OTT<ConnType,numPol>::coo2C(connec[2]);
123           int N4 = OTT<ConnType,numPol>::coo2C(connec[3]);
124           int N5 = OTT<ConnType,numPol>::coo2C(connec[4]);
125           int N6 = OTT<ConnType,numPol>::coo2C(connec[5]);
126               
127           return INTERP_KERNEL::calculateVolumeForPenta(coords+SPACEDIM*N1,
128                                                         coords+SPACEDIM*N2,
129                                                         coords+SPACEDIM*N3,
130                                                         coords+SPACEDIM*N4,
131                                                         coords+SPACEDIM*N5,
132                                                         coords+SPACEDIM*N6);
133         }
134         break;
135             
136       case INTERP_KERNEL::NORM_HEXA8 :
137       case INTERP_KERNEL::NORM_HEXA20 :
138       case INTERP_KERNEL::NORM_HEXA27 :
139         {
140           int N1 = OTT<ConnType,numPol>::coo2C(connec[0]);
141           int N2 = OTT<ConnType,numPol>::coo2C(connec[1]);
142           int N3 = OTT<ConnType,numPol>::coo2C(connec[2]);
143           int N4 = OTT<ConnType,numPol>::coo2C(connec[3]);
144           int N5 = OTT<ConnType,numPol>::coo2C(connec[4]);
145           int N6 = OTT<ConnType,numPol>::coo2C(connec[5]);
146           int N7 = OTT<ConnType,numPol>::coo2C(connec[6]);
147           int N8 = OTT<ConnType,numPol>::coo2C(connec[7]);
148               
149           return INTERP_KERNEL::calculateVolumeForHexa(coords+SPACEDIM*N1,
150                                                        coords+SPACEDIM*N2,
151                                                        coords+SPACEDIM*N3,
152                                                        coords+SPACEDIM*N4,
153                                                        coords+SPACEDIM*N5,
154                                                        coords+SPACEDIM*N6,
155                                                        coords+SPACEDIM*N7,
156                                                        coords+SPACEDIM*N8);
157         }
158         break;
159       case INTERP_KERNEL::NORM_HEXGP12:
160         {
161           const int connecHexa12[43]={
162             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[4]),OTT<ConnType,numPol>::coo2C(connec[5]),-1,
163             OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[11]),OTT<ConnType,numPol>::coo2C(connec[10]),OTT<ConnType,numPol>::coo2C(connec[9]),OTT<ConnType,numPol>::coo2C(connec[8]),OTT<ConnType,numPol>::coo2C(connec[7]),-1,
164             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[7]),OTT<ConnType,numPol>::coo2C(connec[1]),-1,
165             OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[7]),OTT<ConnType,numPol>::coo2C(connec[8]),OTT<ConnType,numPol>::coo2C(connec[2]),-1,
166             OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[8]),OTT<ConnType,numPol>::coo2C(connec[9]),OTT<ConnType,numPol>::coo2C(connec[3]),-1,
167             OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[9]),OTT<ConnType,numPol>::coo2C(connec[10]),OTT<ConnType,numPol>::coo2C(connec[4]),-1,
168             OTT<ConnType,numPol>::coo2C(connec[4]),OTT<ConnType,numPol>::coo2C(connec[10]),OTT<ConnType,numPol>::coo2C(connec[11]),OTT<ConnType,numPol>::coo2C(connec[5]),-1,
169             OTT<ConnType,numPol>::coo2C(connec[5]),OTT<ConnType,numPol>::coo2C(connec[11]),OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[0])};
170           return calculateVolumeForPolyh2<ConnType,numPol>(connecHexa12,43,coords);
171         }
172       case INTERP_KERNEL::NORM_POLYHED :
173         {
174           return calculateVolumeForPolyh2<ConnType,numPol>(connec,lgth,coords);
175         }
176         break;
177       default:
178         throw INTERP_KERNEL::Exception("Not recognized cell type to get Length/Area/Volume on it !");
179       }
180   }
181
182   template<class ConnType, NumberingPolicy numPolConn>
183   double computeVolSurfOfCell2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim)
184   {
185     if(spaceDim==3)
186       return computeVolSurfOfCell<ConnType,numPolConn,3>(type,connec,lgth,coords);
187     if(spaceDim==2)
188       return computeVolSurfOfCell<ConnType,numPolConn,2>(type,connec,lgth,coords);
189     if(spaceDim==1)
190       return computeVolSurfOfCell<ConnType,numPolConn,1>(type,connec,lgth,coords);
191     throw INTERP_KERNEL::Exception("Invalid spaceDim specified : must be 1, 2 or 3");
192   }
193
194
195   template<class ConnType, NumberingPolicy numPol,int SPACEDIM>
196   void computeBarycenter(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, double *res)
197   {
198     switch(type)
199       {
200       case NORM_SEG2:
201       case NORM_SEG3:
202       case NORM_SEG4:
203         {
204           std::copy(coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]),
205                     coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]+1),res);
206           std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[1]),res,std::plus<double>());
207           std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies<double>(),0.5));
208           break;
209         }
210       case NORM_TRI3:
211       case NORM_TRI6:
212       case NORM_TRI7:
213         {
214           std::copy(coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]),
215                     coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[0]+1),res);
216           std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[1]),res,std::plus<double>());
217           std::transform(res,res+SPACEDIM,coords+SPACEDIM*OTT<ConnType,numPol>::coo2C(connec[2]),res,std::plus<double>());
218           std::transform(res,res+SPACEDIM,res,std::bind2nd(std::multiplies<double>(),1./3.));
219           break;
220         }
221       case NORM_QUAD4:
222       case NORM_POLYGON:
223         {
224           if(SPACEDIM==2)
225             computePolygonBarycenter2D<ConnType,numPol>(connec,lgth,coords,res);
226           else if(SPACEDIM==3)
227             computePolygonBarycenter3D<ConnType,numPol>(connec,lgth,coords,res);
228           else
229             throw INTERP_KERNEL::Exception("Impossible spacedim linked to cell 2D Cell !");
230           break;
231         }
232       case NORM_QUAD8:
233         {
234           if(SPACEDIM==2)
235             computePolygonBarycenter2D<ConnType,numPol>(connec,lgth/2,coords,res);
236           else if(SPACEDIM==3)
237             computePolygonBarycenter3D<ConnType,numPol>(connec,lgth/2,coords,res);
238           else
239             throw INTERP_KERNEL::Exception("Impossible spacedim linked to cell 2D Cell !");
240           break;
241         }
242       case NORM_TETRA4:
243         {
244           res[0]=coords[3*OTT<ConnType,numPol>::coo2C(connec[0])]; 
245           res[1]=coords[3*OTT<ConnType,numPol>::coo2C(connec[0])+1];
246           res[2]=coords[3*OTT<ConnType,numPol>::coo2C(connec[0])+2];
247           res[0]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[1])]; 
248           res[1]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[1])+1];
249           res[2]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[1])+2];
250           res[0]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[2])]; 
251           res[1]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[2])+1];
252           res[2]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[2])+2];
253           res[0]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[3])]; 
254           res[1]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[3])+1];
255           res[2]+=coords[3*OTT<ConnType,numPol>::coo2C(connec[3])+2];
256           res[0]*=0.25; res[1]*=0.25; res[2]*=0.25;
257           break;
258         }
259       case NORM_PYRA5:
260         {
261           double tmp[3];
262           computePolygonBarycenter3D<ConnType,numPol>(connec,lgth-1,coords,tmp);
263           res[0]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[4])]+3.*tmp[0])/4.;
264           res[1]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[4])+1]+3.*tmp[1])/4.;
265           res[2]=(coords[3*OTT<ConnType,numPol>::coo2C(connec[4])+2]+3.*tmp[2])/4.;
266           break;
267         }
268       case NORM_HEXA8:
269         {
270           const int conn[29]={
271             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[3]),-1,
272             OTT<ConnType,numPol>::coo2C(connec[4]),OTT<ConnType,numPol>::coo2C(connec[7]),OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[5]),-1,
273             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[7]),OTT<ConnType,numPol>::coo2C(connec[4]),-1,
274             OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[7]),-1,
275             OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[5]),OTT<ConnType,numPol>::coo2C(connec[6]),-1,
276             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[4]),OTT<ConnType,numPol>::coo2C(connec[5]),OTT<ConnType,numPol>::coo2C(connec[1]),
277             };
278           barycenterOfPolyhedron<ConnType,numPol>(conn,29,coords,res);
279           break;
280         }
281       case NORM_PENTA6:
282         {
283           const int conn[22]={
284             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[2]),-1,
285             OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[5]),OTT<ConnType,numPol>::coo2C(connec[4]),-1,
286             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[5]),OTT<ConnType,numPol>::coo2C(connec[3]),-1,
287             OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[4]),OTT<ConnType,numPol>::coo2C(connec[5]),-1,
288             OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[4])
289           };
290           barycenterOfPolyhedron<ConnType,numPol>(conn,22,coords,res);
291           break;
292         }
293       case INTERP_KERNEL::NORM_HEXGP12:
294         {
295           const int connecHexa12[43]={
296             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[4]),OTT<ConnType,numPol>::coo2C(connec[5]),-1,
297             OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[11]),OTT<ConnType,numPol>::coo2C(connec[10]),OTT<ConnType,numPol>::coo2C(connec[9]),OTT<ConnType,numPol>::coo2C(connec[8]),OTT<ConnType,numPol>::coo2C(connec[7]),-1,
298             OTT<ConnType,numPol>::coo2C(connec[0]),OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[7]),OTT<ConnType,numPol>::coo2C(connec[1]),-1,
299             OTT<ConnType,numPol>::coo2C(connec[1]),OTT<ConnType,numPol>::coo2C(connec[7]),OTT<ConnType,numPol>::coo2C(connec[8]),OTT<ConnType,numPol>::coo2C(connec[2]),-1,
300             OTT<ConnType,numPol>::coo2C(connec[2]),OTT<ConnType,numPol>::coo2C(connec[8]),OTT<ConnType,numPol>::coo2C(connec[9]),OTT<ConnType,numPol>::coo2C(connec[3]),-1,
301             OTT<ConnType,numPol>::coo2C(connec[3]),OTT<ConnType,numPol>::coo2C(connec[9]),OTT<ConnType,numPol>::coo2C(connec[10]),OTT<ConnType,numPol>::coo2C(connec[4]),-1,
302             OTT<ConnType,numPol>::coo2C(connec[4]),OTT<ConnType,numPol>::coo2C(connec[10]),OTT<ConnType,numPol>::coo2C(connec[11]),OTT<ConnType,numPol>::coo2C(connec[5]),-1,
303             OTT<ConnType,numPol>::coo2C(connec[5]),OTT<ConnType,numPol>::coo2C(connec[11]),OTT<ConnType,numPol>::coo2C(connec[6]),OTT<ConnType,numPol>::coo2C(connec[0])};
304           barycenterOfPolyhedron<ConnType,numPol>(connecHexa12,43,coords,res);
305           break;
306         }
307       case NORM_POLYHED:
308         {
309           barycenterOfPolyhedron<ConnType,numPol>(connec,lgth,coords,res);
310           break;
311         }
312       default:
313         throw INTERP_KERNEL::Exception("Not recognized cell type to get Barycenter on it !");
314       }
315   }
316
317   template<class ConnType, NumberingPolicy numPolConn>
318   void computeBarycenter2(NormalizedCellType type, const ConnType *connec, int lgth, const double *coords, int spaceDim, double *res)
319   {
320     if(spaceDim==3)
321       return computeBarycenter<ConnType,numPolConn,3>(type,connec,lgth,coords,res);
322     if(spaceDim==2)
323       return computeBarycenter<ConnType,numPolConn,2>(type,connec,lgth,coords,res);
324     if(spaceDim==1)
325       return computeBarycenter<ConnType,numPolConn,1>(type,connec,lgth,coords,res);
326     throw INTERP_KERNEL::Exception("Invalid spaceDim specified for compute barycenter : must be 1, 2 or 3");
327   }
328 }
329
330 #endif