MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2006 Sandia National Laboratories. Developed at the 00005 University of Wisconsin--Madison under SNL contract number 00006 624796. The U.S. Government and the University of Wisconsin 00007 retain certain rights to this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2006) [email protected] 00024 00025 ***************************************************************** */ 00026 00027 /** \file TetLagrangeShape.cpp 00028 * \brief 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #include "Mesquite.hpp" 00033 #include "TetLagrangeShape.hpp" 00034 #include "MsqError.hpp" 00035 #include <cassert> 00036 00037 namespace MBMesquite 00038 { 00039 00040 EntityTopology TetLagrangeShape::element_topology() const 00041 { 00042 return TETRAHEDRON; 00043 } 00044 00045 int TetLagrangeShape::num_nodes() const 00046 { 00047 return 10; 00048 } 00049 00050 NodeSet TetLagrangeShape::sample_points( NodeSet ns ) const 00051 { 00052 if( ns.have_any_mid_node() ) 00053 { 00054 ns.set_all_corner_nodes( TETRAHEDRON ); 00055 } 00056 else 00057 { 00058 ns.clear(); 00059 ns.set_mid_region_node(); 00060 } 00061 return ns; 00062 } 00063 00064 static void coefficients_at_corner( unsigned corner, double* coeff_out, size_t* indices_out, size_t& num_coeff ) 00065 { 00066 num_coeff = 1; 00067 indices_out[0] = corner; 00068 coeff_out[0] = 1.0; 00069 } 00070 00071 static void coefficients_at_mid_edge( unsigned edge, 00072 NodeSet nodeset, 00073 double* coeff_out, 00074 size_t* indices_out, 00075 size_t& num_coeff ) 00076 { 00077 if( nodeset.mid_edge_node( edge ) ) 00078 { // if mid-edge node is present 00079 num_coeff = 1; 00080 indices_out[0] = 4 + edge; 00081 coeff_out[0] = 1.0; 00082 } 00083 else 00084 { // no mid node on edge 00085 num_coeff = 2; 00086 coeff_out[0] = coeff_out[1] = 0.5; 00087 if( edge < 3 ) 00088 { 00089 indices_out[0] = edge; 00090 indices_out[1] = ( edge + 1 ) % 3; 00091 } 00092 else 00093 { 00094 indices_out[0] = edge - 3; 00095 indices_out[1] = 3; 00096 } 00097 } 00098 } 00099 00100 static void coefficients_at_mid_face( unsigned face, 00101 NodeSet nodeset, 00102 double* coeff_out, 00103 size_t* indices_out, 00104 size_t& num_coeff ) 00105 { 00106 const double one_ninth = 1.0 / 9.0; 00107 const double two_ninth = 2.0 / 9.0; 00108 const double four_ninth = 4.0 / 9.0; 00109 00110 if( face < 3 ) 00111 { 00112 const int next = ( face + 1 ) % 3; 00113 indices_out[0] = face; 00114 indices_out[1] = next; 00115 indices_out[2] = 3; 00116 coeff_out[0] = -one_ninth; 00117 coeff_out[1] = -one_ninth; 00118 coeff_out[2] = -one_ninth; 00119 num_coeff = 3; 00120 if( nodeset.mid_edge_node( face ) ) 00121 { 00122 indices_out[num_coeff] = 4 + face; 00123 coeff_out[num_coeff] = four_ninth; 00124 ++num_coeff; 00125 } 00126 else 00127 { 00128 coeff_out[0] += two_ninth; 00129 coeff_out[1] += two_ninth; 00130 } 00131 if( nodeset.mid_edge_node( 3 + next ) ) 00132 { 00133 indices_out[num_coeff] = 7 + next; 00134 coeff_out[num_coeff] = four_ninth; 00135 ++num_coeff; 00136 } 00137 else 00138 { 00139 coeff_out[1] += two_ninth; 00140 coeff_out[2] += two_ninth; 00141 } 00142 if( nodeset.mid_edge_node( 3 + face ) ) 00143 { 00144 indices_out[num_coeff] = 7 + face; 00145 coeff_out[num_coeff] = four_ninth; 00146 ++num_coeff; 00147 } 00148 else 00149 { 00150 coeff_out[0] += two_ninth; 00151 coeff_out[2] += two_ninth; 00152 } 00153 } 00154 else 00155 { 00156 assert( face == 3 ); 00157 indices_out[0] = 0; 00158 indices_out[1] = 1; 00159 indices_out[2] = 2; 00160 coeff_out[0] = -one_ninth; 00161 coeff_out[1] = -one_ninth; 00162 coeff_out[2] = -one_ninth; 00163 num_coeff = 3; 00164 if( nodeset.mid_edge_node( 0 ) ) 00165 { 00166 indices_out[num_coeff] = 4; 00167 coeff_out[num_coeff] = four_ninth; 00168 ++num_coeff; 00169 } 00170 else 00171 { 00172 coeff_out[0] += two_ninth; 00173 coeff_out[1] += two_ninth; 00174 } 00175 if( nodeset.mid_edge_node( 1 ) ) 00176 { 00177 indices_out[num_coeff] = 5; 00178 coeff_out[num_coeff] = four_ninth; 00179 ++num_coeff; 00180 } 00181 else 00182 { 00183 coeff_out[1] += two_ninth; 00184 coeff_out[2] += two_ninth; 00185 } 00186 if( nodeset.mid_edge_node( 2 ) ) 00187 { 00188 indices_out[num_coeff] = 6; 00189 coeff_out[num_coeff] = four_ninth; 00190 ++num_coeff; 00191 } 00192 else 00193 { 00194 coeff_out[2] += two_ninth; 00195 coeff_out[0] += two_ninth; 00196 } 00197 } 00198 } 00199 00200 static void coefficients_at_mid_elem( NodeSet nodeset, double* coeff_out, size_t* indices_out, size_t& num_coeff ) 00201 { 00202 num_coeff = 4; 00203 indices_out[0] = 0; 00204 indices_out[1] = 1; 00205 indices_out[2] = 2; 00206 indices_out[3] = 3; 00207 coeff_out[0] = -0.125; 00208 coeff_out[1] = -0.125; 00209 coeff_out[2] = -0.125; 00210 coeff_out[3] = -0.125; 00211 if( nodeset.mid_edge_node( 0 ) ) 00212 { 00213 indices_out[num_coeff] = 4; 00214 coeff_out[num_coeff] = 0.25; 00215 ++num_coeff; 00216 } 00217 else 00218 { 00219 coeff_out[0] += 0.125; 00220 coeff_out[1] += 0.125; 00221 } 00222 if( nodeset.mid_edge_node( 1 ) ) 00223 { 00224 indices_out[num_coeff] = 5; 00225 coeff_out[num_coeff] = 0.25; 00226 ++num_coeff; 00227 } 00228 else 00229 { 00230 coeff_out[1] += 0.125; 00231 coeff_out[2] += 0.125; 00232 } 00233 if( nodeset.mid_edge_node( 2 ) ) 00234 { 00235 indices_out[num_coeff] = 6; 00236 coeff_out[num_coeff] = 0.25; 00237 ++num_coeff; 00238 } 00239 else 00240 { 00241 coeff_out[2] += 0.125; 00242 coeff_out[0] += 0.125; 00243 } 00244 if( nodeset.mid_edge_node( 3 ) ) 00245 { 00246 indices_out[num_coeff] = 7; 00247 coeff_out[num_coeff] = 0.25; 00248 ++num_coeff; 00249 } 00250 else 00251 { 00252 coeff_out[0] += 0.125; 00253 coeff_out[3] += 0.125; 00254 } 00255 if( nodeset.mid_edge_node( 4 ) ) 00256 { 00257 indices_out[num_coeff] = 8; 00258 coeff_out[num_coeff] = 0.25; 00259 ++num_coeff; 00260 } 00261 else 00262 { 00263 coeff_out[1] += 0.125; 00264 coeff_out[3] += 0.125; 00265 } 00266 if( nodeset.mid_edge_node( 5 ) ) 00267 { 00268 indices_out[num_coeff] = 9; 00269 coeff_out[num_coeff] = 0.25; 00270 ++num_coeff; 00271 } 00272 else 00273 { 00274 coeff_out[2] += 0.125; 00275 coeff_out[3] += 0.125; 00276 } 00277 } 00278 00279 void TetLagrangeShape::coefficients( Sample loc, 00280 NodeSet nodeset, 00281 double* coeff_out, 00282 size_t* indices_out, 00283 size_t& num_coeff, 00284 MsqError& err ) const 00285 { 00286 if( nodeset.have_any_mid_face_node() | nodeset.have_any_mid_region_node() ) 00287 { 00288 MSQ_SETERR( err ) 00289 ( "TetLagrangeShape does not support mid-face/mid-element nodes", MsqError::UNSUPPORTED_ELEMENT ); 00290 return; 00291 } 00292 00293 switch( loc.dimension ) 00294 { 00295 case 0: 00296 coefficients_at_corner( loc.number, coeff_out, indices_out, num_coeff ); 00297 break; 00298 case 1: 00299 coefficients_at_mid_edge( loc.number, nodeset, coeff_out, indices_out, num_coeff ); 00300 break; 00301 case 2: 00302 coefficients_at_mid_face( loc.number, nodeset, coeff_out, indices_out, num_coeff ); 00303 break; 00304 case 3: 00305 coefficients_at_mid_elem( nodeset, coeff_out, indices_out, num_coeff ); 00306 break; 00307 default: 00308 MSQ_SETERR( err )( "Invalid/unsupported logical dimension", MsqError::INVALID_ARG ); 00309 } 00310 } 00311 00312 static void get_linear_derivatives( size_t* vertices, MsqVector< 3 >* derivs ) 00313 { 00314 vertices[0] = 0; 00315 derivs[0][0] = -1.0; 00316 derivs[0][1] = -1.0; 00317 derivs[0][2] = -1.0; 00318 00319 vertices[1] = 1; 00320 derivs[1][0] = 1.0; 00321 derivs[1][1] = 0.0; 00322 derivs[1][2] = 0.0; 00323 00324 vertices[2] = 2; 00325 derivs[2][0] = 0.0; 00326 derivs[2][1] = 1.0; 00327 derivs[2][2] = 0.0; 00328 00329 vertices[3] = 3; 00330 derivs[3][0] = 0.0; 00331 derivs[3][1] = 0.0; 00332 derivs[3][2] = 1.0; 00333 } 00334 00335 static const unsigned edges[][2] = { { 0, 1 }, { 1, 2 }, { 2, 0 }, { 0, 3 }, { 1, 3 }, { 2, 3 } }; 00336 00337 static void derivatives_at_corner( unsigned corner, 00338 NodeSet nodeset, 00339 size_t* vertices, 00340 MsqVector< 3 >* derivs, 00341 size_t& num_vtx ) 00342 { 00343 // begin with derivatives for linear tetrahedron 00344 num_vtx = 4; 00345 get_linear_derivatives( vertices, derivs ); 00346 00347 // adjust for the presence of mid-edge nodes 00348 switch( corner ) 00349 { 00350 case 0: 00351 if( nodeset.mid_edge_node( 0 ) ) 00352 { 00353 vertices[num_vtx] = 4; 00354 derivs[num_vtx][0] = 4.0; 00355 derivs[num_vtx][1] = 0.0; 00356 derivs[num_vtx][2] = 0.0; 00357 derivs[0][0] -= 2.0; 00358 derivs[1][0] -= 2.0; 00359 ++num_vtx; 00360 } 00361 if( nodeset.mid_edge_node( 2 ) ) 00362 { 00363 vertices[num_vtx] = 6; 00364 derivs[num_vtx][0] = 0.0; 00365 derivs[num_vtx][1] = 4.0; 00366 derivs[num_vtx][2] = 0.0; 00367 derivs[0][1] -= 2.0; 00368 derivs[2][1] -= 2.0; 00369 ++num_vtx; 00370 } 00371 if( nodeset.mid_edge_node( 3 ) ) 00372 { 00373 vertices[num_vtx] = 7; 00374 derivs[num_vtx][0] = 0.0; 00375 derivs[num_vtx][1] = 0.0; 00376 derivs[num_vtx][2] = 4.0; 00377 derivs[0][2] -= 2.0; 00378 derivs[3][2] -= 2.0; 00379 ++num_vtx; 00380 } 00381 break; 00382 00383 case 1: 00384 if( nodeset.mid_edge_node( 0 ) ) 00385 { 00386 vertices[num_vtx] = 4; 00387 derivs[num_vtx][0] = -4.0; 00388 derivs[num_vtx][1] = -4.0; 00389 derivs[num_vtx][2] = -4.0; 00390 derivs[0][0] += 2.0; 00391 derivs[0][1] += 2.0; 00392 derivs[0][2] += 2.0; 00393 derivs[1][0] += 2.0; 00394 derivs[1][1] += 2.0; 00395 derivs[1][2] += 2.0; 00396 ++num_vtx; 00397 } 00398 if( nodeset.mid_edge_node( 1 ) ) 00399 { 00400 vertices[num_vtx] = 5; 00401 derivs[num_vtx][0] = 0.0; 00402 derivs[num_vtx][1] = 4.0; 00403 derivs[num_vtx][2] = 0.0; 00404 derivs[1][1] -= 2.0; 00405 derivs[2][1] -= 2.0; 00406 ++num_vtx; 00407 } 00408 if( nodeset.mid_edge_node( 4 ) ) 00409 { 00410 vertices[num_vtx] = 8; 00411 derivs[num_vtx][0] = 0.0; 00412 derivs[num_vtx][1] = 0.0; 00413 derivs[num_vtx][2] = 4.0; 00414 derivs[1][2] -= 2.0; 00415 derivs[3][2] -= 2.0; 00416 ++num_vtx; 00417 } 00418 break; 00419 00420 case 2: 00421 if( nodeset.mid_edge_node( 1 ) ) 00422 { 00423 vertices[num_vtx] = 5; 00424 derivs[num_vtx][0] = 4.0; 00425 derivs[num_vtx][1] = 0.0; 00426 derivs[num_vtx][2] = 0.0; 00427 derivs[1][0] -= 2.0; 00428 derivs[2][0] -= 2.0; 00429 ++num_vtx; 00430 } 00431 if( nodeset.mid_edge_node( 2 ) ) 00432 { 00433 vertices[num_vtx] = 6; 00434 derivs[num_vtx][0] = -4.0; 00435 derivs[num_vtx][1] = -4.0; 00436 derivs[num_vtx][2] = -4.0; 00437 derivs[0][0] += 2.0; 00438 derivs[0][1] += 2.0; 00439 derivs[0][2] += 2.0; 00440 derivs[2][0] += 2.0; 00441 derivs[2][1] += 2.0; 00442 derivs[2][2] += 2.0; 00443 ++num_vtx; 00444 } 00445 if( nodeset.mid_edge_node( 5 ) ) 00446 { 00447 vertices[num_vtx] = 9; 00448 derivs[num_vtx][0] = 0.0; 00449 derivs[num_vtx][1] = 0.0; 00450 derivs[num_vtx][2] = 4.0; 00451 derivs[2][2] -= 2.0; 00452 derivs[3][2] -= 2.0; 00453 ++num_vtx; 00454 } 00455 break; 00456 00457 case 3: 00458 if( nodeset.mid_edge_node( 3 ) ) 00459 { 00460 vertices[num_vtx] = 7; 00461 derivs[num_vtx][0] = -4.0; 00462 derivs[num_vtx][1] = -4.0; 00463 derivs[num_vtx][2] = -4.0; 00464 derivs[0][0] += 2.0; 00465 derivs[0][1] += 2.0; 00466 derivs[0][2] += 2.0; 00467 derivs[3][0] += 2.0; 00468 derivs[3][1] += 2.0; 00469 derivs[3][2] += 2.0; 00470 ++num_vtx; 00471 } 00472 if( nodeset.mid_edge_node( 4 ) ) 00473 { 00474 vertices[num_vtx] = 8; 00475 derivs[num_vtx][0] = 4.0; 00476 derivs[num_vtx][1] = 0.0; 00477 derivs[num_vtx][2] = 0.0; 00478 derivs[1][0] -= 2.0; 00479 derivs[3][0] -= 2.0; 00480 ++num_vtx; 00481 } 00482 00483 if( nodeset.mid_edge_node( 5 ) ) 00484 { 00485 vertices[num_vtx] = 9; 00486 derivs[num_vtx][0] = 0.0; 00487 derivs[num_vtx][1] = 4.0; 00488 derivs[num_vtx][2] = 0.0; 00489 derivs[2][1] -= 2.0; 00490 derivs[3][1] -= 2.0; 00491 ++num_vtx; 00492 } 00493 break; 00494 } 00495 } 00496 00497 static void derivatives_at_mid_edge( unsigned edge, 00498 NodeSet nodeset, 00499 size_t* vertices, 00500 MsqVector< 3 >* derivs, 00501 size_t& num_vtx ) 00502 { 00503 int sign; 00504 num_vtx = 2; 00505 switch( edge ) 00506 { 00507 case 0: 00508 vertices[0] = 0; 00509 derivs[0][0] = -1.0; 00510 derivs[0][1] = -1.0; 00511 derivs[0][2] = -1.0; 00512 00513 vertices[1] = 1; 00514 derivs[1][0] = 1.0; 00515 derivs[1][1] = 0.0; 00516 derivs[1][2] = 0.0; 00517 00518 if( nodeset.mid_edge_node( 1 ) == nodeset.mid_edge_node( 2 ) ) 00519 { 00520 vertices[num_vtx] = 2; 00521 sign = 1 - 2 * nodeset.mid_edge_node( 1 ); 00522 derivs[num_vtx][0] = 0.0; 00523 derivs[num_vtx][1] = sign; 00524 derivs[num_vtx][2] = 0.0; 00525 ++num_vtx; 00526 } 00527 00528 if( nodeset.mid_edge_node( 3 ) == nodeset.mid_edge_node( 4 ) ) 00529 { 00530 vertices[num_vtx] = 3; 00531 sign = 1 - 2 * nodeset.mid_edge_node( 3 ); 00532 derivs[num_vtx][0] = 0.0; 00533 derivs[num_vtx][1] = 0.0; 00534 derivs[num_vtx][2] = sign; 00535 ++num_vtx; 00536 } 00537 00538 if( nodeset.mid_edge_node( 0 ) ) 00539 { 00540 vertices[num_vtx] = 4; 00541 derivs[num_vtx][0] = 0.0; 00542 derivs[num_vtx][1] = -2.0; 00543 derivs[num_vtx][2] = -2.0; 00544 derivs[0][1] += 1.0; 00545 derivs[0][2] += 1.0; 00546 derivs[1][1] += 1.0; 00547 derivs[1][2] += 1.0; 00548 ++num_vtx; 00549 } 00550 00551 if( nodeset.mid_edge_node( 1 ) ) 00552 { 00553 vertices[num_vtx] = 5; 00554 derivs[num_vtx][0] = 0.0; 00555 derivs[num_vtx][1] = 2.0; 00556 derivs[num_vtx][2] = 0.0; 00557 derivs[1][1] -= 1.0; 00558 ++num_vtx; 00559 } 00560 00561 if( nodeset.mid_edge_node( 2 ) ) 00562 { 00563 vertices[num_vtx] = 6; 00564 derivs[num_vtx][0] = 0.0; 00565 derivs[num_vtx][1] = 2.0; 00566 derivs[num_vtx][2] = 0.0; 00567 derivs[0][1] -= 1.0; 00568 ++num_vtx; 00569 } 00570 00571 if( nodeset.mid_edge_node( 3 ) ) 00572 { 00573 vertices[num_vtx] = 7; 00574 derivs[num_vtx][0] = 0.0; 00575 derivs[num_vtx][1] = 0.0; 00576 derivs[num_vtx][2] = 2.0; 00577 derivs[0][2] -= 1.0; 00578 ++num_vtx; 00579 } 00580 00581 if( nodeset.mid_edge_node( 4 ) ) 00582 { 00583 vertices[num_vtx] = 8; 00584 derivs[num_vtx][0] = 0.0; 00585 derivs[num_vtx][1] = 0.0; 00586 derivs[num_vtx][2] = 2.0; 00587 derivs[1][2] -= 1.0; 00588 ++num_vtx; 00589 } 00590 break; 00591 00592 case 1: 00593 vertices[0] = 1; 00594 derivs[0][0] = 1.0; 00595 derivs[0][1] = 0.0; 00596 derivs[0][2] = 0.0; 00597 00598 vertices[1] = 2; 00599 derivs[1][0] = 0.0; 00600 derivs[1][1] = 1.0; 00601 derivs[1][2] = 0.0; 00602 00603 if( nodeset.mid_edge_node( 0 ) == nodeset.mid_edge_node( 2 ) ) 00604 { 00605 vertices[num_vtx] = 0; 00606 sign = 2 * nodeset.mid_edge_node( 0 ) - 1; 00607 derivs[num_vtx][0] = sign; 00608 derivs[num_vtx][1] = sign; 00609 derivs[num_vtx][2] = sign; 00610 ++num_vtx; 00611 } 00612 00613 if( nodeset.mid_edge_node( 4 ) == nodeset.mid_edge_node( 5 ) ) 00614 { 00615 vertices[num_vtx] = 3; 00616 sign = 1 - 2 * nodeset.mid_edge_node( 4 ); 00617 derivs[num_vtx][0] = 0.0; 00618 derivs[num_vtx][1] = 0.0; 00619 derivs[num_vtx][2] = sign; 00620 ++num_vtx; 00621 } 00622 00623 if( nodeset.mid_edge_node( 0 ) ) 00624 { 00625 vertices[num_vtx] = 4; 00626 derivs[num_vtx][0] = -2.0; 00627 derivs[num_vtx][1] = -2.0; 00628 derivs[num_vtx][2] = -2.0; 00629 ++num_vtx; 00630 derivs[0][0] += 1.0; 00631 derivs[0][1] += 1.0; 00632 derivs[0][2] += 1.0; 00633 } 00634 00635 if( nodeset.mid_edge_node( 1 ) ) 00636 { 00637 vertices[num_vtx] = 5; 00638 derivs[num_vtx][0] = 2.0; 00639 derivs[num_vtx][1] = 2.0; 00640 derivs[num_vtx][2] = 0.0; 00641 ++num_vtx; 00642 derivs[0][0] -= 1.0; 00643 derivs[0][1] -= 1.0; 00644 derivs[1][0] -= 1.0; 00645 derivs[1][1] -= 1.0; 00646 } 00647 00648 if( nodeset.mid_edge_node( 2 ) ) 00649 { 00650 vertices[num_vtx] = 6; 00651 derivs[num_vtx][0] = -2.0; 00652 derivs[num_vtx][1] = -2.0; 00653 derivs[num_vtx][2] = -2.0; 00654 ++num_vtx; 00655 derivs[1][0] += 1.0; 00656 derivs[1][1] += 1.0; 00657 derivs[1][2] += 1.0; 00658 } 00659 00660 if( nodeset.mid_edge_node( 4 ) ) 00661 { 00662 vertices[num_vtx] = 8; 00663 derivs[num_vtx][0] = 0.0; 00664 derivs[num_vtx][1] = 0.0; 00665 derivs[num_vtx][2] = 2.0; 00666 ++num_vtx; 00667 derivs[0][2] -= 1.0; 00668 } 00669 00670 if( nodeset.mid_edge_node( 5 ) ) 00671 { 00672 vertices[num_vtx] = 9; 00673 derivs[num_vtx][0] = 0.0; 00674 derivs[num_vtx][1] = 0.0; 00675 derivs[num_vtx][2] = 2.0; 00676 ++num_vtx; 00677 derivs[1][2] -= 1.0; 00678 } 00679 break; 00680 00681 case 2: 00682 vertices[0] = 0; 00683 derivs[0][0] = -1.0; 00684 derivs[0][1] = -1.0; 00685 derivs[0][2] = -1.0; 00686 00687 vertices[1] = 2; 00688 derivs[1][0] = 0.0; 00689 derivs[1][1] = 1.0; 00690 derivs[1][2] = 0.0; 00691 00692 if( nodeset.mid_edge_node( 0 ) == nodeset.mid_edge_node( 1 ) ) 00693 { 00694 vertices[num_vtx] = 1; 00695 sign = 1 - 2 * nodeset.mid_edge_node( 0 ); 00696 derivs[num_vtx][0] = sign; 00697 derivs[num_vtx][1] = 0.0; 00698 derivs[num_vtx][2] = 0.0; 00699 ++num_vtx; 00700 } 00701 00702 if( nodeset.mid_edge_node( 3 ) == nodeset.mid_edge_node( 5 ) ) 00703 { 00704 vertices[num_vtx] = 3; 00705 sign = 1 - 2 * nodeset.mid_edge_node( 3 ); 00706 derivs[num_vtx][0] = 0.0; 00707 derivs[num_vtx][1] = 0.0; 00708 derivs[num_vtx][2] = sign; 00709 ++num_vtx; 00710 } 00711 00712 if( nodeset.mid_edge_node( 0 ) ) 00713 { 00714 vertices[num_vtx] = 4; 00715 derivs[num_vtx][0] = 2.0; 00716 derivs[num_vtx][1] = 0.0; 00717 derivs[num_vtx][2] = 0.0; 00718 ++num_vtx; 00719 derivs[0][0] -= 1.0; 00720 } 00721 00722 if( nodeset.mid_edge_node( 1 ) ) 00723 { 00724 vertices[num_vtx] = 5; 00725 derivs[num_vtx][0] = 2.0; 00726 derivs[num_vtx][1] = 0.0; 00727 derivs[num_vtx][2] = 0.0; 00728 ++num_vtx; 00729 derivs[1][0] -= 1.0; 00730 } 00731 00732 if( nodeset.mid_edge_node( 2 ) ) 00733 { 00734 vertices[num_vtx] = 6; 00735 derivs[num_vtx][0] = -2.0; 00736 derivs[num_vtx][1] = 0.0; 00737 derivs[num_vtx][2] = -2.0; 00738 ++num_vtx; 00739 derivs[0][0] += 1.0; 00740 derivs[0][2] += 1.0; 00741 derivs[1][0] += 1.0; 00742 derivs[1][2] += 1.0; 00743 } 00744 00745 if( nodeset.mid_edge_node( 3 ) ) 00746 { 00747 vertices[num_vtx] = 7; 00748 derivs[num_vtx][0] = 0.0; 00749 derivs[num_vtx][1] = 0.0; 00750 derivs[num_vtx][2] = 2.0; 00751 ++num_vtx; 00752 derivs[0][2] -= 1.0; 00753 } 00754 00755 if( nodeset.mid_edge_node( 5 ) ) 00756 { 00757 vertices[num_vtx] = 9; 00758 derivs[num_vtx][0] = 0.0; 00759 derivs[num_vtx][1] = 0.0; 00760 derivs[num_vtx][2] = 2.0; 00761 ++num_vtx; 00762 derivs[1][2] -= 1.0; 00763 } 00764 break; 00765 00766 case 3: 00767 vertices[0] = 0; 00768 derivs[0][0] = -1.0; 00769 derivs[0][1] = -1.0; 00770 derivs[0][2] = -1.0; 00771 00772 vertices[1] = 3; 00773 derivs[1][0] = 0.0; 00774 derivs[1][1] = 0.0; 00775 derivs[1][2] = 1.0; 00776 00777 if( nodeset.mid_edge_node( 0 ) == nodeset.mid_edge_node( 4 ) ) 00778 { 00779 vertices[num_vtx] = 1; 00780 sign = 1 - 2 * nodeset.mid_edge_node( 0 ); 00781 derivs[num_vtx][0] = sign; 00782 derivs[num_vtx][1] = 0.0; 00783 derivs[num_vtx][2] = 0.0; 00784 ++num_vtx; 00785 } 00786 00787 if( nodeset.mid_edge_node( 2 ) == nodeset.mid_edge_node( 5 ) ) 00788 { 00789 vertices[num_vtx] = 2; 00790 sign = 1 - 2 * nodeset.mid_edge_node( 2 ); 00791 derivs[num_vtx][0] = 0.0; 00792 derivs[num_vtx][1] = sign; 00793 derivs[num_vtx][2] = 0.0; 00794 ++num_vtx; 00795 } 00796 00797 if( nodeset.mid_edge_node( 0 ) ) 00798 { 00799 vertices[num_vtx] = 4; 00800 derivs[num_vtx][0] = 2.0; 00801 derivs[num_vtx][1] = 0.0; 00802 derivs[num_vtx][2] = 0.0; 00803 ++num_vtx; 00804 derivs[0][0] -= 1.0; 00805 } 00806 00807 if( nodeset.mid_edge_node( 2 ) ) 00808 { 00809 vertices[num_vtx] = 6; 00810 derivs[num_vtx][0] = 0.0; 00811 derivs[num_vtx][1] = 2.0; 00812 derivs[num_vtx][2] = 0.0; 00813 ++num_vtx; 00814 derivs[0][1] -= 1.0; 00815 } 00816 00817 if( nodeset.mid_edge_node( 3 ) ) 00818 { 00819 vertices[num_vtx] = 7; 00820 derivs[num_vtx][0] = -2.0; 00821 derivs[num_vtx][1] = -2.0; 00822 derivs[num_vtx][2] = 0.0; 00823 ++num_vtx; 00824 derivs[0][0] += 1.0; 00825 derivs[0][1] += 1.0; 00826 derivs[1][0] += 1.0; 00827 derivs[1][1] += 1.0; 00828 } 00829 00830 if( nodeset.mid_edge_node( 4 ) ) 00831 { 00832 vertices[num_vtx] = 8; 00833 derivs[num_vtx][0] = 2.0; 00834 derivs[num_vtx][1] = 0.0; 00835 derivs[num_vtx][2] = 0.0; 00836 ++num_vtx; 00837 derivs[1][0] -= 1.0; 00838 } 00839 00840 if( nodeset.mid_edge_node( 5 ) ) 00841 { 00842 vertices[num_vtx] = 9; 00843 derivs[num_vtx][0] = 0.0; 00844 derivs[num_vtx][1] = 2.0; 00845 derivs[num_vtx][2] = 0.0; 00846 ++num_vtx; 00847 derivs[1][1] -= 1.0; 00848 } 00849 break; 00850 00851 case 4: 00852 vertices[0] = 1; 00853 derivs[0][0] = 1.0; 00854 derivs[0][1] = 0.0; 00855 derivs[0][2] = 0.0; 00856 00857 vertices[1] = 3; 00858 derivs[1][0] = 0.0; 00859 derivs[1][1] = 0.0; 00860 derivs[1][2] = 1.0; 00861 00862 if( nodeset.mid_edge_node( 0 ) == nodeset.mid_edge_node( 3 ) ) 00863 { 00864 vertices[num_vtx] = 0; 00865 sign = 2 * nodeset.mid_edge_node( 0 ) - 1; 00866 derivs[num_vtx][0] = sign; 00867 derivs[num_vtx][1] = sign; 00868 derivs[num_vtx][2] = sign; 00869 ++num_vtx; 00870 } 00871 00872 if( nodeset.mid_edge_node( 1 ) == nodeset.mid_edge_node( 5 ) ) 00873 { 00874 vertices[num_vtx] = 2; 00875 sign = 1 - 2 * nodeset.mid_edge_node( 1 ); 00876 derivs[num_vtx][0] = 0.0; 00877 derivs[num_vtx][1] = sign; 00878 derivs[num_vtx][2] = 0.0; 00879 ++num_vtx; 00880 } 00881 00882 if( nodeset.mid_edge_node( 0 ) ) 00883 { 00884 vertices[num_vtx] = 4; 00885 derivs[num_vtx][0] = -2.0; 00886 derivs[num_vtx][1] = -2.0; 00887 derivs[num_vtx][2] = -2.0; 00888 ++num_vtx; 00889 derivs[0][0] += 1.0; 00890 derivs[0][1] += 1.0; 00891 derivs[0][2] += 1.0; 00892 } 00893 00894 if( nodeset.mid_edge_node( 1 ) ) 00895 { 00896 vertices[num_vtx] = 5; 00897 derivs[num_vtx][0] = 0.0; 00898 derivs[num_vtx][1] = 2.0; 00899 derivs[num_vtx][2] = 0.0; 00900 ++num_vtx; 00901 derivs[0][1] -= 1.0; 00902 } 00903 00904 if( nodeset.mid_edge_node( 3 ) ) 00905 { 00906 vertices[num_vtx] = 7; 00907 derivs[num_vtx][0] = -2.0; 00908 derivs[num_vtx][1] = -2.0; 00909 derivs[num_vtx][2] = -2.0; 00910 ++num_vtx; 00911 derivs[1][0] += 1.0; 00912 derivs[1][1] += 1.0; 00913 derivs[1][2] += 1.0; 00914 } 00915 00916 if( nodeset.mid_edge_node( 4 ) ) 00917 { 00918 vertices[num_vtx] = 8; 00919 derivs[num_vtx][0] = 2.0; 00920 derivs[num_vtx][1] = 0.0; 00921 derivs[num_vtx][2] = 2.0; 00922 ++num_vtx; 00923 derivs[0][0] -= 1.0; 00924 derivs[0][2] -= 1.0; 00925 derivs[1][0] -= 1.0; 00926 derivs[1][2] -= 1.0; 00927 } 00928 00929 if( nodeset.mid_edge_node( 5 ) ) 00930 { 00931 vertices[num_vtx] = 9; 00932 derivs[num_vtx][0] = 0.0; 00933 derivs[num_vtx][1] = 2.0; 00934 derivs[num_vtx][2] = 0.0; 00935 ++num_vtx; 00936 derivs[1][1] -= 1.0; 00937 } 00938 break; 00939 00940 case 5: 00941 vertices[0] = 2; 00942 derivs[0][0] = 0.0; 00943 derivs[0][1] = 1.0; 00944 derivs[0][2] = 0.0; 00945 00946 vertices[1] = 3; 00947 derivs[1][0] = 0.0; 00948 derivs[1][1] = 0.0; 00949 derivs[1][2] = 1.0; 00950 00951 if( nodeset.mid_edge_node( 2 ) == nodeset.mid_edge_node( 3 ) ) 00952 { 00953 vertices[num_vtx] = 0; 00954 sign = 2 * nodeset.mid_edge_node( 2 ) - 1; 00955 derivs[num_vtx][0] = sign; 00956 derivs[num_vtx][1] = sign; 00957 derivs[num_vtx][2] = sign; 00958 ++num_vtx; 00959 } 00960 00961 if( nodeset.mid_edge_node( 1 ) == nodeset.mid_edge_node( 4 ) ) 00962 { 00963 vertices[num_vtx] = 1; 00964 sign = 1 - 2 * nodeset.mid_edge_node( 1 ); 00965 derivs[num_vtx][0] = sign; 00966 derivs[num_vtx][1] = 0.0; 00967 derivs[num_vtx][2] = 0.0; 00968 ++num_vtx; 00969 } 00970 00971 if( nodeset.mid_edge_node( 1 ) ) 00972 { 00973 vertices[num_vtx] = 5; 00974 derivs[num_vtx][0] = 2.0; 00975 derivs[num_vtx][1] = 0.0; 00976 derivs[num_vtx][2] = 0.0; 00977 ++num_vtx; 00978 derivs[0][0] -= 1.0; 00979 } 00980 00981 if( nodeset.mid_edge_node( 2 ) ) 00982 { 00983 vertices[num_vtx] = 6; 00984 derivs[num_vtx][0] = -2.0; 00985 derivs[num_vtx][1] = -2.0; 00986 derivs[num_vtx][2] = -2.0; 00987 ++num_vtx; 00988 derivs[0][0] += 1.0; 00989 derivs[0][1] += 1.0; 00990 derivs[0][2] += 1.0; 00991 } 00992 00993 if( nodeset.mid_edge_node( 3 ) ) 00994 { 00995 vertices[num_vtx] = 7; 00996 derivs[num_vtx][0] = -2.0; 00997 derivs[num_vtx][1] = -2.0; 00998 derivs[num_vtx][2] = -2.0; 00999 ++num_vtx; 01000 derivs[1][0] += 1.0; 01001 derivs[1][1] += 1.0; 01002 derivs[1][2] += 1.0; 01003 } 01004 01005 if( nodeset.mid_edge_node( 4 ) ) 01006 { 01007 vertices[num_vtx] = 8; 01008 derivs[num_vtx][0] = 2.0; 01009 derivs[num_vtx][1] = 0.0; 01010 derivs[num_vtx][2] = 0.0; 01011 ++num_vtx; 01012 derivs[1][0] -= 1.0; 01013 } 01014 01015 if( nodeset.mid_edge_node( 5 ) ) 01016 { 01017 vertices[num_vtx] = 9; 01018 derivs[num_vtx][0] = 0.0; 01019 derivs[num_vtx][1] = 2.0; 01020 derivs[num_vtx][2] = 2.0; 01021 ++num_vtx; 01022 derivs[0][1] -= 1.0; 01023 derivs[0][2] -= 1.0; 01024 derivs[1][1] -= 1.0; 01025 derivs[1][2] -= 1.0; 01026 } 01027 break; 01028 } 01029 } 01030 01031 // Derivatives of coefficients for mid-edge nodes 01032 01033 const double ft = 4.0 / 3.0; 01034 01035 const double ho_dr[6][4] = { { 0., -ft, ft, 0. }, { 0., ft, ft, ft }, { 0., -ft, -ft, -ft }, 01036 { -ft, -ft, -ft, 0. }, { ft, ft, ft, 0. }, { 0., 0., 0., 0. } }; 01037 01038 const double ho_ds[6][4] = { { -ft, -ft, 0., -ft }, { ft, ft, 0., ft }, { ft, -ft, 0., 0. }, 01039 { -ft, -ft, -ft, 0. }, { 0., 0., 0., 0. }, { ft, ft, ft, 0. } }; 01040 01041 const double ho_dt[6][4] = { { -ft, -ft, 0., -ft }, { 0., 0., 0., 0. }, { 0., -ft, -ft, -ft }, 01042 { 0., -ft, 0., ft }, { ft, ft, 0., ft }, { 0., ft, ft, ft } }; 01043 01044 static void derivatives_at_mid_face( unsigned face, 01045 NodeSet nodeset, 01046 size_t* vertices, 01047 MsqVector< 3 >* derivs, 01048 size_t& num_vtx ) 01049 { 01050 // begin with derivatives for linear tetrahedron 01051 num_vtx = 4; 01052 get_linear_derivatives( vertices, derivs ); 01053 01054 for( unsigned i = 0; i < 6; ++i ) 01055 if( nodeset.mid_edge_node( i ) ) 01056 { 01057 vertices[num_vtx] = i + 4; 01058 derivs[num_vtx][0] = ho_dr[i][face]; 01059 derivs[num_vtx][1] = ho_ds[i][face]; 01060 derivs[num_vtx][2] = ho_dt[i][face]; 01061 ++num_vtx; 01062 int j = edges[i][0]; 01063 derivs[j][0] -= 0.5 * ho_dr[i][face]; 01064 derivs[j][1] -= 0.5 * ho_ds[i][face]; 01065 derivs[j][2] -= 0.5 * ho_dt[i][face]; 01066 j = edges[i][1]; 01067 derivs[j][0] -= 0.5 * ho_dr[i][face]; 01068 derivs[j][1] -= 0.5 * ho_ds[i][face]; 01069 derivs[j][2] -= 0.5 * ho_dt[i][face]; 01070 } 01071 } 01072 01073 // position (0->r, 1->s, 2->t) of zero-valued term for mid-edge node 01074 static const int zeros[6] = { 0, 2, 1, 2, 1, 0 }; 01075 // value of mid-edge terms 01076 static const int signs[6] = { -1, 1, -1, -1, 1, 1 }; 01077 01078 static void derivatives_at_mid_elem( NodeSet nodeset, size_t* vertices, MsqVector< 3 >* derivs, size_t& num_vtx ) 01079 { 01080 01081 bool corners[4] = { false, false, false, false }; 01082 double corner_vals[4][3] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; 01083 01084 num_vtx = 0; 01085 for( unsigned i = 4; i < 10; ++i ) 01086 { 01087 int sign = signs[i - 4]; 01088 int zero = zeros[i - 4]; 01089 01090 if( nodeset.mid_edge_node( i - 4 ) ) 01091 { 01092 vertices[num_vtx] = i; 01093 derivs[num_vtx][0] = (double)sign; 01094 derivs[num_vtx][1] = (double)sign; 01095 derivs[num_vtx][2] = (double)sign; 01096 derivs[num_vtx][zero] = 0.0; 01097 ++num_vtx; 01098 } 01099 else 01100 { 01101 for( unsigned j = 0; j < 2; ++j ) 01102 { 01103 int corner = edges[i - 4][j]; 01104 int v1 = ( zero + 1 ) % 3; 01105 int v2 = ( zero + 2 ) % 3; 01106 corners[corner] = true; 01107 corner_vals[corner][v1] += 0.5 * sign; 01108 corner_vals[corner][v2] += 0.5 * sign; 01109 } 01110 } 01111 } 01112 01113 for( unsigned i = 0; i < 4; ++i ) 01114 if( corners[i] ) 01115 { 01116 vertices[num_vtx] = i; 01117 derivs[num_vtx][0] = corner_vals[i][0]; 01118 derivs[num_vtx][1] = corner_vals[i][1]; 01119 derivs[num_vtx][2] = corner_vals[i][2]; 01120 ++num_vtx; 01121 } 01122 } 01123 01124 void TetLagrangeShape::derivatives( Sample loc, 01125 NodeSet nodeset, 01126 size_t* vertex_indices_out, 01127 MsqVector< 3 >* d_coeff_d_xi_out, 01128 size_t& num_vtx, 01129 MsqError& err ) const 01130 { 01131 if( !nodeset.have_any_mid_node() ) 01132 { 01133 num_vtx = 4; 01134 get_linear_derivatives( vertex_indices_out, d_coeff_d_xi_out ); 01135 return; 01136 } 01137 01138 if( nodeset.have_any_mid_face_node() | nodeset.have_any_mid_region_node() ) 01139 { 01140 MSQ_SETERR( err ) 01141 ( "TetLagrangeShape does not support mid-face/mid-element nodes", MsqError::UNSUPPORTED_ELEMENT ); 01142 return; 01143 } 01144 01145 switch( loc.dimension ) 01146 { 01147 case 0: 01148 derivatives_at_corner( loc.number, nodeset, vertex_indices_out, d_coeff_d_xi_out, num_vtx ); 01149 break; 01150 case 1: 01151 derivatives_at_mid_edge( loc.number, nodeset, vertex_indices_out, d_coeff_d_xi_out, num_vtx ); 01152 break; 01153 case 2: 01154 derivatives_at_mid_face( loc.number, nodeset, vertex_indices_out, d_coeff_d_xi_out, num_vtx ); 01155 break; 01156 case 3: 01157 derivatives_at_mid_elem( nodeset, vertex_indices_out, d_coeff_d_xi_out, num_vtx ); 01158 break; 01159 default: 01160 MSQ_SETERR( err )( "Invalid/unsupported logical dimension", MsqError::INVALID_ARG ); 01161 } 01162 } 01163 01164 void TetLagrangeShape::ideal( Sample, MsqMatrix< 3, 3 >& J, MsqError& ) const 01165 { 01166 const double a = 1.122462048309373; // 6th root of 2 01167 const double b = 1.7320508075688772; // sqrt(3) 01168 const double c = 1.5874010519681994; // 2 to the 2/3 01169 J( 0, 0 ) = a; 01170 J( 0, 1 ) = 0.5 * a; 01171 J( 0, 2 ) = 0.5 * a; 01172 J( 1, 0 ) = 0.0; 01173 J( 1, 1 ) = 0.5 * a * b; 01174 J( 1, 2 ) = 0.5 * a / b; 01175 J( 2, 0 ) = 0.0; 01176 J( 2, 1 ) = 0.0; 01177 J( 2, 2 ) = c / b; 01178 } 01179 01180 } // namespace MBMesquite