MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2006 Sandia National Laboratories. Developed at the 00005 University of Wisconsin--Madison under SNL contract number 00006 624796. The U.S. Government and the University of Wisconsin 00007 retain certain rights to this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 (2006) [email protected] 00024 00025 ***************************************************************** */ 00026 00027 /** \file TShapeSize2DB2.cpp 00028 * \brief 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #include "Mesquite.hpp" 00033 #include "TShapeSize2DB2.hpp" 00034 #include "MsqMatrix.hpp" 00035 #include "MsqError.hpp" 00036 #include "TMPDerivs.hpp" 00037 00038 #include <iostream> 00039 00040 namespace MBMesquite 00041 { 00042 00043 std::string TShapeSize2DB2::get_name() const 00044 { 00045 return "TShapeSize2DB2"; 00046 } 00047 00048 TShapeSize2DB2::~TShapeSize2DB2() {} 00049 00050 bool TShapeSize2DB2::evaluate( const MsqMatrix< 2, 2 >& T, double& result, MsqError& err ) 00051 { 00052 const double two_det = 2.0 * det( T ); 00053 if( invalid_determinant( two_det ) ) 00054 { // barrier 00055 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00056 return false; 00057 } 00058 00059 const double frob_sqr = sqr_Frobenius( T ); 00060 result = ( frob_sqr - 2.0 * sqrt( frob_sqr + two_det ) + 2.0 ) / two_det; 00061 return true; 00062 } 00063 00064 bool TShapeSize2DB2::evaluate_with_grad( const MsqMatrix< 2, 2 >& T, 00065 double& result, 00066 MsqMatrix< 2, 2 >& deriv_wrt_T, 00067 MsqError& err ) 00068 { 00069 const double d = det( T ); 00070 if( invalid_determinant( d ) ) 00071 { // barrier 00072 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00073 return false; 00074 } 00075 const double frob_sqr = sqr_Frobenius( T ); 00076 const double psi = sqrt( frob_sqr + 2.0 * det( T ) ); 00077 const double v = frob_sqr - 2.0 * psi + 2.0; 00078 result = v / ( 2 * d ); 00079 00080 // deriv of V wrt T 00081 MsqMatrix< 2, 2 > adjt = transpose_adj( T ); 00082 MsqMatrix< 2, 2 > v_wrt_T( T ); 00083 if( psi > 1e-50 ) 00084 { 00085 v_wrt_T *= ( 1.0 - 1.0 / psi ); 00086 v_wrt_T -= 1.0 / psi * adjt; 00087 v_wrt_T *= 2; 00088 } 00089 else 00090 { 00091 std::cout << "Warning: Division by zero avoided in TShapeSize2DB2::evaluate_with_grad()" << std::endl; 00092 } 00093 00094 // deriv of mu wrt T 00095 deriv_wrt_T = v_wrt_T; 00096 deriv_wrt_T *= 0.5 / d; 00097 deriv_wrt_T -= v / ( 2 * d * d ) * adjt; 00098 00099 return true; 00100 } 00101 00102 bool TShapeSize2DB2::evaluate_with_hess( const MsqMatrix< 2, 2 >& T, 00103 double& result, 00104 MsqMatrix< 2, 2 >& deriv_wrt_T, 00105 MsqMatrix< 2, 2 > second[3], 00106 MsqError& err ) 00107 { 00108 const double d = det( T ); 00109 if( invalid_determinant( d ) ) 00110 { // barrier 00111 MSQ_SETERR( err )( barrier_violated_msg, MsqError::BARRIER_VIOLATED ); 00112 return false; 00113 } 00114 const double frob_sqr = sqr_Frobenius( T ); 00115 const double psi = sqrt( frob_sqr + 2.0 * det( T ) ); 00116 const double v = frob_sqr - 2.0 * psi + 2.0; 00117 result = v / ( 2 * d ); 00118 00119 // deriv of V wrt T 00120 MsqMatrix< 2, 2 > adjt = transpose_adj( T ); 00121 MsqMatrix< 2, 2 > v_wrt_T( T ); 00122 if( psi > 1e-50 ) 00123 { 00124 v_wrt_T *= ( 1.0 - 1.0 / psi ); 00125 v_wrt_T -= 1.0 / psi * adjt; 00126 v_wrt_T *= 2; 00127 } 00128 else 00129 { 00130 std::cout << "Warning: Division by zero avoided in TShapeSize2DB2::evaluate_with_hess()" << std::endl; 00131 } 00132 00133 // deriv of mu wrt T 00134 deriv_wrt_T = v_wrt_T; 00135 deriv_wrt_T *= 0.5 / d; 00136 deriv_wrt_T -= v / ( 2 * d * d ) * adjt; 00137 00138 // second of V wrt T 00139 const double s = T( 0, 1 ) - T( 1, 0 ); 00140 const double tr = trace( T ); 00141 const double f = -2.0 / ( psi * psi * psi ); 00142 second[0]( 0, 0 ) = second[1]( 0, 1 ) = second[2]( 1, 1 ) = f * s * s; 00143 second[0]( 0, 1 ) = second[0]( 1, 0 ) = second[1]( 1, 1 ) = -f * s * tr; 00144 second[1]( 0, 0 ) = second[2]( 0, 1 ) = second[2]( 1, 0 ) = f * s * tr; 00145 second[0]( 1, 1 ) = second[2]( 0, 0 ) = -( second[1]( 1, 0 ) = -f * tr * tr ); 00146 pluseq_scaled_I( second, 2 ); 00147 00148 // second of mu wrt T 00149 const double x = 1.0 / ( 2 * d ); 00150 second[0] *= x; 00151 second[1] *= x; 00152 second[2] *= x; 00153 pluseq_scaled_2nd_deriv_of_det( second, v / ( -2 * d * d ) ); 00154 pluseq_scaled_outer_product( second, v / ( d * d * d ), adjt ); 00155 pluseq_scaled_sum_outer_product( second, -1 / ( 2 * d * d ), v_wrt_T, adjt ); 00156 00157 return true; 00158 } 00159 00160 } // namespace MBMesquite