Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /*========================================================================= 00002 00003 Module: $RCSfile: V_HexMetric.cpp,v $ 00004 00005 Copyright (c) 2006 Sandia Corporation. 00006 All rights reserved. 00007 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00008 00009 This software is distributed WITHOUT ANY WARRANTY; without even 00010 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00011 PURPOSE. See the above copyright notice for more information. 00012 00013 =========================================================================*/ 00014 00015 /* 00016 * 00017 * HexMetric.cpp contains quality calculations for hexes 00018 * 00019 * This file is part of VERDICT 00020 * 00021 */ 00022 00023 #define VERDICT_EXPORTS 00024 00025 #include "moab/verdict.h" 00026 #include "VerdictVector.hpp" 00027 #include "V_GaussIntegration.hpp" 00028 #include "verdict_defines.hpp" 00029 #include <memory.h> 00030 00031 #if defined( __BORLANDC__ ) 00032 #pragma warn - 8004 /* "assigned a value that is never used" */ 00033 #endif 00034 00035 //! the average volume of a hex 00036 double verdict_hex_size = 0; 00037 00038 //! weights based on the average size of a hex 00039 int v_hex_get_weight( VerdictVector& v1, VerdictVector& v2, VerdictVector& v3 ) 00040 { 00041 00042 if( verdict_hex_size == 0 ) return 0; 00043 00044 v1.set( 1, 0, 0 ); 00045 v2.set( 0, 1, 0 ); 00046 v3.set( 0, 0, 1 ); 00047 00048 double scale = pow( verdict_hex_size / ( v1 % ( v2 * v3 ) ), 0.33333333333 ); 00049 v1 *= scale; 00050 v2 *= scale; 00051 v3 *= scale; 00052 00053 return 1; 00054 } 00055 00056 //! returns the average volume of a hex 00057 C_FUNC_DEF void v_set_hex_size( double size ) 00058 { 00059 verdict_hex_size = size; 00060 } 00061 00062 #define make_hex_nodes( coord, pos ) \ 00063 for( int mhcii = 0; mhcii < 8; mhcii++ ) \ 00064 { \ 00065 ( pos )[mhcii].set( ( coord )[mhcii][0], ( coord )[mhcii][1], ( coord )[mhcii][2] ); \ 00066 } 00067 00068 #define make_edge_length_squares( edges, lengths ) \ 00069 { \ 00070 for( int melii = 0; melii < 12; melii++ ) \ 00071 ( lengths )[melii] = ( edges )[melii].length_squared(); \ 00072 } 00073 00074 //! make VerdictVectors from coordinates 00075 void make_hex_edges( double coordinates[][3], VerdictVector edges[12] ) 00076 { 00077 edges[0].set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], 00078 coordinates[1][2] - coordinates[0][2] ); 00079 edges[1].set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], 00080 coordinates[2][2] - coordinates[1][2] ); 00081 edges[2].set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1], 00082 coordinates[3][2] - coordinates[2][2] ); 00083 edges[3].set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1], 00084 coordinates[0][2] - coordinates[3][2] ); 00085 edges[4].set( coordinates[5][0] - coordinates[4][0], coordinates[5][1] - coordinates[4][1], 00086 coordinates[5][2] - coordinates[4][2] ); 00087 edges[5].set( coordinates[6][0] - coordinates[5][0], coordinates[6][1] - coordinates[5][1], 00088 coordinates[6][2] - coordinates[5][2] ); 00089 edges[6].set( coordinates[7][0] - coordinates[6][0], coordinates[7][1] - coordinates[6][1], 00090 coordinates[7][2] - coordinates[6][2] ); 00091 edges[7].set( coordinates[4][0] - coordinates[7][0], coordinates[4][1] - coordinates[7][1], 00092 coordinates[4][2] - coordinates[7][2] ); 00093 edges[8].set( coordinates[4][0] - coordinates[0][0], coordinates[4][1] - coordinates[0][1], 00094 coordinates[4][2] - coordinates[0][2] ); 00095 edges[9].set( coordinates[5][0] - coordinates[1][0], coordinates[5][1] - coordinates[1][1], 00096 coordinates[5][2] - coordinates[1][2] ); 00097 edges[10].set( coordinates[6][0] - coordinates[2][0], coordinates[6][1] - coordinates[2][1], 00098 coordinates[6][2] - coordinates[2][2] ); 00099 edges[11].set( coordinates[7][0] - coordinates[3][0], coordinates[7][1] - coordinates[3][1], 00100 coordinates[7][2] - coordinates[3][2] ); 00101 } 00102 00103 /*! 00104 localizes hex coordinates 00105 */ 00106 void localize_hex_coordinates( double coordinates[][3], VerdictVector position[8] ) 00107 { 00108 00109 int ii; 00110 for( ii = 0; ii < 8; ii++ ) 00111 { 00112 position[ii].set( coordinates[ii][0], coordinates[ii][1], coordinates[ii][2] ); 00113 } 00114 00115 // ... Make centroid of element the center of coordinate system 00116 VerdictVector point_1256 = position[1]; 00117 point_1256 += position[2]; 00118 point_1256 += position[5]; 00119 point_1256 += position[6]; 00120 00121 VerdictVector point_0374 = position[0]; 00122 point_0374 += position[3]; 00123 point_0374 += position[7]; 00124 point_0374 += position[4]; 00125 00126 VerdictVector centroid = point_1256; 00127 centroid += point_0374; 00128 centroid /= 8.0; 00129 00130 int i; 00131 for( i = 0; i < 8; i++ ) 00132 position[i] -= centroid; 00133 00134 // ... Rotate element such that center of side 1-2 and 0-3 define X axis 00135 double DX = point_1256.x() - point_0374.x(); 00136 double DY = point_1256.y() - point_0374.y(); 00137 double DZ = point_1256.z() - point_0374.z(); 00138 00139 double AMAGX = sqrt( DX * DX + DZ * DZ ); 00140 double AMAGY = sqrt( DX * DX + DY * DY + DZ * DZ ); 00141 double FMAGX = AMAGX == 0.0 ? 1.0 : 0.0; 00142 double FMAGY = AMAGY == 0.0 ? 1.0 : 0.0; 00143 00144 double CZ = DX / ( AMAGX + FMAGX ) + FMAGX; 00145 double SZ = DZ / ( AMAGX + FMAGX ); 00146 double CY = AMAGX / ( AMAGY + FMAGY ) + FMAGY; 00147 double SY = DY / ( AMAGY + FMAGY ); 00148 00149 double temp; 00150 00151 for( i = 0; i < 8; i++ ) 00152 { 00153 temp = CY * CZ * position[i].x() + CY * SZ * position[i].z() + SY * position[i].y(); 00154 position[i].y( -SY * CZ * position[i].x() - SY * SZ * position[i].z() + CY * position[i].y() ); 00155 position[i].z( -SZ * position[i].x() + CZ * position[i].z() ); 00156 position[i].x( temp ); 00157 } 00158 00159 // ... Now, rotate about Y 00160 VerdictVector delta = -position[0]; 00161 delta -= position[1]; 00162 delta += position[2]; 00163 delta += position[3]; 00164 delta -= position[4]; 00165 delta -= position[5]; 00166 delta += position[6]; 00167 delta += position[7]; 00168 00169 DY = delta.y(); 00170 DZ = delta.z(); 00171 00172 AMAGY = sqrt( DY * DY + DZ * DZ ); 00173 FMAGY = AMAGY == 0.0 ? 1.0 : 0.0; 00174 00175 double CX = DY / ( AMAGY + FMAGY ) + FMAGY; 00176 double SX = DZ / ( AMAGY + FMAGY ); 00177 00178 for( i = 0; i < 8; i++ ) 00179 { 00180 temp = CX * position[i].y() + SX * position[i].z(); 00181 position[i].z( -SX * position[i].y() + CX * position[i].z() ); 00182 position[i].y( temp ); 00183 } 00184 } 00185 00186 double safe_ratio3( const double numerator, const double denominator, const double max_ratio ) 00187 { 00188 // this filter is essential for good running time in practice 00189 double return_value; 00190 00191 const double filter_n = max_ratio * 1.0e-16; 00192 const double filter_d = 1.0e-16; 00193 if( fabs( numerator ) <= filter_n && fabs( denominator ) >= filter_d ) 00194 { 00195 return_value = numerator / denominator; 00196 } 00197 else 00198 { 00199 return_value = fabs( numerator ) / max_ratio >= fabs( denominator ) 00200 ? ( ( numerator >= 0.0 && denominator >= 0.0 ) || ( numerator < 0.0 && denominator < 0.0 ) 00201 ? max_ratio 00202 : -max_ratio ) 00203 : numerator / denominator; 00204 } 00205 00206 return return_value; 00207 } 00208 00209 double safe_ratio( const double numerator, const double denominator ) 00210 { 00211 00212 double return_value; 00213 const double filter_n = VERDICT_DBL_MAX; 00214 const double filter_d = VERDICT_DBL_MIN; 00215 if( fabs( numerator ) <= filter_n && fabs( denominator ) >= filter_d ) 00216 { 00217 return_value = numerator / denominator; 00218 } 00219 else 00220 { 00221 return_value = VERDICT_DBL_MAX; 00222 } 00223 00224 return return_value; 00225 } 00226 00227 double condition_comp( const VerdictVector& xxi, const VerdictVector& xet, const VerdictVector& xze ) 00228 { 00229 double det = xxi % ( xet * xze ); 00230 00231 if( det <= VERDICT_DBL_MIN ) 00232 { 00233 return VERDICT_DBL_MAX; 00234 } 00235 00236 double term1 = xxi % xxi + xet % xet + xze % xze; 00237 double term2 = 00238 ( ( xxi * xet ) % ( xxi * xet ) ) + ( ( xet * xze ) % ( xet * xze ) ) + ( ( xze * xxi ) % ( xze * xxi ) ); 00239 00240 return sqrt( term1 * term2 ) / det; 00241 } 00242 00243 double oddy_comp( const VerdictVector& xxi, const VerdictVector& xet, const VerdictVector& xze ) 00244 { 00245 static const double third = 1.0 / 3.0; 00246 00247 double g11, g12, g13, g22, g23, g33, rt_g; 00248 00249 g11 = xxi % xxi; 00250 g12 = xxi % xet; 00251 g13 = xxi % xze; 00252 g22 = xet % xet; 00253 g23 = xet % xze; 00254 g33 = xze % xze; 00255 rt_g = xxi % ( xet * xze ); 00256 00257 double oddy_metric; 00258 if( rt_g > VERDICT_DBL_MIN ) 00259 { 00260 double norm_G_squared = g11 * g11 + 2.0 * g12 * g12 + 2.0 * g13 * g13 + g22 * g22 + 2.0 * g23 * g23 + g33 * g33; 00261 00262 double norm_J_squared = g11 + g22 + g33; 00263 00264 oddy_metric = ( norm_G_squared - third * norm_J_squared * norm_J_squared ) / pow( rt_g, 4. * third ); 00265 } 00266 00267 else 00268 oddy_metric = VERDICT_DBL_MAX; 00269 00270 return oddy_metric; 00271 } 00272 00273 //! calcualates edge lengths of a hex 00274 double hex_edge_length( int max_min, double coordinates[][3] ) 00275 { 00276 double temp[3], edge[12]; 00277 int i; 00278 00279 // lengths^2 of edges 00280 for( i = 0; i < 3; i++ ) 00281 { 00282 temp[i] = coordinates[1][i] - coordinates[0][i]; 00283 temp[i] = temp[i] * temp[i]; 00284 } 00285 edge[0] = sqrt( temp[0] + temp[1] + temp[2] ); 00286 00287 for( i = 0; i < 3; i++ ) 00288 { 00289 temp[i] = coordinates[2][i] - coordinates[1][i]; 00290 temp[i] = temp[i] * temp[i]; 00291 } 00292 edge[1] = sqrt( temp[0] + temp[1] + temp[2] ); 00293 00294 for( i = 0; i < 3; i++ ) 00295 { 00296 temp[i] = coordinates[3][i] - coordinates[2][i]; 00297 temp[i] = temp[i] * temp[i]; 00298 } 00299 edge[2] = sqrt( temp[0] + temp[1] + temp[2] ); 00300 00301 for( i = 0; i < 3; i++ ) 00302 { 00303 temp[i] = coordinates[0][i] - coordinates[3][i]; 00304 temp[i] = temp[i] * temp[i]; 00305 } 00306 edge[3] = sqrt( temp[0] + temp[1] + temp[2] ); 00307 00308 for( i = 0; i < 3; i++ ) 00309 { 00310 temp[i] = coordinates[5][i] - coordinates[4][i]; 00311 temp[i] = temp[i] * temp[i]; 00312 } 00313 edge[4] = sqrt( temp[0] + temp[1] + temp[2] ); 00314 00315 for( i = 0; i < 3; i++ ) 00316 { 00317 temp[i] = coordinates[6][i] - coordinates[5][i]; 00318 temp[i] = temp[i] * temp[i]; 00319 } 00320 edge[5] = sqrt( temp[0] + temp[1] + temp[2] ); 00321 00322 for( i = 0; i < 3; i++ ) 00323 { 00324 temp[i] = coordinates[7][i] - coordinates[6][i]; 00325 temp[i] = temp[i] * temp[i]; 00326 } 00327 edge[6] = sqrt( temp[0] + temp[1] + temp[2] ); 00328 00329 for( i = 0; i < 3; i++ ) 00330 { 00331 temp[i] = coordinates[4][i] - coordinates[7][i]; 00332 temp[i] = temp[i] * temp[i]; 00333 } 00334 edge[7] = sqrt( temp[0] + temp[1] + temp[2] ); 00335 00336 for( i = 0; i < 3; i++ ) 00337 { 00338 temp[i] = coordinates[4][i] - coordinates[0][i]; 00339 temp[i] = temp[i] * temp[i]; 00340 } 00341 edge[8] = sqrt( temp[0] + temp[1] + temp[2] ); 00342 00343 for( i = 0; i < 3; i++ ) 00344 { 00345 temp[i] = coordinates[5][i] - coordinates[1][i]; 00346 temp[i] = temp[i] * temp[i]; 00347 } 00348 edge[9] = sqrt( temp[0] + temp[1] + temp[2] ); 00349 00350 for( i = 0; i < 3; i++ ) 00351 { 00352 temp[i] = coordinates[6][i] - coordinates[2][i]; 00353 temp[i] = temp[i] * temp[i]; 00354 } 00355 edge[10] = sqrt( temp[0] + temp[1] + temp[2] ); 00356 00357 for( i = 0; i < 3; i++ ) 00358 { 00359 temp[i] = coordinates[7][i] - coordinates[3][i]; 00360 temp[i] = temp[i] * temp[i]; 00361 } 00362 edge[11] = sqrt( temp[0] + temp[1] + temp[2] ); 00363 00364 double _edge = edge[0]; 00365 00366 if( max_min == 0 ) 00367 { 00368 for( i = 1; i < 12; i++ ) 00369 _edge = VERDICT_MIN( _edge, edge[i] ); 00370 return (double)_edge; 00371 } 00372 else 00373 { 00374 for( i = 1; i < 12; i++ ) 00375 _edge = VERDICT_MAX( _edge, edge[i] ); 00376 return (double)_edge; 00377 } 00378 } 00379 00380 double diag_length( int max_min, double coordinates[][3] ) 00381 { 00382 double temp[3], diag[4]; 00383 int i; 00384 00385 // lengths^2 f diag nals 00386 for( i = 0; i < 3; i++ ) 00387 { 00388 temp[i] = coordinates[6][i] - coordinates[0][i]; 00389 temp[i] = temp[i] * temp[i]; 00390 } 00391 diag[0] = sqrt( temp[0] + temp[1] + temp[2] ); 00392 00393 for( i = 0; i < 3; i++ ) 00394 { 00395 temp[i] = coordinates[4][i] - coordinates[2][i]; 00396 temp[i] = temp[i] * temp[i]; 00397 } 00398 diag[1] = sqrt( temp[0] + temp[1] + temp[2] ); 00399 00400 for( i = 0; i < 3; i++ ) 00401 { 00402 temp[i] = coordinates[7][i] - coordinates[1][i]; 00403 temp[i] = temp[i] * temp[i]; 00404 } 00405 diag[2] = sqrt( temp[0] + temp[1] + temp[2] ); 00406 00407 for( i = 0; i < 3; i++ ) 00408 { 00409 temp[i] = coordinates[5][i] - coordinates[3][i]; 00410 temp[i] = temp[i] * temp[i]; 00411 } 00412 diag[3] = sqrt( temp[0] + temp[1] + temp[2] ); 00413 00414 double diagonal = diag[0]; 00415 if( max_min == 0 ) // Return min diagonal 00416 { 00417 for( i = 1; i < 4; i++ ) 00418 diagonal = VERDICT_MIN( diagonal, diag[i] ); 00419 return (double)diagonal; 00420 } 00421 else // Return max diagonal 00422 { 00423 for( i = 1; i < 4; i++ ) 00424 diagonal = VERDICT_MAX( diagonal, diag[i] ); 00425 return (double)diagonal; 00426 } 00427 } 00428 00429 //! calculates efg values 00430 VerdictVector calc_hex_efg( int efg_index, VerdictVector coordinates[8] ) 00431 { 00432 00433 VerdictVector efg; 00434 00435 switch( efg_index ) 00436 { 00437 00438 case 1: 00439 efg = coordinates[1]; 00440 efg += coordinates[2]; 00441 efg += coordinates[5]; 00442 efg += coordinates[6]; 00443 efg -= coordinates[0]; 00444 efg -= coordinates[3]; 00445 efg -= coordinates[4]; 00446 efg -= coordinates[7]; 00447 break; 00448 00449 case 2: 00450 efg = coordinates[2]; 00451 efg += coordinates[3]; 00452 efg += coordinates[6]; 00453 efg += coordinates[7]; 00454 efg -= coordinates[0]; 00455 efg -= coordinates[1]; 00456 efg -= coordinates[4]; 00457 efg -= coordinates[5]; 00458 break; 00459 00460 case 3: 00461 efg = coordinates[4]; 00462 efg += coordinates[5]; 00463 efg += coordinates[6]; 00464 efg += coordinates[7]; 00465 efg -= coordinates[0]; 00466 efg -= coordinates[1]; 00467 efg -= coordinates[2]; 00468 efg -= coordinates[3]; 00469 break; 00470 00471 case 12: 00472 efg = coordinates[0]; 00473 efg += coordinates[2]; 00474 efg += coordinates[4]; 00475 efg += coordinates[6]; 00476 efg -= coordinates[1]; 00477 efg -= coordinates[3]; 00478 efg -= coordinates[5]; 00479 efg -= coordinates[7]; 00480 break; 00481 00482 case 13: 00483 efg = coordinates[0]; 00484 efg += coordinates[3]; 00485 efg += coordinates[5]; 00486 efg += coordinates[6]; 00487 efg -= coordinates[1]; 00488 efg -= coordinates[2]; 00489 efg -= coordinates[4]; 00490 efg -= coordinates[7]; 00491 break; 00492 00493 case 23: 00494 efg = coordinates[0]; 00495 efg += coordinates[1]; 00496 efg += coordinates[6]; 00497 efg += coordinates[7]; 00498 efg -= coordinates[2]; 00499 efg -= coordinates[3]; 00500 efg -= coordinates[4]; 00501 efg -= coordinates[5]; 00502 break; 00503 00504 case 123: 00505 efg = coordinates[0]; 00506 efg += coordinates[2]; 00507 efg += coordinates[5]; 00508 efg += coordinates[7]; 00509 efg -= coordinates[1]; 00510 efg -= coordinates[5]; 00511 efg -= coordinates[6]; 00512 efg -= coordinates[2]; 00513 break; 00514 00515 default: 00516 efg.set( 0, 0, 0 ); 00517 } 00518 00519 return efg; 00520 } 00521 00522 /*! 00523 the edge ratio of a hex 00524 00525 NB (P. Pebay 01/23/07): 00526 Hmax / Hmin where Hmax and Hmin are respectively the maximum and the 00527 minimum edge lengths 00528 */ 00529 C_FUNC_DEF double v_hex_edge_ratio( int /*num_nodes*/, double coordinates[][3] ) 00530 { 00531 00532 VerdictVector edges[12]; 00533 make_hex_edges( coordinates, edges ); 00534 00535 double a2 = edges[0].length_squared(); 00536 double b2 = edges[1].length_squared(); 00537 double c2 = edges[2].length_squared(); 00538 double d2 = edges[3].length_squared(); 00539 double e2 = edges[4].length_squared(); 00540 double f2 = edges[5].length_squared(); 00541 double g2 = edges[6].length_squared(); 00542 double h2 = edges[7].length_squared(); 00543 double i2 = edges[8].length_squared(); 00544 double j2 = edges[9].length_squared(); 00545 double k2 = edges[10].length_squared(); 00546 double l2 = edges[11].length_squared(); 00547 00548 double mab, mcd, mef, Mab, Mcd, Mef; 00549 double mgh, mij, mkl, Mgh, Mij, Mkl; 00550 00551 if( a2 < b2 ) 00552 { 00553 mab = a2; 00554 Mab = b2; 00555 } 00556 else // b2 <= a2 00557 { 00558 mab = b2; 00559 Mab = a2; 00560 } 00561 if( c2 < d2 ) 00562 { 00563 mcd = c2; 00564 Mcd = d2; 00565 } 00566 else // d2 <= c2 00567 { 00568 mcd = d2; 00569 Mcd = c2; 00570 } 00571 if( e2 < f2 ) 00572 { 00573 mef = e2; 00574 Mef = f2; 00575 } 00576 else // f2 <= e2 00577 { 00578 mef = f2; 00579 Mef = e2; 00580 } 00581 if( g2 < h2 ) 00582 { 00583 mgh = g2; 00584 Mgh = h2; 00585 } 00586 else // h2 <= g2 00587 { 00588 mgh = h2; 00589 Mgh = g2; 00590 } 00591 if( i2 < j2 ) 00592 { 00593 mij = i2; 00594 Mij = j2; 00595 } 00596 else // j2 <= i2 00597 { 00598 mij = j2; 00599 Mij = i2; 00600 } 00601 if( k2 < l2 ) 00602 { 00603 mkl = k2; 00604 Mkl = l2; 00605 } 00606 else // l2 <= k2 00607 { 00608 mkl = l2; 00609 Mkl = k2; 00610 } 00611 00612 double m2; 00613 m2 = mab < mcd ? mab : mcd; 00614 m2 = m2 < mef ? m2 : mef; 00615 m2 = m2 < mgh ? m2 : mgh; 00616 m2 = m2 < mij ? m2 : mij; 00617 m2 = m2 < mkl ? m2 : mkl; 00618 00619 if( m2 < VERDICT_DBL_MIN ) return (double)VERDICT_DBL_MAX; 00620 00621 double M2; 00622 M2 = Mab > Mcd ? Mab : Mcd; 00623 M2 = M2 > Mef ? M2 : Mef; 00624 M2 = M2 > Mgh ? M2 : Mgh; 00625 M2 = M2 > Mij ? M2 : Mij; 00626 M2 = M2 > Mkl ? M2 : Mkl; 00627 m2 = m2 < mef ? m2 : mef; 00628 00629 M2 = Mab > Mcd ? Mab : Mcd; 00630 M2 = M2 > Mef ? M2 : Mef; 00631 00632 double edge_ratio = sqrt( M2 / m2 ); 00633 00634 if( edge_ratio > 0 ) return (double)VERDICT_MIN( edge_ratio, VERDICT_DBL_MAX ); 00635 return (double)VERDICT_MAX( edge_ratio, -VERDICT_DBL_MAX ); 00636 } 00637 00638 /*! 00639 max edge ratio of a hex 00640 00641 Maximum edge length ratio at hex center 00642 */ 00643 C_FUNC_DEF double v_hex_max_edge_ratio( int /*num_nodes*/, double coordinates[][3] ) 00644 { 00645 double aspect; 00646 VerdictVector node_pos[8]; 00647 make_hex_nodes( coordinates, node_pos ); 00648 00649 double aspect_12, aspect_13, aspect_23; 00650 00651 VerdictVector efg1 = calc_hex_efg( 1, node_pos ); 00652 VerdictVector efg2 = calc_hex_efg( 2, node_pos ); 00653 VerdictVector efg3 = calc_hex_efg( 3, node_pos ); 00654 00655 double mag_efg1 = efg1.length(); 00656 double mag_efg2 = efg2.length(); 00657 double mag_efg3 = efg3.length(); 00658 00659 aspect_12 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg2 ), VERDICT_MIN( mag_efg1, mag_efg2 ) ); 00660 aspect_13 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg3 ), VERDICT_MIN( mag_efg1, mag_efg3 ) ); 00661 aspect_23 = safe_ratio( VERDICT_MAX( mag_efg2, mag_efg3 ), VERDICT_MIN( mag_efg2, mag_efg3 ) ); 00662 00663 aspect = VERDICT_MAX( aspect_12, VERDICT_MAX( aspect_13, aspect_23 ) ); 00664 00665 if( aspect > 0 ) return (double)VERDICT_MIN( aspect, VERDICT_DBL_MAX ); 00666 return (double)VERDICT_MAX( aspect, -VERDICT_DBL_MAX ); 00667 } 00668 00669 /*! 00670 skew of a hex 00671 00672 Maximum ||cosA|| where A is the angle between edges at hex center. 00673 */ 00674 C_FUNC_DEF double v_hex_skew( int /*num_nodes*/, double coordinates[][3] ) 00675 { 00676 VerdictVector node_pos[8]; 00677 make_hex_nodes( coordinates, node_pos ); 00678 00679 double skew_1, skew_2, skew_3; 00680 00681 VerdictVector efg1 = calc_hex_efg( 1, node_pos ); 00682 VerdictVector efg2 = calc_hex_efg( 2, node_pos ); 00683 VerdictVector efg3 = calc_hex_efg( 3, node_pos ); 00684 00685 if( efg1.normalize() <= VERDICT_DBL_MIN ) return VERDICT_DBL_MAX; 00686 if( efg2.normalize() <= VERDICT_DBL_MIN ) return VERDICT_DBL_MAX; 00687 if( efg3.normalize() <= VERDICT_DBL_MIN ) return VERDICT_DBL_MAX; 00688 00689 skew_1 = fabs( efg1 % efg2 ); 00690 skew_2 = fabs( efg1 % efg3 ); 00691 skew_3 = fabs( efg2 % efg3 ); 00692 00693 double skew = ( VERDICT_MAX( skew_1, VERDICT_MAX( skew_2, skew_3 ) ) ); 00694 00695 if( skew > 0 ) return (double)VERDICT_MIN( skew, VERDICT_DBL_MAX ); 00696 return (double)VERDICT_MAX( skew, -VERDICT_DBL_MAX ); 00697 } 00698 00699 /*! 00700 taper of a hex 00701 00702 Maximum ratio of lengths derived from opposite edges. 00703 */ 00704 C_FUNC_DEF double v_hex_taper( int /*num_nodes*/, double coordinates[][3] ) 00705 { 00706 VerdictVector node_pos[8]; 00707 make_hex_nodes( coordinates, node_pos ); 00708 00709 VerdictVector efg1 = calc_hex_efg( 1, node_pos ); 00710 VerdictVector efg2 = calc_hex_efg( 2, node_pos ); 00711 VerdictVector efg3 = calc_hex_efg( 3, node_pos ); 00712 00713 VerdictVector efg12 = calc_hex_efg( 12, node_pos ); 00714 VerdictVector efg13 = calc_hex_efg( 13, node_pos ); 00715 VerdictVector efg23 = calc_hex_efg( 23, node_pos ); 00716 00717 double taper_1 = fabs( safe_ratio( efg12.length(), VERDICT_MIN( efg1.length(), efg2.length() ) ) ); 00718 double taper_2 = fabs( safe_ratio( efg13.length(), VERDICT_MIN( efg1.length(), efg3.length() ) ) ); 00719 double taper_3 = fabs( safe_ratio( efg23.length(), VERDICT_MIN( efg2.length(), efg3.length() ) ) ); 00720 00721 double taper = (double)VERDICT_MAX( taper_1, VERDICT_MAX( taper_2, taper_3 ) ); 00722 00723 if( taper > 0 ) return (double)VERDICT_MIN( taper, VERDICT_DBL_MAX ); 00724 return (double)VERDICT_MAX( taper, -VERDICT_DBL_MAX ); 00725 } 00726 00727 /*! 00728 volume of a hex 00729 00730 Jacobian at hex center 00731 */ 00732 C_FUNC_DEF double v_hex_volume( int /*num_nodes*/, double coordinates[][3] ) 00733 { 00734 VerdictVector node_pos[8]; 00735 make_hex_nodes( coordinates, node_pos ); 00736 00737 VerdictVector efg1 = calc_hex_efg( 1, node_pos ); 00738 VerdictVector efg2 = calc_hex_efg( 2, node_pos ); 00739 VerdictVector efg3 = calc_hex_efg( 3, node_pos ); 00740 00741 double volume; 00742 volume = (double)( efg1 % ( efg2 * efg3 ) ) / 64.0; 00743 00744 if( volume > 0 ) return (double)VERDICT_MIN( volume, VERDICT_DBL_MAX ); 00745 return (double)VERDICT_MAX( volume, -VERDICT_DBL_MAX ); 00746 } 00747 00748 /*! 00749 stretch of a hex 00750 00751 sqrt(3) * minimum edge length / maximum diagonal length 00752 */ 00753 C_FUNC_DEF double v_hex_stretch( int /*num_nodes*/, double coordinates[][3] ) 00754 { 00755 static const double HEX_STRETCH_SCALE_FACTOR = sqrt( 3.0 ); 00756 00757 double min_edge = hex_edge_length( 0, coordinates ); 00758 double max_diag = diag_length( 1, coordinates ); 00759 00760 double stretch = HEX_STRETCH_SCALE_FACTOR * safe_ratio( min_edge, max_diag ); 00761 00762 if( stretch > 0 ) return (double)VERDICT_MIN( stretch, VERDICT_DBL_MAX ); 00763 return (double)VERDICT_MAX( stretch, -VERDICT_DBL_MAX ); 00764 } 00765 00766 /*! 00767 diagonal ratio of a hex 00768 00769 Minimum diagonal length / maximum diagonal length 00770 */ 00771 C_FUNC_DEF double v_hex_diagonal( int /*num_nodes*/, double coordinates[][3] ) 00772 { 00773 00774 double min_diag = diag_length( 0, coordinates ); 00775 double max_diag = diag_length( 1, coordinates ); 00776 00777 double diagonal = safe_ratio( min_diag, max_diag ); 00778 00779 if( diagonal > 0 ) return (double)VERDICT_MIN( diagonal, VERDICT_DBL_MAX ); 00780 return (double)VERDICT_MAX( diagonal, -VERDICT_DBL_MAX ); 00781 } 00782 00783 #define SQR( x ) ( ( x ) * ( x ) ) 00784 00785 /*! 00786 dimension of a hex 00787 00788 Pronto-specific characteristic length for stable time step calculation. 00789 Char_length = Volume / 2 grad Volume 00790 */ 00791 C_FUNC_DEF double v_hex_dimension( int /*num_nodes*/, double coordinates[][3] ) 00792 { 00793 00794 double gradop[9][4]; 00795 00796 double x1 = coordinates[0][0]; 00797 double x2 = coordinates[1][0]; 00798 double x3 = coordinates[2][0]; 00799 double x4 = coordinates[3][0]; 00800 double x5 = coordinates[4][0]; 00801 double x6 = coordinates[5][0]; 00802 double x7 = coordinates[6][0]; 00803 double x8 = coordinates[7][0]; 00804 00805 double y1 = coordinates[0][1]; 00806 double y2 = coordinates[1][1]; 00807 double y3 = coordinates[2][1]; 00808 double y4 = coordinates[3][1]; 00809 double y5 = coordinates[4][1]; 00810 double y6 = coordinates[5][1]; 00811 double y7 = coordinates[6][1]; 00812 double y8 = coordinates[7][1]; 00813 00814 double z1 = coordinates[0][2]; 00815 double z2 = coordinates[1][2]; 00816 double z3 = coordinates[2][2]; 00817 double z4 = coordinates[3][2]; 00818 double z5 = coordinates[4][2]; 00819 double z6 = coordinates[5][2]; 00820 double z7 = coordinates[6][2]; 00821 double z8 = coordinates[7][2]; 00822 00823 double z24 = z2 - z4; 00824 double z52 = z5 - z2; 00825 double z45 = z4 - z5; 00826 gradop[1][1] = 00827 ( y2 * ( z6 - z3 - z45 ) + y3 * z24 + y4 * ( z3 - z8 - z52 ) + y5 * ( z8 - z6 - z24 ) + y6 * z52 + y8 * z45 ) / 00828 12.0; 00829 00830 double z31 = z3 - z1; 00831 double z63 = z6 - z3; 00832 double z16 = z1 - z6; 00833 gradop[2][1] = 00834 ( y3 * ( z7 - z4 - z16 ) + y4 * z31 + y1 * ( z4 - z5 - z63 ) + y6 * ( z5 - z7 - z31 ) + y7 * z63 + y5 * z16 ) / 00835 12.0; 00836 00837 double z42 = z4 - z2; 00838 double z74 = z7 - z4; 00839 double z27 = z2 - z7; 00840 gradop[3][1] = 00841 ( y4 * ( z8 - z1 - z27 ) + y1 * z42 + y2 * ( z1 - z6 - z74 ) + y7 * ( z6 - z8 - z42 ) + y8 * z74 + y6 * z27 ) / 00842 12.0; 00843 00844 double z13 = z1 - z3; 00845 double z81 = z8 - z1; 00846 double z38 = z3 - z8; 00847 gradop[4][1] = 00848 ( y1 * ( z5 - z2 - z38 ) + y2 * z13 + y3 * ( z2 - z7 - z81 ) + y8 * ( z7 - z5 - z13 ) + y5 * z81 + y7 * z38 ) / 00849 12.0; 00850 00851 double z86 = z8 - z6; 00852 double z18 = z1 - z8; 00853 double z61 = z6 - z1; 00854 gradop[5][1] = 00855 ( y8 * ( z4 - z7 - z61 ) + y7 * z86 + y6 * ( z7 - z2 - z18 ) + y1 * ( z2 - z4 - z86 ) + y4 * z18 + y2 * z61 ) / 00856 12.0; 00857 00858 double z57 = z5 - z7; 00859 double z25 = z2 - z5; 00860 double z72 = z7 - z2; 00861 gradop[6][1] = 00862 ( y5 * ( z1 - z8 - z72 ) + y8 * z57 + y7 * ( z8 - z3 - z25 ) + y2 * ( z3 - z1 - z57 ) + y1 * z25 + y3 * z72 ) / 00863 12.0; 00864 00865 double z68 = z6 - z8; 00866 double z36 = z3 - z6; 00867 double z83 = z8 - z3; 00868 gradop[7][1] = 00869 ( y6 * ( z2 - z5 - z83 ) + y5 * z68 + y8 * ( z5 - z4 - z36 ) + y3 * ( z4 - z2 - z68 ) + y2 * z36 + y4 * z83 ) / 00870 12.0; 00871 00872 double z75 = z7 - z5; 00873 double z47 = z4 - z7; 00874 double z54 = z5 - z4; 00875 gradop[8][1] = 00876 ( y7 * ( z3 - z6 - z54 ) + y6 * z75 + y5 * ( z6 - z1 - z47 ) + y4 * ( z1 - z3 - z75 ) + y3 * z47 + y1 * z54 ) / 00877 12.0; 00878 00879 double x24 = x2 - x4; 00880 double x52 = x5 - x2; 00881 double x45 = x4 - x5; 00882 gradop[1][2] = 00883 ( z2 * ( x6 - x3 - x45 ) + z3 * x24 + z4 * ( x3 - x8 - x52 ) + z5 * ( x8 - x6 - x24 ) + z6 * x52 + z8 * x45 ) / 00884 12.0; 00885 00886 double x31 = x3 - x1; 00887 double x63 = x6 - x3; 00888 double x16 = x1 - x6; 00889 gradop[2][2] = 00890 ( z3 * ( x7 - x4 - x16 ) + z4 * x31 + z1 * ( x4 - x5 - x63 ) + z6 * ( x5 - x7 - x31 ) + z7 * x63 + z5 * x16 ) / 00891 12.0; 00892 00893 double x42 = x4 - x2; 00894 double x74 = x7 - x4; 00895 double x27 = x2 - x7; 00896 gradop[3][2] = 00897 ( z4 * ( x8 - x1 - x27 ) + z1 * x42 + z2 * ( x1 - x6 - x74 ) + z7 * ( x6 - x8 - x42 ) + z8 * x74 + z6 * x27 ) / 00898 12.0; 00899 00900 double x13 = x1 - x3; 00901 double x81 = x8 - x1; 00902 double x38 = x3 - x8; 00903 gradop[4][2] = 00904 ( z1 * ( x5 - x2 - x38 ) + z2 * x13 + z3 * ( x2 - x7 - x81 ) + z8 * ( x7 - x5 - x13 ) + z5 * x81 + z7 * x38 ) / 00905 12.0; 00906 00907 double x86 = x8 - x6; 00908 double x18 = x1 - x8; 00909 double x61 = x6 - x1; 00910 gradop[5][2] = 00911 ( z8 * ( x4 - x7 - x61 ) + z7 * x86 + z6 * ( x7 - x2 - x18 ) + z1 * ( x2 - x4 - x86 ) + z4 * x18 + z2 * x61 ) / 00912 12.0; 00913 00914 double x57 = x5 - x7; 00915 double x25 = x2 - x5; 00916 double x72 = x7 - x2; 00917 gradop[6][2] = 00918 ( z5 * ( x1 - x8 - x72 ) + z8 * x57 + z7 * ( x8 - x3 - x25 ) + z2 * ( x3 - x1 - x57 ) + z1 * x25 + z3 * x72 ) / 00919 12.0; 00920 00921 double x68 = x6 - x8; 00922 double x36 = x3 - x6; 00923 double x83 = x8 - x3; 00924 gradop[7][2] = 00925 ( z6 * ( x2 - x5 - x83 ) + z5 * x68 + z8 * ( x5 - x4 - x36 ) + z3 * ( x4 - x2 - x68 ) + z2 * x36 + z4 * x83 ) / 00926 12.0; 00927 00928 double x75 = x7 - x5; 00929 double x47 = x4 - x7; 00930 double x54 = x5 - x4; 00931 gradop[8][2] = 00932 ( z7 * ( x3 - x6 - x54 ) + z6 * x75 + z5 * ( x6 - x1 - x47 ) + z4 * ( x1 - x3 - x75 ) + z3 * x47 + z1 * x54 ) / 00933 12.0; 00934 00935 double y24 = y2 - y4; 00936 double y52 = y5 - y2; 00937 double y45 = y4 - y5; 00938 gradop[1][3] = 00939 ( x2 * ( y6 - y3 - y45 ) + x3 * y24 + x4 * ( y3 - y8 - y52 ) + x5 * ( y8 - y6 - y24 ) + x6 * y52 + x8 * y45 ) / 00940 12.0; 00941 00942 double y31 = y3 - y1; 00943 double y63 = y6 - y3; 00944 double y16 = y1 - y6; 00945 gradop[2][3] = 00946 ( x3 * ( y7 - y4 - y16 ) + x4 * y31 + x1 * ( y4 - y5 - y63 ) + x6 * ( y5 - y7 - y31 ) + x7 * y63 + x5 * y16 ) / 00947 12.0; 00948 00949 double y42 = y4 - y2; 00950 double y74 = y7 - y4; 00951 double y27 = y2 - y7; 00952 gradop[3][3] = 00953 ( x4 * ( y8 - y1 - y27 ) + x1 * y42 + x2 * ( y1 - y6 - y74 ) + x7 * ( y6 - y8 - y42 ) + x8 * y74 + x6 * y27 ) / 00954 12.0; 00955 00956 double y13 = y1 - y3; 00957 double y81 = y8 - y1; 00958 double y38 = y3 - y8; 00959 gradop[4][3] = 00960 ( x1 * ( y5 - y2 - y38 ) + x2 * y13 + x3 * ( y2 - y7 - y81 ) + x8 * ( y7 - y5 - y13 ) + x5 * y81 + x7 * y38 ) / 00961 12.0; 00962 00963 double y86 = y8 - y6; 00964 double y18 = y1 - y8; 00965 double y61 = y6 - y1; 00966 gradop[5][3] = 00967 ( x8 * ( y4 - y7 - y61 ) + x7 * y86 + x6 * ( y7 - y2 - y18 ) + x1 * ( y2 - y4 - y86 ) + x4 * y18 + x2 * y61 ) / 00968 12.0; 00969 00970 double y57 = y5 - y7; 00971 double y25 = y2 - y5; 00972 double y72 = y7 - y2; 00973 gradop[6][3] = 00974 ( x5 * ( y1 - y8 - y72 ) + x8 * y57 + x7 * ( y8 - y3 - y25 ) + x2 * ( y3 - y1 - y57 ) + x1 * y25 + x3 * y72 ) / 00975 12.0; 00976 00977 double y68 = y6 - y8; 00978 double y36 = y3 - y6; 00979 double y83 = y8 - y3; 00980 gradop[7][3] = 00981 ( x6 * ( y2 - y5 - y83 ) + x5 * y68 + x8 * ( y5 - y4 - y36 ) + x3 * ( y4 - y2 - y68 ) + x2 * y36 + x4 * y83 ) / 00982 12.0; 00983 00984 double y75 = y7 - y5; 00985 double y47 = y4 - y7; 00986 double y54 = y5 - y4; 00987 gradop[8][3] = 00988 ( x7 * ( y3 - y6 - y54 ) + x6 * y75 + x5 * ( y6 - y1 - y47 ) + x4 * ( y1 - y3 - y75 ) + x3 * y47 + x1 * y54 ) / 00989 12.0; 00990 00991 // calculate element volume and characteristic element aspect ratio 00992 // (used in time step and hourglass control) - 00993 00994 double volume = coordinates[0][0] * gradop[1][1] + coordinates[1][0] * gradop[2][1] + 00995 coordinates[2][0] * gradop[3][1] + coordinates[3][0] * gradop[4][1] + 00996 coordinates[4][0] * gradop[5][1] + coordinates[5][0] * gradop[6][1] + 00997 coordinates[6][0] * gradop[7][1] + coordinates[7][0] * gradop[8][1]; 00998 double aspect = 00999 .5 * SQR( volume ) / 01000 ( SQR( gradop[1][1] ) + SQR( gradop[2][1] ) + SQR( gradop[3][1] ) + SQR( gradop[4][1] ) + SQR( gradop[5][1] ) + 01001 SQR( gradop[6][1] ) + SQR( gradop[7][1] ) + SQR( gradop[8][1] ) + SQR( gradop[1][2] ) + SQR( gradop[2][2] ) + 01002 SQR( gradop[3][2] ) + SQR( gradop[4][2] ) + SQR( gradop[5][2] ) + SQR( gradop[6][2] ) + SQR( gradop[7][2] ) + 01003 SQR( gradop[8][2] ) + SQR( gradop[1][3] ) + SQR( gradop[2][3] ) + SQR( gradop[3][3] ) + SQR( gradop[4][3] ) + 01004 SQR( gradop[5][3] ) + SQR( gradop[6][3] ) + SQR( gradop[7][3] ) + SQR( gradop[8][3] ) ); 01005 01006 return (double)sqrt( aspect ); 01007 } 01008 01009 /*! 01010 oddy of a hex 01011 01012 General distortion measure based on left Cauchy-Green Tensor 01013 */ 01014 C_FUNC_DEF double v_hex_oddy( int /*num_nodes*/, double coordinates[][3] ) 01015 { 01016 01017 double oddy = 0.0, current_oddy; 01018 VerdictVector xxi, xet, xze; 01019 01020 VerdictVector node_pos[8]; 01021 make_hex_nodes( coordinates, node_pos ); 01022 01023 xxi = calc_hex_efg( 1, node_pos ); 01024 xet = calc_hex_efg( 2, node_pos ); 01025 xze = calc_hex_efg( 3, node_pos ); 01026 01027 current_oddy = oddy_comp( xxi, xet, xze ); 01028 if( current_oddy > oddy ) 01029 { 01030 oddy = current_oddy; 01031 } 01032 01033 xxi.set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1], 01034 coordinates[1][2] - coordinates[0][2] ); 01035 01036 xet.set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1], 01037 coordinates[3][2] - coordinates[0][2] ); 01038 01039 xze.set( coordinates[4][0] - coordinates[0][0], coordinates[4][1] - coordinates[0][1], 01040 coordinates[4][2] - coordinates[0][2] ); 01041 01042 current_oddy = oddy_comp( xxi, xet, xze ); 01043 if( current_oddy > oddy ) 01044 { 01045 oddy = current_oddy; 01046 } 01047 01048 xxi.set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1], 01049 coordinates[2][2] - coordinates[1][2] ); 01050 01051 xet.set( coordinates[0][0] - coordinates[1][0], coordinates[0][1] - coordinates[1][1], 01052 coordinates[0][2] - coordinates[1][2] ); 01053 01054 xze.set( coordinates[5][0] - coordinates[1][0], coordinates[5][1] - coordinates[1][1], 01055 coordinates[5][2] - coordinates[1][2] ); 01056 01057 current_oddy = oddy_comp( xxi, xet, xze ); 01058 if( current_oddy > oddy ) 01059 { 01060 oddy = current_oddy; 01061 } 01062 01063 xxi.set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1], 01064 coordinates[3][2] - coordinates[2][2] ); 01065 01066 xet.set( coordinates[1][0] - coordinates[2][0], coordinates[1][1] - coordinates[2][1], 01067 coordinates[1][2] - coordinates[2][2] ); 01068 01069 xze.set( coordinates[6][0] - coordinates[2][0], coordinates[6][1] - coordinates[2][1], 01070 coordinates[6][2] - coordinates[2][2] ); 01071 01072 current_oddy = oddy_comp( xxi, xet, xze ); 01073 if( current_oddy > oddy ) 01074 { 01075 oddy = current_oddy; 01076 } 01077 01078 xxi.set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1], 01079 coordinates[0][2] - coordinates[3][2] ); 01080 01081 xet.set( coordinates[2][0] - coordinates[3][0], coordinates[2][1] - coordinates[3][1], 01082 coordinates[2][2] - coordinates[3][2] ); 01083 01084 xze.set( coordinates[7][0] - coordinates[3][0], coordinates[7][1] - coordinates[3][1], 01085 coordinates[7][2] - coordinates[3][2] ); 01086 01087 current_oddy = oddy_comp( xxi, xet, xze ); 01088 if( current_oddy > oddy ) 01089 { 01090 oddy = current_oddy; 01091 } 01092 01093 xxi.set( coordinates[7][0] - coordinates[4][0], coordinates[7][1] - coordinates[4][1], 01094 coordinates[7][2] - coordinates[4][2] ); 01095 01096 xet.set( coordinates[5][0] - coordinates[4][0], coordinates[5][1] - coordinates[4][1], 01097 coordinates[5][2] - coordinates[4][2] ); 01098 01099 xze.set( coordinates[0][0] - coordinates[4][0], coordinates[0][1] - coordinates[4][1], 01100 coordinates[0][2] - coordinates[4][2] ); 01101 01102 current_oddy = oddy_comp( xxi, xet, xze ); 01103 if( current_oddy > oddy ) 01104 { 01105 oddy = current_oddy; 01106 } 01107 01108 xxi.set( coordinates[4][0] - coordinates[5][0], coordinates[4][1] - coordinates[5][1], 01109 coordinates[4][2] - coordinates[5][2] ); 01110 01111 xet.set( coordinates[6][0] - coordinates[5][0], coordinates[6][1] - coordinates[5][1], 01112 coordinates[6][2] - coordinates[5][2] ); 01113 01114 xze.set( coordinates[1][0] - coordinates[5][0], coordinates[1][1] - coordinates[5][1], 01115 coordinates[1][2] - coordinates[5][2] ); 01116 01117 current_oddy = oddy_comp( xxi, xet, xze ); 01118 if( current_oddy > oddy ) 01119 { 01120 oddy = current_oddy; 01121 } 01122 01123 xxi.set( coordinates[5][0] - coordinates[6][0], coordinates[5][1] - coordinates[6][1], 01124 coordinates[5][2] - coordinates[6][2] ); 01125 01126 xet.set( coordinates[7][0] - coordinates[6][0], coordinates[7][1] - coordinates[6][1], 01127 coordinates[7][2] - coordinates[6][2] ); 01128 01129 xze.set( coordinates[2][0] - coordinates[6][0], coordinates[2][1] - coordinates[6][1], 01130 coordinates[2][2] - coordinates[6][2] ); 01131 01132 current_oddy = oddy_comp( xxi, xet, xze ); 01133 if( current_oddy > oddy ) 01134 { 01135 oddy = current_oddy; 01136 } 01137 01138 xxi.set( coordinates[6][0] - coordinates[7][0], coordinates[6][1] - coordinates[7][1], 01139 coordinates[6][2] - coordinates[7][2] ); 01140 01141 xet.set( coordinates[4][0] - coordinates[7][0], coordinates[4][1] - coordinates[7][1], 01142 coordinates[4][2] - coordinates[7][2] ); 01143 01144 xze.set( coordinates[3][0] - coordinates[7][0], coordinates[3][1] - coordinates[7][1], 01145 coordinates[3][2] - coordinates[7][2] ); 01146 01147 current_oddy = oddy_comp( xxi, xet, xze ); 01148 if( current_oddy > oddy ) 01149 { 01150 oddy = current_oddy; 01151 } 01152 01153 if( oddy > 0 ) return (double)VERDICT_MIN( oddy, VERDICT_DBL_MAX ); 01154 return (double)VERDICT_MAX( oddy, -VERDICT_DBL_MAX ); 01155 } 01156 01157 /*! 01158 the average Frobenius aspect of a hex 01159 01160 NB (P. Pebay 01/20/07): 01161 this metric is calculated by averaging the 8 Frobenius aspects at 01162 each corner of the hex, when the reference corner is right isosceles. 01163 */ 01164 C_FUNC_DEF double v_hex_med_aspect_frobenius( int /*num_nodes*/, double coordinates[][3] ) 01165 { 01166 01167 VerdictVector node_pos[8]; 01168 make_hex_nodes( coordinates, node_pos ); 01169 01170 double med_aspect_frobenius = 0.; 01171 VerdictVector xxi, xet, xze; 01172 01173 // J(0,0,0): 01174 01175 xxi = node_pos[1] - node_pos[0]; 01176 xet = node_pos[3] - node_pos[0]; 01177 xze = node_pos[4] - node_pos[0]; 01178 01179 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01180 // J(1,0,0): 01181 01182 xxi = node_pos[2] - node_pos[1]; 01183 xet = node_pos[0] - node_pos[1]; 01184 xze = node_pos[5] - node_pos[1]; 01185 01186 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01187 // J(1,1,0): 01188 01189 xxi = node_pos[3] - node_pos[2]; 01190 xet = node_pos[1] - node_pos[2]; 01191 xze = node_pos[6] - node_pos[2]; 01192 01193 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01194 // J(0,1,0): 01195 01196 xxi = node_pos[0] - node_pos[3]; 01197 xet = node_pos[2] - node_pos[3]; 01198 xze = node_pos[7] - node_pos[3]; 01199 01200 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01201 // J(0,0,1): 01202 01203 xxi = node_pos[7] - node_pos[4]; 01204 xet = node_pos[5] - node_pos[4]; 01205 xze = node_pos[0] - node_pos[4]; 01206 01207 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01208 // J(1,0,1): 01209 01210 xxi = node_pos[4] - node_pos[5]; 01211 xet = node_pos[6] - node_pos[5]; 01212 xze = node_pos[1] - node_pos[5]; 01213 01214 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01215 // J(1,1,1): 01216 01217 xxi = node_pos[5] - node_pos[6]; 01218 xet = node_pos[7] - node_pos[6]; 01219 xze = node_pos[2] - node_pos[6]; 01220 01221 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01222 // J(1,1,1): 01223 01224 xxi = node_pos[6] - node_pos[7]; 01225 xet = node_pos[4] - node_pos[7]; 01226 xze = node_pos[3] - node_pos[7]; 01227 01228 med_aspect_frobenius += condition_comp( xxi, xet, xze ); 01229 med_aspect_frobenius /= 24.; 01230 01231 if( med_aspect_frobenius > 0 ) return (double)VERDICT_MIN( med_aspect_frobenius, VERDICT_DBL_MAX ); 01232 return (double)VERDICT_MAX( med_aspect_frobenius, -VERDICT_DBL_MAX ); 01233 } 01234 01235 /*! 01236 maximum Frobenius condition number of a hex 01237 01238 Maximum Frobenius condition number of the Jacobian matrix at 8 corners 01239 NB (P. Pebay 01/25/07): 01240 this metric is calculated by taking the maximum of the 8 Frobenius aspects at 01241 each corner of the hex, when the reference corner is right isosceles. 01242 */ 01243 C_FUNC_DEF double v_hex_max_aspect_frobenius( int /*num_nodes*/, double coordinates[][3] ) 01244 { 01245 01246 VerdictVector node_pos[8]; 01247 make_hex_nodes( coordinates, node_pos ); 01248 01249 double condition = 0.0, current_condition; 01250 VerdictVector xxi, xet, xze; 01251 01252 xxi = calc_hex_efg( 1, node_pos ); 01253 xet = calc_hex_efg( 2, node_pos ); 01254 xze = calc_hex_efg( 3, node_pos ); 01255 01256 current_condition = condition_comp( xxi, xet, xze ); 01257 if( current_condition > condition ) 01258 { 01259 condition = current_condition; 01260 } 01261 01262 // J(0,0,0): 01263 01264 xxi = node_pos[1] - node_pos[0]; 01265 xet = node_pos[3] - node_pos[0]; 01266 xze = node_pos[4] - node_pos[0]; 01267 01268 current_condition = condition_comp( xxi, xet, xze ); 01269 if( current_condition > condition ) 01270 { 01271 condition = current_condition; 01272 } 01273 01274 // J(1,0,0): 01275 01276 xxi = node_pos[2] - node_pos[1]; 01277 xet = node_pos[0] - node_pos[1]; 01278 xze = node_pos[5] - node_pos[1]; 01279 01280 current_condition = condition_comp( xxi, xet, xze ); 01281 if( current_condition > condition ) 01282 { 01283 condition = current_condition; 01284 } 01285 01286 // J(1,1,0): 01287 01288 xxi = node_pos[3] - node_pos[2]; 01289 xet = node_pos[1] - node_pos[2]; 01290 xze = node_pos[6] - node_pos[2]; 01291 01292 current_condition = condition_comp( xxi, xet, xze ); 01293 if( current_condition > condition ) 01294 { 01295 condition = current_condition; 01296 } 01297 01298 // J(0,1,0): 01299 01300 xxi = node_pos[0] - node_pos[3]; 01301 xet = node_pos[2] - node_pos[3]; 01302 xze = node_pos[7] - node_pos[3]; 01303 01304 current_condition = condition_comp( xxi, xet, xze ); 01305 if( current_condition > condition ) 01306 { 01307 condition = current_condition; 01308 } 01309 01310 // J(0,0,1): 01311 01312 xxi = node_pos[7] - node_pos[4]; 01313 xet = node_pos[5] - node_pos[4]; 01314 xze = node_pos[0] - node_pos[4]; 01315 01316 current_condition = condition_comp( xxi, xet, xze ); 01317 if( current_condition > condition ) 01318 { 01319 condition = current_condition; 01320 } 01321 01322 // J(1,0,1): 01323 01324 xxi = node_pos[4] - node_pos[5]; 01325 xet = node_pos[6] - node_pos[5]; 01326 xze = node_pos[1] - node_pos[5]; 01327 01328 current_condition = condition_comp( xxi, xet, xze ); 01329 if( current_condition > condition ) 01330 { 01331 condition = current_condition; 01332 } 01333 01334 // J(1,1,1): 01335 01336 xxi = node_pos[5] - node_pos[6]; 01337 xet = node_pos[7] - node_pos[6]; 01338 xze = node_pos[2] - node_pos[6]; 01339 01340 current_condition = condition_comp( xxi, xet, xze ); 01341 if( current_condition > condition ) 01342 { 01343 condition = current_condition; 01344 } 01345 01346 // J(1,1,1): 01347 01348 xxi = node_pos[6] - node_pos[7]; 01349 xet = node_pos[4] - node_pos[7]; 01350 xze = node_pos[3] - node_pos[7]; 01351 01352 current_condition = condition_comp( xxi, xet, xze ); 01353 if( current_condition > condition ) 01354 { 01355 condition = current_condition; 01356 } 01357 01358 condition /= 3.0; 01359 01360 if( condition > 0 ) return (double)VERDICT_MIN( condition, VERDICT_DBL_MAX ); 01361 return (double)VERDICT_MAX( condition, -VERDICT_DBL_MAX ); 01362 } 01363 01364 /*! 01365 The maximum Frobenius condition of a hex, a.k.a. condition 01366 NB (P. Pebay 01/25/07): 01367 this method is maintained for backwards compatibility only. 01368 It will become deprecated at some point. 01369 01370 */ 01371 C_FUNC_DEF double v_hex_condition( int /*num_nodes*/, double coordinates[][3] ) 01372 { 01373 01374 return v_hex_max_aspect_frobenius( 8, coordinates ); 01375 } 01376 01377 /*! 01378 jacobian of a hex 01379 01380 Minimum pointwise volume of local map at 8 corners & center of hex 01381 */ 01382 C_FUNC_DEF double v_hex_jacobian( int /*num_nodes*/, double coordinates[][3] ) 01383 { 01384 01385 VerdictVector node_pos[8]; 01386 make_hex_nodes( coordinates, node_pos ); 01387 01388 double jacobian = VERDICT_DBL_MAX; 01389 double current_jacobian; 01390 VerdictVector xxi, xet, xze; 01391 01392 xxi = calc_hex_efg( 1, node_pos ); 01393 xet = calc_hex_efg( 2, node_pos ); 01394 xze = calc_hex_efg( 3, node_pos ); 01395 01396 current_jacobian = xxi % ( xet * xze ) / 64.0; 01397 if( current_jacobian < jacobian ) 01398 { 01399 jacobian = current_jacobian; 01400 } 01401 01402 // J(0,0,0): 01403 01404 xxi = node_pos[1] - node_pos[0]; 01405 xet = node_pos[3] - node_pos[0]; 01406 xze = node_pos[4] - node_pos[0]; 01407 01408 current_jacobian = xxi % ( xet * xze ); 01409 if( current_jacobian < jacobian ) 01410 { 01411 jacobian = current_jacobian; 01412 } 01413 01414 // J(1,0,0): 01415 01416 xxi = node_pos[2] - node_pos[1]; 01417 xet = node_pos[0] - node_pos[1]; 01418 xze = node_pos[5] - node_pos[1]; 01419 01420 current_jacobian = xxi % ( xet * xze ); 01421 if( current_jacobian < jacobian ) 01422 { 01423 jacobian = current_jacobian; 01424 } 01425 01426 // J(1,1,0): 01427 01428 xxi = node_pos[3] - node_pos[2]; 01429 xet = node_pos[1] - node_pos[2]; 01430 xze = node_pos[6] - node_pos[2]; 01431 01432 current_jacobian = xxi % ( xet * xze ); 01433 if( current_jacobian < jacobian ) 01434 { 01435 jacobian = current_jacobian; 01436 } 01437 01438 // J(0,1,0): 01439 01440 xxi = node_pos[0] - node_pos[3]; 01441 xet = node_pos[2] - node_pos[3]; 01442 xze = node_pos[7] - node_pos[3]; 01443 01444 current_jacobian = xxi % ( xet * xze ); 01445 if( current_jacobian < jacobian ) 01446 { 01447 jacobian = current_jacobian; 01448 } 01449 01450 // J(0,0,1): 01451 01452 xxi = node_pos[7] - node_pos[4]; 01453 xet = node_pos[5] - node_pos[4]; 01454 xze = node_pos[0] - node_pos[4]; 01455 01456 current_jacobian = xxi % ( xet * xze ); 01457 if( current_jacobian < jacobian ) 01458 { 01459 jacobian = current_jacobian; 01460 } 01461 01462 // J(1,0,1): 01463 01464 xxi = node_pos[4] - node_pos[5]; 01465 xet = node_pos[6] - node_pos[5]; 01466 xze = node_pos[1] - node_pos[5]; 01467 01468 current_jacobian = xxi % ( xet * xze ); 01469 if( current_jacobian < jacobian ) 01470 { 01471 jacobian = current_jacobian; 01472 } 01473 01474 // J(1,1,1): 01475 01476 xxi = node_pos[5] - node_pos[6]; 01477 xet = node_pos[7] - node_pos[6]; 01478 xze = node_pos[2] - node_pos[6]; 01479 01480 current_jacobian = xxi % ( xet * xze ); 01481 if( current_jacobian < jacobian ) 01482 { 01483 jacobian = current_jacobian; 01484 } 01485 01486 // J(0,1,1): 01487 01488 xxi = node_pos[6] - node_pos[7]; 01489 xet = node_pos[4] - node_pos[7]; 01490 xze = node_pos[3] - node_pos[7]; 01491 01492 current_jacobian = xxi % ( xet * xze ); 01493 if( current_jacobian < jacobian ) 01494 { 01495 jacobian = current_jacobian; 01496 } 01497 01498 if( jacobian > 0 ) return (double)VERDICT_MIN( jacobian, VERDICT_DBL_MAX ); 01499 return (double)VERDICT_MAX( jacobian, -VERDICT_DBL_MAX ); 01500 } 01501 01502 /*! 01503 scaled jacobian of a hex 01504 01505 Minimum Jacobian divided by the lengths of the 3 edge vectors 01506 */ 01507 C_FUNC_DEF double v_hex_scaled_jacobian( int /*num_nodes*/, double coordinates[][3] ) 01508 { 01509 01510 double jacobi, min_norm_jac = VERDICT_DBL_MAX; 01511 // double min_jacobi = VERDICT_DBL_MAX; 01512 double temp_norm_jac, lengths; 01513 double len1_sq, len2_sq, len3_sq; 01514 VerdictVector xxi, xet, xze; 01515 01516 VerdictVector node_pos[8]; 01517 make_hex_nodes( coordinates, node_pos ); 01518 01519 xxi = calc_hex_efg( 1, node_pos ); 01520 xet = calc_hex_efg( 2, node_pos ); 01521 xze = calc_hex_efg( 3, node_pos ); 01522 01523 jacobi = xxi % ( xet * xze ); 01524 // if( jacobi < min_jacobi) { min_jacobi = jacobi; } 01525 01526 len1_sq = xxi.length_squared(); 01527 len2_sq = xet.length_squared(); 01528 len3_sq = xze.length_squared(); 01529 01530 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01531 return (double)VERDICT_DBL_MAX; 01532 01533 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01534 temp_norm_jac = jacobi / lengths; 01535 01536 if( temp_norm_jac < min_norm_jac ) 01537 min_norm_jac = temp_norm_jac; 01538 else 01539 temp_norm_jac = jacobi; 01540 01541 // J(0,0,0): 01542 01543 xxi = node_pos[1] - node_pos[0]; 01544 xet = node_pos[3] - node_pos[0]; 01545 xze = node_pos[4] - node_pos[0]; 01546 01547 jacobi = xxi % ( xet * xze ); 01548 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01549 01550 len1_sq = xxi.length_squared(); 01551 len2_sq = xet.length_squared(); 01552 len3_sq = xze.length_squared(); 01553 01554 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01555 return (double)VERDICT_DBL_MAX; 01556 01557 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01558 temp_norm_jac = jacobi / lengths; 01559 if( temp_norm_jac < min_norm_jac ) 01560 min_norm_jac = temp_norm_jac; 01561 else 01562 temp_norm_jac = jacobi; 01563 01564 // J(1,0,0): 01565 01566 xxi = node_pos[2] - node_pos[1]; 01567 xet = node_pos[0] - node_pos[1]; 01568 xze = node_pos[5] - node_pos[1]; 01569 01570 jacobi = xxi % ( xet * xze ); 01571 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01572 01573 len1_sq = xxi.length_squared(); 01574 len2_sq = xet.length_squared(); 01575 len3_sq = xze.length_squared(); 01576 01577 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01578 return (double)VERDICT_DBL_MAX; 01579 01580 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01581 temp_norm_jac = jacobi / lengths; 01582 if( temp_norm_jac < min_norm_jac ) 01583 min_norm_jac = temp_norm_jac; 01584 else 01585 temp_norm_jac = jacobi; 01586 01587 // J(1,1,0): 01588 01589 xxi = node_pos[3] - node_pos[2]; 01590 xet = node_pos[1] - node_pos[2]; 01591 xze = node_pos[6] - node_pos[2]; 01592 01593 jacobi = xxi % ( xet * xze ); 01594 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01595 01596 len1_sq = xxi.length_squared(); 01597 len2_sq = xet.length_squared(); 01598 len3_sq = xze.length_squared(); 01599 01600 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01601 return (double)VERDICT_DBL_MAX; 01602 01603 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01604 temp_norm_jac = jacobi / lengths; 01605 if( temp_norm_jac < min_norm_jac ) 01606 min_norm_jac = temp_norm_jac; 01607 else 01608 temp_norm_jac = jacobi; 01609 01610 // J(0,1,0): 01611 01612 xxi = node_pos[0] - node_pos[3]; 01613 xet = node_pos[2] - node_pos[3]; 01614 xze = node_pos[7] - node_pos[3]; 01615 01616 jacobi = xxi % ( xet * xze ); 01617 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01618 01619 len1_sq = xxi.length_squared(); 01620 len2_sq = xet.length_squared(); 01621 len3_sq = xze.length_squared(); 01622 01623 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01624 return (double)VERDICT_DBL_MAX; 01625 01626 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01627 temp_norm_jac = jacobi / lengths; 01628 if( temp_norm_jac < min_norm_jac ) 01629 min_norm_jac = temp_norm_jac; 01630 else 01631 temp_norm_jac = jacobi; 01632 01633 // J(0,0,1): 01634 01635 xxi = node_pos[7] - node_pos[4]; 01636 xet = node_pos[5] - node_pos[4]; 01637 xze = node_pos[0] - node_pos[4]; 01638 01639 jacobi = xxi % ( xet * xze ); 01640 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01641 01642 len1_sq = xxi.length_squared(); 01643 len2_sq = xet.length_squared(); 01644 len3_sq = xze.length_squared(); 01645 01646 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01647 return (double)VERDICT_DBL_MAX; 01648 01649 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01650 temp_norm_jac = jacobi / lengths; 01651 if( temp_norm_jac < min_norm_jac ) 01652 min_norm_jac = temp_norm_jac; 01653 else 01654 temp_norm_jac = jacobi; 01655 01656 // J(1,0,1): 01657 01658 xxi = node_pos[4] - node_pos[5]; 01659 xet = node_pos[6] - node_pos[5]; 01660 xze = node_pos[1] - node_pos[5]; 01661 01662 jacobi = xxi % ( xet * xze ); 01663 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01664 01665 len1_sq = xxi.length_squared(); 01666 len2_sq = xet.length_squared(); 01667 len3_sq = xze.length_squared(); 01668 01669 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01670 return (double)VERDICT_DBL_MAX; 01671 01672 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01673 temp_norm_jac = jacobi / lengths; 01674 if( temp_norm_jac < min_norm_jac ) 01675 min_norm_jac = temp_norm_jac; 01676 else 01677 temp_norm_jac = jacobi; 01678 01679 // J(1,1,1): 01680 01681 xxi = node_pos[5] - node_pos[6]; 01682 xet = node_pos[7] - node_pos[6]; 01683 xze = node_pos[2] - node_pos[6]; 01684 01685 jacobi = xxi % ( xet * xze ); 01686 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01687 01688 len1_sq = xxi.length_squared(); 01689 len2_sq = xet.length_squared(); 01690 len3_sq = xze.length_squared(); 01691 01692 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01693 return (double)VERDICT_DBL_MAX; 01694 01695 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01696 temp_norm_jac = jacobi / lengths; 01697 if( temp_norm_jac < min_norm_jac ) 01698 min_norm_jac = temp_norm_jac; 01699 else 01700 temp_norm_jac = jacobi; 01701 01702 // J(0,1,1): 01703 01704 xxi = node_pos[6] - node_pos[7]; 01705 xet = node_pos[4] - node_pos[7]; 01706 xze = node_pos[3] - node_pos[7]; 01707 01708 jacobi = xxi % ( xet * xze ); 01709 // if( jacobi < min_jacobi ) { min_jacobi = jacobi; } 01710 01711 len1_sq = xxi.length_squared(); 01712 len2_sq = xet.length_squared(); 01713 len3_sq = xze.length_squared(); 01714 01715 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) 01716 return (double)VERDICT_DBL_MAX; 01717 01718 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01719 temp_norm_jac = jacobi / lengths; 01720 if( temp_norm_jac < min_norm_jac ) min_norm_jac = temp_norm_jac; 01721 // else 01722 // temp_norm_jac = jacobi; 01723 01724 if( min_norm_jac > 0 ) return (double)VERDICT_MIN( min_norm_jac, VERDICT_DBL_MAX ); 01725 return (double)VERDICT_MAX( min_norm_jac, -VERDICT_DBL_MAX ); 01726 } 01727 01728 /*! 01729 shear of a hex 01730 01731 3/Condition number of Jacobian Skew matrix 01732 */ 01733 C_FUNC_DEF double v_hex_shear( int /*num_nodes*/, double coordinates[][3] ) 01734 { 01735 01736 double shear; 01737 double min_shear = 1.0; 01738 VerdictVector xxi, xet, xze; 01739 double det, len1_sq, len2_sq, len3_sq, lengths; 01740 01741 VerdictVector node_pos[8]; 01742 make_hex_nodes( coordinates, node_pos ); 01743 01744 // J(0,0,0): 01745 01746 xxi = node_pos[1] - node_pos[0]; 01747 xet = node_pos[3] - node_pos[0]; 01748 xze = node_pos[4] - node_pos[0]; 01749 01750 len1_sq = xxi.length_squared(); 01751 len2_sq = xet.length_squared(); 01752 len3_sq = xze.length_squared(); 01753 01754 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01755 01756 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01757 det = xxi % ( xet * xze ); 01758 if( det < VERDICT_DBL_MIN ) 01759 { 01760 return 0; 01761 } 01762 01763 shear = det / lengths; 01764 min_shear = VERDICT_MIN( shear, min_shear ); 01765 01766 // J(1,0,0): 01767 01768 xxi = node_pos[2] - node_pos[1]; 01769 xet = node_pos[0] - node_pos[1]; 01770 xze = node_pos[5] - node_pos[1]; 01771 01772 len1_sq = xxi.length_squared(); 01773 len2_sq = xet.length_squared(); 01774 len3_sq = xze.length_squared(); 01775 01776 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01777 01778 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01779 det = xxi % ( xet * xze ); 01780 if( det < VERDICT_DBL_MIN ) 01781 { 01782 return 0; 01783 } 01784 01785 shear = det / lengths; 01786 min_shear = VERDICT_MIN( shear, min_shear ); 01787 01788 // J(1,1,0): 01789 01790 xxi = node_pos[3] - node_pos[2]; 01791 xet = node_pos[1] - node_pos[2]; 01792 xze = node_pos[6] - node_pos[2]; 01793 01794 len1_sq = xxi.length_squared(); 01795 len2_sq = xet.length_squared(); 01796 len3_sq = xze.length_squared(); 01797 01798 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01799 01800 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01801 det = xxi % ( xet * xze ); 01802 if( det < VERDICT_DBL_MIN ) 01803 { 01804 return 0; 01805 } 01806 01807 shear = det / lengths; 01808 min_shear = VERDICT_MIN( shear, min_shear ); 01809 01810 // J(0,1,0): 01811 01812 xxi = node_pos[0] - node_pos[3]; 01813 xet = node_pos[2] - node_pos[3]; 01814 xze = node_pos[7] - node_pos[3]; 01815 01816 len1_sq = xxi.length_squared(); 01817 len2_sq = xet.length_squared(); 01818 len3_sq = xze.length_squared(); 01819 01820 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01821 01822 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01823 det = xxi % ( xet * xze ); 01824 if( det < VERDICT_DBL_MIN ) 01825 { 01826 return 0; 01827 } 01828 01829 shear = det / lengths; 01830 min_shear = VERDICT_MIN( shear, min_shear ); 01831 01832 // J(0,0,1): 01833 01834 xxi = node_pos[7] - node_pos[4]; 01835 xet = node_pos[5] - node_pos[4]; 01836 xze = node_pos[0] - node_pos[4]; 01837 01838 len1_sq = xxi.length_squared(); 01839 len2_sq = xet.length_squared(); 01840 len3_sq = xze.length_squared(); 01841 01842 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01843 01844 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01845 det = xxi % ( xet * xze ); 01846 if( det < VERDICT_DBL_MIN ) 01847 { 01848 return 0; 01849 } 01850 01851 shear = det / lengths; 01852 min_shear = VERDICT_MIN( shear, min_shear ); 01853 01854 // J(1,0,1): 01855 01856 xxi = node_pos[4] - node_pos[5]; 01857 xet = node_pos[6] - node_pos[5]; 01858 xze = node_pos[1] - node_pos[5]; 01859 01860 len1_sq = xxi.length_squared(); 01861 len2_sq = xet.length_squared(); 01862 len3_sq = xze.length_squared(); 01863 01864 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01865 01866 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01867 det = xxi % ( xet * xze ); 01868 if( det < VERDICT_DBL_MIN ) 01869 { 01870 return 0; 01871 } 01872 01873 shear = det / lengths; 01874 min_shear = VERDICT_MIN( shear, min_shear ); 01875 01876 // J(1,1,1): 01877 01878 xxi = node_pos[5] - node_pos[6]; 01879 xet = node_pos[7] - node_pos[6]; 01880 xze = node_pos[2] - node_pos[6]; 01881 01882 len1_sq = xxi.length_squared(); 01883 len2_sq = xet.length_squared(); 01884 len3_sq = xze.length_squared(); 01885 01886 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01887 01888 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01889 det = xxi % ( xet * xze ); 01890 if( det < VERDICT_DBL_MIN ) 01891 { 01892 return 0; 01893 } 01894 01895 shear = det / lengths; 01896 min_shear = VERDICT_MIN( shear, min_shear ); 01897 01898 // J(0,1,1): 01899 01900 xxi = node_pos[6] - node_pos[7]; 01901 xet = node_pos[4] - node_pos[7]; 01902 xze = node_pos[3] - node_pos[7]; 01903 01904 len1_sq = xxi.length_squared(); 01905 len2_sq = xet.length_squared(); 01906 len3_sq = xze.length_squared(); 01907 01908 if( len1_sq <= VERDICT_DBL_MIN || len2_sq <= VERDICT_DBL_MIN || len3_sq <= VERDICT_DBL_MIN ) return 0; 01909 01910 lengths = sqrt( len1_sq * len2_sq * len3_sq ); 01911 det = xxi % ( xet * xze ); 01912 if( det < VERDICT_DBL_MIN ) 01913 { 01914 return 0; 01915 } 01916 01917 shear = det / lengths; 01918 min_shear = VERDICT_MIN( shear, min_shear ); 01919 01920 if( min_shear <= VERDICT_DBL_MIN ) min_shear = 0; 01921 01922 if( min_shear > 0 ) return (double)VERDICT_MIN( min_shear, VERDICT_DBL_MAX ); 01923 return (double)VERDICT_MAX( min_shear, -VERDICT_DBL_MAX ); 01924 } 01925 01926 /*! 01927 shape of a hex 01928 01929 3/Condition number of weighted Jacobian matrix 01930 */ 01931 C_FUNC_DEF double v_hex_shape( int /*num_nodes*/, double coordinates[][3] ) 01932 { 01933 01934 double det, shape; 01935 double min_shape = 1.0; 01936 static const double two_thirds = 2.0 / 3.0; 01937 01938 VerdictVector xxi, xet, xze; 01939 01940 VerdictVector node_pos[8]; 01941 make_hex_nodes( coordinates, node_pos ); 01942 01943 // J(0,0,0): 01944 01945 xxi = node_pos[1] - node_pos[0]; 01946 xet = node_pos[3] - node_pos[0]; 01947 xze = node_pos[4] - node_pos[0]; 01948 01949 det = xxi % ( xet * xze ); 01950 if( det > VERDICT_DBL_MIN ) 01951 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 01952 else 01953 return 0; 01954 01955 if( shape < min_shape ) 01956 { 01957 min_shape = shape; 01958 } 01959 01960 // J(1,0,0): 01961 01962 xxi = node_pos[2] - node_pos[1]; 01963 xet = node_pos[0] - node_pos[1]; 01964 xze = node_pos[5] - node_pos[1]; 01965 01966 det = xxi % ( xet * xze ); 01967 if( det > VERDICT_DBL_MIN ) 01968 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 01969 else 01970 return 0; 01971 01972 if( shape < min_shape ) 01973 { 01974 min_shape = shape; 01975 } 01976 01977 // J(1,1,0): 01978 01979 xxi = node_pos[3] - node_pos[2]; 01980 xet = node_pos[1] - node_pos[2]; 01981 xze = node_pos[6] - node_pos[2]; 01982 01983 det = xxi % ( xet * xze ); 01984 if( det > VERDICT_DBL_MIN ) 01985 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 01986 else 01987 return 0; 01988 01989 if( shape < min_shape ) 01990 { 01991 min_shape = shape; 01992 } 01993 01994 // J(0,1,0): 01995 01996 xxi = node_pos[0] - node_pos[3]; 01997 xet = node_pos[2] - node_pos[3]; 01998 xze = node_pos[7] - node_pos[3]; 01999 02000 det = xxi % ( xet * xze ); 02001 if( det > VERDICT_DBL_MIN ) 02002 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 02003 else 02004 return 0; 02005 02006 if( shape < min_shape ) 02007 { 02008 min_shape = shape; 02009 } 02010 02011 // J(0,0,1): 02012 02013 xxi = node_pos[7] - node_pos[4]; 02014 xet = node_pos[5] - node_pos[4]; 02015 xze = node_pos[0] - node_pos[4]; 02016 02017 det = xxi % ( xet * xze ); 02018 if( det > VERDICT_DBL_MIN ) 02019 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 02020 else 02021 return 0; 02022 02023 if( shape < min_shape ) 02024 { 02025 min_shape = shape; 02026 } 02027 02028 // J(1,0,1): 02029 02030 xxi = node_pos[4] - node_pos[5]; 02031 xet = node_pos[6] - node_pos[5]; 02032 xze = node_pos[1] - node_pos[5]; 02033 02034 det = xxi % ( xet * xze ); 02035 if( det > VERDICT_DBL_MIN ) 02036 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 02037 else 02038 return 0; 02039 02040 if( shape < min_shape ) 02041 { 02042 min_shape = shape; 02043 } 02044 02045 // J(1,1,1): 02046 02047 xxi = node_pos[5] - node_pos[6]; 02048 xet = node_pos[7] - node_pos[6]; 02049 xze = node_pos[2] - node_pos[6]; 02050 02051 det = xxi % ( xet * xze ); 02052 if( det > VERDICT_DBL_MIN ) 02053 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 02054 else 02055 return 0; 02056 02057 if( shape < min_shape ) 02058 { 02059 min_shape = shape; 02060 } 02061 02062 // J(1,1,1): 02063 02064 xxi = node_pos[6] - node_pos[7]; 02065 xet = node_pos[4] - node_pos[7]; 02066 xze = node_pos[3] - node_pos[7]; 02067 02068 det = xxi % ( xet * xze ); 02069 if( det > VERDICT_DBL_MIN ) 02070 shape = 3 * pow( det, two_thirds ) / ( xxi % xxi + xet % xet + xze % xze ); 02071 else 02072 return 0; 02073 02074 if( shape < min_shape ) 02075 { 02076 min_shape = shape; 02077 } 02078 02079 if( min_shape <= VERDICT_DBL_MIN ) min_shape = 0; 02080 02081 if( min_shape > 0 ) return (double)VERDICT_MIN( min_shape, VERDICT_DBL_MAX ); 02082 return (double)VERDICT_MAX( min_shape, -VERDICT_DBL_MAX ); 02083 } 02084 02085 /*! 02086 relative size of a hex 02087 02088 Min( J, 1/J ), where J is determinant of weighted Jacobian matrix 02089 */ 02090 C_FUNC_DEF double v_hex_relative_size_squared( int /*num_nodes*/, double coordinates[][3] ) 02091 { 02092 double size = 0; 02093 double tau; 02094 02095 VerdictVector xxi, xet, xze; 02096 double det, det_sum = 0; 02097 02098 v_hex_get_weight( xxi, xet, xze ); 02099 02100 // This is the average relative size 02101 double detw = xxi % ( xet * xze ); 02102 02103 if( detw < VERDICT_DBL_MIN ) return 0; 02104 02105 VerdictVector node_pos[8]; 02106 make_hex_nodes( coordinates, node_pos ); 02107 02108 // J(0,0,0): 02109 02110 xxi = node_pos[1] - node_pos[0]; 02111 xet = node_pos[3] - node_pos[0]; 02112 xze = node_pos[4] - node_pos[0]; 02113 02114 det = xxi % ( xet * xze ); 02115 det_sum += det; 02116 02117 // J(1,0,0): 02118 02119 xxi = node_pos[2] - node_pos[1]; 02120 xet = node_pos[0] - node_pos[1]; 02121 xze = node_pos[5] - node_pos[1]; 02122 02123 det = xxi % ( xet * xze ); 02124 det_sum += det; 02125 02126 // J(0,1,0): 02127 02128 xxi = node_pos[3] - node_pos[2]; 02129 xet = node_pos[1] - node_pos[2]; 02130 xze = node_pos[6] - node_pos[2]; 02131 02132 det = xxi % ( xet * xze ); 02133 det_sum += det; 02134 02135 // J(1,1,0): 02136 02137 xxi = node_pos[0] - node_pos[3]; 02138 xet = node_pos[2] - node_pos[3]; 02139 xze = node_pos[7] - node_pos[3]; 02140 02141 det = xxi % ( xet * xze ); 02142 det_sum += det; 02143 02144 // J(0,1,0): 02145 02146 xxi = node_pos[7] - node_pos[4]; 02147 xet = node_pos[5] - node_pos[4]; 02148 xze = node_pos[0] - node_pos[4]; 02149 02150 det = xxi % ( xet * xze ); 02151 det_sum += det; 02152 02153 // J(1,0,1): 02154 02155 xxi = node_pos[4] - node_pos[5]; 02156 xet = node_pos[6] - node_pos[5]; 02157 xze = node_pos[1] - node_pos[5]; 02158 02159 det = xxi % ( xet * xze ); 02160 det_sum += det; 02161 02162 // J(1,1,1): 02163 02164 xxi = node_pos[5] - node_pos[6]; 02165 xet = node_pos[7] - node_pos[6]; 02166 xze = node_pos[2] - node_pos[6]; 02167 02168 det = xxi % ( xet * xze ); 02169 det_sum += det; 02170 02171 // J(1,1,1): 02172 02173 xxi = node_pos[6] - node_pos[7]; 02174 xet = node_pos[4] - node_pos[7]; 02175 xze = node_pos[3] - node_pos[7]; 02176 02177 det = xxi % ( xet * xze ); 02178 det_sum += det; 02179 02180 if( det_sum > VERDICT_DBL_MIN ) 02181 { 02182 tau = det_sum / ( 8 * detw ); 02183 02184 tau = VERDICT_MIN( tau, 1.0 / tau ); 02185 02186 size = tau * tau; 02187 } 02188 02189 if( size > 0 ) return (double)VERDICT_MIN( size, VERDICT_DBL_MAX ); 02190 return (double)VERDICT_MAX( size, -VERDICT_DBL_MAX ); 02191 } 02192 02193 /*! 02194 shape and size of a hex 02195 02196 Product of Shape and Relative Size 02197 */ 02198 C_FUNC_DEF double v_hex_shape_and_size( int num_nodes, double coordinates[][3] ) 02199 { 02200 double size = v_hex_relative_size_squared( num_nodes, coordinates ); 02201 double shape = v_hex_shape( num_nodes, coordinates ); 02202 02203 double shape_size = size * shape; 02204 02205 if( shape_size > 0 ) return (double)VERDICT_MIN( shape_size, VERDICT_DBL_MAX ); 02206 return (double)VERDICT_MAX( shape_size, -VERDICT_DBL_MAX ); 02207 } 02208 02209 /*! 02210 shear and size of a hex 02211 02212 Product of Shear and Relative Size 02213 */ 02214 C_FUNC_DEF double v_hex_shear_and_size( int num_nodes, double coordinates[][3] ) 02215 { 02216 double size = v_hex_relative_size_squared( num_nodes, coordinates ); 02217 double shear = v_hex_shear( num_nodes, coordinates ); 02218 02219 double shear_size = shear * size; 02220 02221 if( shear_size > 0 ) return (double)VERDICT_MIN( shear_size, VERDICT_DBL_MAX ); 02222 return (double)VERDICT_MAX( shear_size, -VERDICT_DBL_MAX ); 02223 } 02224 02225 /*! 02226 distortion of a hex 02227 */ 02228 C_FUNC_DEF double v_hex_distortion( int num_nodes, double coordinates[][3] ) 02229 { 02230 02231 // use 2x2 gauss points for linear hex and 3x3 for 2nd order hex 02232 int number_of_gauss_points = 0; 02233 if( num_nodes == 8 ) 02234 // 2x2 quadrature rule 02235 number_of_gauss_points = 2; 02236 else if( num_nodes == 20 ) 02237 // 3x3 quadrature rule 02238 number_of_gauss_points = 3; 02239 02240 int number_dimension = 3; 02241 int total_number_of_gauss_points = number_of_gauss_points * number_of_gauss_points * number_of_gauss_points; 02242 double distortion = VERDICT_DBL_MAX; 02243 02244 // maxTotalNumberGaussPoints =27, maxNumberNodes = 20 02245 // they are defined in GaussIntegration.hpp 02246 // This is used to make these arrays static. 02247 // I tried dynamically allocated arrays but the new and delete 02248 // was very expensive 02249 02250 double shape_function[maxTotalNumberGaussPoints][maxNumberNodes]; 02251 double dndy1[maxTotalNumberGaussPoints][maxNumberNodes]; 02252 double dndy2[maxTotalNumberGaussPoints][maxNumberNodes]; 02253 double dndy3[maxTotalNumberGaussPoints][maxNumberNodes]; 02254 double weight[maxTotalNumberGaussPoints]; 02255 02256 // create an object of GaussIntegration 02257 GaussIntegration::initialize( number_of_gauss_points, num_nodes, number_dimension ); 02258 GaussIntegration::calculate_shape_function_3d_hex(); 02259 GaussIntegration::get_shape_func( shape_function[0], dndy1[0], dndy2[0], dndy3[0], weight ); 02260 02261 VerdictVector xxi, xet, xze, xin; 02262 02263 double jacobian, minimum_jacobian; 02264 double element_volume = 0.0; 02265 minimum_jacobian = VERDICT_DBL_MAX; 02266 // calculate element volume 02267 int ife, ja; 02268 for( ife = 0; ife < total_number_of_gauss_points; ife++ ) 02269 { 02270 02271 xxi.set( 0.0, 0.0, 0.0 ); 02272 xet.set( 0.0, 0.0, 0.0 ); 02273 xze.set( 0.0, 0.0, 0.0 ); 02274 02275 for( ja = 0; ja < num_nodes; ja++ ) 02276 { 02277 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] ); 02278 xxi += dndy1[ife][ja] * xin; 02279 xet += dndy2[ife][ja] * xin; 02280 xze += dndy3[ife][ja] * xin; 02281 } 02282 02283 jacobian = xxi % ( xet * xze ); 02284 if( minimum_jacobian > jacobian ) minimum_jacobian = jacobian; 02285 02286 element_volume += weight[ife] * jacobian; 02287 } 02288 02289 // loop through all nodes 02290 double dndy1_at_node[maxNumberNodes][maxNumberNodes]; 02291 double dndy2_at_node[maxNumberNodes][maxNumberNodes]; 02292 double dndy3_at_node[maxNumberNodes][maxNumberNodes]; 02293 02294 GaussIntegration::calculate_derivative_at_nodes_3d( dndy1_at_node, dndy2_at_node, dndy3_at_node ); 02295 int node_id; 02296 for( node_id = 0; node_id < num_nodes; node_id++ ) 02297 { 02298 02299 xxi.set( 0.0, 0.0, 0.0 ); 02300 xet.set( 0.0, 0.0, 0.0 ); 02301 xze.set( 0.0, 0.0, 0.0 ); 02302 02303 for( ja = 0; ja < num_nodes; ja++ ) 02304 { 02305 xin.set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] ); 02306 xxi += dndy1_at_node[node_id][ja] * xin; 02307 xet += dndy2_at_node[node_id][ja] * xin; 02308 xze += dndy3_at_node[node_id][ja] * xin; 02309 } 02310 02311 jacobian = xxi % ( xet * xze ); 02312 if( minimum_jacobian > jacobian ) minimum_jacobian = jacobian; 02313 } 02314 distortion = minimum_jacobian / element_volume * 8.; 02315 return (double)distortion; 02316 } 02317 02318 /* 02319 C_FUNC_DEF double hex_jac_normjac_oddy_cond( int choices[], 02320 double coordinates[][3], 02321 double answers[4] ) 02322 { 02323 02324 //Define variables 02325 int i; 02326 02327 double xxi[3], xet[3], xze[3]; 02328 double norm_jacobian = 0.0, current_norm_jac = 0.0; 02329 double jacobian = 0.0, current_jacobian = 0.0; 02330 double oddy = 0.0, current_oddy = 0.0; 02331 double condition = 0.0, current_condition = 0.0; 02332 02333 02334 for( i=0; i<3; i++) 02335 xxi[i] = calc_hex_efg( 2, i, coordinates ); 02336 for( i=0; i<3; i++) 02337 xet[i] = calc_hex_efg( 3, i, coordinates ); 02338 for( i=0; i<3; i++) 02339 xze[i] = calc_hex_efg( 6, i, coordinates ); 02340 02341 // norm jacobian and jacobian 02342 if( choices[0] || choices[1] ) 02343 { 02344 current_jacobian = determinant( xxi, xet, xze ); 02345 current_norm_jac = normalize_jacobian( current_jacobian, 02346 xxi, xet, xze ); 02347 02348 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02349 02350 current_jacobian /= 64.0; 02351 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02352 } 02353 02354 // oddy 02355 if( choices[2] ) 02356 { 02357 current_oddy = oddy_comp( xxi, xet, xze ); 02358 if ( current_oddy > oddy ) { oddy = current_oddy; } 02359 } 02360 02361 // condition 02362 if( choices[3] ) 02363 { 02364 current_condition = condition_comp( xxi, xet, xze ); 02365 if ( current_condition > condition ) { condition = current_condition; } 02366 } 02367 02368 02369 for( i=0; i<3; i++) 02370 { 02371 xxi[i] = coordinates[1][i] - coordinates[0][i]; 02372 xet[i] = coordinates[3][i] - coordinates[0][i]; 02373 xze[i] = coordinates[4][i] - coordinates[0][i]; 02374 } 02375 02376 // norm jacobian and jacobian 02377 if( choices[0] || choices[1] ) 02378 { 02379 current_jacobian = determinant( xxi, xet, xze ); 02380 current_norm_jac = normalize_jacobian( current_jacobian, 02381 xxi, xet, xze ); 02382 02383 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02384 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02385 } 02386 02387 // oddy 02388 if( choices[2] ) 02389 { 02390 current_oddy = oddy_comp( xxi, xet, xze ); 02391 if ( current_oddy > oddy ) { oddy = current_oddy; } 02392 } 02393 02394 // condition 02395 if( choices[3] ) 02396 { 02397 current_condition = condition_comp( xxi, xet, xze ); 02398 if ( current_condition > condition ) { condition = current_condition; } 02399 } 02400 02401 02402 for( i=0; i<3; i++) 02403 { 02404 xxi[i] = coordinates[1][i] - coordinates[0][i]; 02405 xet[i] = coordinates[2][i] - coordinates[1][i]; 02406 xze[i] = coordinates[5][i] - coordinates[1][i]; 02407 } 02408 02409 // norm jacobian and jacobian 02410 if( choices[0] || choices[1] ) 02411 { 02412 current_jacobian = determinant( xxi, xet, xze ); 02413 current_norm_jac = normalize_jacobian( current_jacobian, 02414 xxi, xet, xze ); 02415 02416 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02417 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02418 } 02419 02420 // oddy 02421 if( choices[2] ) 02422 { 02423 current_oddy = oddy_comp( xxi, xet, xze ); 02424 if ( current_oddy > oddy ) { oddy = current_oddy; } 02425 } 02426 02427 // condition 02428 if( choices[3] ) 02429 { 02430 current_condition = condition_comp( xxi, xet, xze ); 02431 if ( current_condition > condition ) { condition = current_condition; } 02432 } 02433 02434 02435 for( i=0; i<3; i++) 02436 { 02437 xxi[i] = coordinates[2][i] - coordinates[3][i]; 02438 xet[i] = coordinates[3][i] - coordinates[0][i]; 02439 xze[i] = coordinates[7][i] - coordinates[3][i]; 02440 } 02441 02442 // norm jacobian and jacobian 02443 if( choices[0] || choices[1] ) 02444 { 02445 current_jacobian = determinant( xxi, xet, xze ); 02446 current_norm_jac = normalize_jacobian( current_jacobian, 02447 xxi, xet, xze ); 02448 02449 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02450 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02451 } 02452 02453 // oddy 02454 if( choices[2] ) 02455 { 02456 current_oddy = oddy_comp( xxi, xet, xze ); 02457 if ( current_oddy > oddy ) { oddy = current_oddy; } 02458 } 02459 02460 // condition 02461 if( choices[3] ) 02462 { 02463 current_condition = condition_comp( xxi, xet, xze ); 02464 if ( current_condition > condition ) { condition = current_condition; } 02465 } 02466 02467 02468 for( i=0; i<3; i++) 02469 { 02470 xxi[i] = coordinates[5][i] - coordinates[4][i]; 02471 xet[i] = coordinates[7][i] - coordinates[4][i]; 02472 xze[i] = coordinates[4][i] - coordinates[0][i]; 02473 } 02474 02475 02476 // norm jacobian and jacobian 02477 if( choices[0] || choices[1] ) 02478 { 02479 current_jacobian = determinant( xxi, xet, xze ); 02480 current_norm_jac = normalize_jacobian( current_jacobian, 02481 xxi, xet, xze ); 02482 02483 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02484 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02485 } 02486 02487 // oddy 02488 if( choices[2] ) 02489 { 02490 current_oddy = oddy_comp( xxi, xet, xze ); 02491 if ( current_oddy > oddy ) { oddy = current_oddy; } 02492 } 02493 02494 // condition 02495 if( choices[3] ) 02496 { 02497 current_condition = condition_comp( xxi, xet, xze ); 02498 if ( current_condition > condition ) { condition = current_condition; } 02499 } 02500 02501 02502 for( i=0; i<3; i++) 02503 { 02504 xxi[i] = coordinates[2][i] - coordinates[3][i]; 02505 xet[i] = coordinates[2][i] - coordinates[1][i]; 02506 xze[i] = coordinates[6][i] - coordinates[2][i]; 02507 } 02508 02509 // norm jacobian and jacobian 02510 if( choices[0] || choices[1] ) 02511 { 02512 current_jacobian = determinant( xxi, xet, xze ); 02513 current_norm_jac = normalize_jacobian( current_jacobian, 02514 xxi, xet, xze ); 02515 02516 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02517 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02518 } 02519 02520 // oddy 02521 if( choices[2] ) 02522 { 02523 current_oddy = oddy_comp( xxi, xet, xze ); 02524 if ( current_oddy > oddy ) { oddy = current_oddy; } 02525 } 02526 02527 // condition 02528 if( choices[3] ) 02529 { 02530 current_condition = condition_comp( xxi, xet, xze ); 02531 if ( current_condition > condition ) { condition = current_condition; } 02532 } 02533 02534 02535 for( i=0; i<3; i++) 02536 { 02537 xxi[i] = coordinates[5][i] - coordinates[4][i]; 02538 xet[i] = coordinates[6][i] - coordinates[5][i]; 02539 xze[i] = coordinates[5][i] - coordinates[1][i]; 02540 } 02541 02542 02543 // norm jacobian and jacobian 02544 if( choices[0] || choices[1] ) 02545 { 02546 current_jacobian = determinant( xxi, xet, xze ); 02547 current_norm_jac = normalize_jacobian( current_jacobian, 02548 xxi, xet, xze ); 02549 02550 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02551 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02552 } 02553 02554 // oddy 02555 if( choices[2] ) 02556 { 02557 current_oddy = oddy_comp( xxi, xet, xze ); 02558 if ( current_oddy > oddy ) { oddy = current_oddy; } 02559 } 02560 02561 // condition 02562 if( choices[3] ) 02563 { 02564 current_condition = condition_comp( xxi, xet, xze ); 02565 if ( current_condition > condition ) { condition = current_condition; } 02566 } 02567 02568 02569 for( i=0; i<3; i++) 02570 { 02571 xxi[i] = coordinates[6][i] - coordinates[7][i]; 02572 xet[i] = coordinates[7][i] - coordinates[4][i]; 02573 xze[i] = coordinates[7][i] - coordinates[3][i]; 02574 } 02575 02576 02577 // norm jacobian and jacobian 02578 if( choices[0] || choices[1] ) 02579 { 02580 current_jacobian = determinant( xxi, xet, xze ); 02581 current_norm_jac = normalize_jacobian( current_jacobian, 02582 xxi, xet, xze ); 02583 02584 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02585 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02586 } 02587 02588 // oddy 02589 if( choices[2] ) 02590 { 02591 current_oddy = oddy_comp( xxi, xet, xze ); 02592 if ( current_oddy > oddy ) { oddy = current_oddy; } 02593 } 02594 02595 // condition 02596 if( choices[3] ) 02597 { 02598 current_condition = condition_comp( xxi, xet, xze ); 02599 if ( current_condition > condition ) { condition = current_condition; } 02600 } 02601 02602 02603 for( i=0; i<3; i++) 02604 { 02605 xxi[i] = coordinates[6][i] - coordinates[7][i]; 02606 xet[i] = coordinates[6][i] - coordinates[5][i]; 02607 xze[i] = coordinates[6][i] - coordinates[2][i]; 02608 } 02609 02610 // norm jacobian and jacobian 02611 if( choices[0] || choices[1] ) 02612 { 02613 current_jacobian = determinant( xxi, xet, xze ); 02614 current_norm_jac = normalize_jacobian( current_jacobian, 02615 xxi, xet, xze ); 02616 02617 if (current_norm_jac < norm_jacobian) { norm_jacobian = current_norm_jac; } 02618 if (current_jacobian < jacobian) { jacobian = current_jacobian; } 02619 } 02620 02621 // oddy 02622 if( choices[2] ) 02623 { 02624 current_oddy = oddy_comp( xxi, xet, xze ); 02625 if ( current_oddy > oddy ) { oddy = current_oddy; } 02626 } 02627 02628 // condition 02629 if( choices[3] ) 02630 { 02631 current_condition = condition_comp( xxi, xet, xze ); 02632 if ( current_condition > condition ) { condition = current_condition; } 02633 02634 condition /= 3.0; 02635 } 02636 02637 02638 answers[0] = jacobian; 02639 answers[1] = norm_jacobian; 02640 answers[2] = oddy; 02641 answers[3] = condition; 02642 02643 return 1.0; 02644 02645 } 02646 */ 02647 02648 /*! 02649 multiple quality metrics of a hex 02650 */ 02651 C_FUNC_DEF void v_hex_quality( int num_nodes, 02652 double coordinates[][3], 02653 unsigned int metrics_request_flag, 02654 HexMetricVals* metric_vals ) 02655 { 02656 memset( metric_vals, 0, sizeof( HexMetricVals ) ); 02657 02658 // max edge ratio, skew, taper, and volume 02659 if( metrics_request_flag & ( V_HEX_MAX_EDGE_RATIO | V_HEX_SKEW | V_HEX_TAPER ) ) 02660 { 02661 VerdictVector node_pos[8]; 02662 make_hex_nodes( coordinates, node_pos ); 02663 02664 VerdictVector efg1, efg2, efg3; 02665 efg1 = calc_hex_efg( 1, node_pos ); 02666 efg2 = calc_hex_efg( 2, node_pos ); 02667 efg3 = calc_hex_efg( 3, node_pos ); 02668 02669 if( metrics_request_flag & V_HEX_MAX_EDGE_RATIO ) 02670 { 02671 double max_edge_ratio_12, max_edge_ratio_13, max_edge_ratio_23; 02672 02673 double mag_efg1 = efg1.length(); 02674 double mag_efg2 = efg2.length(); 02675 double mag_efg3 = efg3.length(); 02676 02677 max_edge_ratio_12 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg2 ), VERDICT_MIN( mag_efg1, mag_efg2 ) ); 02678 max_edge_ratio_13 = safe_ratio( VERDICT_MAX( mag_efg1, mag_efg3 ), VERDICT_MIN( mag_efg1, mag_efg3 ) ); 02679 max_edge_ratio_23 = safe_ratio( VERDICT_MAX( mag_efg2, mag_efg3 ), VERDICT_MIN( mag_efg2, mag_efg3 ) ); 02680 02681 metric_vals->max_edge_ratio = 02682 (double)VERDICT_MAX( max_edge_ratio_12, VERDICT_MAX( max_edge_ratio_13, max_edge_ratio_23 ) ); 02683 } 02684 02685 if( metrics_request_flag & V_HEX_SKEW ) 02686 { 02687 02688 VerdictVector vec1 = efg1; 02689 VerdictVector vec2 = efg2; 02690 VerdictVector vec3 = efg3; 02691 02692 if( vec1.normalize() <= VERDICT_DBL_MIN || vec2.normalize() <= VERDICT_DBL_MIN || 02693 vec3.normalize() <= VERDICT_DBL_MIN ) 02694 { 02695 metric_vals->skew = (double)VERDICT_DBL_MAX; 02696 } 02697 else 02698 { 02699 double skewx = fabs( vec1 % vec2 ); 02700 double skewy = fabs( vec1 % vec3 ); 02701 double skewz = fabs( vec2 % vec3 ); 02702 02703 metric_vals->skew = (double)( VERDICT_MAX( skewx, VERDICT_MAX( skewy, skewz ) ) ); 02704 } 02705 } 02706 02707 if( metrics_request_flag & V_HEX_TAPER ) 02708 { 02709 VerdictVector efg12 = calc_hex_efg( 12, node_pos ); 02710 VerdictVector efg13 = calc_hex_efg( 13, node_pos ); 02711 VerdictVector efg23 = calc_hex_efg( 23, node_pos ); 02712 02713 double taperx = fabs( safe_ratio( efg12.length(), VERDICT_MIN( efg1.length(), efg2.length() ) ) ); 02714 double tapery = fabs( safe_ratio( efg13.length(), VERDICT_MIN( efg1.length(), efg3.length() ) ) ); 02715 double taperz = fabs( safe_ratio( efg23.length(), VERDICT_MIN( efg2.length(), efg3.length() ) ) ); 02716 02717 metric_vals->taper = (double)VERDICT_MAX( taperx, VERDICT_MAX( tapery, taperz ) ); 02718 } 02719 } 02720 02721 if( metrics_request_flag & V_HEX_VOLUME ) 02722 { 02723 metric_vals->volume = v_hex_volume( 8, coordinates ); 02724 } 02725 02726 if( metrics_request_flag & 02727 ( V_HEX_JACOBIAN | V_HEX_SCALED_JACOBIAN | V_HEX_CONDITION | V_HEX_SHEAR | V_HEX_SHAPE | 02728 V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE | V_HEX_STRETCH ) ) 02729 { 02730 02731 static const double two_thirds = 2.0 / 3.0; 02732 VerdictVector edges[12]; 02733 // the length squares 02734 double length_squared[12]; 02735 // make vectors from coordinates 02736 make_hex_edges( coordinates, edges ); 02737 02738 // calculate the length squares if we need to 02739 if( metrics_request_flag & 02740 ( V_HEX_JACOBIAN | V_HEX_SHEAR | V_HEX_SCALED_JACOBIAN | V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE | 02741 V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHEAR_AND_SIZE | V_HEX_STRETCH ) ) 02742 make_edge_length_squares( edges, length_squared ); 02743 02744 double jacobian = VERDICT_DBL_MAX, scaled_jacobian = VERDICT_DBL_MAX, condition = 0.0, shear = 1.0, shape = 1.0, 02745 oddy = 0.0; 02746 double current_jacobian, current_scaled_jacobian, current_condition, current_shape, detw = 0, det_sum = 0, 02747 current_oddy; 02748 VerdictBoolean rel_size_error = VERDICT_FALSE; 02749 02750 VerdictVector xxi, xet, xze; 02751 02752 // get weights if we need based on average size of a hex 02753 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 02754 { 02755 v_hex_get_weight( xxi, xet, xze ); 02756 detw = xxi % ( xet * xze ); 02757 if( detw < VERDICT_DBL_MIN ) rel_size_error = VERDICT_TRUE; 02758 } 02759 02760 xxi = edges[0] - edges[2] + edges[4] - edges[6]; 02761 xet = edges[1] - edges[3] + edges[5] - edges[7]; 02762 xze = edges[8] + edges[9] + edges[10] + edges[11]; 02763 02764 current_jacobian = xxi % ( xet * xze ) / 64.0; 02765 if( current_jacobian < jacobian ) jacobian = current_jacobian; 02766 02767 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 02768 { 02769 current_jacobian *= 64.0; 02770 current_scaled_jacobian = 02771 current_jacobian / sqrt( xxi.length_squared() * xet.length_squared() * xze.length_squared() ); 02772 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 02773 } 02774 02775 if( metrics_request_flag & V_HEX_CONDITION ) 02776 { 02777 current_condition = condition_comp( xxi, xet, xze ); 02778 if( current_condition > condition ) 02779 { 02780 condition = current_condition; 02781 } 02782 } 02783 02784 if( metrics_request_flag & V_HEX_ODDY ) 02785 { 02786 current_oddy = oddy_comp( xxi, xet, xze ); 02787 if( current_oddy > oddy ) 02788 { 02789 oddy = current_oddy; 02790 } 02791 } 02792 02793 // J(0,0,0) 02794 current_jacobian = edges[0] % ( -edges[3] * edges[8] ); 02795 if( current_jacobian < jacobian ) jacobian = current_jacobian; 02796 02797 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 02798 { 02799 det_sum += current_jacobian; 02800 } 02801 02802 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 02803 { 02804 if( length_squared[0] <= VERDICT_DBL_MIN || length_squared[3] <= VERDICT_DBL_MIN || 02805 length_squared[8] <= VERDICT_DBL_MIN ) 02806 { 02807 current_scaled_jacobian = VERDICT_DBL_MAX; 02808 } 02809 else 02810 { 02811 current_scaled_jacobian = 02812 current_jacobian / sqrt( length_squared[0] * length_squared[3] * length_squared[8] ); 02813 } 02814 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 02815 } 02816 02817 if( metrics_request_flag & V_HEX_CONDITION ) 02818 { 02819 current_condition = condition_comp( edges[0], -edges[3], edges[8] ); 02820 if( current_condition > condition ) 02821 { 02822 condition = current_condition; 02823 } 02824 } 02825 02826 if( metrics_request_flag & V_HEX_ODDY ) 02827 { 02828 current_oddy = oddy_comp( edges[0], -edges[3], edges[8] ); 02829 if( current_oddy > oddy ) 02830 { 02831 oddy = current_oddy; 02832 } 02833 } 02834 02835 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 02836 { 02837 if( current_jacobian > VERDICT_DBL_MIN ) 02838 current_shape = 3 * pow( current_jacobian, two_thirds ) / 02839 ( length_squared[0] + length_squared[3] + length_squared[8] ); 02840 else 02841 current_shape = 0; 02842 02843 if( current_shape < shape ) 02844 { 02845 shape = current_shape; 02846 } 02847 } 02848 02849 // J(1,0,0) 02850 current_jacobian = edges[1] % ( -edges[0] * edges[9] ); 02851 if( current_jacobian < jacobian ) jacobian = current_jacobian; 02852 02853 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 02854 { 02855 det_sum += current_jacobian; 02856 } 02857 02858 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 02859 { 02860 if( length_squared[1] <= VERDICT_DBL_MIN || length_squared[0] <= VERDICT_DBL_MIN || 02861 length_squared[9] <= VERDICT_DBL_MIN ) 02862 { 02863 current_scaled_jacobian = VERDICT_DBL_MAX; 02864 } 02865 else 02866 { 02867 current_scaled_jacobian = 02868 current_jacobian / sqrt( length_squared[1] * length_squared[0] * length_squared[9] ); 02869 } 02870 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 02871 } 02872 02873 if( metrics_request_flag & V_HEX_CONDITION ) 02874 { 02875 current_condition = condition_comp( edges[1], -edges[0], edges[9] ); 02876 if( current_condition > condition ) 02877 { 02878 condition = current_condition; 02879 } 02880 } 02881 02882 if( metrics_request_flag & V_HEX_ODDY ) 02883 { 02884 current_oddy = oddy_comp( edges[1], -edges[0], edges[9] ); 02885 if( current_oddy > oddy ) 02886 { 02887 oddy = current_oddy; 02888 } 02889 } 02890 02891 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 02892 { 02893 if( current_jacobian > VERDICT_DBL_MIN ) 02894 current_shape = 3 * pow( current_jacobian, two_thirds ) / 02895 ( length_squared[1] + length_squared[0] + length_squared[9] ); 02896 else 02897 current_shape = 0; 02898 02899 if( current_shape < shape ) 02900 { 02901 shape = current_shape; 02902 } 02903 } 02904 02905 // J(1,1,0) 02906 current_jacobian = edges[2] % ( -edges[1] * edges[10] ); 02907 if( current_jacobian < jacobian ) jacobian = current_jacobian; 02908 02909 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 02910 { 02911 det_sum += current_jacobian; 02912 } 02913 02914 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 02915 { 02916 if( length_squared[2] <= VERDICT_DBL_MIN || length_squared[1] <= VERDICT_DBL_MIN || 02917 length_squared[10] <= VERDICT_DBL_MIN ) 02918 { 02919 current_scaled_jacobian = VERDICT_DBL_MAX; 02920 } 02921 else 02922 { 02923 current_scaled_jacobian = 02924 current_jacobian / sqrt( length_squared[2] * length_squared[1] * length_squared[10] ); 02925 } 02926 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 02927 } 02928 02929 if( metrics_request_flag & V_HEX_CONDITION ) 02930 { 02931 current_condition = condition_comp( edges[2], -edges[1], edges[10] ); 02932 if( current_condition > condition ) 02933 { 02934 condition = current_condition; 02935 } 02936 } 02937 02938 if( metrics_request_flag & V_HEX_ODDY ) 02939 { 02940 current_oddy = oddy_comp( edges[2], -edges[1], edges[10] ); 02941 if( current_oddy > oddy ) 02942 { 02943 oddy = current_oddy; 02944 } 02945 } 02946 02947 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 02948 { 02949 if( current_jacobian > VERDICT_DBL_MIN ) 02950 current_shape = 3 * pow( current_jacobian, two_thirds ) / 02951 ( length_squared[2] + length_squared[1] + length_squared[10] ); 02952 else 02953 current_shape = 0; 02954 02955 if( current_shape < shape ) 02956 { 02957 shape = current_shape; 02958 } 02959 } 02960 02961 // J(0,1,0) 02962 current_jacobian = edges[3] % ( -edges[2] * edges[11] ); 02963 if( current_jacobian < jacobian ) jacobian = current_jacobian; 02964 02965 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 02966 { 02967 det_sum += current_jacobian; 02968 } 02969 02970 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 02971 { 02972 if( length_squared[3] <= VERDICT_DBL_MIN || length_squared[2] <= VERDICT_DBL_MIN || 02973 length_squared[11] <= VERDICT_DBL_MIN ) 02974 { 02975 current_scaled_jacobian = VERDICT_DBL_MAX; 02976 } 02977 else 02978 { 02979 current_scaled_jacobian = 02980 current_jacobian / sqrt( length_squared[3] * length_squared[2] * length_squared[11] ); 02981 } 02982 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 02983 } 02984 02985 if( metrics_request_flag & V_HEX_CONDITION ) 02986 { 02987 current_condition = condition_comp( edges[3], -edges[2], edges[11] ); 02988 if( current_condition > condition ) 02989 { 02990 condition = current_condition; 02991 } 02992 } 02993 02994 if( metrics_request_flag & V_HEX_ODDY ) 02995 { 02996 current_oddy = oddy_comp( edges[3], -edges[2], edges[11] ); 02997 if( current_oddy > oddy ) 02998 { 02999 oddy = current_oddy; 03000 } 03001 } 03002 03003 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 03004 { 03005 if( current_jacobian > VERDICT_DBL_MIN ) 03006 current_shape = 3 * pow( current_jacobian, two_thirds ) / 03007 ( length_squared[3] + length_squared[2] + length_squared[11] ); 03008 else 03009 current_shape = 0; 03010 03011 if( current_shape < shape ) 03012 { 03013 shape = current_shape; 03014 } 03015 } 03016 03017 // J(0,0,1) 03018 current_jacobian = edges[4] % ( -edges[8] * -edges[7] ); 03019 if( current_jacobian < jacobian ) jacobian = current_jacobian; 03020 03021 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 03022 { 03023 det_sum += current_jacobian; 03024 } 03025 03026 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 03027 { 03028 if( length_squared[4] <= VERDICT_DBL_MIN || length_squared[8] <= VERDICT_DBL_MIN || 03029 length_squared[7] <= VERDICT_DBL_MIN ) 03030 { 03031 current_scaled_jacobian = VERDICT_DBL_MAX; 03032 } 03033 else 03034 { 03035 current_scaled_jacobian = 03036 current_jacobian / sqrt( length_squared[4] * length_squared[8] * length_squared[7] ); 03037 } 03038 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 03039 } 03040 03041 if( metrics_request_flag & V_HEX_CONDITION ) 03042 { 03043 current_condition = condition_comp( edges[4], -edges[8], -edges[7] ); 03044 if( current_condition > condition ) 03045 { 03046 condition = current_condition; 03047 } 03048 } 03049 03050 if( metrics_request_flag & V_HEX_ODDY ) 03051 { 03052 current_oddy = oddy_comp( edges[4], -edges[8], -edges[7] ); 03053 if( current_oddy > oddy ) 03054 { 03055 oddy = current_oddy; 03056 } 03057 } 03058 03059 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 03060 { 03061 if( current_jacobian > VERDICT_DBL_MIN ) 03062 current_shape = 3 * pow( current_jacobian, two_thirds ) / 03063 ( length_squared[4] + length_squared[8] + length_squared[7] ); 03064 else 03065 current_shape = 0; 03066 03067 if( current_shape < shape ) 03068 { 03069 shape = current_shape; 03070 } 03071 } 03072 03073 // J(1,0,1) 03074 current_jacobian = -edges[4] % ( edges[5] * -edges[9] ); 03075 if( current_jacobian < jacobian ) jacobian = current_jacobian; 03076 03077 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 03078 { 03079 det_sum += current_jacobian; 03080 } 03081 03082 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 03083 { 03084 if( length_squared[4] <= VERDICT_DBL_MIN || length_squared[5] <= VERDICT_DBL_MIN || 03085 length_squared[9] <= VERDICT_DBL_MIN ) 03086 { 03087 current_scaled_jacobian = VERDICT_DBL_MAX; 03088 } 03089 else 03090 { 03091 current_scaled_jacobian = 03092 current_jacobian / sqrt( length_squared[4] * length_squared[5] * length_squared[9] ); 03093 } 03094 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 03095 } 03096 03097 if( metrics_request_flag & V_HEX_CONDITION ) 03098 { 03099 current_condition = condition_comp( -edges[4], edges[5], -edges[9] ); 03100 if( current_condition > condition ) 03101 { 03102 condition = current_condition; 03103 } 03104 } 03105 03106 if( metrics_request_flag & V_HEX_ODDY ) 03107 { 03108 current_oddy = oddy_comp( -edges[4], edges[5], -edges[9] ); 03109 if( current_oddy > oddy ) 03110 { 03111 oddy = current_oddy; 03112 } 03113 } 03114 03115 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 03116 { 03117 if( current_jacobian > VERDICT_DBL_MIN ) 03118 current_shape = 3 * pow( current_jacobian, two_thirds ) / 03119 ( length_squared[4] + length_squared[5] + length_squared[9] ); 03120 else 03121 current_shape = 0; 03122 03123 if( current_shape < shape ) 03124 { 03125 shape = current_shape; 03126 } 03127 } 03128 03129 // J(1,1,1) 03130 current_jacobian = -edges[5] % ( edges[6] * -edges[10] ); 03131 if( current_jacobian < jacobian ) jacobian = current_jacobian; 03132 03133 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 03134 { 03135 det_sum += current_jacobian; 03136 } 03137 03138 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 03139 { 03140 if( length_squared[5] <= VERDICT_DBL_MIN || length_squared[6] <= VERDICT_DBL_MIN || 03141 length_squared[10] <= VERDICT_DBL_MIN ) 03142 { 03143 current_scaled_jacobian = VERDICT_DBL_MAX; 03144 } 03145 else 03146 { 03147 current_scaled_jacobian = 03148 current_jacobian / sqrt( length_squared[5] * length_squared[6] * length_squared[10] ); 03149 } 03150 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 03151 } 03152 03153 if( metrics_request_flag & V_HEX_CONDITION ) 03154 { 03155 current_condition = condition_comp( -edges[5], edges[6], -edges[10] ); 03156 if( current_condition > condition ) 03157 { 03158 condition = current_condition; 03159 } 03160 } 03161 03162 if( metrics_request_flag & V_HEX_ODDY ) 03163 { 03164 current_oddy = oddy_comp( -edges[5], edges[6], -edges[10] ); 03165 if( current_oddy > oddy ) 03166 { 03167 oddy = current_oddy; 03168 } 03169 } 03170 03171 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 03172 { 03173 if( current_jacobian > VERDICT_DBL_MIN ) 03174 current_shape = 3 * pow( current_jacobian, two_thirds ) / 03175 ( length_squared[5] + length_squared[6] + length_squared[10] ); 03176 else 03177 current_shape = 0; 03178 03179 if( current_shape < shape ) 03180 { 03181 shape = current_shape; 03182 } 03183 } 03184 03185 // J(0,1,1) 03186 current_jacobian = -edges[6] % ( edges[7] * -edges[11] ); 03187 if( current_jacobian < jacobian ) jacobian = current_jacobian; 03188 03189 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 03190 { 03191 det_sum += current_jacobian; 03192 } 03193 03194 if( metrics_request_flag & ( V_HEX_SCALED_JACOBIAN | V_HEX_SHEAR | V_HEX_SHEAR_AND_SIZE ) ) 03195 { 03196 if( length_squared[6] <= VERDICT_DBL_MIN || length_squared[7] <= VERDICT_DBL_MIN || 03197 length_squared[11] <= VERDICT_DBL_MIN ) 03198 { 03199 current_scaled_jacobian = VERDICT_DBL_MAX; 03200 } 03201 else 03202 { 03203 current_scaled_jacobian = 03204 current_jacobian / sqrt( length_squared[6] * length_squared[7] * length_squared[11] ); 03205 } 03206 if( current_scaled_jacobian < scaled_jacobian ) shear = scaled_jacobian = current_scaled_jacobian; 03207 } 03208 03209 if( metrics_request_flag & V_HEX_CONDITION ) 03210 { 03211 current_condition = condition_comp( -edges[6], edges[7], -edges[11] ); 03212 if( current_condition > condition ) 03213 { 03214 condition = current_condition; 03215 } 03216 } 03217 03218 if( metrics_request_flag & V_HEX_ODDY ) 03219 { 03220 current_oddy = oddy_comp( -edges[6], edges[7], -edges[11] ); 03221 if( current_oddy > oddy ) 03222 { 03223 oddy = current_oddy; 03224 } 03225 } 03226 03227 if( metrics_request_flag & ( V_HEX_SHAPE | V_HEX_SHAPE_AND_SIZE ) ) 03228 { 03229 if( current_jacobian > VERDICT_DBL_MIN ) 03230 current_shape = 3 * pow( current_jacobian, two_thirds ) / 03231 ( length_squared[6] + length_squared[7] + length_squared[11] ); 03232 else 03233 current_shape = 0; 03234 03235 if( current_shape < shape ) 03236 { 03237 shape = current_shape; 03238 } 03239 } 03240 03241 if( metrics_request_flag & ( V_HEX_RELATIVE_SIZE_SQUARED | V_HEX_SHAPE_AND_SIZE | V_HEX_SHEAR_AND_SIZE ) ) 03242 { 03243 if( det_sum > VERDICT_DBL_MIN && rel_size_error != VERDICT_TRUE ) 03244 { 03245 double tau = det_sum / ( 8 * detw ); 03246 metric_vals->relative_size_squared = (double)VERDICT_MIN( tau * tau, 1.0 / tau / tau ); 03247 } 03248 else 03249 metric_vals->relative_size_squared = 0.0; 03250 } 03251 03252 // set values from above calculations 03253 if( metrics_request_flag & V_HEX_JACOBIAN ) metric_vals->jacobian = (double)jacobian; 03254 03255 if( metrics_request_flag & V_HEX_SCALED_JACOBIAN ) metric_vals->scaled_jacobian = (double)scaled_jacobian; 03256 03257 if( metrics_request_flag & V_HEX_CONDITION ) metric_vals->condition = (double)( condition / 3.0 ); 03258 03259 if( metrics_request_flag & V_HEX_SHEAR ) 03260 { 03261 if( shear < VERDICT_DBL_MIN ) // shear has range 0 to +1 03262 shear = 0; 03263 metric_vals->shear = (double)shear; 03264 } 03265 03266 if( metrics_request_flag & V_HEX_SHAPE ) metric_vals->shape = (double)shape; 03267 03268 if( metrics_request_flag & V_HEX_SHAPE_AND_SIZE ) 03269 metric_vals->shape_and_size = (double)( shape * metric_vals->relative_size_squared ); 03270 03271 if( metrics_request_flag & V_HEX_SHEAR_AND_SIZE ) 03272 metric_vals->shear_and_size = (double)( shear * metric_vals->relative_size_squared ); 03273 03274 if( metrics_request_flag & V_HEX_ODDY ) metric_vals->oddy = (double)oddy; 03275 03276 if( metrics_request_flag & V_HEX_STRETCH ) 03277 { 03278 static const double HEX_STRETCH_SCALE_FACTOR = sqrt( 3.0 ); 03279 double min_edge = length_squared[0]; 03280 for( int j = 1; j < 12; j++ ) 03281 min_edge = VERDICT_MIN( min_edge, length_squared[j] ); 03282 03283 double max_diag = diag_length( 1, coordinates ); 03284 03285 metric_vals->stretch = (double)( HEX_STRETCH_SCALE_FACTOR * ( safe_ratio( sqrt( min_edge ), max_diag ) ) ); 03286 } 03287 } 03288 03289 if( metrics_request_flag & V_HEX_DIAGONAL ) metric_vals->diagonal = v_hex_diagonal( num_nodes, coordinates ); 03290 if( metrics_request_flag & V_HEX_DIMENSION ) metric_vals->dimension = v_hex_dimension( num_nodes, coordinates ); 03291 if( metrics_request_flag & V_HEX_DISTORTION ) metric_vals->distortion = v_hex_distortion( num_nodes, coordinates ); 03292 03293 // take care of any overflow problems 03294 // max_edge_ratio 03295 if( metric_vals->max_edge_ratio > 0 ) 03296 metric_vals->max_edge_ratio = (double)VERDICT_MIN( metric_vals->max_edge_ratio, VERDICT_DBL_MAX ); 03297 else 03298 metric_vals->max_edge_ratio = (double)VERDICT_MAX( metric_vals->max_edge_ratio, -VERDICT_DBL_MAX ); 03299 03300 // skew 03301 if( metric_vals->skew > 0 ) 03302 metric_vals->skew = (double)VERDICT_MIN( metric_vals->skew, VERDICT_DBL_MAX ); 03303 else 03304 metric_vals->skew = (double)VERDICT_MAX( metric_vals->skew, -VERDICT_DBL_MAX ); 03305 03306 // taper 03307 if( metric_vals->taper > 0 ) 03308 metric_vals->taper = (double)VERDICT_MIN( metric_vals->taper, VERDICT_DBL_MAX ); 03309 else 03310 metric_vals->taper = (double)VERDICT_MAX( metric_vals->taper, -VERDICT_DBL_MAX ); 03311 03312 // volume 03313 if( metric_vals->volume > 0 ) 03314 metric_vals->volume = (double)VERDICT_MIN( metric_vals->volume, VERDICT_DBL_MAX ); 03315 else 03316 metric_vals->volume = (double)VERDICT_MAX( metric_vals->volume, -VERDICT_DBL_MAX ); 03317 03318 // stretch 03319 if( metric_vals->stretch > 0 ) 03320 metric_vals->stretch = (double)VERDICT_MIN( metric_vals->stretch, VERDICT_DBL_MAX ); 03321 else 03322 metric_vals->stretch = (double)VERDICT_MAX( metric_vals->stretch, -VERDICT_DBL_MAX ); 03323 03324 // diagonal 03325 if( metric_vals->diagonal > 0 ) 03326 metric_vals->diagonal = (double)VERDICT_MIN( metric_vals->diagonal, VERDICT_DBL_MAX ); 03327 else 03328 metric_vals->diagonal = (double)VERDICT_MAX( metric_vals->diagonal, -VERDICT_DBL_MAX ); 03329 03330 // dimension 03331 if( metric_vals->dimension > 0 ) 03332 metric_vals->dimension = (double)VERDICT_MIN( metric_vals->dimension, VERDICT_DBL_MAX ); 03333 else 03334 metric_vals->dimension = (double)VERDICT_MAX( metric_vals->dimension, -VERDICT_DBL_MAX ); 03335 03336 // oddy 03337 if( metric_vals->oddy > 0 ) 03338 metric_vals->oddy = (double)VERDICT_MIN( metric_vals->oddy, VERDICT_DBL_MAX ); 03339 else 03340 metric_vals->oddy = (double)VERDICT_MAX( metric_vals->oddy, -VERDICT_DBL_MAX ); 03341 03342 // condition 03343 if( metric_vals->condition > 0 ) 03344 metric_vals->condition = (double)VERDICT_MIN( metric_vals->condition, VERDICT_DBL_MAX ); 03345 else 03346 metric_vals->condition = (double)VERDICT_MAX( metric_vals->condition, -VERDICT_DBL_MAX ); 03347 03348 // jacobian 03349 if( metric_vals->jacobian > 0 ) 03350 metric_vals->jacobian = (double)VERDICT_MIN( metric_vals->jacobian, VERDICT_DBL_MAX ); 03351 else 03352 metric_vals->jacobian = (double)VERDICT_MAX( metric_vals->jacobian, -VERDICT_DBL_MAX ); 03353 03354 // scaled_jacobian 03355 if( metric_vals->scaled_jacobian > 0 ) 03356 metric_vals->scaled_jacobian = (double)VERDICT_MIN( metric_vals->scaled_jacobian, VERDICT_DBL_MAX ); 03357 else 03358 metric_vals->scaled_jacobian = (double)VERDICT_MAX( metric_vals->scaled_jacobian, -VERDICT_DBL_MAX ); 03359 03360 // shear 03361 if( metric_vals->shear > 0 ) 03362 metric_vals->shear = (double)VERDICT_MIN( metric_vals->shear, VERDICT_DBL_MAX ); 03363 else 03364 metric_vals->shear = (double)VERDICT_MAX( metric_vals->shear, -VERDICT_DBL_MAX ); 03365 03366 // shape 03367 if( metric_vals->shape > 0 ) 03368 metric_vals->shape = (double)VERDICT_MIN( metric_vals->shape, VERDICT_DBL_MAX ); 03369 else 03370 metric_vals->shape = (double)VERDICT_MAX( metric_vals->shape, -VERDICT_DBL_MAX ); 03371 03372 // relative_size_squared 03373 if( metric_vals->relative_size_squared > 0 ) 03374 metric_vals->relative_size_squared = (double)VERDICT_MIN( metric_vals->relative_size_squared, VERDICT_DBL_MAX ); 03375 else 03376 metric_vals->relative_size_squared = 03377 (double)VERDICT_MAX( metric_vals->relative_size_squared, -VERDICT_DBL_MAX ); 03378 03379 // shape_and_size 03380 if( metric_vals->shape_and_size > 0 ) 03381 metric_vals->shape_and_size = (double)VERDICT_MIN( metric_vals->shape_and_size, VERDICT_DBL_MAX ); 03382 else 03383 metric_vals->shape_and_size = (double)VERDICT_MAX( metric_vals->shape_and_size, -VERDICT_DBL_MAX ); 03384 03385 // shear_and_size 03386 if( metric_vals->shear_and_size > 0 ) 03387 metric_vals->shear_and_size = (double)VERDICT_MIN( metric_vals->shear_and_size, VERDICT_DBL_MAX ); 03388 else 03389 metric_vals->shear_and_size = (double)VERDICT_MAX( metric_vals->shear_and_size, -VERDICT_DBL_MAX ); 03390 03391 // distortion 03392 if( metric_vals->distortion > 0 ) 03393 metric_vals->distortion = (double)VERDICT_MIN( metric_vals->distortion, VERDICT_DBL_MAX ); 03394 else 03395 metric_vals->distortion = (double)VERDICT_MAX( metric_vals->distortion, -VERDICT_DBL_MAX ); 03396 03397 if( metrics_request_flag & V_HEX_MED_ASPECT_FROBENIUS ) 03398 metric_vals->med_aspect_frobenius = v_hex_med_aspect_frobenius( 8, coordinates ); 03399 03400 if( metrics_request_flag & V_HEX_EDGE_RATIO ) metric_vals->edge_ratio = v_hex_edge_ratio( 8, coordinates ); 03401 }