MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2007 Sandia National Laboratories. Developed at the 00005 University of Wisconsin--Madison under SNL contract number 00006 624796. The U.S. Government and the University of Wisconsin 00007 retain certain rights to this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2008) [email protected] 00024 00025 ***************************************************************** */ 00026 00027 /** \file TInverseMeanRatio.cpp 00028 * \brief 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #include "Mesquite.hpp" 00033 #include "TInverseMeanRatio.hpp" 00034 #include "MsqMatrix.hpp" 00035 #include "MsqError.hpp" 00036 00037 namespace MBMesquite 00038 { 00039 00040 std::string TInverseMeanRatio::get_name() const 00041 { 00042 return "TInverseMeanRatio"; 00043 } 00044 00045 TInverseMeanRatio::~TInverseMeanRatio() {} 00046 00047 bool TInverseMeanRatio::evaluate( const MsqMatrix< 2, 2 >& T, double& result, MsqError& err ) 00048 { 00049 const double d = det( T ); 00050 if( invalid_determinant( d ) ) 00051 { 00052 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00053 return false; 00054 } 00055 else 00056 { 00057 result = sqr_Frobenius( T ) / ( 2 * d ) - 1; 00058 return true; 00059 } 00060 } 00061 00062 bool TInverseMeanRatio::evaluate_with_grad( const MsqMatrix< 2, 2 >& T, 00063 double& result, 00064 MsqMatrix< 2, 2 >& deriv_wrt_T, 00065 MsqError& err ) 00066 { 00067 const double d = det( T ); 00068 if( invalid_determinant( d ) ) 00069 { 00070 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00071 deriv_wrt_T = MsqMatrix< 2, 2 >( 0.0 ); 00072 return false; 00073 } 00074 else 00075 { 00076 result = sqr_Frobenius( T ) / ( 2 * d ); 00077 deriv_wrt_T = transpose_adj( T ); 00078 deriv_wrt_T *= -result; 00079 deriv_wrt_T += T; 00080 deriv_wrt_T *= 1.0 / d; 00081 result -= 1.0; 00082 return true; 00083 } 00084 } 00085 00086 bool TInverseMeanRatio::evaluate_with_hess( const MsqMatrix< 2, 2 >& T, 00087 double& result, 00088 MsqMatrix< 2, 2 >& dA, 00089 MsqMatrix< 2, 2 > d2A[3], 00090 MsqError& err ) 00091 { 00092 const double d = det( T ); 00093 if( invalid_determinant( d ) ) 00094 { 00095 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00096 dA = d2A[0] = d2A[1] = d2A[2] = MsqMatrix< 2, 2 >( 0.0 ); 00097 return false; 00098 } 00099 else 00100 { 00101 const double inv_det = 1.0 / d; 00102 result = sqr_Frobenius( T ) * 0.5 * inv_det; 00103 00104 const MsqMatrix< 2, 2 > AT = transpose_adj( T ); 00105 dA = AT; 00106 dA *= -result; 00107 dA += T; 00108 dA *= inv_det; 00109 00110 const double p3 = -result * inv_det; 00111 const double p1 = -2.0 * p3 * inv_det; 00112 const double p2 = -inv_det * inv_det; 00113 const MsqMatrix< 2, 2 > AT_T_op_00 = outer( AT.row( 0 ), T.row( 0 ) ); 00114 const MsqMatrix< 2, 2 > AT_T_op_11 = outer( AT.row( 1 ), T.row( 1 ) ); 00115 d2A[0] = p1 * outer( AT.row( 0 ), AT.row( 0 ) ) + p2 * ( AT_T_op_00 + transpose( AT_T_op_00 ) ); 00116 d2A[1] = p1 * outer( AT.row( 0 ), AT.row( 1 ) ) + 00117 p2 * ( outer( AT.row( 0 ), T.row( 1 ) ) + outer( T.row( 0 ), AT.row( 1 ) ) ); 00118 d2A[2] = p1 * outer( AT.row( 1 ), AT.row( 1 ) ) + p2 * ( AT_T_op_11 + transpose( AT_T_op_11 ) ); 00119 00120 d2A[0]( 0, 0 ) += inv_det; 00121 d2A[0]( 1, 1 ) += inv_det; 00122 d2A[1]( 0, 1 ) += p3; 00123 d2A[1]( 1, 0 ) -= p3; 00124 d2A[2]( 0, 0 ) += inv_det; 00125 d2A[2]( 1, 1 ) += inv_det; 00126 00127 result -= 1.0; 00128 return true; 00129 } 00130 } 00131 00132 bool TInverseMeanRatio::evaluate( const MsqMatrix< 3, 3 >& T, double& result, MsqError& err ) 00133 { 00134 const double d = det( T ); 00135 if( invalid_determinant( d ) ) 00136 { 00137 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00138 return false; 00139 } 00140 else 00141 { 00142 const double det_cbrt = MBMesquite::cbrt( d ); 00143 result = sqr_Frobenius( T ) / ( 3 * det_cbrt * det_cbrt ) - 1; 00144 return true; 00145 } 00146 } 00147 00148 bool TInverseMeanRatio::evaluate_with_grad( const MsqMatrix< 3, 3 >& T, 00149 double& result, 00150 MsqMatrix< 3, 3 >& deriv_wrt_T, 00151 MsqError& err ) 00152 { 00153 const double d = det( T ); 00154 if( invalid_determinant( d ) ) 00155 { 00156 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00157 deriv_wrt_T = MsqMatrix< 3, 3 >( 0.0 ); 00158 return false; 00159 } 00160 00161 const double inv_det = 1.0 / d; 00162 const double inv_det_cbrt = MBMesquite::cbrt( inv_det ); 00163 const double inv_3_det_twothirds = inv_det_cbrt * inv_det_cbrt / 3.0; 00164 const double fnorm = sqr_Frobenius( T ); 00165 result = fnorm * inv_3_det_twothirds - 1; 00166 deriv_wrt_T = transpose_adj( T ); 00167 deriv_wrt_T *= -fnorm * inv_det / 3.0; 00168 deriv_wrt_T += T; 00169 deriv_wrt_T *= 2.0 * inv_3_det_twothirds; 00170 return true; 00171 } 00172 00173 bool TInverseMeanRatio::evaluate_with_hess( const MsqMatrix< 3, 3 >& T, 00174 double& result, 00175 MsqMatrix< 3, 3 >& dA, 00176 MsqMatrix< 3, 3 > d2A[6], 00177 MsqError& err ) 00178 { 00179 const double d = det( T ); 00180 if( invalid_determinant( d ) ) 00181 { 00182 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00183 dA = MsqMatrix< 3, 3 >( 0.0 ); 00184 return false; 00185 } 00186 00187 const double f0 = 1.0 / d; 00188 const double c = MBMesquite::cbrt( f0 ); 00189 const double f1 = 1.0 / 3.0 * c * c; 00190 const double f2 = sqr_Frobenius( T ); 00191 result = f1 * f2; 00192 00193 const double f3 = 2 * f1; 00194 const double f4 = result * ( 10.0 / 9.0 ) * f0 * f0; 00195 const double f5 = ( 1.0 / 3.0 ) * f0 * f3; 00196 const double f6 = 2 * f5; 00197 const double f7 = f2 * f5; 00198 00199 const MsqMatrix< 3, 3 > AT = transpose_adj( T ); 00200 dA = AT; 00201 dA *= ( -1.0 / 3.0 ) * f0 * f2; 00202 dA += T; 00203 dA *= f3; 00204 00205 MsqMatrix< 3, 3 > op; 00206 int i = 0; 00207 double s = 1; 00208 for( int r = 0; r < 3; ++r ) 00209 { 00210 d2A[i] = outer( AT.row( r ), AT.row( r ) ); 00211 d2A[i] *= f4; 00212 op = outer( AT.row( r ), T.row( r ) ); 00213 op += transpose( op ); 00214 op *= f6; 00215 d2A[i] -= op; 00216 00217 d2A[i]( 0, 0 ) += f3; 00218 d2A[i]( 1, 1 ) += f3; 00219 d2A[i]( 2, 2 ) += f3; 00220 00221 ++i; 00222 00223 for( int cc = r + 1; cc < 3; ++cc ) 00224 { 00225 d2A[i] = outer( AT.row( r ), AT.row( cc ) ); 00226 d2A[i] *= f4; 00227 op = outer( AT.row( r ), T.row( cc ) ); 00228 op += outer( T.row( r ), AT.row( cc ) ); 00229 op *= f6; 00230 d2A[i] -= op; 00231 00232 MsqMatrix< 1, 3 > rt = T.row( 3 - r - cc ); 00233 rt *= s * f7; 00234 d2A[i]( 0, 1 ) -= rt( 0, 2 ); 00235 d2A[i]( 0, 2 ) += rt( 0, 1 ); 00236 d2A[i]( 1, 0 ) += rt( 0, 2 ); 00237 d2A[i]( 1, 2 ) -= rt( 0, 0 ); 00238 d2A[i]( 2, 0 ) -= rt( 0, 1 ); 00239 d2A[i]( 2, 1 ) += rt( 0, 0 ); 00240 00241 ++i; 00242 s = -s; 00243 } 00244 } 00245 00246 result -= 1.0; 00247 return true; 00248 } 00249 00250 } // namespace MBMesquite