1 /*
2 XLiFE++ is an extended library of finite elements written in C++
3     Copyright (C) 2014  Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 /*!
18   \file Hexahedron.cpp
19   \author Y. Lafranche
20   \since 3 Fev 2014
21   \date 19 Mar 2014
22 
23   \brief Implementation of xlifepp::subdivision::Hexahedron class members and related functions
24 */
25 
26 #include "Hexahedron.hpp"
27 
28 #include <algorithm>
29 using namespace std;
30 
31 namespace xlifepp {
32 namespace subdivision {
33 
34 //-------------------------------------------------------------------------------
35 //  Static variables
36 //-------------------------------------------------------------------------------
37 // Index array defining the edges according to the following numering convention:
38 // edge #1=(1,2), edge #2 =(3,4), edge #3 =(5,6), edge #4 =(7,8),
39 // edge #5=(1,3), edge #6 =(2,4), edge #7 =(5,7), edge #8 =(6,8),
40 // edge #9=(1,5), edge #10=(2,6), edge #11=(3,7), edge #12=(4,8),
41 short Hexahedron::rkEdge[/* nb_edges_ */][2] = {{0,1}, {2,3}, {4,5}, {6,7},
42                                                 {0,2}, {1,3}, {4,6}, {5,7},
43                                                 {0,4}, {1,5}, {2,6}, {3,7}};
44 
45 // Index array defining the faces according to the following numering convention:
46 // face #1=(1,3,4,2), face #2=(5,7,8,6) : orthogonal to X
47 // face #3=(1,2,6,5), face #4=(3,4,8,7) : orthogonal to Y
48 // face #5=(1,5,7,3), face #6=(2,6,8,4) : orthogonal to Z
49 short Hexahedron::rkFace[/* nb_faces_ */][4] = {{0,2,3,1}, {4,6,7,5}, {0,1,5,4},
50                                                 {2,3,7,6}, {0,4,6,2}, {1,5,7,3}};
51 
52 // Array containing the edge numbers (>=1) defining a face
53 // face #1=(5,2,6,1),   face #2=(7,4,8,3),  face #3=(1,10,3,9),
54 // face #4=(2,12,4,11), face #5=(9,7,11,5), face #6=(10,8,12,6)
55 short Hexahedron::nuEdge[/* nb_faces_ */][4] = {{5,2,6,1},   {7,4,8,3},  {1,10,3,9},
56                                                 {2,12,4,11}, {9,7,11,5}, {10,8,12,6}};
57 //-------------------------------------------------------------------------------
58 //  Constructors, Destructor
59 //-------------------------------------------------------------------------------
60 /*!
61  Conversion constructor. Constructor by vertices, given by their rank in the list
62  */
Hexahedron(const number_t num,const number_t rV1,const number_t rV2,const number_t rV3,const number_t rV4,const number_t rV5,const number_t rV6,const number_t rV7,const number_t rV8,const number_t bdSideNum)63 Hexahedron::Hexahedron(const number_t num,
64                        const number_t rV1, const number_t rV2, const number_t rV3, const number_t rV4,
65                        const number_t rV5, const number_t rV6, const number_t rV7, const number_t rV8,
66                        const number_t bdSideNum)
67 :CartesianFig<Hexahedron>(num,bdSideNum){
68    vertices_[0] = rV1;
69    vertices_[1] = rV2;
70    vertices_[2] = rV3;
71    vertices_[3] = rV4;
72    vertices_[4] = rV5;
73    vertices_[5] = rV6;
74    vertices_[6] = rV7;
75    vertices_[7] = rV8;
76 }
77 
78 //-------------------------------------------------------------------------------
79 //  Other public member functions
80 //-------------------------------------------------------------------------------
81 /*!
82  returns the numbers (>= 1) of the edges defining the face number i
83  */
numEdgesOfFace(const number_t i)84 vector<short> Hexahedron::numEdgesOfFace(const number_t i) {
85    return vector<short> (nuEdge[i-1], nuEdge[i-1]+4);
86 }
87 /*!
88  returns the ranks (>= 0) of the vertices defining the edges of the hexahedron
89  */
rkEdgeVertices()90 vector<pair<short,short> > Hexahedron::rkEdgeVertices() {
91    vector<pair<short,short> > V(nb_edges_);
92    for (number_t i=0; i<nb_edges_; i++) { V[i] = make_pair(rkEdge[i][0],rkEdge[i][1]); }
93    return V;
94 }
95 /*!
96  This function gives the local position of the vertices of any hexahedron of
97  the mesh correspondig to the numbering convention explained on top of the
98  Hexahedron class header file (Hexahedron.hpp).
99 
100  The numbering convention of high order vertices is deduced from a triple tensor
101  product of the standard numbering over the segment defined by the integers [0,1,...k].
102  Thus, the entry BC[i] in the returned vector BC contains a vector of 3 integers whose
103  components BC[i][j] are such that 0<= BC[i][j] <= k, where k is the order of the mesh.
104  Each component is the result of a permutation of a 3D tensor product of the uniform
105  subdivision of the interval [0,1,...k]. This gives an intrinsic way of numbering and
106  localization of the points if these components are sorted in alphanumeric order.
107  Nota: this does not match with the numbering of the vertices XLiFE++ uses.
108 
109  Moreover, the returned vector gives the location of the vertices according
110  to the way they are encountered in the numbering process implemented by the
111  functions GeomFigureMesh<T_>::createHOV, GeomFigureMesh<T_>::createHOeV, HexahedronMesh::createHOfV
112  and HexahedronMesh::createHOiV.
113  */
numberingOfVertices(const number_t Order)114 vector< vector<number_t> > Hexahedron::numberingOfVertices(const number_t Order) {
115    number_t order = Order;
116    if (order < 1) {order = 1;}
117 
118    number_t NbVert((order+1)*(order+1)*(order+1));
119    vector<number_t> V(3,0);
120    vector< vector<number_t> > BC(NbVert,V);
121 
122 //    main vertices (order 1)
123 //    #1 -> (0, 0, 0), #2 -> (0, 0, k), #3 -> (0, k, 0), #4 -> (0, k, k)
124 //    #5 -> (k, 0, 0), #6 -> (k, 0, k), #7 -> (k, k, 0), #8 -> (k, k, k)
125 //    int rkVert[] = {3,7,2,6, 0,4,1,5}; // Vertices 4,8,3,7, 1,5,2,6 in Melina++
126    const number_t ivx(0), ivy(1), ivz(2);
127    number_t indBC(0);
128    for (number_t ix=0; ix<2; ix++) {
129       V[ivx] = ix*order;
130       for (number_t iy=0; iy<2; iy++) {
131          V[ivy] = iy*order;
132          for (number_t iz=0; iz<2; iz++) {
133             V[ivz] = iz*order;
134 //             BC[rkVert[indBC++]] = V;
135             BC[indBC++] = V;
136             }
137          }
138       }
139 // Order 2 : rkVert[] = {4, 12, 8, 14, 24, 17, 3, 18, 7, 13, 25, 19, 26, 27, 23, 16, 22, 10, 1, 15, 5, 20, 21, 11, 2, 9, 6}
140 
141 /*
142       edge vertices (cf. GeomFigureMesh<T_>::createHOeV)
143       vertex numbering is decreasing along the edges
144         1. 4 edges along Z : edge #1 =(1,2) -> (0, 0, .)
145                              edge #2 =(3,4) -> (0, k, .)
146                              edge #3 =(5,6) -> (k, 0, .)
147                              edge #4 =(7,8) -> (k, k, .)
148         2. 4 edges along Y : edge #5 =(1,3) -> (0, ., 0)
149                              edge #6 =(2,4) -> (0, ., k)
150                              edge #7 =(5,7) -> (k, ., 0)
151                              edge #8 =(6,8) -> (k, ., k)
152         3. 4 edges along X : edge #9 =(1,5) -> (., 0, 0)
153                              edge #10=(2,6) -> (., 0, k)
154                              edge #11=(3,7) -> (., k, 0)
155                              edge #12=(4,8) -> (., k, k)
156 */
157    number_t tiv[]={2,1,0}; // Z, Y, X
158    for (number_t indEdge=0; indEdge<nb_edges_; indEdge++) {
159       V = BC[rkEdge[indEdge][0]];
160       number_t iv = tiv[indEdge/4];
161       for (number_t i1=1; i1<order; i1++) {
162          V[iv] = order-i1;
163          BC[indBC++] = V;
164       }
165    }
166 /*
167       face vertices (cf. HexahedronMesh::createHOfV)
168         1. 2 faces orthogonal to X : face #1=(1,3,4,2) -> (0, ., .)
169                                      face #2=(5,7,8,6) -> (k, ., .)
170                                                    increasing order along Y first then Z
171         2. 2 faces orthogonal to Y : face #3=(1,2,6,5) -> (., 0, .)
172                                      face #4=(3,4,8,7) -> (., k, .)
173                                                    increasing order along Z first then X
174         3. 2 faces orthogonal to Z : face #5=(1,5,7,3) -> (., ., 0)
175                                      face #6=(2,6,8,4) -> (., ., k)
176                                                    increasing order along X first then Y
177 */
178    number_t tiv1[]={2,0,1}, tiv2[]={1,2,0}; // couples (iv1,iv2) : (Z,Y), (X,Z) and (Y,X)
179    for (number_t indFace=0; indFace<nb_faces_; indFace++) {
180       V = BC[rkFace[indFace][0]];
181       number_t iv1 = tiv1[indFace/2], iv2 = tiv2[indFace/2];
182       for (number_t i1=1; i1<order; i1++) {
183          V[iv1] = i1;
184          for (number_t i2=1; i2<order; i2++) {
185             V[iv2] = i2;
186             BC[indBC++] = V;
187          }
188       }
189    }
190 //    internal vertices (cf. HexahedronMesh::createHOiV)
191 //    increasing order along X first then Y then Z
192    for (number_t iz=1; iz<order; iz++) {
193       V[ivz] = iz;
194       for (number_t iy=1; iy<order; iy++) {
195          V[ivy] = iy;
196          for (number_t ix=1; ix<order; ix++) {
197             V[ivx] = ix;
198             BC[indBC++] = V;
199             }
200          }
201       }
202    return BC;
203 }
204 
205 } // end of namespace subdivision
206 } // end of namespace xlifepp
207