MOAB: Mesh Oriented datABase  (version 5.4.1)
TInverseMeanRatio.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines