|
Intrepid
|
00001 // @HEADER 00002 // ************************************************************************ 00003 // 00004 // Intrepid Package 00005 // Copyright (2007) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Pavel Bochev (pbboche@sandia.gov) 00025 // Denis Ridzal (dridzal@sandia.gov), or 00026 // Kara Peterson (kjpeter@sandia.gov) 00027 // 00028 // ************************************************************************ 00029 // @HEADER 00030 00031 00036 #ifndef INTREPID_CELLTOOLSDEF_HPP 00037 #define INTREPID_CELLTOOLSDEF_HPP 00038 00039 00040 namespace Intrepid { 00041 00042 template<class Scalar> 00043 const FieldContainer<double>& CellTools<Scalar>::getSubcellParametrization(const int subcellDim, 00044 const shards::CellTopology& parentCell){ 00045 00046 #ifdef HAVE_INTREPID_DEBUG 00047 TEST_FOR_EXCEPTION( !(hasReferenceCell(parentCell) ), std::invalid_argument, 00048 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): the specified cell topology does not have a reference cell."); 00049 00050 TEST_FOR_EXCEPTION( !( (1 <= subcellDim) && (subcellDim <= 2 ) ), std::invalid_argument, 00051 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): parametrization defined only for 1 and 2-dimensional subcells."); 00052 #endif 00053 00054 // Coefficients of the coordinate functions defining the parametrization maps are stored in 00055 // rank-3 arrays with dimensions (SC, PCD, COEF) where: 00056 // - SC is the subcell count of subcells with the specified dimension in the parent cell 00057 // - PCD is Parent Cell Dimension, which gives the number of coordinate functions in the map: 00058 // PCD = 2 for standard 2D cells and non-standard 2D cells: shell line and beam 00059 // PCD = 3 for standard 3D cells and non-standard 3D cells: shell Tri and Quad 00060 // - COEF is number of coefficients needed to specify a coordinate function: 00061 // COEFF = 2 for edge parametrizations 00062 // COEFF = 3 for both Quad and Tri face parametrizations. Because all Quad reference faces 00063 // are affine, the coefficient of the bilinear term u*v is zero and is not stored, i.e., 00064 // 3 coefficients are sufficient to store Quad face parameterization maps. 00065 // 00066 // Arrays are sized and filled only when parametrization of a particular subcell is requested 00067 // by setSubcellParametrization. 00068 00069 // Edge maps for 2D non-standard cells: ShellLine and Beam 00070 static FieldContainer<double> lineEdges; static int lineEdgesSet = 0; 00071 00072 // Edge maps for 2D standard cells: Triangle and Quadrilateral 00073 static FieldContainer<double> triEdges; static int triEdgesSet = 0; 00074 static FieldContainer<double> quadEdges; static int quadEdgesSet = 0; 00075 00076 // Edge maps for 3D non-standard cells: Shell Tri and Quad 00077 static FieldContainer<double> shellTriEdges; static int shellTriEdgesSet = 0; 00078 static FieldContainer<double> shellQuadEdges; static int shellQuadEdgesSet = 0; 00079 00080 // Edge maps for 3D standard cells: 00081 static FieldContainer<double> tetEdges; static int tetEdgesSet = 0; 00082 static FieldContainer<double> hexEdges; static int hexEdgesSet = 0; 00083 static FieldContainer<double> pyrEdges; static int pyrEdgesSet = 0; 00084 static FieldContainer<double> wedgeEdges; static int wedgeEdgesSet = 0; 00085 00086 00087 // Face maps for 3D non-standard cells: Shell Triangle and Quadrilateral 00088 static FieldContainer<double> shellTriFaces; static int shellTriFacesSet = 0; 00089 static FieldContainer<double> shellQuadFaces; static int shellQuadFacesSet = 0; 00090 00091 // Face maps for 3D standard cells: 00092 static FieldContainer<double> tetFaces; static int tetFacesSet = 0; 00093 static FieldContainer<double> hexFaces; static int hexFacesSet = 0; 00094 static FieldContainer<double> pyrFaces; static int pyrFacesSet = 0; 00095 static FieldContainer<double> wedgeFaces; static int wedgeFacesSet = 0; 00096 00097 // Select subcell parametrization according to its parent cell type 00098 switch(parentCell.getKey() ) { 00099 00100 // Tet cells 00101 case shards::Tetrahedron<4>::key: 00102 case shards::Tetrahedron<8>::key: 00103 case shards::Tetrahedron<10>::key: 00104 if(subcellDim == 2) { 00105 if(!tetFacesSet){ 00106 setSubcellParametrization(tetFaces, subcellDim, parentCell); 00107 tetFacesSet = 1; 00108 } 00109 return tetFaces; 00110 } 00111 else if(subcellDim == 1) { 00112 if(!tetEdgesSet){ 00113 setSubcellParametrization(tetEdges, subcellDim, parentCell); 00114 tetEdgesSet = 1; 00115 } 00116 return tetEdges; 00117 } 00118 else{ 00119 TEST_FOR_EXCEPTION( (subcellDim != 1 || subcellDim != 2), std::invalid_argument, 00120 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Tet parametrizations defined for 1 and 2-subcells only"); 00121 } 00122 break; 00123 00124 // Hex cells 00125 case shards::Hexahedron<8>::key: 00126 case shards::Hexahedron<20>::key: 00127 case shards::Hexahedron<27>::key: 00128 if(subcellDim == 2) { 00129 if(!hexFacesSet){ 00130 setSubcellParametrization(hexFaces, subcellDim, parentCell); 00131 hexFacesSet = 1; 00132 } 00133 return hexFaces; 00134 } 00135 else if(subcellDim == 1) { 00136 if(!hexEdgesSet){ 00137 setSubcellParametrization(hexEdges, subcellDim, parentCell); 00138 hexEdgesSet = 1; 00139 } 00140 return hexEdges; 00141 } 00142 else{ 00143 TEST_FOR_EXCEPTION( (subcellDim != 1 || subcellDim != 2), std::invalid_argument, 00144 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Hex parametrizations defined for 1 and 2-subcells only"); 00145 } 00146 break; 00147 00148 // Pyramid cells 00149 case shards::Pyramid<5>::key: 00150 case shards::Pyramid<13>::key: 00151 case shards::Pyramid<14>::key: 00152 if(subcellDim == 2) { 00153 if(!pyrFacesSet){ 00154 setSubcellParametrization(pyrFaces, subcellDim, parentCell); 00155 pyrFacesSet = 1; 00156 } 00157 return pyrFaces; 00158 } 00159 else if(subcellDim == 1) { 00160 if(!pyrEdgesSet){ 00161 setSubcellParametrization(pyrEdges, subcellDim, parentCell); 00162 pyrEdgesSet = 1; 00163 } 00164 return pyrEdges; 00165 } 00166 else { 00167 TEST_FOR_EXCEPTION( (subcellDim != 1 || subcellDim != 2), std::invalid_argument, 00168 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Pyramid parametrizations defined for 1 and 2-subcells only"); 00169 } 00170 break; 00171 00172 // Wedge cells 00173 case shards::Wedge<6>::key: 00174 case shards::Wedge<15>::key: 00175 case shards::Wedge<18>::key: 00176 if(subcellDim == 2) { 00177 if(!wedgeFacesSet){ 00178 setSubcellParametrization(wedgeFaces, subcellDim, parentCell); 00179 wedgeFacesSet = 1; 00180 } 00181 return wedgeFaces; 00182 } 00183 else if(subcellDim == 1) { 00184 if(!wedgeEdgesSet){ 00185 setSubcellParametrization(wedgeEdges, subcellDim, parentCell); 00186 wedgeEdgesSet = 1; 00187 } 00188 return wedgeEdges; 00189 } 00190 else { 00191 TEST_FOR_EXCEPTION( (subcellDim != 1 || subcellDim != 2), std::invalid_argument, 00192 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Wedge parametrization defined for 1 and 2-subcells only"); 00193 } 00194 break; 00195 // 00196 // Standard 2D cells have only 1-subcells 00197 // 00198 case shards::Triangle<3>::key: 00199 case shards::Triangle<4>::key: 00200 case shards::Triangle<6>::key: 00201 if(subcellDim == 1) { 00202 if(!triEdgesSet){ 00203 setSubcellParametrization(triEdges, subcellDim, parentCell); 00204 triEdgesSet = 1; 00205 } 00206 return triEdges; 00207 } 00208 else{ 00209 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00210 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Triangle parametrizations defined for 1-subcells only"); 00211 } 00212 break; 00213 00214 case shards::Quadrilateral<4>::key: 00215 case shards::Quadrilateral<8>::key: 00216 case shards::Quadrilateral<9>::key: 00217 if(subcellDim == 1) { 00218 if(!quadEdgesSet){ 00219 setSubcellParametrization(quadEdges, subcellDim, parentCell); 00220 quadEdgesSet = 1; 00221 } 00222 return quadEdges; 00223 } 00224 else{ 00225 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00226 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Quad parametrizations defined for 1-subcells only"); 00227 } 00228 break; 00229 // 00230 // Non-standard 3D Shell Tri and Quad cells have 1 and 2-subcells. Because they are 3D cells 00231 // can't reuse edge parametrization arrays for 2D Triangle and Quadrilateral. 00232 // 00233 case shards::ShellTriangle<3>::key: 00234 case shards::ShellTriangle<6>::key: 00235 if(subcellDim == 2) { 00236 if(!shellTriFacesSet){ 00237 setSubcellParametrization(shellTriFaces, subcellDim, parentCell); 00238 shellTriFacesSet = 1; 00239 } 00240 return shellTriFaces; 00241 } 00242 else if(subcellDim == 1) { 00243 if(!shellTriEdgesSet){ 00244 setSubcellParametrization(shellTriEdges, subcellDim, parentCell); 00245 shellTriEdgesSet = 1; 00246 } 00247 return shellTriEdges; 00248 } 00249 else if( subcellDim != 1 || subcellDim != 2){ 00250 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00251 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Shell Triangle parametrizations defined for 1 and 2-subcells only"); 00252 } 00253 break; 00254 00255 case shards::ShellQuadrilateral<4>::key: 00256 case shards::ShellQuadrilateral<8>::key: 00257 case shards::ShellQuadrilateral<9>::key: 00258 if(subcellDim == 2) { 00259 if(!shellQuadFacesSet){ 00260 setSubcellParametrization(shellQuadFaces, subcellDim, parentCell); 00261 shellQuadFacesSet = 1; 00262 } 00263 return shellQuadFaces; 00264 } 00265 else if(subcellDim == 1) { 00266 if(!shellQuadEdgesSet){ 00267 setSubcellParametrization(shellQuadEdges, subcellDim, parentCell); 00268 shellQuadEdgesSet = 1; 00269 } 00270 return shellQuadEdges; 00271 } 00272 else if( subcellDim != 1 || subcellDim != 2){ 00273 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00274 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): Shell Quad parametrizations defined for 1 and 2-subcells only"); 00275 } 00276 break; 00277 00278 // 00279 // Non-standard 2D cells: Shell Lines and Beams have 1-subcells 00280 // 00281 case shards::ShellLine<2>::key: 00282 case shards::ShellLine<3>::key: 00283 case shards::Beam<2>::key: 00284 case shards::Beam<3>::key: 00285 if(subcellDim == 1) { 00286 if(!lineEdgesSet){ 00287 setSubcellParametrization(lineEdges, subcellDim, parentCell); 00288 lineEdgesSet = 1; 00289 } 00290 return lineEdges; 00291 } 00292 else{ 00293 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00294 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): shell line/beam parametrizations defined for 1-subcells only"); 00295 } 00296 break; 00297 00298 default: 00299 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00300 ">>> ERROR (Intrepid::CellTools::getSubcellParametrization): invalid cell topology."); 00301 }//cell key 00302 // To disable compiler warning, should never be reached 00303 return lineEdges; 00304 } 00305 00306 00307 00308 template<class Scalar> 00309 void CellTools<Scalar>::setSubcellParametrization(FieldContainer<double>& subcellParametrization, 00310 const int subcellDim, 00311 const shards::CellTopology& parentCell) 00312 { 00313 #ifdef HAVE_INTREPID_DEBUG 00314 TEST_FOR_EXCEPTION( !(hasReferenceCell(parentCell) ), std::invalid_argument, 00315 ">>> ERROR (Intrepid::CellTools::setSubcellParametrization): the specified cell topology does not have a reference cell."); 00316 00317 TEST_FOR_EXCEPTION( !( (1 <= subcellDim) && (subcellDim <= 2 ) ), std::invalid_argument, 00318 ">>> ERROR (Intrepid::CellTools::setSubcellParametrization): parametrization defined only for 1 and 2-dimensional subcells."); 00319 #endif 00320 // subcellParametrization is rank-3 FieldContainer with dimensions (SC, PCD, COEF) where: 00321 // - SC is the subcell count of subcells with the specified dimension in the parent cell 00322 // - PCD is Parent Cell Dimension, which gives the number of coordinate functions in the map 00323 // PCD = 2 for standard 2D cells and non-standard 2D cells: shell line and beam 00324 // PCD = 3 for standard 3D cells and non-standard 3D cells: shell Tri and Quad 00325 // - COEF is number of coefficients needed to specify a coordinate function: 00326 // COEFF = 2 for edge parametrizations 00327 // COEFF = 3 for both Quad and Tri face parametrizations. Because all Quad reference faces 00328 // are affine, the coefficient of the bilinear term u*v is zero and is not stored, i.e., 00329 // 3 coefficients are sufficient to store Quad face parameterization maps. 00330 // 00331 // Edge parametrization maps [-1,1] to edge defined by (v0, v1) 00332 // Face parametrization maps [-1,1]^2 to quadrilateral face (v0, v1, v2, v3), or 00333 // standard 2-simplex {(0,0),(1,0),(0,1)} to traingle face (v0, v1, v2). 00334 // This defines orientation-preserving parametrizations with respect to reference edge and 00335 // face orientations induced by their vertex order. 00336 00337 // get subcellParametrization dimensions: (sc, pcd, coeff) 00338 unsigned sc = parentCell.getSubcellCount(subcellDim); 00339 unsigned pcd = parentCell.getDimension(); 00340 unsigned coeff = (subcellDim == 1) ? 2 : 3; 00341 00342 00343 // Resize container 00344 subcellParametrization.resize(sc, pcd, coeff); 00345 00346 // Edge parametrizations of 2D and 3D cells (shell lines and beams are 2D cells with edges) 00347 if(subcellDim == 1){ 00348 for(unsigned subcellOrd = 0; subcellOrd < sc; subcellOrd++){ 00349 00350 int v0ord = parentCell.getNodeMap(subcellDim, subcellOrd, 0); 00351 int v1ord = parentCell.getNodeMap(subcellDim, subcellOrd, 1); 00352 00353 // vertexK[0] = x_k; vertexK[1] = y_k; vertexK[2] = z_k; z_k = 0 for 2D cells 00354 // Note that ShellLine and Beam are 2D cells! 00355 const double* v0 = getReferenceVertex(parentCell, v0ord); 00356 const double* v1 = getReferenceVertex(parentCell, v1ord); 00357 00358 // x(t) = (x0 + x1)/2 + t*(x1 - x0)/2 00359 subcellParametrization(subcellOrd, 0, 0) = (v0[0] + v1[0])/2.0; 00360 subcellParametrization(subcellOrd, 0, 1) = (v1[0] - v0[0])/2.0; 00361 00362 // y(t) = (y0 + y1)/2 + t*(y1 - y0)/2 00363 subcellParametrization(subcellOrd, 1, 0) = (v0[1] + v1[1])/2.0; 00364 subcellParametrization(subcellOrd, 1, 1) = (v1[1] - v0[1])/2.0; 00365 00366 if( pcd == 3 ) { 00367 // z(t) = (z0 + z1)/2 + t*(z1 - z0)/2 00368 subcellParametrization(subcellOrd, 2, 0) = (v0[2] + v1[2])/2.0; 00369 subcellParametrization(subcellOrd, 2, 1) = (v1[2] - v0[2])/2.0; 00370 } 00371 }// for loop over 1-subcells 00372 } 00373 00374 // Face parametrizations of 3D cells: (shell Tri and Quad are 3D cells with faces) 00375 // A 3D cell can have both Tri and Quad faces, but because they are affine images of the 00376 // parametrization domain, 3 coefficients are enough to store them in both cases. 00377 else if(subcellDim == 2) { 00378 for(unsigned subcellOrd = 0; subcellOrd < sc; subcellOrd++){ 00379 00380 switch(parentCell.getKey(subcellDim,subcellOrd)){ 00381 00382 // Admissible triangular faces for 3D cells in Shards: 00383 case shards::Triangle<3>::key: 00384 case shards::Triangle<4>::key: 00385 case shards::Triangle<6>::key: 00386 { 00387 int v0ord = parentCell.getNodeMap(subcellDim, subcellOrd, 0); 00388 int v1ord = parentCell.getNodeMap(subcellDim, subcellOrd, 1); 00389 int v2ord = parentCell.getNodeMap(subcellDim, subcellOrd, 2); 00390 const double* v0 = getReferenceVertex(parentCell, v0ord); 00391 const double* v1 = getReferenceVertex(parentCell, v1ord); 00392 const double* v2 = getReferenceVertex(parentCell, v2ord); 00393 00394 // x(u,v) = x0 + (x1 - x0)*u + (x2 - x0)*v 00395 subcellParametrization(subcellOrd, 0, 0) = v0[0]; 00396 subcellParametrization(subcellOrd, 0, 1) = v1[0] - v0[0]; 00397 subcellParametrization(subcellOrd, 0, 2) = v2[0] - v0[0]; 00398 00399 // y(u,v) = y0 + (y1 - y0)*u + (y2 - y0)*v 00400 subcellParametrization(subcellOrd, 1, 0) = v0[1]; 00401 subcellParametrization(subcellOrd, 1, 1) = v1[1] - v0[1]; 00402 subcellParametrization(subcellOrd, 1, 2) = v2[1] - v0[1]; 00403 00404 // z(u,v) = z0 + (z1 - z0)*u + (z2 - z0)*v 00405 subcellParametrization(subcellOrd, 2, 0) = v0[2]; 00406 subcellParametrization(subcellOrd, 2, 1) = v1[2] - v0[2]; 00407 subcellParametrization(subcellOrd, 2, 2) = v2[2] - v0[2]; 00408 } 00409 break; 00410 00411 // Admissible quadrilateral faces for 3D cells in Shards: 00412 case shards::Quadrilateral<4>::key: 00413 case shards::Quadrilateral<8>::key: 00414 case shards::Quadrilateral<9>::key: 00415 { 00416 int v0ord = parentCell.getNodeMap(subcellDim, subcellOrd, 0); 00417 int v1ord = parentCell.getNodeMap(subcellDim, subcellOrd, 1); 00418 int v2ord = parentCell.getNodeMap(subcellDim, subcellOrd, 2); 00419 int v3ord = parentCell.getNodeMap(subcellDim, subcellOrd, 3); 00420 const double* v0 = getReferenceVertex(parentCell, v0ord); 00421 const double* v1 = getReferenceVertex(parentCell, v1ord); 00422 const double* v2 = getReferenceVertex(parentCell, v2ord); 00423 const double* v3 = getReferenceVertex(parentCell, v3ord); 00424 00425 // x(u,v) = (x0+x1+x2+x3)/4+u*(-x0+x1+x2-x3)/4+v*(-x0-x1+x2+x3)/4+uv*(0=x0-x1+x2-x3)/4 00426 subcellParametrization(subcellOrd, 0, 0) = ( v0[0] + v1[0] + v2[0] + v3[0])/4.0; 00427 subcellParametrization(subcellOrd, 0, 1) = (-v0[0] + v1[0] + v2[0] - v3[0])/4.0; 00428 subcellParametrization(subcellOrd, 0, 2) = (-v0[0] - v1[0] + v2[0] + v3[0])/4.0; 00429 00430 // y(u,v) = (y0+y1+y2+y3)/4+u*(-y0+y1+y2-y3)/4+v*(-y0-y1+y2+y3)/4+uv*(0=y0-y1+y2-y3)/4 00431 subcellParametrization(subcellOrd, 1, 0) = ( v0[1] + v1[1] + v2[1] + v3[1])/4.0; 00432 subcellParametrization(subcellOrd, 1, 1) = (-v0[1] + v1[1] + v2[1] - v3[1])/4.0; 00433 subcellParametrization(subcellOrd, 1, 2) = (-v0[1] - v1[1] + v2[1] + v3[1])/4.0; 00434 00435 // z(u,v) = (z0+z1+z2+z3)/4+u*(-z0+z1+z2-z3)/4+v*(-z0-z1+z2+z3)/4+uv*(0=z0-z1+z2-z3)/4 00436 subcellParametrization(subcellOrd, 2, 0) = ( v0[2] + v1[2] + v2[2] + v3[2])/4.0; 00437 subcellParametrization(subcellOrd, 2, 1) = (-v0[2] + v1[2] + v2[2] - v3[2])/4.0; 00438 subcellParametrization(subcellOrd, 2, 2) = (-v0[2] - v1[2] + v2[2] + v3[2])/4.0; 00439 } 00440 break; 00441 default: 00442 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00443 ">>> ERROR (Intrepid::CellTools::setSubcellParametrization): parametrization not defined for the specified face topology."); 00444 00445 }// switch face topology key 00446 }// for subcellOrd 00447 } 00448 } 00449 00450 00451 00452 template<class Scalar> 00453 const double* CellTools<Scalar>::getReferenceVertex(const shards::CellTopology& cell, 00454 const int vertexOrd){ 00455 00456 #ifdef HAVE_INTREPID_DEBUG 00457 TEST_FOR_EXCEPTION( !(hasReferenceCell(cell) ), std::invalid_argument, 00458 ">>> ERROR (Intrepid::CellTools::getReferenceVertex): the specified cell topology does not have a reference cell."); 00459 00460 TEST_FOR_EXCEPTION( !( (0 <= vertexOrd) && (vertexOrd < (int)cell.getVertexCount() ) ), std::invalid_argument, 00461 ">>> ERROR (Intrepid::CellTools::getReferenceVertex): invalid node ordinal for the specified cell topology. "); 00462 #endif 00463 00464 // Simply call getReferenceNode with the base topology of the cell 00465 return getReferenceNode(cell.getBaseTopology(), vertexOrd); 00466 } 00467 00468 00469 00470 template<class Scalar> 00471 template<class ArraySubcellVert> 00472 void CellTools<Scalar>::getReferenceSubcellVertices(ArraySubcellVert & subcellVertices, 00473 const int subcellDim, 00474 const int subcellOrd, 00475 const shards::CellTopology& parentCell){ 00476 #ifdef HAVE_INTREPID_DEBUG 00477 TEST_FOR_EXCEPTION( !(hasReferenceCell(parentCell) ), std::invalid_argument, 00478 ">>> ERROR (Intrepid::CellTools::getReferenceSubcellVertices): the specified cell topology does not have a reference cell."); 00479 00480 // subcellDim can equal the cell dimension because the cell itself is a valid subcell! In this case 00481 // the method will return all cell cellWorkset. 00482 TEST_FOR_EXCEPTION( !( (0 <= subcellDim) && (subcellDim <= (int)parentCell.getDimension()) ), std::invalid_argument, 00483 ">>> ERROR (Intrepid::CellTools::getReferenceSubcellVertices): subcell dimension out of range."); 00484 00485 TEST_FOR_EXCEPTION( !( (0 <= subcellOrd) && (subcellOrd < (int)parentCell.getSubcellCount(subcellDim) ) ), std::invalid_argument, 00486 ">>> ERROR (Intrepid::CellTools::getReferenceSubcellVertices): subcell ordinal out of range."); 00487 00488 // Verify subcellVertices rank and dimensions 00489 { 00490 std::string errmsg = ">>> ERROR (Intrepid::CellTools::getReferenceSubcellVertices):"; 00491 TEST_FOR_EXCEPTION( !( requireRankRange(errmsg, subcellVertices, 2, 2) ), std::invalid_argument, errmsg); 00492 00493 int subcVertexCount = parentCell.getVertexCount(subcellDim, subcellOrd); 00494 int spaceDim = parentCell.getDimension(); 00495 00496 TEST_FOR_EXCEPTION( !( requireDimensionRange(errmsg, subcellVertices, 0, subcVertexCount, subcVertexCount) ), 00497 std::invalid_argument, errmsg); 00498 00499 TEST_FOR_EXCEPTION( !( requireDimensionRange(errmsg, subcellVertices, 1, spaceDim, spaceDim) ), 00500 std::invalid_argument, errmsg); 00501 } 00502 #endif 00503 00504 // Simply call getReferenceNodes with the base topology 00505 getReferenceSubcellNodes(subcellVertices, subcellDim, subcellOrd, parentCell.getBaseTopology() ); 00506 } 00507 00508 00509 00510 template<class Scalar> 00511 const double* CellTools<Scalar>::getReferenceNode(const shards::CellTopology& cell, 00512 const int nodeOrd){ 00513 00514 #ifdef HAVE_INTREPID_DEBUG 00515 TEST_FOR_EXCEPTION( !(hasReferenceCell(cell) ), std::invalid_argument, 00516 ">>> ERROR (Intrepid::CellTools::getReferenceNode): the specified cell topology does not have a reference cell."); 00517 00518 TEST_FOR_EXCEPTION( !( (0 <= nodeOrd) && (nodeOrd < (int)cell.getNodeCount() ) ), std::invalid_argument, 00519 ">>> ERROR (Intrepid::CellTools::getReferenceNode): invalid node ordinal for the specified cell topology. "); 00520 #endif 00521 00522 // Cartesian coordinates of supported reference cell cellWorkset, padded to three-dimensions. 00523 // Node order follows cell topology definition in Shards 00524 static const double line[2][3] ={ 00525 {-1.0, 0.0, 0.0}, { 1.0, 0.0, 0.0} 00526 }; 00527 static const double line_3[3][3] = { 00528 {-1.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, 00529 // Extension node: edge midpoint 00530 { 0.0, 0.0, 0.0} 00531 }; 00532 00533 00534 // Triangle topologies 00535 static const double triangle[3][3] = { 00536 { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0} 00537 }; 00538 static const double triangle_4[4][3] = { 00539 { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, 00540 // Extension node: cell center 00541 { 1/3, 1/3, 0.0} 00542 }; 00543 static const double triangle_6[6][3] = { 00544 { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, 00545 // Extension cellWorkset: 3 edge midpoints 00546 { 0.5, 0.0, 0.0}, { 0.5, 0.5, 0.0}, { 0.0, 0.5, 0.0} 00547 }; 00548 00549 00550 // Quadrilateral topologies 00551 static const double quadrilateral[4][3] = { 00552 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0} 00553 }; 00554 static const double quadrilateral_8[8][3] = { 00555 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0}, 00556 // Extension cellWorkset: 4 edge midpoints 00557 { 0.0,-1.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0} 00558 }; 00559 static const double quadrilateral_9[9][3] = { 00560 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0}, 00561 // Extension cellWorkset: 4 edge midpoints + 1 cell center 00562 { 0.0,-1.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, { 0.0, 0.0, 0.0} 00563 }; 00564 00565 00566 // Tetrahedron topologies 00567 static const double tetrahedron[4][3] = { 00568 { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, { 0.0, 0.0, 1.0} 00569 }; 00570 static const double tetrahedron_8[8][3] = { 00571 { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, { 0.0, 0.0, 1.0}, 00572 // Extension cellWorkset: 4 face centers (do not follow natural face order - see the cell topology!) 00573 { 1/3, 0.0, 1/3}, { 1/3, 1/3, 1/3}, { 1/3, 1/3, 0.0}, { 0.0, 1/3, 1/3} 00574 }; 00575 static const double tetrahedron_10[10][3] = { 00576 { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, { 0.0, 0.0, 1.0}, 00577 // Extension cellWorkset: 6 edge midpoints 00578 { 0.5, 0.0, 0.0}, { 0.5, 0.5, 0.0}, { 0.0, 0.5, 0.0}, { 0.0, 0.0, 0.5}, { 0.5, 0.0, 0.5}, { 0.0, 0.5, 0.5} 00579 }; 00580 00581 00582 // Hexahedron topologies 00583 static const double hexahedron[8][3] = { 00584 {-1.0,-1.0,-1.0}, { 1.0,-1.0,-1.0}, { 1.0, 1.0,-1.0}, {-1.0, 1.0,-1.0}, 00585 {-1.0,-1.0, 1.0}, { 1.0,-1.0, 1.0}, { 1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0} 00586 }; 00587 static const double hexahedron_20[20][3] = { 00588 {-1.0,-1.0,-1.0}, { 1.0,-1.0,-1.0}, { 1.0, 1.0,-1.0}, {-1.0, 1.0,-1.0}, 00589 {-1.0,-1.0, 1.0}, { 1.0,-1.0, 1.0}, { 1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0}, 00590 // Extension cellWorkset: 12 edge midpoints (do not follow natural edge order - see cell topology!) 00591 { 0.0,-1.0,-1.0}, { 1.0, 0.0,-1.0}, { 0.0, 1.0,-1.0}, {-1.0, 0.0,-1.0}, 00592 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0}, 00593 { 0.0,-1.0, 1.0}, { 1.0, 0.0, 1.0}, { 0.0, 1.0, 1.0}, {-1.0, 0.0, 1.0} 00594 }; 00595 static const double hexahedron_27[27][3] = { 00596 {-1.0,-1.0,-1.0}, { 1.0,-1.0,-1.0}, { 1.0, 1.0,-1.0}, {-1.0, 1.0,-1.0}, 00597 {-1.0,-1.0, 1.0}, { 1.0,-1.0, 1.0}, { 1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0}, 00598 // Extension cellWorkset: 12 edge midpoints + 1 cell center + 6 face centers (do not follow natural subcell order!) 00599 { 0.0,-1.0,-1.0}, { 1.0, 0.0,-1.0}, { 0.0, 1.0,-1.0}, {-1.0, 0.0,-1.0}, 00600 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0}, 00601 { 0.0,-1.0, 1.0}, { 1.0, 0.0, 1.0}, { 0.0, 1.0, 1.0}, {-1.0, 0.0, 1.0}, 00602 { 0.0, 0.0, 0.0}, 00603 { 0.0, 0.0,-1.0}, { 0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, {0.0,-1.0, 0.0}, {0.0, 1.0, 0.0} 00604 }; 00605 00606 00607 // Pyramid topologies 00608 static const double pyramid[5][3] = { 00609 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0}, { 0.0, 0.0, 1.0} 00610 }; 00611 static const double pyramid_13[13][3] = { 00612 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0}, { 0.0, 0.0, 1.0}, 00613 // Extension cellWorkset: 8 edge midpoints 00614 { 0.0,-1.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 00615 {-0.5,-0.5, 0.5}, { 0.5,-0.5, 0.5}, { 0.5, 0.5, 0.5}, {-0.5, 0.5, 0.5} 00616 }; 00617 static const double pyramid_14[14][3] = { 00618 {-1.0,-1.0, 0.0}, { 1.0,-1.0, 0.0}, { 1.0, 1.0, 0.0}, {-1.0, 1.0, 0.0}, { 0.0, 0.0, 1.0}, 00619 // Extension cellWorkset: 8 edge midpoints + quadrilateral face midpoint 00620 { 0.0,-1.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 00621 {-0.5,-0.5, 0.5}, { 0.5,-0.5, 0.5}, { 0.5, 0.5, 0.5}, {-0.5, 0.5, 0.5}, { 0.0, 0.0, 0.0} 00622 }; 00623 00624 00625 // Wedge topologies 00626 static const double wedge[6][3] = { 00627 { 0.0, 0.0,-1.0}, { 1.0, 0.0,-1.0}, { 0.0, 1.0,-1.0}, { 0.0, 0.0, 1.0}, { 1.0, 0.0, 1.0}, { 0.0, 1.0, 1.0} 00628 }; 00629 static const double wedge_15[15][3] = { 00630 { 0.0, 0.0,-1.0}, { 1.0, 0.0,-1.0}, { 0.0, 1.0,-1.0}, { 0.0, 0.0, 1.0}, { 1.0, 0.0, 1.0}, { 0.0, 1.0, 1.0}, 00631 // Extension cellWorkset: 9 edge midpoints (do not follow natural edge order - see cell topology!) 00632 { 0.5, 0.0,-1.0}, { 0.5, 0.5,-1.0}, { 0.0, 0.5,-1.0}, { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, 00633 { 0.5, 0.0, 1.0}, { 0.5, 0.5, 1.0}, { 0.0, 0.5, 1.0} 00634 }; 00635 static const double wedge_18[18][3] = { 00636 { 0.0, 0.0,-1.0}, { 1.0, 0.0,-1.0}, { 0.0, 1.0,-1.0}, { 0.0, 0.0, 1.0}, { 1.0, 0.0, 1.0}, { 0.0, 1.0, 1.0}, 00637 // Extension cellWorkset: 9 edge midpoints + 3 quad face centers (do not follow natural subcell order - see cell topology!) 00638 { 0.5, 0.0,-1.0}, { 0.5, 0.5,-1.0}, { 0.0, 0.5,-1.0}, { 0.0, 0.0, 0.0}, { 1.0, 0.0, 0.0}, { 0.0, 1.0, 0.0}, 00639 { 0.5, 0.0, 1.0}, { 0.5, 0.5, 1.0}, { 0.0, 0.5, 1.0}, 00640 { 0.5, 0.0, 0.0}, { 0.5, 0.5, 0.0}, { 0.0, 0.5, 0.0} 00641 }; 00642 00643 00644 switch(cell.getKey() ) { 00645 00646 // Base line topologies 00647 case shards::Line<2>::key: 00648 case shards::ShellLine<2>::key: 00649 case shards::Beam<2>::key: 00650 return line[nodeOrd]; 00651 break; 00652 00653 // Extended line topologies 00654 case shards::Line<3>::key: 00655 case shards::ShellLine<3>::key: 00656 case shards::Beam<3>::key: 00657 return line_3[nodeOrd]; 00658 break; 00659 00660 00661 // Base triangle topologies 00662 case shards::Triangle<3>::key: 00663 case shards::ShellTriangle<3>::key: 00664 return triangle[nodeOrd]; 00665 break; 00666 00667 // Extened Triangle topologies 00668 case shards::Triangle<4>::key: 00669 return triangle_4[nodeOrd]; 00670 break; 00671 case shards::Triangle<6>::key: 00672 case shards::ShellTriangle<6>::key: 00673 return triangle_6[nodeOrd]; 00674 break; 00675 00676 00677 // Base Quadrilateral topologies 00678 case shards::Quadrilateral<4>::key: 00679 case shards::ShellQuadrilateral<4>::key: 00680 return quadrilateral[nodeOrd]; 00681 break; 00682 00683 // Extended Quadrilateral topologies 00684 case shards::Quadrilateral<8>::key: 00685 case shards::ShellQuadrilateral<8>::key: 00686 return quadrilateral_8[nodeOrd]; 00687 break; 00688 case shards::Quadrilateral<9>::key: 00689 case shards::ShellQuadrilateral<9>::key: 00690 return quadrilateral_9[nodeOrd]; 00691 break; 00692 00693 00694 // Base Tetrahedron topology 00695 case shards::Tetrahedron<4>::key: 00696 return tetrahedron[nodeOrd]; 00697 break; 00698 00699 // Extended Tetrahedron topologies 00700 case shards::Tetrahedron<8>::key: 00701 return tetrahedron_8[nodeOrd]; 00702 break; 00703 case shards::Tetrahedron<10>::key: 00704 return tetrahedron_10[nodeOrd]; 00705 break; 00706 00707 00708 // Base Hexahedron topology 00709 case shards::Hexahedron<8>::key: 00710 return hexahedron[nodeOrd]; 00711 break; 00712 00713 // Extended Hexahedron topologies 00714 case shards::Hexahedron<20>::key: 00715 return hexahedron_20[nodeOrd]; 00716 break; 00717 case shards::Hexahedron<27>::key: 00718 return hexahedron_27[nodeOrd]; 00719 break; 00720 00721 00722 // Base Pyramid topology 00723 case shards::Pyramid<5>::key: 00724 return pyramid[nodeOrd]; 00725 break; 00726 00727 // Extended pyramid topologies 00728 case shards::Pyramid<13>::key: 00729 return pyramid_13[nodeOrd]; 00730 break; 00731 case shards::Pyramid<14>::key: 00732 return pyramid_14[nodeOrd]; 00733 break; 00734 00735 00736 // Base Wedge topology 00737 case shards::Wedge<6>::key: 00738 return wedge[nodeOrd]; 00739 break; 00740 00741 // Extended Wedge topologies 00742 case shards::Wedge<15>::key: 00743 return wedge_15[nodeOrd]; 00744 break; 00745 case shards::Wedge<18>::key: 00746 return wedge_18[nodeOrd]; 00747 break; 00748 00749 default: 00750 TEST_FOR_EXCEPTION( true, std::invalid_argument, 00751 ">>> ERROR (Intrepid::CellTools::getReferenceNode): invalid cell topology."); 00752 } 00753 // To disable compiler warning, should never be reached 00754 return line[0]; 00755 } 00756 00757 00758 00759 template<class Scalar> 00760 template<class ArraySubcellNode> 00761 void CellTools<Scalar>::getReferenceSubcellNodes(ArraySubcellNode & subcellNodes, 00762 const int subcellDim, 00763 const int subcellOrd, 00764 const shards::CellTopology& parentCell){ 00765 #ifdef HAVE_INTREPID_DEBUG 00766 TEST_FOR_EXCEPTION( !(hasReferenceCell(parentCell) ), std::invalid_argument, 00767 ">>> ERROR (Intrepid::CellTools::getReferenceSubcellNodes): the specified cell topology does not have a reference cell."); 00768 00769 // subcellDim can equal the cell dimension because the cell itself is a valid subcell! In this case 00770 // the method will return all cell cellWorkset. 00771 TEST_FOR_EXCEPTION( !( (0 <= subcellDim) && (subcellDim <= (int)parentCell.getDimension()) ), std::invalid_argument, 00772 ">>> ERROR (Intrepid::CellTools::getReferenceSubcellNodes): subcell dimension out of range."); 00773 00774 TEST_FOR_EXCEPTION( !( (0 <= subcellOrd) && (subcellOrd < (int)parentCell.getSubcellCount(subcellDim) ) ), std::invalid_argument, 00775 ">>> ERROR (Intrepid::CellTools::getReferenceSubcellNodes): subcell ordinal out of range."); 00776 00777 // Verify subcellNodes rank and dimensions 00778 { 00779 std::string errmsg = ">>> ERROR (Intrepid::CellTools::getReferenceSubcellNodes):"; 00780 TEST_FOR_EXCEPTION( !( requireRankRange(errmsg, subcellNodes, 2, 2) ), std::invalid_argument, errmsg); 00781 00782 int subcNodeCount = parentCell.getNodeCount(subcellDim, subcellOrd); 00783 int spaceDim = parentCell.getDimension(); 00784 00785 TEST_FOR_EXCEPTION( !( requireDimensionRange(errmsg, subcellNodes, 0, subcNodeCount, subcNodeCount) ), 00786 std::invalid_argument, errmsg); 00787 00788 TEST_FOR_EXCEPTION( !( requireDimensionRange(errmsg, subcellNodes, 1, spaceDim, spaceDim) ), 00789 std::invalid_argument, errmsg); 00790 } 00791 #endif 00792 00793 // Find how many cellWorkset does the specified subcell have. 00794 int subcNodeCount = parentCell.getNodeCount(subcellDim, subcellOrd); 00795 00796 // Loop over subcell cellWorkset 00797 for(int subcNodeOrd = 0; subcNodeOrd < subcNodeCount; subcNodeOrd++){ 00798 00799 // Get the node number relative to the parent reference cell 00800 int cellNodeOrd = parentCell.getNodeMap(subcellDim, subcellOrd, subcNodeOrd); 00801 00802 // Loop over node's Cartesian coordinates 00803 for(int dim = 0; dim < (int)parentCell.getDimension(); dim++){ 00804 subcellNodes(subcNodeOrd, dim) = CellTools::getReferenceNode(parentCell, cellNodeOrd)[dim]; 00805 } 00806 } 00807 } 00808 00809 00810 00811 template<class Scalar> 00812 int CellTools<Scalar>::hasReferenceCell(const shards::CellTopology& cell) { 00813 00814 switch(cell.getKey() ) { 00815 case shards::Line<2>::key: 00816 case shards::Line<3>::key: 00817 case shards::ShellLine<2>::key: 00818 case shards::ShellLine<3>::key: 00819 case shards::Beam<2>::key: 00820 case shards::Beam<3>::key: 00821 00822 case shards::Triangle<3>::key: 00823 case shards::Triangle<4>::key: 00824 case shards::Triangle<6>::key: 00825 case shards::ShellTriangle<3>::key: 00826 case shards::ShellTriangle<6>::key: 00827 00828 case shards::Quadrilateral<4>::key: 00829 case shards::Quadrilateral<8>::key: 00830 case shards::Quadrilateral<9>::key: 00831 case shards::ShellQuadrilateral<4>::key: 00832 case shards::ShellQuadrilateral<8>::key: 00833 case shards::ShellQuadrilateral<9>::key: 00834 00835 case shards::Tetrahedron<4>::key: 00836 case shards::Tetrahedron<8>::key: 00837 case shards::Tetrahedron<10>::key: 00838 00839 case shards::Hexahedron<8>::key: 00840 case shards::Hexahedron<20>::key: 00841 case shards::Hexahedron<27>::key: 00842 00843 case shards::Pyramid<5>::key: 00844 case shards::Pyramid<13>::key: 00845 case shards::Pyramid<14>::key: 00846 00847 case shards::Wedge<6>::key: 00848 case shards::Wedge<15>::key: 00849 case shards::Wedge<18>::key: 00850 return 1; 00851 break; 00852 00853 default: 00854 return 0; 00855 } 00856 return 0; 00857 } 00858 00859 //============================================================================================// 00860 // // 00861 // Jacobian, inverse Jacobian and Jacobian determinant // 00862 // // 00863 //============================================================================================// 00864 00865 template<class Scalar> 00866 template<class ArrayJac, class ArrayPoint, class ArrayCell> 00867 void CellTools<Scalar>::setJacobian(ArrayJac & jacobian, 00868 const ArrayPoint & points, 00869 const ArrayCell & cellWorkset, 00870 const shards::CellTopology & cellTopo, 00871 const int & whichCell) 00872 { 00873 INTREPID_VALIDATE( validateArguments_setJacobian(jacobian, points, cellWorkset, whichCell, cellTopo) ); 00874 00875 int spaceDim = (int)cellTopo.getDimension(); 00876 int numCells = cellWorkset.dimension(0); 00877 //points can be rank-2 (P,D), or rank-3 (C,P,D) 00878 int numPoints = (points.rank() == 2) ? points.dimension(0) : points.dimension(1); 00879 00880 // Jacobian is computed using gradients of an appropriate H(grad) basis function: define RCP to the base class 00881 Teuchos::RCP< Basis< Scalar, FieldContainer<Scalar> > > HGRAD_Basis; 00882 00883 // Choose the H(grad) basis depending on the cell topology. \todo define maps for shells and beams 00884 switch( cellTopo.getKey() ){ 00885 00886 // Standard Base topologies (number of cellWorkset = number of vertices) 00887 case shards::Line<2>::key: 00888 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_LINE_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 00889 break; 00890 00891 case shards::Triangle<3>::key: 00892 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TRI_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 00893 break; 00894 00895 case shards::Quadrilateral<4>::key: 00896 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_QUAD_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 00897 break; 00898 00899 case shards::Tetrahedron<4>::key: 00900 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TET_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 00901 break; 00902 00903 case shards::Hexahedron<8>::key: 00904 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_HEX_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 00905 break; 00906 00907 case shards::Wedge<6>::key: 00908 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_WEDGE_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 00909 break; 00910 00911 // Standard Extended topologies 00912 case shards::Triangle<6>::key: 00913 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TRI_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 00914 break; 00915 case shards::Quadrilateral<9>::key: 00916 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_QUAD_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 00917 break; 00918 00919 case shards::Tetrahedron<10>::key: 00920 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TET_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 00921 break; 00922 00923 case shards::Hexahedron<27>::key: 00924 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_HEX_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 00925 break; 00926 00927 case shards::Wedge<18>::key: 00928 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_WEDGE_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 00929 break; 00930 00931 // These extended topologies are not used for mapping purposes 00932 case shards::Quadrilateral<8>::key: 00933 case shards::Hexahedron<20>::key: 00934 case shards::Wedge<15>::key: 00935 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 00936 ">>> ERROR (Intrepid::CellTools::setJacobian): Cell topology not supported. "); 00937 break; 00938 00939 // Base and Extended Line, Beam and Shell topologies 00940 case shards::Line<3>::key: 00941 case shards::Beam<2>::key: 00942 case shards::Beam<3>::key: 00943 case shards::ShellLine<2>::key: 00944 case shards::ShellLine<3>::key: 00945 case shards::ShellTriangle<3>::key: 00946 case shards::ShellTriangle<6>::key: 00947 case shards::ShellQuadrilateral<4>::key: 00948 case shards::ShellQuadrilateral<8>::key: 00949 case shards::ShellQuadrilateral<9>::key: 00950 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 00951 ">>> ERROR (Intrepid::CellTools::setJacobian): Cell topology not supported. "); 00952 break; 00953 default: 00954 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 00955 ">>> ERROR (Intrepid::CellTools::setJacobian): Cell topology not supported."); 00956 }// switch 00957 00958 // Temp (F,P,D) array for the values of basis functions gradients at the reference points 00959 int basisCardinality = HGRAD_Basis -> getCardinality(); 00960 FieldContainer<Scalar> basisGrads(basisCardinality, numPoints, spaceDim); 00961 00962 // Initialize jacobian 00963 for(int i = 0; i < jacobian.size(); i++){ 00964 jacobian[i] = 0.0; 00965 } 00966 00967 // Handle separately rank-2 (P,D) and rank-3 (C,P,D) cases of points arrays. 00968 switch(points.rank()) { 00969 00970 // refPoints is (P,D): a single or multiple cell jacobians computed for a single set of ref. points 00971 case 2: 00972 { 00973 // getValues requires rank-2 (P,D) input array, but points cannot be passed directly as argument because they are a user type 00974 FieldContainer<Scalar> tempPoints( points.dimension(0), points.dimension(1) ); 00975 // Copy point set corresponding to this cell oridinal to the temp (P,D) array 00976 for(int pt = 0; pt < points.dimension(0); pt++){ 00977 for(int dm = 0; dm < points.dimension(1) ; dm++){ 00978 tempPoints(pt, dm) = points(pt, dm); 00979 }//dm 00980 }//pt 00981 HGRAD_Basis -> getValues(basisGrads, tempPoints, OPERATOR_GRAD); 00982 00983 // The outer loops select the multi-index of the Jacobian entry: cell, point, row, col 00984 // If whichCell = -1, all jacobians are computed, otherwise a single cell jacobian is computed 00985 int cellLoop = (whichCell == -1) ? numCells : 1 ; 00986 00987 for(int cellOrd = 0; cellOrd < cellLoop; cellOrd++) { 00988 for(int pointOrd = 0; pointOrd < numPoints; pointOrd++) { 00989 for(int row = 0; row < spaceDim; row++){ 00990 for(int col = 0; col < spaceDim; col++){ 00991 00992 // The entry is computed by contracting the basis index. Number of basis functions and vertices must be the same 00993 for(int bfOrd = 0; bfOrd < basisCardinality; bfOrd++){ 00994 00995 if(whichCell == -1) { 00996 jacobian(cellOrd, pointOrd, row, col) += cellWorkset(cellOrd, bfOrd, row)*basisGrads(bfOrd, pointOrd, col); 00997 } 00998 else { 00999 jacobian(pointOrd, row, col) += cellWorkset(whichCell, bfOrd, row)*basisGrads(bfOrd, pointOrd, col); 01000 } 01001 } // bfOrd 01002 } // col 01003 } // row 01004 } // pointOrd 01005 } // cellOrd 01006 }// case 2 01007 break; 01008 01009 // points is (C,P,D): multiple jacobians computed at multiple point sets, one jacobian per cell 01010 case 3: 01011 { 01012 // getValues requires rank-2 (P,D) input array, refPoints cannot be used as argument: need temp (P,D) array 01013 FieldContainer<Scalar> tempPoints( points.dimension(1), points.dimension(2) ); 01014 01015 for(int cellOrd = 0; cellOrd < numCells; cellOrd++) { 01016 01017 // Copy point set corresponding to this cell oridinal to the temp (P,D) array 01018 for(int pt = 0; pt < points.dimension(1); pt++){ 01019 for(int dm = 0; dm < points.dimension(2) ; dm++){ 01020 tempPoints(pt, dm) = points(cellOrd, pt, dm); 01021 }//dm 01022 }//pt 01023 01024 // Compute gradients of basis functions at this set of ref. points 01025 HGRAD_Basis -> getValues(basisGrads, tempPoints, OPERATOR_GRAD); 01026 01027 // Compute jacobians for the point set corresponding to the current cellordinal 01028 for(int pointOrd = 0; pointOrd < numPoints; pointOrd++) { 01029 for(int row = 0; row < spaceDim; row++){ 01030 for(int col = 0; col < spaceDim; col++){ 01031 01032 // The entry is computed by contracting the basis index. Number of basis functions and vertices must be the same 01033 for(int bfOrd = 0; bfOrd < basisCardinality; bfOrd++){ 01034 jacobian(cellOrd, pointOrd, row, col) += cellWorkset(cellOrd, bfOrd, row)*basisGrads(bfOrd, pointOrd, col); 01035 } // bfOrd 01036 } // col 01037 } // row 01038 } // pointOrd 01039 }//cellOrd 01040 }// case 3 01041 01042 break; 01043 01044 default: 01045 TEST_FOR_EXCEPTION( !( (points.rank() == 2) && (points.rank() == 3) ), std::invalid_argument, 01046 ">>> ERROR (Intrepid::CellTools::setJacobian): rank 2 or 3 required for points array. "); 01047 }//switch 01048 } 01049 01050 01051 01052 template<class Scalar> 01053 template<class ArrayJacInv, class ArrayJac> 01054 void CellTools<Scalar>::setJacobianInv(ArrayJacInv & jacobianInv, 01055 const ArrayJac & jacobian) 01056 { 01057 INTREPID_VALIDATE( validateArguments_setJacobianInv(jacobianInv, jacobian) ); 01058 01059 RealSpaceTools<Scalar>::inverse(jacobianInv, jacobian); 01060 } 01061 01062 01063 01064 template<class Scalar> 01065 template<class ArrayJacDet, class ArrayJac> 01066 void CellTools<Scalar>::setJacobianDet(ArrayJacDet & jacobianDet, 01067 const ArrayJac & jacobian) 01068 { 01069 INTREPID_VALIDATE( validateArguments_setJacobianDetArgs(jacobianDet, jacobian) ); 01070 01071 RealSpaceTools<Scalar>::det(jacobianDet, jacobian); 01072 } 01073 01074 //============================================================================================// 01075 // // 01076 // Reference-to-physical frame mapping and its inverse // 01077 // // 01078 //============================================================================================// 01079 01080 template<class Scalar> 01081 template<class ArrayPhysPoint, class ArrayRefPoint, class ArrayCell> 01082 void CellTools<Scalar>::mapToPhysicalFrame(ArrayPhysPoint & physPoints, 01083 const ArrayRefPoint & refPoints, 01084 const ArrayCell & cellWorkset, 01085 const shards::CellTopology & cellTopo, 01086 const int & whichCell) 01087 { 01088 INTREPID_VALIDATE(validateArguments_mapToPhysicalFrame( physPoints, refPoints, cellWorkset, cellTopo, whichCell) ); 01089 01090 int spaceDim = (int)cellTopo.getDimension(); 01091 int numCells = cellWorkset.dimension(0); 01092 //points can be rank-2 (P,D), or rank-3 (C,P,D) 01093 int numPoints = (refPoints.rank() == 2) ? refPoints.dimension(0) : refPoints.dimension(1); 01094 01095 // Mapping is computed using an appropriate H(grad) basis function: define RCP to the base class 01096 Teuchos::RCP<Basis<Scalar, FieldContainer<Scalar> > > HGRAD_Basis; 01097 01098 // Choose the H(grad) basis depending on the cell topology. \todo define maps for shells and beams 01099 switch( cellTopo.getKey() ){ 01100 01101 // Standard Base topologies (number of cellWorkset = number of vertices) 01102 case shards::Line<2>::key: 01103 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_LINE_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 01104 break; 01105 01106 case shards::Triangle<3>::key: 01107 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TRI_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 01108 break; 01109 01110 case shards::Quadrilateral<4>::key: 01111 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_QUAD_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 01112 break; 01113 01114 case shards::Tetrahedron<4>::key: 01115 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TET_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 01116 break; 01117 01118 case shards::Hexahedron<8>::key: 01119 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_HEX_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 01120 break; 01121 01122 case shards::Wedge<6>::key: 01123 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_WEDGE_C1_FEM<Scalar, FieldContainer<Scalar> >() ); 01124 break; 01125 01126 // Standard Extended topologies 01127 case shards::Triangle<6>::key: 01128 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TRI_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 01129 break; 01130 01131 case shards::Quadrilateral<9>::key: 01132 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_QUAD_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 01133 break; 01134 01135 case shards::Tetrahedron<10>::key: 01136 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_TET_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 01137 break; 01138 01139 case shards::Hexahedron<27>::key: 01140 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_HEX_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 01141 break; 01142 01143 case shards::Wedge<18>::key: 01144 HGRAD_Basis = Teuchos::rcp( new Basis_HGRAD_WEDGE_C2_FEM<Scalar, FieldContainer<Scalar> >() ); 01145 break; 01146 01147 // These extended topologies are not used for mapping purposes 01148 case shards::Quadrilateral<8>::key: 01149 case shards::Hexahedron<20>::key: 01150 case shards::Wedge<15>::key: 01151 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 01152 ">>> ERROR (Intrepid::CellTools::mapToPhysicalFrame): Cell topology not supported. "); 01153 break; 01154 01155 // Base and Extended Line, Beam and Shell topologies 01156 case shards::Line<3>::key: 01157 case shards::Beam<2>::key: 01158 case shards::Beam<3>::key: 01159 case shards::ShellLine<2>::key: 01160 case shards::ShellLine<3>::key: 01161 case shards::ShellTriangle<3>::key: 01162 case shards::ShellTriangle<6>::key: 01163 case shards::ShellQuadrilateral<4>::key: 01164 case shards::ShellQuadrilateral<8>::key: 01165 case shards::ShellQuadrilateral<9>::key: 01166 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 01167 ">>> ERROR (Intrepid::CellTools::mapToPhysicalFrame): Cell topology not supported. "); 01168 break; 01169 default: 01170 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 01171 ">>> ERROR (Intrepid::CellTools::mapToPhysicalFrame): Cell topology not supported."); 01172 }// switch 01173 01174 // Temp (F,P) array for the values of nodal basis functions at the reference points 01175 int basisCardinality = HGRAD_Basis -> getCardinality(); 01176 FieldContainer<Scalar> basisVals(basisCardinality, numPoints); 01177 01178 // Initialize physPoints 01179 for(int i = 0; i < physPoints.size(); i++){ 01180 physPoints[i] = 0.0; 01181 } 01182 01183 // handle separately rank-2 (P,D) and rank-3 (C,P,D) cases of refPoints 01184 switch(refPoints.rank()) { 01185 01186 // refPoints is (P,D): single set of ref. points is mapped to one or multiple physical cells 01187 case 2: 01188 { 01189 // getValues requires rank-2 (P,D) input array, but refPoints cannot be passed directly as argument because they are a user type 01190 FieldContainer<Scalar> tempPoints( refPoints.dimension(0), refPoints.dimension(1) ); 01191 // Copy point set corresponding to this cell oridinal to the temp (P,D) array 01192 for(int pt = 0; pt < refPoints.dimension(0); pt++){ 01193 for(int dm = 0; dm < refPoints.dimension(1) ; dm++){ 01194 tempPoints(pt, dm) = refPoints(pt, dm); 01195 }//dm 01196 }//pt 01197 HGRAD_Basis -> getValues(basisVals, tempPoints, OPERATOR_VALUE); 01198 01199 // If whichCell = -1, ref pt. set is mapped to all cells, otherwise, the set is mapped to one cell only 01200 int cellLoop = (whichCell == -1) ? numCells : 1 ; 01201 01202 // Compute the map F(refPoints) = sum node_coordinate*basis(refPoints) 01203 for(int cellOrd = 0; cellOrd < cellLoop; cellOrd++) { 01204 for(int pointOrd = 0; pointOrd < numPoints; pointOrd++) { 01205 for(int dim = 0; dim < spaceDim; dim++){ 01206 for(int bfOrd = 0; bfOrd < basisCardinality; bfOrd++){ 01207 01208 if(whichCell == -1){ 01209 physPoints(cellOrd, pointOrd, dim) += cellWorkset(cellOrd, bfOrd, dim)*basisVals(bfOrd, pointOrd); 01210 } 01211 else{ 01212 physPoints(pointOrd, dim) += cellWorkset(whichCell, bfOrd, dim)*basisVals(bfOrd, pointOrd); 01213 } 01214 } // bfOrd 01215 }// dim 01216 }// pointOrd 01217 }//cellOrd 01218 }// case 2 01219 break; 01220 01221 // refPoints is (C,P,D): multiple sets of ref. points are mapped to matching number of physical cells. 01222 case 3: 01223 { 01224 // getValues requires rank-2 (P,D) input array, refPoints cannot be used as argument: need temp (P,D) array 01225 FieldContainer<Scalar> tempPoints( refPoints.dimension(1), refPoints.dimension(2) ); 01226 01227 // Compute the map F(refPoints) = sum node_coordinate*basis(refPoints) 01228 for(int cellOrd = 0; cellOrd < numCells; cellOrd++) { 01229 01230 // Copy point set corresponding to this cell oridinal to the temp (P,D) array 01231 for(int pt = 0; pt < refPoints.dimension(1); pt++){ 01232 for(int dm = 0; dm < refPoints.dimension(2) ; dm++){ 01233 tempPoints(pt, dm) = refPoints(cellOrd, pt, dm); 01234 }//dm 01235 }//pt 01236 01237 // Compute basis values for this set of ref. points 01238 HGRAD_Basis -> getValues(basisVals, tempPoints, OPERATOR_VALUE); 01239 01240 for(int pointOrd = 0; pointOrd < numPoints; pointOrd++) { 01241 for(int dim = 0; dim < spaceDim; dim++){ 01242 for(int bfOrd = 0; bfOrd < basisCardinality; bfOrd++){ 01243 01244 physPoints(cellOrd, pointOrd, dim) += cellWorkset(cellOrd, bfOrd, dim)*basisVals(bfOrd, pointOrd); 01245 01246 } // bfOrd 01247 }// dim 01248 }// pointOrd 01249 }//cellOrd 01250 }// case 3 01251 break; 01252 01253 default: 01254 TEST_FOR_EXCEPTION( !( (refPoints.rank() == 2) && (refPoints.rank() == 3) ), std::invalid_argument, 01255 ">>> ERROR (Intrepid::CellTools::mapToPhysicalFrame): rank 2 or 3 required for refPoints array. "); 01256 } 01257 } 01258 01259 01260 01261 template<class Scalar> 01262 template<class ArrayRefPoint, class ArrayPhysPoint, class ArrayCell> 01263 void CellTools<Scalar>::mapToReferenceFrame(ArrayRefPoint & refPoints, 01264 const ArrayPhysPoint & physPoints, 01265 const ArrayCell & cellWorkset, 01266 const shards::CellTopology & cellTopo, 01267 const int & whichCell) 01268 { 01269 INTREPID_VALIDATE( validateArguments_mapToReferenceFrame(refPoints, physPoints, cellWorkset, cellTopo, whichCell) ); 01270 01271 int spaceDim = (int)cellTopo.getDimension(); 01272 int numPoints; 01273 int numCells; 01274 01275 // Define initial guesses to be the Cell centers of the reference cell topology 01276 FieldContainer<Scalar> cellCenter(spaceDim); 01277 switch( cellTopo.getKey() ){ 01278 // Standard Base topologies (number of cellWorkset = number of vertices) 01279 case shards::Line<2>::key: 01280 cellCenter(0) = 0.0; break; 01281 01282 case shards::Triangle<3>::key: 01283 case shards::Triangle<6>::key: 01284 cellCenter(0) = 1./3.; cellCenter(1) = 1./3.; break; 01285 01286 case shards::Quadrilateral<4>::key: 01287 case shards::Quadrilateral<9>::key: 01288 cellCenter(0) = 0.0; cellCenter(1) = 0.0; break; 01289 01290 case shards::Tetrahedron<4>::key: 01291 case shards::Tetrahedron<10>::key: 01292 cellCenter(0) = 1./6.; cellCenter(1) = 1./6.; cellCenter(2) = 1./6.; break; 01293 01294 case shards::Hexahedron<8>::key: 01295 case shards::Hexahedron<27>::key: 01296 cellCenter(0) = 0.0; cellCenter(1) = 0.0; cellCenter(2) = 0.0; break; 01297 01298 case shards::Wedge<6>::key: 01299 case shards::Wedge<18>::key: 01300 cellCenter(0) = 1./3.; cellCenter(1) = 1./3.; cellCenter(2) = 0.0; break; 01301 01302 // These extended topologies are not used for mapping purposes 01303 case shards::Quadrilateral<8>::key: 01304 case shards::Hexahedron<20>::key: 01305 case shards::Wedge<15>::key: 01306 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 01307 ">>> ERROR (Intrepid::CellTools::mapToReferenceFrame): Cell topology not supported. "); 01308 break; 01309 01310 // Base and Extended Line, Beam and Shell topologies 01311 case shards::Line<3>::key: 01312 case shards::Beam<2>::key: 01313 case shards::Beam<3>::key: 01314 case shards::ShellLine<2>::key: 01315 case shards::ShellLine<3>::key: 01316 case shards::ShellTriangle<3>::key: 01317 case shards::ShellTriangle<6>::key: 01318 case shards::ShellQuadrilateral<4>::key: 01319 case shards::ShellQuadrilateral<8>::key: 01320 case shards::ShellQuadrilateral<9>::key: 01321 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 01322 ">>> ERROR (Intrepid::CellTools::mapToReferenceFrame): Cell topology not supported. "); 01323 break; 01324 default: 01325 TEST_FOR_EXCEPTION( (true), std::invalid_argument, 01326 ">>> ERROR (Intrepid::CellTools::mapToReferenceFrame): Cell topology not supported."); 01327 }// switch key 01328 01329 // Resize initial guess depending on the rank of the physical points array 01330 FieldContainer<Scalar> initGuess; 01331 01332 // Default: map (C,P,D) array of physical pt. sets to (C,P,D) array. Requires (C,P,D) initial guess. 01333 if(whichCell == -1){ 01334 numPoints = physPoints.dimension(1); 01335 numCells = cellWorkset.dimension(0); 01336 initGuess.resize(numCells, numPoints, spaceDim); 01337 // Set initial guess: 01338 for(int c = 0; c < numCells; c++){ 01339 for(int p = 0; p < numPoints; p++){ 01340 for(int d = 0; d < spaceDim; d++){ 01341 initGuess(c, p, d) = cellCenter(d); 01342 }// d 01343 }// p 01344 }// c 01345 } 01346 // Custom: map (P,D) array of physical pts. to (P,D) array. Requires (P,D) initial guess. 01347 else { 01348 numPoints = physPoints.dimension(0); 01349 initGuess.resize(numPoints, spaceDim); 01350 // Set initial guess: 01351 for(int p = 0; p < numPoints; p++){ 01352 for(int d = 0; d < spaceDim; d++){ 01353 initGuess(p, d) = cellCenter(d); 01354 }// d 01355 }// p 01356 } 01357 01358 // Call method with initial guess 01359 mapToReferenceFrameInitGuess(refPoints, initGuess, physPoints, cellWorkset, cellTopo, whichCell); 01360 } 01361 01362 01363 01364 template<class Scalar> 01365 template<class ArrayRefPoint, class ArrayInitGuess, class ArrayPhysPoint, class ArrayCell> 01366 void CellTools<Scalar>::mapToReferenceFrameInitGuess(ArrayRefPoint & refPoints, 01367 const ArrayInitGuess & initGuess, 01368 const ArrayPhysPoint & physPoints, 01369 const ArrayCell & cellWorkset, 01370 const shards::CellTopology & cellTopo, 01371 const int & whichCell) 01372 { 01373 INTREPID_VALIDATE( validateArguments_mapToReferenceFrame(refPoints, initGuess, physPoints, cellWorkset, cellTopo, whichCell) ); 01374 01375 int spaceDim = (int)cellTopo.getDimension(); 01376 int numPoints; 01377 int numCells=0; 01378 01379 // Temp arrays for Newton iterates and Jacobians. Resize according to rank of ref. point array 01380 FieldContainer<Scalar> xOld; 01381 FieldContainer<Scalar> xTem; 01382 FieldContainer<Scalar> jacobian; 01383 FieldContainer<Scalar> jacobInv; 01384 FieldContainer<Scalar> error; 01385 FieldContainer<Scalar> cellCenter(spaceDim); 01386 01387 // Default: map (C,P,D) array of physical pt. sets to (C,P,D) array. Requires (C,P,D) temp arrays and (C,P,D,D) Jacobians. 01388 if(whichCell == -1){ 01389 numPoints = physPoints.dimension(1); 01390 numCells = cellWorkset.dimension(0); 01391 xOld.resize(numCells, numPoints, spaceDim); 01392 xTem.resize(numCells, numPoints, spaceDim); 01393 jacobian.resize(numCells,numPoints, spaceDim, spaceDim); 01394 jacobInv.resize(numCells,numPoints, spaceDim, spaceDim); 01395 error.resize(numCells,numPoints); 01396 // Set initial guess to xOld 01397 for(int c = 0; c < numCells; c++){ 01398 for(int p = 0; p < numPoints; p++){ 01399 for(int d = 0; d < spaceDim; d++){ 01400 xOld(c, p, d) = initGuess(c, p, d); 01401 }// d 01402 }// p 01403 }// c 01404 } 01405 // Custom: map (P,D) array of physical pts. to (P,D) array. Requires (P,D) temp arrays and (P,D,D) Jacobians. 01406 else { 01407 numPoints = physPoints.dimension(0); 01408 xOld.resize(numPoints, spaceDim); 01409 xTem.resize(numPoints, spaceDim); 01410 jacobian.resize(numPoints, spaceDim, spaceDim); 01411 jacobInv.resize(numPoints, spaceDim, spaceDim); 01412 error.resize(numPoints); 01413 // Set initial guess to xOld 01414 for(int p = 0; p < numPoints; p++){ 01415 for(int d = 0; d < spaceDim; d++){ 01416 xOld(p, d) = initGuess(p, d); 01417 }// d 01418 }// p 01419 } 01420 01421 01422 // Newton method to solve the equation F(refPoints) - physPoints = 0: 01423 // refPoints = xOld - DF^{-1}(xOld)*(F(xOld) - physPoints) = xOld + DF^{-1}(xOld)*(physPoints - F(xOld)) 01424 for(int iter = 0; iter < INTREPID_MAX_NEWTON; ++iter) { 01425 01426 // Jacobians at the old iterates and their inverses. 01427 setJacobian(jacobian, xOld, cellWorkset, cellTopo, whichCell); 01428 setJacobianInv(jacobInv, jacobian); 01429 01430 // The Newton step. 01431 mapToPhysicalFrame( xTem, xOld, cellWorkset, cellTopo, whichCell ); // xTem <- F(xOld) 01432 RealSpaceTools<Scalar>::subtract( xTem, physPoints, xTem ); // xTem <- physPoints - F(xOld) 01433 RealSpaceTools<Scalar>::matvec( refPoints, jacobInv, xTem); // refPoints <- DF^{-1}( physPoints - F(xOld) ) 01434 RealSpaceTools<Scalar>::add( refPoints, xOld ); // refPoints <- DF^{-1}( physPoints - F(xOld) ) + xOld 01435 01436 // l2 error (Euclidean distance) between old and new iterates: |xOld - xNew| 01437 RealSpaceTools<Scalar>::subtract( xTem, xOld, refPoints ); 01438 RealSpaceTools<Scalar>::vectorNorm( error, xTem, NORM_TWO ); 01439 01440 // Average L2 error for a multiple sets of physical points: error is rank-2 (C,P) array 01441 double totalError; 01442 if(whichCell == -1) { 01443 FieldContainer<Scalar> cellWiseError(numCells); 01444 // error(C,P) -> cellWiseError(P) 01445 RealSpaceTools<Scalar>::vectorNorm( cellWiseError, error, NORM_ONE ); 01446 totalError = RealSpaceTools<Scalar>::vectorNorm( cellWiseError, NORM_ONE ); 01447 } 01448 //Average L2 error for a single set of physical points: error is rank-1 (P) array 01449 else{ 01450 totalError = RealSpaceTools<Scalar>::vectorNorm( error, NORM_ONE ); 01451 totalError = totalError; 01452 } 01453 01454 // Stopping criterion: 01455 if (totalError < INTREPID_TOL) { 01456 break; 01457 } 01458 else if ( iter > INTREPID_MAX_NEWTON) { 01459 INTREPID_VALIDATE(std::cout << " Intrepid::CellTools::mapToReferenceFrameInitGuess failed to converge to desired tolerance within " 01460 << INTREPID_MAX_NEWTON << " iterations\n" ); 01461 break; 01462 } 01463 01464 // initialize next Newton step 01465 xOld = refPoints; 01466 } // for(iter) 01467 } 01468 01469 01470 01471 template<class Scalar> 01472 template<class ArraySubcellPoint, class ArrayParamPoint> 01473 void CellTools<Scalar>::mapToReferenceSubcell(ArraySubcellPoint & refSubcellPoints, 01474 const ArrayParamPoint & paramPoints, 01475 const int subcellDim, 01476 const int subcellOrd, 01477 const shards::CellTopology & parentCell){ 01478 01479 int cellDim = parentCell.getDimension(); 01480 int numPts = paramPoints.dimension(0); 01481 01482 #ifdef HAVE_INTREPID_DEBUG 01483 TEST_FOR_EXCEPTION( !(hasReferenceCell(parentCell) ), std::invalid_argument, 01484 ">>> ERROR (Intrepid::CellTools::mapToReferenceSubcell): the specified cell topology does not have a reference cell."); 01485 01486 TEST_FOR_EXCEPTION( !( (1 <= subcellDim) && (subcellDim <= 2 ) ), std::invalid_argument, 01487 ">>> ERROR (Intrepid::CellTools::mapToReferenceSubcell): method defined only for 1 and 2-dimensional subcells."); 01488 01489 TEST_FOR_EXCEPTION( !( (0 <= subcellOrd) && (subcellOrd < (int)parentCell.getSubcellCount(subcellDim) ) ), std::invalid_argument, 01490 ">>> ERROR (Intrepid::CellTools::mapToReferenceSubcell): subcell ordinal out of range."); 01491 01492 // refSubcellPoints is rank-2 (P,D1), D1 = cell dimension 01493 std::string errmsg = ">>> ERROR (Intrepid::mapToReferenceSubcell):"; 01494 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, refSubcellPoints, 2,2), std::invalid_argument, errmsg); 01495 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, refSubcellPoints, 1, cellDim, cellDim), std::invalid_argument, errmsg); 01496 01497 // paramPoints is rank-2 (P,D2) with D2 = subcell dimension 01498 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, paramPoints, 2,2), std::invalid_argument, errmsg); 01499 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, paramPoints, 1, subcellDim, subcellDim), std::invalid_argument, errmsg); 01500 01501 // cross check: refSubcellPoints and paramPoints: dimension 0 must match 01502 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg, refSubcellPoints, 0, paramPoints, 0), std::invalid_argument, errmsg); 01503 #endif 01504 01505 01506 // Get the subcell map, i.e., the coefficients of the parametrization function for the subcell 01507 const FieldContainer<double>& subcellMap = getSubcellParametrization(subcellDim, parentCell); 01508 01509 // Apply the parametrization map to every point in parameter domain 01510 if(subcellDim == 2) { 01511 for(int pt = 0; pt < numPts; pt++){ 01512 double u = paramPoints(pt,0); 01513 double v = paramPoints(pt,1); 01514 01515 // map_dim(u,v) = c_0(dim) + c_1(dim)*u + c_2(dim)*v because both Quad and Tri ref faces are affine! 01516 for(int dim = 0; dim < cellDim; dim++){ 01517 refSubcellPoints(pt, dim) = subcellMap(subcellOrd, dim, 0) + \ 01518 subcellMap(subcellOrd, dim, 1)*u + \ 01519 subcellMap(subcellOrd, dim, 2)*v; 01520 } 01521 } 01522 } 01523 else if(subcellDim == 1) { 01524 for(int pt = 0; pt < numPts; pt++){ 01525 for(int dim = 0; dim < cellDim; dim++) { 01526 refSubcellPoints(pt, dim) = subcellMap(subcellOrd, dim, 0) + subcellMap(subcellOrd, dim, 1)*paramPoints(pt,0); 01527 } 01528 } 01529 } 01530 else{ 01531 TEST_FOR_EXCEPTION( !( (subcellDim == 1) || (subcellDim == 2) ), std::invalid_argument, 01532 ">>> ERROR (Intrepid::CellTools::mapToReferenceSubcell): method defined only for 1 and 2-subcells"); 01533 } 01534 } 01535 01536 01537 01538 template<class Scalar> 01539 template<class ArrayEdgeTangent> 01540 void CellTools<Scalar>::getReferenceEdgeTangent(ArrayEdgeTangent & refEdgeTangent, 01541 const int & edgeOrd, 01542 const shards::CellTopology & parentCell){ 01543 01544 int spaceDim = parentCell.getDimension(); 01545 01546 #ifdef HAVE_INTREPID_DEBUG 01547 01548 TEST_FOR_EXCEPTION( !( (spaceDim == 2) || (spaceDim == 3) ), std::invalid_argument, 01549 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): two or three-dimensional parent cell required"); 01550 01551 TEST_FOR_EXCEPTION( !( (0 <= edgeOrd) && (edgeOrd < (int)parentCell.getSubcellCount(1) ) ), std::invalid_argument, 01552 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): edge ordinal out of bounds"); 01553 01554 TEST_FOR_EXCEPTION( !( refEdgeTangent.size() == spaceDim ), std::invalid_argument, 01555 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): output array size is required to match space dimension"); 01556 #endif 01557 01558 // Edge parametrizations are computed in setSubcellParametrization and stored in rank-3 array 01559 // (subcOrd, coordinate, coefficient) 01560 const FieldContainer<double>& edgeMap = getSubcellParametrization(1, parentCell); 01561 01562 // All ref. edge maps have affine coordinate functions: f_dim(u) = C_0(dim) + C_1(dim)*u, 01563 // => edge Tangent: -> C_1(*) 01564 refEdgeTangent(0) = edgeMap(edgeOrd, 0, 1); 01565 refEdgeTangent(1) = edgeMap(edgeOrd, 1, 1); 01566 01567 // Skip last coordinate for 2D parent cells 01568 if(spaceDim == 3) { 01569 refEdgeTangent(2) = edgeMap(edgeOrd, 2, 1); 01570 } 01571 } 01572 01573 01574 01575 template<class Scalar> 01576 template<class ArrayFaceTangentU, class ArrayFaceTangentV> 01577 void CellTools<Scalar>::getReferenceFaceTangents(ArrayFaceTangentU & uTan, 01578 ArrayFaceTangentV & vTan, 01579 const int & faceOrd, 01580 const shards::CellTopology & parentCell){ 01581 01582 #ifdef HAVE_INTREPID_DEBUG 01583 int spaceDim = parentCell.getDimension(); 01584 TEST_FOR_EXCEPTION( !(spaceDim == 3), std::invalid_argument, 01585 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): three-dimensional parent cell required"); 01586 01587 TEST_FOR_EXCEPTION( !( (0 <= faceOrd) && (faceOrd < (int)parentCell.getSubcellCount(2) ) ), std::invalid_argument, 01588 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): face ordinal out of bounds"); 01589 01590 TEST_FOR_EXCEPTION( !( (uTan.rank() == 1) && (vTan.rank() == 1) ), std::invalid_argument, 01591 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): rank = 1 required for output arrays"); 01592 01593 TEST_FOR_EXCEPTION( !( uTan.dimension(0) == spaceDim ), std::invalid_argument, 01594 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): dim0 (spatial dim) must match that of parent cell"); 01595 01596 TEST_FOR_EXCEPTION( !( vTan.dimension(0) == spaceDim ), std::invalid_argument, 01597 ">>> ERROR (Intrepid::CellTools::getReferenceFaceTangents): dim0 (spatial dim) must match that of parent cell"); 01598 #endif 01599 01600 // Face parametrizations are computed in setSubcellParametrization and stored in rank-3 array 01601 // (subcOrd, coordinate, coefficient): retrieve this array 01602 const FieldContainer<double>& faceMap = getSubcellParametrization(2, parentCell); 01603 01604 /* All ref. face maps have affine coordinate functions: f_dim(u,v) = C_0(dim) + C_1(dim)*u + C_2(dim)*v 01605 * ` => Tangent vectors are: uTan -> C_1(*); vTan -> C_2(*) 01606 */ 01607 // set uTan -> C_1(*) 01608 uTan(0) = faceMap(faceOrd, 0, 1); 01609 uTan(1) = faceMap(faceOrd, 1, 1); 01610 uTan(2) = faceMap(faceOrd, 2, 1); 01611 01612 // set vTan -> C_2(*) 01613 vTan(0) = faceMap(faceOrd, 0, 2); 01614 vTan(1) = faceMap(faceOrd, 1, 2); 01615 vTan(2) = faceMap(faceOrd, 2, 2); 01616 } 01617 01618 01619 01620 template<class Scalar> 01621 template<class ArraySideNormal> 01622 void CellTools<Scalar>::getReferenceSideNormal(ArraySideNormal & refSideNormal, 01623 const int & sideOrd, 01624 const shards::CellTopology & parentCell){ 01625 int spaceDim = parentCell.getDimension(); 01626 #ifdef HAVE_INTREPID_DEBUG 01627 01628 TEST_FOR_EXCEPTION( !( (spaceDim == 2) || (spaceDim == 3) ), std::invalid_argument, 01629 ">>> ERROR (Intrepid::CellTools::getReferenceSideNormal): two or three-dimensional parent cell required"); 01630 01631 // Check side ordinal: by definition side is subcell whose dimension = spaceDim-1 01632 TEST_FOR_EXCEPTION( !( (0 <= sideOrd) && (sideOrd < (int)parentCell.getSubcellCount(spaceDim - 1) ) ), std::invalid_argument, 01633 ">>> ERROR (Intrepid::CellTools::getReferenceSideNormal): side ordinal out of bounds"); 01634 #endif 01635 01636 if(spaceDim == 2){ 01637 01638 // 2D parent cells: side = 1D subcell (edge), call the edge tangent method and rotate tangents 01639 getReferenceEdgeTangent(refSideNormal, sideOrd, parentCell); 01640 01641 // rotate t(t1, t2) to get n(t2, -t1) so that (n,t) is positively oriented: det(n1,n2/t1,t2)>0 01642 Scalar temp = refSideNormal(0); 01643 refSideNormal(0) = refSideNormal(1); 01644 refSideNormal(1) = -temp; 01645 } 01646 else{ 01647 // 3D parent cell: side = 2D subcell (face), call the face normal method. 01648 getReferenceFaceNormal(refSideNormal, sideOrd, parentCell); 01649 } 01650 } 01651 01652 01653 01654 template<class Scalar> 01655 template<class ArrayFaceNormal> 01656 void CellTools<Scalar>::getReferenceFaceNormal(ArrayFaceNormal & refFaceNormal, 01657 const int & faceOrd, 01658 const shards::CellTopology & parentCell){ 01659 int spaceDim = parentCell.getDimension(); 01660 01661 #ifdef HAVE_INTREPID_DEBUG 01662 01663 TEST_FOR_EXCEPTION( !(spaceDim == 3), std::invalid_argument, 01664 ">>> ERROR (Intrepid::CellTools::getReferenceFaceNormal): three-dimensional parent cell required"); 01665 01666 TEST_FOR_EXCEPTION( !( (0 <= faceOrd) && (faceOrd < (int)parentCell.getSubcellCount(2) ) ), std::invalid_argument, 01667 ">>> ERROR (Intrepid::CellTools::getReferenceFaceNormal): face ordinal out of bounds"); 01668 01669 TEST_FOR_EXCEPTION( !( refFaceNormal.rank() == 1 ), std::invalid_argument, 01670 ">>> ERROR (Intrepid::CellTools::getReferenceFaceNormal): rank = 1 required for output array"); 01671 01672 TEST_FOR_EXCEPTION( !( refFaceNormal.dimension(0) == spaceDim ), std::invalid_argument, 01673 ">>> ERROR (Intrepid::CellTools::getReferenceFaceNormal): dim0 (spatial dim) must match that of parent cell"); 01674 #endif 01675 01676 // Reference face normal = vector product of reference face tangents. Allocate temp FC storage: 01677 FieldContainer<Scalar> uTan(spaceDim); 01678 FieldContainer<Scalar> vTan(spaceDim); 01679 getReferenceFaceTangents(uTan, vTan, faceOrd, parentCell); 01680 01681 // Compute the vector product of the reference face tangents: 01682 RealSpaceTools<Scalar>::vecprod(refFaceNormal, uTan, vTan); 01683 } 01684 01685 01686 01687 template<class Scalar> 01688 template<class ArrayEdgeTangent, class ArrayJac> 01689 void CellTools<Scalar>::getPhysicalEdgeTangents(ArrayEdgeTangent & edgeTangents, 01690 const ArrayJac & worksetJacobians, 01691 const int & worksetEdgeOrd, 01692 const shards::CellTopology & parentCell){ 01693 int worksetSize = worksetJacobians.dimension(0); 01694 int edgePtCount = worksetJacobians.dimension(1); 01695 int pCellDim = parentCell.getDimension(); 01696 01697 #ifdef HAVE_INTREPID_DEBUG 01698 std::string errmsg = ">>> ERROR (Intrepid::CellTools::getPhysicalEdgeTangents):"; 01699 01700 TEST_FOR_EXCEPTION( !( (pCellDim == 3) || (pCellDim == 2) ), std::invalid_argument, 01701 ">>> ERROR (Intrepid::CellTools::getPhysicalEdgeTangents): 2D or 3D parent cell required"); 01702 01703 // (1) edgeTangents is rank-3 (C,P,D) and D=2, or 3 is required 01704 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, edgeTangents, 3,3), std::invalid_argument, errmsg); 01705 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, edgeTangents, 2, 2,3), std::invalid_argument, errmsg); 01706 01707 // (2) worksetJacobians in rank-4 (C,P,D,D) and D=2, or 3 is required 01708 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, worksetJacobians, 4,4), std::invalid_argument, errmsg); 01709 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, worksetJacobians, 2, 2,3), std::invalid_argument, errmsg); 01710 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, worksetJacobians, 3, 2,3), std::invalid_argument, errmsg); 01711 01712 // (4) cross-check array dimensions: edgeTangents (C,P,D) vs. worksetJacobians (C,P,D,D) 01713 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg, edgeTangents, 0,1,2,2, worksetJacobians, 0,1,2,3), std::invalid_argument, errmsg); 01714 01715 #endif 01716 01717 // Temp storage for constant reference edge tangent: rank-1 (D) arrays 01718 FieldContainer<double> refEdgeTan(pCellDim); 01719 getReferenceEdgeTangent(refEdgeTan, worksetEdgeOrd, parentCell); 01720 01721 // Loop over workset faces and edge points 01722 for(int pCell = 0; pCell < worksetSize; pCell++){ 01723 for(int pt = 0; pt < edgePtCount; pt++){ 01724 01725 // Apply parent cell Jacobian to ref. edge tangent 01726 for(int i = 0; i < pCellDim; i++){ 01727 edgeTangents(pCell, pt, i) = 0.0; 01728 for(int j = 0; j < pCellDim; j++){ 01729 edgeTangents(pCell, pt, i) += worksetJacobians(pCell, pt, i, j)*refEdgeTan(j); 01730 }// for j 01731 }// for i 01732 }// for pt 01733 }// for pCell 01734 } 01735 01736 01737 01738 template<class Scalar> 01739 template<class ArrayFaceTangentU, class ArrayFaceTangentV, class ArrayJac> 01740 void CellTools<Scalar>::getPhysicalFaceTangents(ArrayFaceTangentU & faceTanU, 01741 ArrayFaceTangentV & faceTanV, 01742 const ArrayJac & worksetJacobians, 01743 const int & worksetFaceOrd, 01744 const shards::CellTopology & parentCell){ 01745 int worksetSize = worksetJacobians.dimension(0); 01746 int facePtCount = worksetJacobians.dimension(1); 01747 int pCellDim = parentCell.getDimension(); 01748 01749 #ifdef HAVE_INTREPID_DEBUG 01750 std::string errmsg = ">>> ERROR (Intrepid::CellTools::getPhysicalFaceTangents):"; 01751 01752 TEST_FOR_EXCEPTION( !(pCellDim == 3), std::invalid_argument, 01753 ">>> ERROR (Intrepid::CellTools::getPhysicalFaceTangents): three-dimensional parent cell required"); 01754 01755 // (1) faceTanU and faceTanV are rank-3 (C,P,D) and D=3 is required 01756 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, faceTanU, 3,3), std::invalid_argument, errmsg); 01757 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, faceTanU, 2, 3,3), std::invalid_argument, errmsg); 01758 01759 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, faceTanV, 3,3), std::invalid_argument, errmsg); 01760 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, faceTanV, 2, 3,3), std::invalid_argument, errmsg); 01761 01762 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg, faceTanU, faceTanV), std::invalid_argument, errmsg); 01763 01764 // (3) worksetJacobians in rank-4 (C,P,D,D) and D=3 is required 01765 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, worksetJacobians, 4,4), std::invalid_argument, errmsg); 01766 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, worksetJacobians, 2, 3,3), std::invalid_argument, errmsg); 01767 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, worksetJacobians, 3, 3,3), std::invalid_argument, errmsg); 01768 01769 // (4) cross-check array dimensions: faceTanU (C,P,D) vs. worksetJacobians (C,P,D,D) 01770 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg, faceTanU, 0,1,2,2, worksetJacobians, 0,1,2,3), std::invalid_argument, errmsg); 01771 01772 #endif 01773 01774 // Temp storage for the pair of constant ref. face tangents: rank-1 (D) arrays 01775 FieldContainer<double> refFaceTanU(pCellDim); 01776 FieldContainer<double> refFaceTanV(pCellDim); 01777 getReferenceFaceTangents(refFaceTanU, refFaceTanV, worksetFaceOrd, parentCell); 01778 01779 // Loop over workset faces and face points 01780 for(int pCell = 0; pCell < worksetSize; pCell++){ 01781 for(int pt = 0; pt < facePtCount; pt++){ 01782 01783 // Apply parent cell Jacobian to ref. face tangents 01784 for(int dim = 0; dim < pCellDim; dim++){ 01785 faceTanU(pCell, pt, dim) = 0.0; 01786 faceTanV(pCell, pt, dim) = 0.0; 01787 01788 // Unroll loops: parent cell dimension can only be 3 01789 faceTanU(pCell, pt, dim) = \ 01790 worksetJacobians(pCell, pt, dim, 0)*refFaceTanU(0) + \ 01791 worksetJacobians(pCell, pt, dim, 1)*refFaceTanU(1) + \ 01792 worksetJacobians(pCell, pt, dim, 2)*refFaceTanU(2); 01793 faceTanV(pCell, pt, dim) = \ 01794 worksetJacobians(pCell, pt, dim, 0)*refFaceTanV(0) + \ 01795 worksetJacobians(pCell, pt, dim, 1)*refFaceTanV(1) + \ 01796 worksetJacobians(pCell, pt, dim, 2)*refFaceTanV(2); 01797 }// for dim 01798 }// for pt 01799 }// for pCell 01800 } 01801 01802 01803 template<class Scalar> 01804 template<class ArraySideNormal, class ArrayJac> 01805 void CellTools<Scalar>::getPhysicalSideNormals(ArraySideNormal & sideNormals, 01806 const ArrayJac & worksetJacobians, 01807 const int & worksetSideOrd, 01808 const shards::CellTopology & parentCell){ 01809 int worksetSize = worksetJacobians.dimension(0); 01810 int sidePtCount = worksetJacobians.dimension(1); 01811 int spaceDim = parentCell.getDimension(); 01812 01813 #ifdef HAVE_INTREPID_DEBUG 01814 TEST_FOR_EXCEPTION( !( (spaceDim == 2) || (spaceDim == 3) ), std::invalid_argument, 01815 ">>> ERROR (Intrepid::CellTools::getPhysicalSideNormals): two or three-dimensional parent cell required"); 01816 01817 // Check side ordinal: by definition side is subcell whose dimension = spaceDim-1 01818 TEST_FOR_EXCEPTION( !( (0 <= worksetSideOrd) && (worksetSideOrd < (int)parentCell.getSubcellCount(spaceDim - 1) ) ), std::invalid_argument, 01819 ">>> ERROR (Intrepid::CellTools::getPhysicalSideNormals): side ordinal out of bounds"); 01820 #endif 01821 01822 if(spaceDim == 2){ 01823 01824 // 2D parent cells: side = 1D subcell (edge), call the edge tangent method and rotate tangents 01825 getPhysicalEdgeTangents(sideNormals, worksetJacobians, worksetSideOrd, parentCell); 01826 01827 // rotate t(t1, t2) to get n(t2, -t1) so that (n,t) is positively oriented: det(n1,n2/t1,t2)>0 01828 for(int cell = 0; cell < worksetSize; cell++){ 01829 for(int pt = 0; pt < sidePtCount; pt++){ 01830 Scalar temp = sideNormals(cell, pt, 0); 01831 sideNormals(cell, pt, 0) = sideNormals(cell, pt, 1); 01832 sideNormals(cell, pt, 1) = -temp; 01833 }// for pt 01834 }// for cell 01835 } 01836 else{ 01837 // 3D parent cell: side = 2D subcell (face), call the face normal method. 01838 getPhysicalFaceNormals(sideNormals, worksetJacobians, worksetSideOrd, parentCell); 01839 } 01840 } 01841 01842 01843 01844 template<class Scalar> 01845 template<class ArrayFaceNormal, class ArrayJac> 01846 void CellTools<Scalar>::getPhysicalFaceNormals(ArrayFaceNormal & faceNormals, 01847 const ArrayJac & worksetJacobians, 01848 const int & worksetFaceOrd, 01849 const shards::CellTopology & parentCell){ 01850 int worksetSize = worksetJacobians.dimension(0); 01851 int facePtCount = worksetJacobians.dimension(1); 01852 int pCellDim = parentCell.getDimension(); 01853 01854 #ifdef HAVE_INTREPID_DEBUG 01855 std::string errmsg = ">>> ERROR (Intrepid::CellTools::getPhysicalFaceNormals):"; 01856 01857 TEST_FOR_EXCEPTION( !(pCellDim == 3), std::invalid_argument, 01858 ">>> ERROR (Intrepid::CellTools::getPhysicalFaceNormals): three-dimensional parent cell required"); 01859 01860 // (1) faceNormals is rank-3 (C,P,D) and D=3 is required 01861 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, faceNormals, 3,3), std::invalid_argument, errmsg); 01862 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, faceNormals, 2, 3,3), std::invalid_argument, errmsg); 01863 01864 // (3) worksetJacobians in rank-4 (C,P,D,D) and D=3 is required 01865 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, worksetJacobians, 4,4), std::invalid_argument, errmsg); 01866 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, worksetJacobians, 2, 3,3), std::invalid_argument, errmsg); 01867 TEST_FOR_EXCEPTION( !requireDimensionRange(errmsg, worksetJacobians, 3, 3,3), std::invalid_argument, errmsg); 01868 01869 // (4) cross-check array dimensions: faceNormals (C,P,D) vs. worksetJacobians (C,P,D,D) 01870 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg, faceNormals, 0,1,2,2, worksetJacobians, 0,1,2,3), std::invalid_argument, errmsg); 01871 #endif 01872 01873 // Temp storage for physical face tangents: rank-3 (C,P,D) arrays 01874 FieldContainer<double> faceTanU(worksetSize, facePtCount, pCellDim); 01875 FieldContainer<double> faceTanV(worksetSize, facePtCount, pCellDim); 01876 getPhysicalFaceTangents(faceTanU, faceTanV, worksetJacobians, worksetFaceOrd, parentCell); 01877 01878 // Compute the vector product of the physical face tangents: 01879 RealSpaceTools<Scalar>::vecprod(faceNormals, faceTanU, faceTanV); 01880 01881 01882 } 01883 01884 //============================================================================================// 01885 // // 01886 // Inclusion tests // 01887 // // 01888 //============================================================================================// 01889 01890 01891 template<class Scalar> 01892 int CellTools<Scalar>::checkPointInclusion(const Scalar* point, 01893 const int pointDim, 01894 const shards::CellTopology & cellTopo, 01895 const double & threshold) { 01896 #ifdef HAVE_INTREPID_DEBUG 01897 TEST_FOR_EXCEPTION( !(pointDim == (int)cellTopo.getDimension() ), std::invalid_argument, 01898 ">>> ERROR (Intrepid::CellTools::checkPointInclusion): Point and cell dimensions do not match. "); 01899 #endif 01900 int testResult = 1; 01901 01902 // Using these values in the tests effectievly inflates the reference element to a larger one 01903 double minus_one = -1.0 - threshold; 01904 double plus_one = 1.0 + threshold; 01905 double minus_zero = - threshold; 01906 01907 // A cell with extended topology has the same reference cell as a cell with base topology. 01908 // => testing for inclusion in a reference Triangle<> and a reference Triangle<6> relies on 01909 // on the same set of inequalities. To eliminate unnecessary cases we switch on the base topology 01910 unsigned key = cellTopo.getBaseTopology() -> key ; 01911 switch( key ) { 01912 01913 case shards::Line<>::key : 01914 if( !(minus_one <= point[0] && point[0] <= plus_one)) testResult = 0; 01915 break; 01916 01917 case shards::Triangle<>::key : { 01918 Scalar distance = std::max( std::max( -point[0], -point[1] ), point[0] + point[1] - 1.0 ); 01919 if( distance > threshold ) testResult = 0; 01920 break; 01921 } 01922 01923 case shards::Quadrilateral<>::key : 01924 if(!( (minus_one <= point[0] && point[0] <= plus_one) && \ 01925 (minus_one <= point[1] && point[1] <= plus_one) ) ) testResult = 0; 01926 break; 01927 01928 case shards::Tetrahedron<>::key : { 01929 Scalar distance = std::max( std::max(-point[0],-point[1]), \ 01930 std::max(-point[2], point[0] + point[1] + point[2] - 1) ); 01931 if( distance > threshold ) testResult = 0; 01932 break; 01933 } 01934 01935 case shards::Hexahedron<>::key : 01936 if(!((minus_one <= point[0] && point[0] <= plus_one) && \ 01937 (minus_one <= point[1] && point[1] <= plus_one) && \ 01938 (minus_one <= point[2] && point[2] <= plus_one))) \ 01939 testResult = 0; 01940 break; 01941 01942 // The base of the reference prism is the same as the reference triangle => apply triangle test 01943 // to X and Y coordinates and test whether Z is in [-1,1] 01944 case shards::Wedge<>::key : { 01945 Scalar distance = std::max( std::max( -point[0], -point[1] ), point[0] + point[1] - 1 ); 01946 if( distance > threshold || \ 01947 point[2] < minus_one || point[2] > plus_one) \ 01948 testResult = 0; 01949 break; 01950 } 01951 01952 // The base of the reference pyramid is the same as the reference quad cell => a horizontal plane 01953 // through a point P(x,y,z) intersects the pyramid at a quadrilateral that equals the base quad 01954 // scaled by (1-z) => P(x,y,z) is inside the pyramid <=> (x,y) is in [-1+z,1-z]^2 && 0 <= Z <= 1 01955 case shards::Pyramid<>::key : { 01956 Scalar left = minus_one + point[2]; 01957 Scalar right = plus_one - point[2]; 01958 if(!( (left <= point[0] && point[0] <= right) && \ 01959 (left <= point[1] && point[1] <= right) && 01960 (minus_zero <= point[2] && point[2] <= plus_one) ) ) \ 01961 testResult = 0; 01962 break; 01963 } 01964 01965 default: 01966 TEST_FOR_EXCEPTION( !( (key == shards::Line<>::key ) || 01967 (key == shards::Triangle<>::key) || 01968 (key == shards::Quadrilateral<>::key) || 01969 (key == shards::Tetrahedron<>::key) || 01970 (key == shards::Hexahedron<>::key) || 01971 (key == shards::Wedge<>::key) || 01972 (key == shards::Pyramid<>::key) ), 01973 std::invalid_argument, 01974 ">>> ERROR (Intrepid::CellTools::checkPointInclusion): Invalid cell topology. "); 01975 } 01976 return testResult; 01977 } 01978 01979 01980 01981 template<class Scalar> 01982 template<class ArrayPoint> 01983 int CellTools<Scalar>::checkPointsetInclusion(const ArrayPoint& points, 01984 const shards::CellTopology & cellTopo, 01985 const double & threshold) { 01986 01987 int rank = points.rank(); 01988 01989 #ifdef HAVE_INTREPID_DEBUG 01990 TEST_FOR_EXCEPTION( !( (1 <= points.rank() ) && (points.rank() <= 3) ), std::invalid_argument, 01991 ">>> ERROR (Intrepid::CellTools::checkPointsetInclusion): rank-1, 2 or 3 required for input points array. "); 01992 01993 // The last dimension of points array at (rank - 1) is the spatial dimension. Must equal the cell dimension. 01994 TEST_FOR_EXCEPTION( !( points.dimension(rank - 1) == (int)cellTopo.getDimension() ), std::invalid_argument, 01995 ">>> ERROR (Intrepid::CellTools::checkPointsetInclusion): Point and cell dimensions do not match. "); 01996 #endif 01997 01998 // create temp output array depending on the rank of the input array 01999 FieldContainer<int> inRefCell; 02000 switch(rank) { 02001 case 1: inRefCell.resize(1); break; 02002 case 2: inRefCell.resize( points.dimension(0) ); break; 02003 case 3: inRefCell.resize( points.dimension(0), points.dimension(1) ); break; 02004 } 02005 02006 // Call the inclusion method which returns inclusion results for all points 02007 checkPointwiseInclusion(inRefCell, points, cellTopo, threshold); 02008 02009 // Check if any points were outside, break when finding the first one 02010 int allInside = 1; 02011 for(int i = 0; i < inRefCell.size(); i++ ){ 02012 if (inRefCell[i] == 0) { 02013 allInside = 0; 02014 break; 02015 } 02016 } 02017 return allInside; 02018 } 02019 02020 02021 02022 template<class Scalar> 02023 template<class ArrayIncl, class ArrayPoint> 02024 void CellTools<Scalar>::checkPointwiseInclusion(ArrayIncl & inRefCell, 02025 const ArrayPoint & points, 02026 const shards::CellTopology & cellTopo, 02027 const double & threshold) { 02028 int apRank = points.rank(); 02029 02030 #ifdef HAVE_INTREPID_DEBUG 02031 02032 // Verify that points and inRefCell have correct ranks and dimensions 02033 std::string errmsg = ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion):"; 02034 if(points.rank() == 1) { 02035 TEST_FOR_EXCEPTION( !(inRefCell.rank() == 1 ), std::invalid_argument, 02036 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): rank-1 input array requires rank-1 output array."); 02037 TEST_FOR_EXCEPTION( !(inRefCell.dimension(0) == 1), std::invalid_argument, 02038 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): rank-1 input array requires dim0 = 1 for output array."); 02039 } 02040 else if(points.rank() == 2){ 02041 TEST_FOR_EXCEPTION( !(inRefCell.rank() == 1 ), std::invalid_argument, 02042 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): rank-2 input array requires rank-1 output array."); 02043 // dimension 0 of the arrays must match 02044 TEST_FOR_EXCEPTION( !requireDimensionMatch( errmsg, inRefCell, 0, points, 0), std::invalid_argument, errmsg); 02045 } 02046 else if (points.rank() == 3) { 02047 TEST_FOR_EXCEPTION( !(inRefCell.rank() == 2 ), std::invalid_argument, 02048 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): rank-3 input array requires rank-2 output array."); 02049 // dimensions 0 and 1 of the arrays must match 02050 TEST_FOR_EXCEPTION( !requireDimensionMatch( errmsg, inRefCell, 0,1, points, 0,1), std::invalid_argument, errmsg); 02051 } 02052 else{ 02053 TEST_FOR_EXCEPTION( !( (points.rank() == 1) || (points.rank() == 2) || (points.rank() == 3) ), std::invalid_argument, 02054 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): rank-1, 2 or 3 required for input points array. "); 02055 } 02056 02057 // The last dimension of points array at (rank - 1) is the spatial dimension. Must equal the cell dimension. 02058 TEST_FOR_EXCEPTION( !( points.dimension(apRank - 1) == (int)cellTopo.getDimension() ), std::invalid_argument, 02059 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): Point and cell dimensions do not match. "); 02060 02061 #endif 02062 02063 // Initializations 02064 int dim0 = 1; 02065 int dim1 = 1; 02066 int pointDim = 0; 02067 switch(apRank) { 02068 case 1: 02069 pointDim = points.dimension(0); 02070 break; 02071 case 2: 02072 dim1 = points.dimension(0); 02073 pointDim = points.dimension(1); 02074 break; 02075 case 3: 02076 dim0 = points.dimension(0); 02077 dim1 = points.dimension(1); 02078 pointDim = points.dimension(2); 02079 break; 02080 default: 02081 TEST_FOR_EXCEPTION( !( (1 <= points.rank() ) && (points.rank() <= 3) ), std::invalid_argument, 02082 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): rank-1, 2 or 3 required for input points array. "); 02083 }// switch 02084 02085 02086 // This method can handle up to rank-3 input arrays. The spatial dim must be the last dimension. 02087 // The method uses [] accessor because array rank is determined at runtime and the appropriate 02088 // (i,j,..,k) accessor is not known. Use of [] requires the following offsets: 02089 // for input array = i0*dim1*pointDim + i1*dim1 (computed in 2 pieces: inPtr0 and inPtr1, resp) 02090 // for output array = i0*dim1 (computed in one piece: outPtr0) 02091 int inPtr0 = 0; 02092 int inPtr1 = 0; 02093 int outPtr0 = 0; 02094 Scalar point[3] = {0.0, 0.0, 0.0}; 02095 02096 for(int i0 = 0; i0 < dim0; i0++){ 02097 outPtr0 = i0*dim1; 02098 inPtr0 = outPtr0*pointDim; 02099 02100 for(int i1 = 0; i1 < dim1; i1++) { 02101 inPtr1 = inPtr0 + i1*pointDim; 02102 point[0] = points[inPtr1]; 02103 if(pointDim > 1) { 02104 point[1] = points[inPtr1 + 1]; 02105 if(pointDim > 2) { 02106 point[2] = points[inPtr1 + 2]; 02107 if(pointDim > 3) { 02108 TEST_FOR_EXCEPTION( !( (1 <= pointDim) && (pointDim <= 3)), std::invalid_argument, 02109 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): Input array specifies invalid point dimension "); 02110 } 02111 } 02112 } //if(pointDim > 1) 02113 inRefCell[outPtr0 + i1] = checkPointInclusion(point, pointDim, cellTopo, threshold); 02114 } // for (i1) 02115 } // for(i2) 02116 02117 } 02118 02119 02120 template<class Scalar> 02121 template<class ArrayIncl, class ArrayPoint, class ArrayCell> 02122 void CellTools<Scalar>::checkPointwiseInclusion(ArrayIncl & inCell, 02123 const ArrayPoint & points, 02124 const ArrayCell & cellWorkset, 02125 const shards::CellTopology & cell, 02126 const int & whichCell, 02127 const double & threshold) 02128 { 02129 INTREPID_VALIDATE( validateArguments_checkPointwiseInclusion(inCell, points, cellWorkset, whichCell, cell) ); 02130 02131 // For cell topologies with reference cells this test maps the points back to the reference cell 02132 // and uses the method for reference cells 02133 unsigned baseKey = cell.getBaseTopology() -> key; 02134 02135 switch(baseKey){ 02136 02137 case shards::Line<>::key : 02138 case shards::Triangle<>::key: 02139 case shards::Quadrilateral<>::key : 02140 case shards::Tetrahedron<>::key : 02141 case shards::Hexahedron<>::key : 02142 case shards::Wedge<>::key : 02143 case shards::Pyramid<>::key : 02144 { 02145 FieldContainer<Scalar> refPoints; 02146 02147 if(points.rank() == 2){ 02148 refPoints.resize(points.dimension(0), points.dimension(1) ); 02149 mapToReferenceFrame(refPoints, points, cellWorkset, cell, whichCell); 02150 checkPointwiseInclusion(inCell, refPoints, cell, threshold ); 02151 } 02152 else if(points.rank() == 3){ 02153 refPoints.resize(points.dimension(0), points.dimension(1), points.dimension(2) ); 02154 mapToReferenceFrame(refPoints, points, cellWorkset, cell, whichCell); 02155 checkPointwiseInclusion(inCell, refPoints, cell, threshold ); 02156 } 02157 break; 02158 } 02159 default: 02160 TEST_FOR_EXCEPTION( true, std::invalid_argument, 02161 ">>> ERROR (Intrepid::CellTools::checkPointwiseInclusion): cell topology not supported"); 02162 }// switch 02163 02164 } 02165 02166 02167 //============================================================================================// 02168 // // 02169 // Validation of input/output arguments for CellTools methods // 02170 // // 02171 //============================================================================================// 02172 02173 template<class Scalar> 02174 template<class ArrayJac, class ArrayPoint, class ArrayCell> 02175 void CellTools<Scalar>::validateArguments_setJacobian(const ArrayJac & jacobian, 02176 const ArrayPoint & points, 02177 const ArrayCell & cellWorkset, 02178 const int & whichCell, 02179 const shards::CellTopology & cellTopo){ 02180 02181 // Validate cellWorkset array 02182 TEST_FOR_EXCEPTION( (cellWorkset.rank() != 3), std::invalid_argument, 02183 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): rank = 3 required for cellWorkset array"); 02184 02185 TEST_FOR_EXCEPTION( (cellWorkset.dimension(0) <= 0), std::invalid_argument, 02186 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 0 (number of cells) >= 1 required for cellWorkset array"); 02187 02188 TEST_FOR_EXCEPTION( (cellWorkset.dimension(1) != (int)cellTopo.getSubcellCount(0) ), std::invalid_argument, 02189 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 (number of cell nodes) of cellWorkset array does not match cell topology"); 02190 02191 TEST_FOR_EXCEPTION( (cellWorkset.dimension(2) != (int)cellTopo.getDimension() ), std::invalid_argument, 02192 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 (spatial dimension) of cellWorkset array does not match cell dimension"); 02193 02194 // validate whichCell. It can be either -1 (default value) or a valid cell ordinal. 02195 TEST_FOR_EXCEPTION( !( ( (0 <= whichCell ) && (whichCell < cellWorkset.dimension(0) ) ) || (whichCell == -1) ), std::invalid_argument, 02196 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): whichCell = -1 or a valid cell ordinal is required."); 02197 02198 02199 // Validate points array: can be rank-2 (P,D) or rank-3 (C,P,D) 02200 // If rank-2: admissible jacobians: rank-3 (P,D,D) or rank-4 (C,P,D,D); admissible whichCell: -1 (default) or cell ordinal. 02201 if(points.rank() == 2) { 02202 TEST_FOR_EXCEPTION( (points.dimension(0) <= 0), std::invalid_argument, 02203 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 0 (number of points) >= 1 required for points array "); 02204 02205 TEST_FOR_EXCEPTION( (points.dimension(1) != (int)cellTopo.getDimension() ), std::invalid_argument, 02206 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 (spatial dimension) of points array does not match cell dimension"); 02207 02208 // Validate the output array for the Jacobian: if whichCell == -1 all Jacobians are computed, rank-4 (C,P,D,D) required 02209 if(whichCell == -1) { 02210 TEST_FOR_EXCEPTION( (jacobian.rank() != 4), std::invalid_argument, 02211 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): rank = 4 required for jacobian array"); 02212 02213 TEST_FOR_EXCEPTION( (jacobian.dimension(0) != cellWorkset.dimension(0)), std::invalid_argument, 02214 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 0 (number of cells) of jacobian array must equal dim 0 of cellWorkset array"); 02215 02216 TEST_FOR_EXCEPTION( (jacobian.dimension(1) != points.dimension(0)), std::invalid_argument, 02217 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 (number of points) of jacobian array must equal dim 0 of points array"); 02218 02219 TEST_FOR_EXCEPTION( (jacobian.dimension(2) != points.dimension(1)), std::invalid_argument, 02220 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 (spatial dimension) of jacobian array must equal dim 1 of points array"); 02221 02222 TEST_FOR_EXCEPTION( !(jacobian.dimension(2) == jacobian.dimension(3) ), std::invalid_argument, 02223 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 = dim 3 (same spatial dimensions) required for jacobian array. "); 02224 02225 TEST_FOR_EXCEPTION( !( (0 < jacobian.dimension(3) ) && (jacobian.dimension(3) < 4) ), std::invalid_argument, 02226 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 and dim 3 (spatial dimensions) must be between 1 and 3. "); 02227 } 02228 // A single cell Jacobian is computed when whichCell != -1 (whichCell has been already validated), rank-3 (P,D,D) required 02229 else { 02230 TEST_FOR_EXCEPTION( (jacobian.rank() != 3), std::invalid_argument, 02231 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): rank = 3 required for jacobian array"); 02232 02233 TEST_FOR_EXCEPTION( (jacobian.dimension(0) != points.dimension(0)), std::invalid_argument, 02234 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 0 (number of points) of jacobian array must equal dim 0 of points array"); 02235 02236 TEST_FOR_EXCEPTION( (jacobian.dimension(1) != points.dimension(1)), std::invalid_argument, 02237 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 (spatial dimension) of jacobian array must equal dim 1 of points array"); 02238 02239 TEST_FOR_EXCEPTION( !(jacobian.dimension(1) == jacobian.dimension(2) ), std::invalid_argument, 02240 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 = dim 2 (same spatial dimensions) required for jacobian array. "); 02241 02242 TEST_FOR_EXCEPTION( !( (0 < jacobian.dimension(1) ) && (jacobian.dimension(1) < 4) ), std::invalid_argument, 02243 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 and dim 2 (spatial dimensions) must be between 1 and 3. "); 02244 } 02245 } 02246 // Point array is rank-3 (C,P,D): requires whichCell = -1 and rank-4 (C,P,D,D) jacobians 02247 else if(points.rank() ==3){ 02248 std::string errmsg = ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian):"; 02249 TEST_FOR_EXCEPTION( (points.dimension(0) != cellWorkset.dimension(0) ), std::invalid_argument, 02250 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 0 (number of cells) of points array must equal dim 0 of cellWorkset array"); 02251 02252 TEST_FOR_EXCEPTION( (points.dimension(1) <= 0), std::invalid_argument, 02253 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 (number of points) >= 1 required for points array "); 02254 02255 TEST_FOR_EXCEPTION( (points.dimension(2) != (int)cellTopo.getDimension() ), std::invalid_argument, 02256 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 (spatial dimension) of points array does not match cell dimension"); 02257 02258 TEST_FOR_EXCEPTION( (whichCell != -1), std::invalid_argument, 02259 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): default value whichCell=-1 required for rank-3 input points"); 02260 02261 // rank-4 (C,P,D,D) jacobian required for rank-3 (C,P,D) input points 02262 TEST_FOR_EXCEPTION( !requireRankRange(errmsg, jacobian, 4, 4), std::invalid_argument,errmsg); 02263 02264 TEST_FOR_EXCEPTION( (jacobian.dimension(0) != points.dimension(0)), std::invalid_argument, 02265 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 0 (number of cells) of jacobian array must equal dim 0 of points array"); 02266 02267 TEST_FOR_EXCEPTION( (jacobian.dimension(1) != points.dimension(1)), std::invalid_argument, 02268 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 1 (number of points) of jacobian array must equal dim 1 of points array"); 02269 02270 TEST_FOR_EXCEPTION( (jacobian.dimension(2) != points.dimension(2)), std::invalid_argument, 02271 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 (spatial dimension) of jacobian array must equal dim 2 of points array"); 02272 02273 TEST_FOR_EXCEPTION( !(jacobian.dimension(2) == jacobian.dimension(3) ), std::invalid_argument, 02274 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 = dim 3 (same spatial dimensions) required for jacobian array. "); 02275 02276 TEST_FOR_EXCEPTION( !( (0 < jacobian.dimension(3) ) && (jacobian.dimension(3) < 4) ), std::invalid_argument, 02277 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): dim 2 and dim 3 (spatial dimensions) must be between 1 and 3. "); 02278 } 02279 else { 02280 TEST_FOR_EXCEPTION( !( (points.rank() == 2) && (points.rank() ==3) ), std::invalid_argument, 02281 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobian): rank = 2 or 3 required for points array"); 02282 } 02283 } 02284 02285 02286 02287 template<class Scalar> 02288 template<class ArrayJacInv, class ArrayJac> 02289 void CellTools<Scalar>::validateArguments_setJacobianInv(const ArrayJacInv & jacobianInv, 02290 const ArrayJac & jacobian) 02291 { 02292 // Validate input jacobian array: admissible ranks & dimensions are: 02293 // - rank-4 with dimensions (C,P,D,D), or rank-3 with dimensions (P,D,D). 02294 int jacobRank = jacobian.rank(); 02295 TEST_FOR_EXCEPTION( !( (jacobRank == 4) || (jacobRank == 3) ), std::invalid_argument, 02296 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianInv): rank = 4 or 3 required for jacobian array. "); 02297 02298 // Verify correctness of spatial dimensions - they are the last two dimensions of the array: rank-2 and rank-1 02299 TEST_FOR_EXCEPTION( !(jacobian.dimension(jacobRank - 1) == jacobian.dimension(jacobRank - 2) ), std::invalid_argument, 02300 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianInv): dim(rank-2) = dim(rank-2) (same spatial dimensions) required for jacobian array. "); 02301 02302 TEST_FOR_EXCEPTION( !( (0 < jacobian.dimension(jacobRank - 1) ) && (jacobian.dimension(jacobRank - 1) < 4) ), std::invalid_argument, 02303 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianInv): dim(rank-1) and dim(rank-2) (spatial dimensions) must be between 1 and 3. "); 02304 02305 // Validate output jacobianInv array: must have the same rank and dimensions as the input array. 02306 std::string errmsg = ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianInv):"; 02307 02308 TEST_FOR_EXCEPTION( !(requireRankMatch(errmsg, jacobianInv, jacobian) ), std::invalid_argument, errmsg); 02309 02310 TEST_FOR_EXCEPTION( !(requireDimensionMatch(errmsg, jacobianInv, jacobian) ), std::invalid_argument, errmsg); 02311 } 02312 02313 02314 02315 template<class Scalar> 02316 template<class ArrayJacDet, class ArrayJac> 02317 void CellTools<Scalar>::validateArguments_setJacobianDetArgs(const ArrayJacDet & jacobianDet, 02318 const ArrayJac & jacobian) 02319 { 02320 // Validate input jacobian array: admissible ranks & dimensions are: 02321 // - rank-4 with dimensions (C,P,D,D), or rank-3 with dimensions (P,D,D). 02322 int jacobRank = jacobian.rank(); 02323 TEST_FOR_EXCEPTION( !( (jacobRank == 4) || (jacobRank == 3) ), std::invalid_argument, 02324 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianInv): rank = 4 or 3 required for jacobian array. "); 02325 02326 // Verify correctness of spatial dimensions - they are the last two dimensions of the array: rank-2 and rank-1 02327 TEST_FOR_EXCEPTION( !(jacobian.dimension(jacobRank - 1) == jacobian.dimension(jacobRank - 2) ), std::invalid_argument, 02328 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianInv): dim(rank-2) = dim(rank-2) (same spatial dimensions) required for jacobian array. "); 02329 02330 TEST_FOR_EXCEPTION( !( (0 < jacobian.dimension(jacobRank - 1) ) && (jacobian.dimension(jacobRank - 1) < 4) ), std::invalid_argument, 02331 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianInv): dim(rank-1) and dim(rank-2) (spatial dimensions) must be between 1 and 3. "); 02332 02333 02334 // Validate output jacobianDet array: must be rank-2 with dimensions (C,P) if jacobian was rank-4: 02335 if(jacobRank == 4){ 02336 TEST_FOR_EXCEPTION( !(jacobianDet.rank() == 2), std::invalid_argument, 02337 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianDetArgs): rank = 2 required for jacobianDet if jacobian is rank-4. "); 02338 02339 TEST_FOR_EXCEPTION( !(jacobianDet.dimension(0) == jacobian.dimension(0) ), std::invalid_argument, 02340 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianDetArgs): dim 0 (number of cells) of jacobianDet array must equal dim 0 of jacobian array. "); 02341 02342 TEST_FOR_EXCEPTION( !(jacobianDet.dimension(1) == jacobian.dimension(1) ), std::invalid_argument, 02343 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianDetArgs): dim 1 (number of points) of jacobianDet array must equal dim 1 of jacobian array."); 02344 } 02345 02346 // must be rank-1 with dimension (P) if jacobian was rank-3 02347 else { 02348 TEST_FOR_EXCEPTION( !(jacobianDet.rank() == 1), std::invalid_argument, 02349 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianDetArgs): rank = 1 required for jacobianDet if jacobian is rank-3. "); 02350 02351 TEST_FOR_EXCEPTION( !(jacobianDet.dimension(0) == jacobian.dimension(0) ), std::invalid_argument, 02352 ">>> ERROR (Intrepid::CellTools::validateArguments_setJacobianDetArgs): dim 0 (number of points) of jacobianDet array must equal dim 0 of jacobian array."); 02353 } 02354 } 02355 02356 02357 02358 template<class Scalar> 02359 template<class ArrayPhysPoint, class ArrayRefPoint, class ArrayCell> 02360 void CellTools<Scalar>::validateArguments_mapToPhysicalFrame(const ArrayPhysPoint & physPoints, 02361 const ArrayRefPoint & refPoints, 02362 const ArrayCell & cellWorkset, 02363 const shards::CellTopology & cellTopo, 02364 const int& whichCell) 02365 { 02366 std::string errmsg = ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame):"; 02367 02368 // Validate cellWorkset array 02369 TEST_FOR_EXCEPTION( (cellWorkset.rank() != 3), std::invalid_argument, 02370 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): rank = 3 required for cellWorkset array"); 02371 02372 TEST_FOR_EXCEPTION( (cellWorkset.dimension(0) <= 0), std::invalid_argument, 02373 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 0 (number of cells) >= 1 required for cellWorkset array"); 02374 02375 TEST_FOR_EXCEPTION( (cellWorkset.dimension(1) != (int)cellTopo.getSubcellCount(0) ), std::invalid_argument, 02376 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 1 (number of cell nodes) of cellWorkset array does not match cell topology"); 02377 02378 TEST_FOR_EXCEPTION( (cellWorkset.dimension(2) != (int)cellTopo.getDimension() ), std::invalid_argument, 02379 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 2 (spatial dimension) of cellWorkset array does not match cell dimension"); 02380 02381 02382 // validate whichCell. It can be either -1 (default value) or a valid cell ordinal. 02383 TEST_FOR_EXCEPTION( !( ( (0 <= whichCell ) && (whichCell < cellWorkset.dimension(0) ) ) || (whichCell == -1) ), std::invalid_argument, 02384 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): whichCell = -1 or a valid cell ordinal is required."); 02385 02386 // Validate refPoints array: can be rank-2 (P,D) or rank-3 (C,P,D) array 02387 // If rank-2: admissible output array is (P,D) or (C,P,D); admissible whichCell: -1 (default) or cell ordinal 02388 if(refPoints.rank() == 2) { 02389 TEST_FOR_EXCEPTION( (refPoints.dimension(0) <= 0), std::invalid_argument, 02390 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 0 (number of points) >= 1 required for refPoints array "); 02391 02392 TEST_FOR_EXCEPTION( (refPoints.dimension(1) != (int)cellTopo.getDimension() ), std::invalid_argument, 02393 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 1 (spatial dimension) of refPoints array does not match cell dimension"); 02394 02395 // Validate output array: whichCell = -1 requires rank-3 array with dimensions (C,P,D) 02396 if(whichCell == -1) { 02397 TEST_FOR_EXCEPTION( ( (physPoints.rank() != 3) && (whichCell == -1) ), std::invalid_argument, 02398 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): rank = 3 required for physPoints array for the default whichCell value"); 02399 02400 TEST_FOR_EXCEPTION( (physPoints.dimension(0) != cellWorkset.dimension(0)), std::invalid_argument, 02401 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 0 (number of cells) of physPoints array must equal dim 0 of cellWorkset array"); 02402 02403 TEST_FOR_EXCEPTION( (physPoints.dimension(1) != refPoints.dimension(0)), std::invalid_argument, 02404 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 1 (number of points) of physPoints array must equal dim 0 of refPoints array"); 02405 02406 TEST_FOR_EXCEPTION( (physPoints.dimension(2) != (int)cellTopo.getDimension()), std::invalid_argument, 02407 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 2 (spatial dimension) does not match cell dimension "); 02408 } 02409 // 0 <= whichCell < num cells requires rank-2 (P,D) arrays for both refPoints and physPoints 02410 else{ 02411 TEST_FOR_EXCEPTION( (physPoints.rank() != 2), std::invalid_argument, 02412 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): rank = 2 required for physPoints array"); 02413 02414 TEST_FOR_EXCEPTION( (physPoints.dimension(0) != refPoints.dimension(0)), std::invalid_argument, 02415 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 0 (number of points) of physPoints array must equal dim 0 of refPoints array"); 02416 02417 TEST_FOR_EXCEPTION( (physPoints.dimension(1) != (int)cellTopo.getDimension()), std::invalid_argument, 02418 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 1 (spatial dimension) does not match cell dimension "); 02419 } 02420 } 02421 // refPoints is (C,P,D): requires physPoints to be (C,P,D) and whichCell=-1 (because all cell mappings are applied) 02422 else if(refPoints.rank() == 3) { 02423 02424 // 1. validate refPoints dimensions and rank 02425 TEST_FOR_EXCEPTION( (refPoints.dimension(0) != cellWorkset.dimension(0) ), std::invalid_argument, 02426 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 0 (number of cells) of refPoints and cellWorkset arraya are required to match "); 02427 02428 TEST_FOR_EXCEPTION( (refPoints.dimension(1) <= 0), std::invalid_argument, 02429 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 1 (number of points) >= 1 required for refPoints array "); 02430 02431 TEST_FOR_EXCEPTION( (refPoints.dimension(2) != (int)cellTopo.getDimension() ), std::invalid_argument, 02432 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): dim 2 (spatial dimension) of refPoints array does not match cell dimension"); 02433 02434 // 2. whichCell must be -1 02435 TEST_FOR_EXCEPTION( (whichCell != -1), std::invalid_argument, 02436 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): default value is required for rank-3 refPoints array"); 02437 02438 // 3. physPoints must match rank and dimensions of refPoints 02439 TEST_FOR_EXCEPTION( !requireRankMatch(errmsg, refPoints, physPoints), std::invalid_argument, errmsg ); 02440 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg, refPoints, physPoints), std::invalid_argument, errmsg); 02441 } 02442 // if rank is not 2 or 3 throw exception 02443 else { 02444 TEST_FOR_EXCEPTION( !( (refPoints.rank() == 2) || (refPoints.rank() == 3) ), std::invalid_argument, 02445 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToPhysicalFrame): rank = 2 or 3 required for refPoints array"); 02446 } 02447 } 02448 02449 02450 02451 template<class Scalar> 02452 template<class ArrayRefPoint, class ArrayPhysPoint, class ArrayCell> 02453 void CellTools<Scalar>::validateArguments_mapToReferenceFrame(const ArrayRefPoint & refPoints, 02454 const ArrayPhysPoint & physPoints, 02455 const ArrayCell & cellWorkset, 02456 const shards::CellTopology & cellTopo, 02457 const int& whichCell) 02458 { 02459 std::string errmsg = ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame):"; 02460 std::string errmsg1 = ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame):"; 02461 02462 // Validate cellWorkset array 02463 TEST_FOR_EXCEPTION( (cellWorkset.rank() != 3), std::invalid_argument, 02464 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame): rank = 3 required for cellWorkset array"); 02465 02466 TEST_FOR_EXCEPTION( (cellWorkset.dimension(0) <= 0), std::invalid_argument, 02467 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame): dim 0 (number of cells) >= 1 required for cellWorkset array"); 02468 02469 TEST_FOR_EXCEPTION( (cellWorkset.dimension(1) != (int)cellTopo.getSubcellCount(0) ), std::invalid_argument, 02470 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame): dim 1 (number of cell nodes) of cellWorkset array does not match cell topology"); 02471 02472 TEST_FOR_EXCEPTION( (cellWorkset.dimension(2) != (int)cellTopo.getDimension() ), std::invalid_argument, 02473 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame): dim 2 (spatial dimension) of cellWorkset array does not match cell dimension"); 02474 02475 // Validate whichCell. It can be either -1 (default value) or a valid cell ordinal. 02476 TEST_FOR_EXCEPTION( !( ( (0 <= whichCell ) && (whichCell < cellWorkset.dimension(0) ) ) || (whichCell == -1) ), std::invalid_argument, 02477 ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame): whichCell = -1 or a valid cell ordinal is required."); 02478 02479 // Admissible ranks and dimensions of refPoints and physPoints depend on whichCell value: 02480 // default is to map multiple sets of points to multiple sets of points. (C,P,D) arrays required 02481 int validRank; 02482 if(whichCell == -1) { 02483 validRank = 3; 02484 errmsg1 += " default value of whichCell requires rank-3 arrays:"; 02485 } 02486 // whichCell is valid cell ordinal => we map single set of pts to a single set of pts. (P,D) arrays required 02487 else{ 02488 errmsg1 += " rank-2 arrays required when whichCell is valid cell ordinal"; 02489 validRank = 2; 02490 } 02491 TEST_FOR_EXCEPTION( !requireRankRange(errmsg1, refPoints, validRank,validRank), std::invalid_argument, errmsg1); 02492 TEST_FOR_EXCEPTION( !requireRankMatch(errmsg1, physPoints, refPoints), std::invalid_argument, errmsg1); 02493 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg1, refPoints, physPoints), std::invalid_argument, errmsg1); 02494 } 02495 02496 02497 02498 template<class Scalar> 02499 template<class ArrayRefPoint, class ArrayInitGuess, class ArrayPhysPoint, class ArrayCell> 02500 void CellTools<Scalar>::validateArguments_mapToReferenceFrame(const ArrayRefPoint & refPoints, 02501 const ArrayInitGuess & initGuess, 02502 const ArrayPhysPoint & physPoints, 02503 const ArrayCell & cellWorkset, 02504 const shards::CellTopology & cellTopo, 02505 const int& whichCell) 02506 { 02507 // Call the method that validates arguments with the default initial guess selection 02508 validateArguments_mapToReferenceFrame(refPoints, physPoints, cellWorkset, cellTopo, whichCell); 02509 02510 // Then check initGuess: its rank and dimensions must match those of physPoints. 02511 std::string errmsg = ">>> ERROR (Intrepid::CellTools::validateArguments_mapToReferenceFrame):"; 02512 TEST_FOR_EXCEPTION( !requireDimensionMatch(errmsg, initGuess, physPoints), std::invalid_argument, errmsg); 02513 } 02514 02515 02516 template<class Scalar> 02517 template<class ArrayIncl, class ArrayPoint, class ArrayCell> 02518 void CellTools<Scalar>::validateArguments_checkPointwiseInclusion(ArrayIncl & inCell, 02519 const ArrayPoint & physPoints, 02520 const ArrayCell & cellWorkset, 02521 const int & whichCell, 02522 const shards::CellTopology & cell) 02523 { 02524 // Validate cellWorkset array 02525 TEST_FOR_EXCEPTION( (cellWorkset.rank() != 3), std::invalid_argument, 02526 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): rank = 3 required for cellWorkset array"); 02527 02528 TEST_FOR_EXCEPTION( (cellWorkset.dimension(0) <= 0), std::invalid_argument, 02529 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 0 (number of cells) >= 1 required for cellWorkset array"); 02530 02531 TEST_FOR_EXCEPTION( (cellWorkset.dimension(1) != (int)cell.getSubcellCount(0) ), std::invalid_argument, 02532 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 1 (number of cell nodes) of cellWorkset array does not match cell topology"); 02533 02534 TEST_FOR_EXCEPTION( (cellWorkset.dimension(2) != (int)cell.getDimension() ), std::invalid_argument, 02535 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 2 (spatial dimension) of cellWorkset array does not match cell dimension"); 02536 02537 02538 // Validate whichCell It can be either -1 (default value) or a valid cell ordinal. 02539 TEST_FOR_EXCEPTION( !( ( (0 <= whichCell ) && (whichCell < cellWorkset.dimension(0) ) ) || (whichCell == -1) ), std::invalid_argument, 02540 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): whichCell = -1 or a valid cell ordinal is required."); 02541 02542 02543 // Validate points array: can be rank-2 (P,D) or rank-3 (C,P,D) 02544 // If rank-2: admissible inCell is rank-1 (P); admissible whichCell is valid cell ordinal but not -1. 02545 if(physPoints.rank() == 2) { 02546 02547 TEST_FOR_EXCEPTION( (whichCell == -1), std::invalid_argument, 02548 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): whichCell = a valid cell ordinal is required with rank-2 input array."); 02549 02550 TEST_FOR_EXCEPTION( (physPoints.dimension(0) <= 0), std::invalid_argument, 02551 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 0 (number of points) >= 1 required for physPoints array "); 02552 02553 TEST_FOR_EXCEPTION( (physPoints.dimension(1) != (int)cell.getDimension() ), std::invalid_argument, 02554 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 1 (spatial dimension) of physPoints array does not match cell dimension"); 02555 02556 // Validate inCell 02557 TEST_FOR_EXCEPTION( (inCell.rank() != 1), std::invalid_argument, 02558 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): rank = 1 required for inCell array"); 02559 02560 TEST_FOR_EXCEPTION( (inCell.dimension(0) != physPoints.dimension(0)), std::invalid_argument, 02561 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 0 (number of points) of inCell array must equal dim 0 of physPoints array"); 02562 } 02563 // If rank-3: admissible inCell is rank-2 (C,P); admissible whichCell = -1. 02564 else if (physPoints.rank() == 3){ 02565 02566 TEST_FOR_EXCEPTION( !(whichCell == -1), std::invalid_argument, 02567 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): whichCell = -1 is required with rank-3 input array."); 02568 02569 TEST_FOR_EXCEPTION( (physPoints.dimension(0) != cellWorkset.dimension(0) ), std::invalid_argument, 02570 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 0 (number of cells) of physPoints array must equal dim 0 of cellWorkset array "); 02571 02572 TEST_FOR_EXCEPTION( (physPoints.dimension(1) <= 0), std::invalid_argument, 02573 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 1 (number of points) >= 1 required for physPoints array "); 02574 02575 TEST_FOR_EXCEPTION( (physPoints.dimension(2) != (int)cell.getDimension() ), std::invalid_argument, 02576 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 2 (spatial dimension) of physPoints array does not match cell dimension"); 02577 02578 // Validate inCell 02579 TEST_FOR_EXCEPTION( (inCell.rank() != 2), std::invalid_argument, 02580 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): rank = 2 required for inCell array"); 02581 02582 TEST_FOR_EXCEPTION( (inCell.dimension(0) != physPoints.dimension(0)), std::invalid_argument, 02583 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 0 (number of cells) of inCell array must equal dim 0 of physPoints array"); 02584 02585 TEST_FOR_EXCEPTION( (inCell.dimension(1) != physPoints.dimension(1)), std::invalid_argument, 02586 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): dim 1 (number of points) of inCell array must equal dim 1 of physPoints array"); 02587 } 02588 else { 02589 TEST_FOR_EXCEPTION( !( (physPoints.rank() == 2) && (physPoints.rank() ==3) ), std::invalid_argument, 02590 ">>> ERROR (Intrepid::CellTools::validateArguments_checkPointwiseInclusion): rank = 2 or 3 required for points array"); 02591 } 02592 } 02593 02594 02595 02596 //============================================================================================// 02597 // // 02598 // Debug // 02599 // // 02600 //============================================================================================// 02601 02602 02603 template<class Scalar> 02604 void CellTools<Scalar>::printSubcellVertices(const int subcellDim, 02605 const int subcellOrd, 02606 const shards::CellTopology & parentCell){ 02607 02608 // Get number of vertices for the specified subcell and parent cell dimension 02609 int subcVertexCount = parentCell.getVertexCount(subcellDim, subcellOrd); 02610 int cellDim = parentCell.getDimension(); 02611 02612 // Allocate space for the subcell vertex coordinates 02613 FieldContainer<double> subcellVertices(subcVertexCount, cellDim); 02614 02615 // Retrieve the vertex coordinates 02616 getReferenceSubcellVertices(subcellVertices, 02617 subcellDim, 02618 subcellOrd, 02619 parentCell); 02620 02621 // Print the vertices 02622 std::cout 02623 << " Subcell " << std::setw(2) << subcellOrd 02624 << " is " << parentCell.getName(subcellDim, subcellOrd) << " with vertices = {"; 02625 02626 // Loop over subcell vertices 02627 for(int subcVertOrd = 0; subcVertOrd < subcVertexCount; subcVertOrd++){ 02628 std::cout<< "("; 02629 02630 // Loop over vertex Cartesian coordinates 02631 for(int dim = 0; dim < (int)parentCell.getDimension(); dim++){ 02632 std::cout << subcellVertices(subcVertOrd, dim); 02633 if(dim < (int)parentCell.getDimension()-1 ) { std::cout << ","; } 02634 } 02635 std::cout<< ")"; 02636 if(subcVertOrd < subcVertexCount - 1) { std::cout << ", "; } 02637 } 02638 std::cout << "}\n"; 02639 } 02640 02641 02642 template<class Scalar> 02643 template<class ArrayCell> 02644 void CellTools<Scalar>::printWorksetSubcell(const ArrayCell & cellWorkset, 02645 const shards::CellTopology & parentCell, 02646 const int& pCellOrd, 02647 const int& subcellDim, 02648 const int& subcellOrd, 02649 const int& fieldWidth){ 02650 02651 // Get the ordinals, relative to reference cell, of subcell cellWorkset 02652 int subcNodeCount = parentCell.getNodeCount(subcellDim, subcellOrd); 02653 int pCellDim = parentCell.getDimension(); 02654 std::vector<int> subcNodeOrdinals(subcNodeCount); 02655 02656 for(int i = 0; i < subcNodeCount; i++){ 02657 subcNodeOrdinals[i] = parentCell.getNodeMap(subcellDim, subcellOrd, i); 02658 } 02659 02660 // Loop over parent cells and print subcell cellWorkset 02661 02662 std::cout 02663 << " Subcell " << subcellOrd << " on parent cell " << pCellOrd << " is " 02664 << parentCell.getName(subcellDim, subcellOrd) << " with node(s) \n ({"; 02665 02666 for(int i = 0; i < subcNodeCount; i++){ 02667 02668 // print Cartesian coordinates of the node 02669 for(int dim = 0; dim < pCellDim; dim++){ 02670 std::cout 02671 << std::setw(fieldWidth) << std::right << cellWorkset(pCellOrd, subcNodeOrdinals[i], dim); 02672 if(dim < pCellDim - 1){ std::cout << ","; } 02673 } 02674 std::cout << "}"; 02675 if(i < subcNodeCount - 1){ std::cout <<", {"; } 02676 } 02677 std::cout << ")\n\n"; 02678 } 02679 02680 02681 02682 } // namespace Intrepid 02683 #endif
1.7.4