MOAB: Mesh Oriented datABase  (version 5.4.1)
MeanRatioFunctions.hpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2004 Sandia Corporation and Argonne National
00005     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
00006     with Sandia Corporation, the U.S. Government retains certain
00007     rights in 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     [email protected], [email protected], [email protected],
00024     [email protected], [email protected], [email protected]
00025 
00026   ***************************************************************** */
00027 // -*- Mode : c++; tab-width: 3; c-tab-always-indent: t; indent-tabs-mode: nil; c-basic-offset: 3
00028 // -*-
00029 
00030 /*! \file MeanRatioFunctions.hpp
00031 
00032 Header that defines generalized Mean Ratio function, gradient, and hessian
00033 evaluations.
00034 
00035 \author Todd Munson
00036 \date   2003-06-11
00037  */
00038 
00039 #ifndef MeanRatioFunctions_hpp
00040 #define MeanRatioFunctions_hpp
00041 
00042 #include <cmath>
00043 #include "Mesquite.hpp"
00044 #include "Vector3D.hpp"
00045 #include "Matrix3D.hpp"
00046 #include "Exponent.hpp"
00047 
00048 namespace MBMesquite
00049 {
00050 /***************************************************************************/
00051 /* Gradient calculation courtesy of Paul Hovland.  The code was modified   */
00052 /* to reduce the number of flops and intermediate variables, and improve   */
00053 /* the locality of reference.                                              */
00054 /***************************************************************************/
00055 /* The Hessian calculation is computes everyting in (x,y,z) blocks and     */
00056 /* stores only the upper triangular blocks.  The results are put into      */
00057 /* (c1,c2,c3,c4) order prior to returning the Hessian matrix.              */
00058 /***************************************************************************/
00059 /* The form of the function, gradient, and Hessian follows:                */
00060 /*   o(x) = a * pow(f(A(x)), b) * pow(g(A(x)), c)                          */
00061 /* where A(x) is the incidence matrix generated by:                        */
00062 /*           [x1-x0 x2-x0 x3-x0]                                           */
00063 /*    A(x) = [y1-y0 y2-y0 y3-y0] * inv(W)                                  */
00064 /*           [z1-z0 z2-z0 z3-z0]                                           */
00065 /* and f() is the squared Frobenius norm of A(x), and g() is the           */
00066 /* determinant of A(x).                                                    */
00067 /*                                                                         */
00068 /* The gradient is calculated as follows:                                  */
00069 /*   alpha := a*b*pow(f(A(x)),b-1)*pow(g(A(x)),c)                          */
00070 /*   beta  := a*c*pow(f(A(x)),b)*pow(g(A(x)),c-1)                          */
00071 /*                                                                         */
00072 /*   do/dx = (alpha * (df/dA) + beta * (dg/dA)) (dA/dx)                    */
00073 /*                                                                         */
00074 /*   (df/dA)_i = 2*A_i                                                     */
00075 /*   (dg/dA)_i = A_j*A_k - A_l*A_m for some {j,k,l,m}                      */
00076 /*                                                                         */
00077 /*   d^2o/dx^2 = (dA/dx)' * ((d alpha/dA) * (df/dA) +                      */
00078 /*                           (d  beta/dA) * (dg/dA)                        */
00079 /*                                  alpha * (d^2f/dA^2)                    */
00080 /*                                   beta * (d^2g/dA^2)) * (dA/dx)         */
00081 /*                                                                         */
00082 /*   Note: since A(x) is a linear function, there are no terms involving   */
00083 /*   d^2A/dx^2 since this matrix is zero.                                  */
00084 /*                                                                         */
00085 /*   gamma := a*b*c*pow(f(A(x)),b-1)*pow(g(A(x)),c-1)                      */
00086 /*   delta := a*c*(c-1)*pow(f(A(x)),b)*pow(g(A(x)),c-2)                    */
00087 /*   psi   := a*b*(b-1)*pow(f(A(x)),b-2)*pow(g(A(x)),c)                    */
00088 /*                                                                         */
00089 /*   d^2o/dx^2 = (dA/dx)' * (gamma*((dg/dA)'*(df/dA) + (df/dA)'*(dg/dA)) + */
00090 /*                           delta* (dg/dA)'*(dg/dA) +                     */
00091 /*                             psi* (df/dA)'*(df/dA) +                     */
00092 /*                           alpha*(d^2f/dA^2) +                           */
00093 /*                            beta*(d^2g/dA^2)) * (dA/dx)                  */
00094 /*                                                                         */
00095 /*   Note: (df/dA) and (dg/dA) are row vectors and we only calculate the   */
00096 /*   upper triangular part of the inner matrices.                          */
00097 /*                                                                         */
00098 /*   For regular tetrahedral elements, we have the following:              */
00099 /*                                                                         */
00100 /*           [-1         1        0         0         ]                    */
00101 /*       M = [-sqrt(3)  -sqrt(3)  2*sqrt(3) 0         ]                    */
00102 /*           [-sqrt(6)  -sqrt(6)  -sqrt(6)  3*sqrt(6) ]                    */
00103 /*                                                                         */
00104 /*           [M 0 0]                                                       */
00105 /*   dA/dx = [0 M 0]                                                       */
00106 /*           [0 0 M]                                                       */
00107 /***************************************************************************/
00108 
00109 /*****************************************************************************/
00110 /* Not all compilers substitute out constants (especially the square root).  */
00111 /* Therefore, they are substituted out manually.  The values below were      */
00112 /* calculated on a solaris machine using long doubles. I believe they are    */
00113 /* accurate.                                                                 */
00114 /*****************************************************************************/
00115 
00116 #define isqrt3  5.77350269189625797959429519858e-01 /*  1.0/sqrt(3.0)*/
00117 #define tisqrt3 1.15470053837925159591885903972e+00 /*  2.0/sqrt(3.0)*/
00118 #define isqrt6  4.08248290463863052509822647505e-01 /*  1.0/sqrt(6.0)*/
00119 #define tisqrt6 1.22474487139158915752946794252e+00 /*  3.0/sqrt(6.0)*/
00120 
00121 /*****************************************************************************/
00122 /* The following set of functions reference triangular elements to an        */
00123 /* equilateral triangle in the plane defined by the normal.  They are        */
00124 /* used when assessing the quality of a triangular element.  A zero          */
00125 /* return value indicates success, while a nonzero value indicates failure.  */
00126 /*****************************************************************************/
00127 
00128 /*****************************************************************************/
00129 /* Function evaluation requires 44 flops.                                    */
00130 /*   Reductions possible when b == 1 or c == 1                               */
00131 /*****************************************************************************/
00132 inline bool m_fcn_2e( double& obj,
00133                       const Vector3D x[3],
00134                       const Vector3D& n,
00135                       const double a,
00136                       const Exponent& b,
00137                       const Exponent& c )
00138 {
00139     double matr[9], f;
00140     double g;
00141 
00142     /* Calculate M = [A*inv(W) n] */
00143     matr[0] = x[1][0] - x[0][0];
00144     matr[1] = ( 2.0 * x[2][0] - x[1][0] - x[0][0] ) * isqrt3;
00145     matr[2] = n[0];
00146 
00147     matr[3] = x[1][1] - x[0][1];
00148     matr[4] = ( 2.0 * x[2][1] - x[1][1] - x[0][1] ) * isqrt3;
00149     matr[5] = n[1];
00150 
00151     matr[6] = x[1][2] - x[0][2];
00152     matr[7] = ( 2.0 * x[2][2] - x[1][2] - x[0][2] ) * isqrt3;
00153     matr[8] = n[2];
00154 
00155     /* Calculate det(M). */
00156     g = matr[0] * ( matr[4] * matr[8] - matr[5] * matr[7] ) + matr[3] * ( matr[2] * matr[7] - matr[1] * matr[8] ) +
00157         matr[6] * ( matr[1] * matr[5] - matr[2] * matr[4] );
00158     if( g < MSQ_MIN )
00159     {
00160         obj = g;
00161         return false;
00162     }
00163 
00164     /* Calculate norm(M). */
00165     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[3] * matr[3] + matr[4] * matr[4] + matr[6] * matr[6] +
00166         matr[7] * matr[7];
00167 
00168     /* Calculate objective function. */
00169     obj = a * b.raise( f ) * c.raise( g );
00170     return true;
00171 }
00172 
00173 /*****************************************************************************/
00174 /* Gradient evaluation requires 88 flops.                                    */
00175 /*   Reductions possible when b == 1 or c == 1                               */
00176 /*****************************************************************************/
00177 inline bool g_fcn_2e( double& obj,
00178                       Vector3D g_obj[3],
00179                       const Vector3D x[3],
00180                       const Vector3D& n,
00181                       const double a,
00182                       const Exponent& b,
00183                       const Exponent& c )
00184 {
00185     double matr[9], f;
00186     double adj_m[9], g;  // adj_m[2,5,8] not used
00187     double loc1, loc2, loc3;
00188 
00189     /* Calculate M = [A*inv(W) n] */
00190     matr[0] = x[1][0] - x[0][0];
00191     matr[1] = ( 2.0 * x[2][0] - x[1][0] - x[0][0] ) * isqrt3;
00192     matr[2] = n[0];
00193 
00194     matr[3] = x[1][1] - x[0][1];
00195     matr[4] = ( 2.0 * x[2][1] - x[1][1] - x[0][1] ) * isqrt3;
00196     matr[5] = n[1];
00197 
00198     matr[6] = x[1][2] - x[0][2];
00199     matr[7] = ( 2.0 * x[2][2] - x[1][2] - x[0][2] ) * isqrt3;
00200     matr[8] = n[2];
00201 
00202     /* Calculate det([n M]). */
00203     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
00204     loc2 = matr[2] * matr[7] - matr[1] * matr[8];
00205     loc3 = matr[1] * matr[5] - matr[2] * matr[4];
00206     g    = matr[0] * loc1 + matr[3] * loc2 + matr[6] * loc3;
00207     if( g < MSQ_MIN )
00208     {
00209         obj = g;
00210         return false;
00211     }
00212 
00213     /* Calculate norm(M). */
00214     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[3] * matr[3] + matr[4] * matr[4] + matr[6] * matr[6] +
00215         matr[7] * matr[7];
00216 
00217     /* Calculate objective function. */
00218     obj = a * b.raise( f ) * c.raise( g );
00219 
00220     /* Calculate the derivative of the objective function.    */
00221     f = b.value() * obj / f; /* Constant on nabla f      */
00222     g = c.value() * obj / g; /* Constant on nable g      */
00223     f *= 2.0;                /* Modification for nabla f */
00224 
00225     adj_m[0] = matr[0] * f + loc1 * g;
00226     adj_m[3] = matr[3] * f + loc2 * g;
00227     adj_m[6] = matr[6] * f + loc3 * g;
00228 
00229     loc1 = matr[0] * g;
00230     loc2 = matr[3] * g;
00231     loc3 = matr[6] * g;
00232 
00233     adj_m[1] = matr[1] * f + loc3 * matr[5] - loc2 * matr[8];
00234     adj_m[4] = matr[4] * f + loc1 * matr[8] - loc3 * matr[2];
00235     adj_m[7] = matr[7] * f + loc2 * matr[2] - loc1 * matr[5];
00236 
00237     loc1        = isqrt3 * adj_m[1];
00238     g_obj[0][0] = -adj_m[0] - loc1;
00239     g_obj[1][0] = adj_m[0] - loc1;
00240     g_obj[2][0] = 2.0 * loc1;
00241 
00242     loc1        = isqrt3 * adj_m[4];
00243     g_obj[0][1] = -adj_m[3] - loc1;
00244     g_obj[1][1] = adj_m[3] - loc1;
00245     g_obj[2][1] = 2.0 * loc1;
00246 
00247     loc1        = isqrt3 * adj_m[7];
00248     g_obj[0][2] = -adj_m[6] - loc1;
00249     g_obj[1][2] = adj_m[6] - loc1;
00250     g_obj[2][2] = 2.0 * loc1;
00251     return true;
00252 }
00253 
00254 /*****************************************************************************/
00255 /* Hessian evaluation requires 316 flops.                                    */
00256 /*   Reductions possible when b == 1 or c == 1                               */
00257 /*****************************************************************************/
00258 inline bool h_fcn_2e( double& obj,
00259                       Vector3D g_obj[3],
00260                       Matrix3D h_obj[6],
00261                       const Vector3D x[3],
00262                       const Vector3D& n,
00263                       const double a,
00264                       const Exponent& b,
00265                       const Exponent& c )
00266 {
00267     double matr[9], f;
00268     double adj_m[9], g;  // adj_m[2,5,8] not used
00269     double dg[9];        // dg[2,5,8] not used
00270     double loc0, loc1, loc2, loc3, loc4;
00271     double A[12], J_A[6], J_B[9], J_C[9], cross;  // only 2x2 corners used
00272 
00273     /* Calculate M = [A*inv(W) n] */
00274     matr[0] = x[1][0] - x[0][0];
00275     matr[1] = ( 2.0 * x[2][0] - x[1][0] - x[0][0] ) * isqrt3;
00276     matr[2] = n[0];
00277 
00278     matr[3] = x[1][1] - x[0][1];
00279     matr[4] = ( 2.0 * x[2][1] - x[1][1] - x[0][1] ) * isqrt3;
00280     matr[5] = n[1];
00281 
00282     matr[6] = x[1][2] - x[0][2];
00283     matr[7] = ( 2.0 * x[2][2] - x[1][2] - x[0][2] ) * isqrt3;
00284     matr[8] = n[2];
00285 
00286     /* Calculate det([n M]). */
00287     dg[0] = matr[4] * matr[8] - matr[5] * matr[7];
00288     dg[3] = matr[2] * matr[7] - matr[1] * matr[8];
00289     dg[6] = matr[1] * matr[5] - matr[2] * matr[4];
00290     g     = matr[0] * dg[0] + matr[3] * dg[3] + matr[6] * dg[6];
00291     if( g < MSQ_MIN )
00292     {
00293         obj = g;
00294         return false;
00295     }
00296 
00297     /* Calculate norm(M). */
00298     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[3] * matr[3] + matr[4] * matr[4] + matr[6] * matr[6] +
00299         matr[7] * matr[7];
00300 
00301     loc3 = f;
00302     loc4 = g;
00303 
00304     /* Calculate objective function. */
00305     obj = a * b.raise( f ) * c.raise( g );
00306 
00307     /* Calculate the derivative of the objective function.    */
00308     f = b.value() * obj / f; /* Constant on nabla f      */
00309     g = c.value() * obj / g; /* Constant on nable g      */
00310     f *= 2.0;                /* Modification for nabla f */
00311 
00312     dg[1] = matr[5] * matr[6] - matr[3] * matr[8];
00313     dg[4] = matr[0] * matr[8] - matr[2] * matr[6];
00314     dg[7] = matr[2] * matr[3] - matr[0] * matr[5];
00315 
00316     adj_m[0] = matr[0] * f + dg[0] * g;
00317     adj_m[1] = matr[1] * f + dg[1] * g;
00318     adj_m[3] = matr[3] * f + dg[3] * g;
00319     adj_m[4] = matr[4] * f + dg[4] * g;
00320     adj_m[6] = matr[6] * f + dg[6] * g;
00321     adj_m[7] = matr[7] * f + dg[7] * g;
00322 
00323     loc1        = isqrt3 * adj_m[1];
00324     g_obj[0][0] = -adj_m[0] - loc1;
00325     g_obj[1][0] = adj_m[0] - loc1;
00326     g_obj[2][0] = 2.0 * loc1;
00327 
00328     loc1        = isqrt3 * adj_m[4];
00329     g_obj[0][1] = -adj_m[3] - loc1;
00330     g_obj[1][1] = adj_m[3] - loc1;
00331     g_obj[2][1] = 2.0 * loc1;
00332 
00333     loc1        = isqrt3 * adj_m[7];
00334     g_obj[0][2] = -adj_m[6] - loc1;
00335     g_obj[1][2] = adj_m[6] - loc1;
00336     g_obj[2][2] = 2.0 * loc1;
00337 
00338     /* Calculate the hessian of the objective.                   */
00339     loc0  = f;                            /* Constant on nabla^2 f       */
00340     loc1  = g;                            /* Constant on nabla^2 g       */
00341     cross = f * c.value() / loc4;         /* Constant on nabla g nabla f */
00342     f     = f * ( b.value() - 1 ) / loc3; /* Constant on nabla f nabla f */
00343     g     = g * ( c.value() - 1 ) / loc4; /* Constant on nabla g nabla g */
00344     f *= 2.0;                             /* Modification for nabla f    */
00345 
00346     /* First block of rows */
00347     loc3 = matr[0] * f + dg[0] * cross;
00348     loc4 = dg[0] * g + matr[0] * cross;
00349 
00350     J_A[0] = loc0 + loc3 * matr[0] + loc4 * dg[0];
00351     J_A[1] = loc3 * matr[1] + loc4 * dg[1];
00352     J_B[0] = loc3 * matr[3] + loc4 * dg[3];
00353     J_B[1] = loc3 * matr[4] + loc4 * dg[4];
00354     J_C[0] = loc3 * matr[6] + loc4 * dg[6];
00355     J_C[1] = loc3 * matr[7] + loc4 * dg[7];
00356 
00357     loc3 = matr[1] * f + dg[1] * cross;
00358     loc4 = dg[1] * g + matr[1] * cross;
00359 
00360     J_A[3] = loc0 + loc3 * matr[1] + loc4 * dg[1];
00361     J_B[3] = loc3 * matr[3] + loc4 * dg[3];
00362     J_B[4] = loc3 * matr[4] + loc4 * dg[4];
00363     J_C[3] = loc3 * matr[6] + loc4 * dg[6];
00364     J_C[4] = loc3 * matr[7] + loc4 * dg[7];
00365 
00366     /* First diagonal block */
00367     loc2 = isqrt3 * J_A[1];
00368     A[0] = -J_A[0] - loc2;
00369     A[1] = J_A[0] - loc2;
00370 
00371     loc2 = isqrt3 * J_A[3];
00372     A[4] = -J_A[1] - loc2;
00373     A[5] = J_A[1] - loc2;
00374     A[6] = 2.0 * loc2;
00375 
00376     loc2           = isqrt3 * A[4];
00377     h_obj[0][0][0] = -A[0] - loc2;
00378     h_obj[1][0][0] = A[0] - loc2;
00379     h_obj[2][0][0] = 2.0 * loc2;
00380 
00381     loc2           = isqrt3 * A[5];
00382     h_obj[3][0][0] = A[1] - loc2;
00383     h_obj[4][0][0] = 2.0 * loc2;
00384 
00385     h_obj[5][0][0] = tisqrt3 * A[6];
00386 
00387     /* First off-diagonal block */
00388     loc2 = matr[8] * loc1;
00389     J_B[1] += loc2;
00390     J_B[3] -= loc2;
00391 
00392     loc2 = isqrt3 * J_B[3];
00393     A[0] = -J_B[0] - loc2;
00394     A[1] = J_B[0] - loc2;
00395     A[2] = 2.0 * loc2;
00396 
00397     loc2 = isqrt3 * J_B[4];
00398     A[4] = -J_B[1] - loc2;
00399     A[5] = J_B[1] - loc2;
00400     A[6] = 2.0 * loc2;
00401 
00402     loc2           = isqrt3 * A[4];
00403     h_obj[0][0][1] = -A[0] - loc2;
00404     h_obj[1][0][1] = A[0] - loc2;
00405     h_obj[2][0][1] = 2.0 * loc2;
00406 
00407     loc2           = isqrt3 * A[5];
00408     h_obj[1][1][0] = -A[1] - loc2;
00409     h_obj[3][0][1] = A[1] - loc2;
00410     h_obj[4][0][1] = 2.0 * loc2;
00411 
00412     loc2           = isqrt3 * A[6];
00413     h_obj[2][1][0] = -A[2] - loc2;
00414     h_obj[4][1][0] = A[2] - loc2;
00415     h_obj[5][0][1] = 2.0 * loc2;
00416 
00417     /* Second off-diagonal block */
00418     loc2 = matr[5] * loc1;
00419     J_C[1] -= loc2;
00420     J_C[3] += loc2;
00421 
00422     loc2 = isqrt3 * J_C[3];
00423     A[0] = -J_C[0] - loc2;
00424     A[1] = J_C[0] - loc2;
00425     A[2] = 2.0 * loc2;
00426 
00427     loc2 = isqrt3 * J_C[4];
00428     A[4] = -J_C[1] - loc2;
00429     A[5] = J_C[1] - loc2;
00430     A[6] = 2.0 * loc2;
00431 
00432     loc2           = isqrt3 * A[4];
00433     h_obj[0][0][2] = -A[0] - loc2;
00434     h_obj[1][0][2] = A[0] - loc2;
00435     h_obj[2][0][2] = 2.0 * loc2;
00436 
00437     loc2           = isqrt3 * A[5];
00438     h_obj[1][2][0] = -A[1] - loc2;
00439     h_obj[3][0][2] = A[1] - loc2;
00440     h_obj[4][0][2] = 2.0 * loc2;
00441 
00442     loc2           = isqrt3 * A[6];
00443     h_obj[2][2][0] = -A[2] - loc2;
00444     h_obj[4][2][0] = A[2] - loc2;
00445     h_obj[5][0][2] = 2.0 * loc2;
00446 
00447     /* Second block of rows */
00448     loc3 = matr[3] * f + dg[3] * cross;
00449     loc4 = dg[3] * g + matr[3] * cross;
00450 
00451     J_A[0] = loc0 + loc3 * matr[3] + loc4 * dg[3];
00452     J_A[1] = loc3 * matr[4] + loc4 * dg[4];
00453     J_B[0] = loc3 * matr[6] + loc4 * dg[6];
00454     J_B[1] = loc3 * matr[7] + loc4 * dg[7];
00455 
00456     loc3 = matr[4] * f + dg[4] * cross;
00457     loc4 = dg[4] * g + matr[4] * cross;
00458 
00459     J_A[3] = loc0 + loc3 * matr[4] + loc4 * dg[4];
00460     J_B[3] = loc3 * matr[6] + loc4 * dg[6];
00461     J_B[4] = loc3 * matr[7] + loc4 * dg[7];
00462 
00463     /* Second diagonal block */
00464     loc2 = isqrt3 * J_A[1];
00465     A[0] = -J_A[0] - loc2;
00466     A[1] = J_A[0] - loc2;
00467 
00468     loc2 = isqrt3 * J_A[3];
00469     A[4] = -J_A[1] - loc2;
00470     A[5] = J_A[1] - loc2;
00471     A[6] = 2.0 * loc2;
00472 
00473     loc2           = isqrt3 * A[4];
00474     h_obj[0][1][1] = -A[0] - loc2;
00475     h_obj[1][1][1] = A[0] - loc2;
00476     h_obj[2][1][1] = 2.0 * loc2;
00477 
00478     loc2           = isqrt3 * A[5];
00479     h_obj[3][1][1] = A[1] - loc2;
00480     h_obj[4][1][1] = 2.0 * loc2;
00481 
00482     h_obj[5][1][1] = tisqrt3 * A[6];
00483 
00484     /* Third off-diagonal block */
00485     loc2 = matr[2] * loc1;
00486     J_B[1] += loc2;
00487     J_B[3] -= loc2;
00488 
00489     loc2 = isqrt3 * J_B[3];
00490     A[0] = -J_B[0] - loc2;
00491     A[1] = J_B[0] - loc2;
00492     A[2] = 2.0 * loc2;
00493 
00494     loc2 = isqrt3 * J_B[4];
00495     A[4] = -J_B[1] - loc2;
00496     A[5] = J_B[1] - loc2;
00497     A[6] = 2.0 * loc2;
00498 
00499     loc2           = isqrt3 * A[4];
00500     h_obj[0][1][2] = -A[0] - loc2;
00501     h_obj[1][1][2] = A[0] - loc2;
00502     h_obj[2][1][2] = 2.0 * loc2;
00503 
00504     loc2           = isqrt3 * A[5];
00505     h_obj[1][2][1] = -A[1] - loc2;
00506     h_obj[3][1][2] = A[1] - loc2;
00507     h_obj[4][1][2] = 2.0 * loc2;
00508 
00509     loc2           = isqrt3 * A[6];
00510     h_obj[2][2][1] = -A[2] - loc2;
00511     h_obj[4][2][1] = A[2] - loc2;
00512     h_obj[5][1][2] = 2.0 * loc2;
00513 
00514     /* Third block of rows */
00515     loc3 = matr[6] * f + dg[6] * cross;
00516     loc4 = dg[6] * g + matr[6] * cross;
00517 
00518     J_A[0] = loc0 + loc3 * matr[6] + loc4 * dg[6];
00519     J_A[1] = loc3 * matr[7] + loc4 * dg[7];
00520 
00521     loc3 = matr[7] * f + dg[7] * cross;
00522     loc4 = dg[7] * g + matr[7] * cross;
00523 
00524     J_A[3] = loc0 + loc3 * matr[7] + loc4 * dg[7];
00525 
00526     /* Third diagonal block */
00527     loc2 = isqrt3 * J_A[1];
00528     A[0] = -J_A[0] - loc2;
00529     A[1] = J_A[0] - loc2;
00530 
00531     loc2 = isqrt3 * J_A[3];
00532     A[4] = -J_A[1] - loc2;
00533     A[5] = J_A[1] - loc2;
00534     A[6] = 2.0 * loc2;
00535 
00536     loc2           = isqrt3 * A[4];
00537     h_obj[0][2][2] = -A[0] - loc2;
00538     h_obj[1][2][2] = A[0] - loc2;
00539     h_obj[2][2][2] = 2.0 * loc2;
00540 
00541     loc2           = isqrt3 * A[5];
00542     h_obj[3][2][2] = A[1] - loc2;
00543     h_obj[4][2][2] = 2.0 * loc2;
00544 
00545     h_obj[5][2][2] = tisqrt3 * A[6];
00546 
00547     // completes diagonal blocks.
00548     h_obj[0].fill_lower_triangle();
00549     h_obj[3].fill_lower_triangle();
00550     h_obj[5].fill_lower_triangle();
00551     return true;
00552 }
00553 
00554 /*****************************************************************************/
00555 /* The following set of functions reference triangular elements to an        */
00556 /* right triangle in the plane defined by the normal.  They are used when    */
00557 /* assessing the quality of a quadrilateral elements.  A zero return value   */
00558 /* indicates success, while a nonzero value indicates failure.               */
00559 /*****************************************************************************/
00560 
00561 /*****************************************************************************/
00562 /* Function evaluation -- requires 41 flops.                                 */
00563 /*   Reductions possible when b == 1, c == 1, or d == 1                      */
00564 /*****************************************************************************/
00565 inline bool m_fcn_2i( double& obj,
00566                       const Vector3D x[3],
00567                       const Vector3D& n,
00568                       const double a,
00569                       const Exponent& b,
00570                       const Exponent& c,
00571                       const Vector3D& d )
00572 {
00573     double matr[9];
00574     double f;
00575     double g;
00576 
00577     /* Calculate M = A*inv(W). */
00578     matr[0] = d[0] * ( x[1][0] - x[0][0] );
00579     matr[1] = d[1] * ( x[2][0] - x[0][0] );
00580     matr[2] = n[0];
00581 
00582     matr[3] = d[0] * ( x[1][1] - x[0][1] );
00583     matr[4] = d[1] * ( x[2][1] - x[0][1] );
00584     matr[5] = n[1];
00585 
00586     matr[6] = d[0] * ( x[1][2] - x[0][2] );
00587     matr[7] = d[1] * ( x[2][2] - x[0][2] );
00588     matr[8] = n[2];
00589 
00590     /* Calculate det(M). */
00591     g = matr[0] * ( matr[4] * matr[8] - matr[5] * matr[7] ) + matr[3] * ( matr[2] * matr[7] - matr[1] * matr[8] ) +
00592         matr[6] * ( matr[1] * matr[5] - matr[2] * matr[4] );
00593     if( g < MSQ_MIN )
00594     {
00595         obj = g;
00596         return false;
00597     }
00598 
00599     /* Calculate norm(M). */
00600     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[3] * matr[3] + matr[4] * matr[4] + matr[6] * matr[6] +
00601         matr[7] * matr[7];
00602 
00603     /* Calculate objective function. */
00604     obj = a * b.raise( f ) * c.raise( g );
00605     return true;
00606 }
00607 
00608 /*****************************************************************************/
00609 /* Gradient requires 82 flops.                                               */
00610 /*   Reductions possible when b == 1, c == 1, or d == 1                      */
00611 /*****************************************************************************/
00612 inline bool g_fcn_2i( double& obj,
00613                       Vector3D g_obj[3],
00614                       const Vector3D x[3],
00615                       const Vector3D& n,
00616                       const double a,
00617                       const Exponent& b,
00618                       const Exponent& c,
00619                       const Vector3D& d )
00620 {
00621     double matr[9], f;
00622     double adj_m[9], g;  // adj_m[2,5,8] not used
00623     double loc1, loc2, loc3;
00624 
00625     /* Calculate M = [A*inv(W) n] */
00626     matr[0] = d[0] * ( x[1][0] - x[0][0] );
00627     matr[1] = d[1] * ( x[2][0] - x[0][0] );
00628     matr[2] = n[0];
00629 
00630     matr[3] = d[0] * ( x[1][1] - x[0][1] );
00631     matr[4] = d[1] * ( x[2][1] - x[0][1] );
00632     matr[5] = n[1];
00633 
00634     matr[6] = d[0] * ( x[1][2] - x[0][2] );
00635     matr[7] = d[1] * ( x[2][2] - x[0][2] );
00636     matr[8] = n[2];
00637 
00638     /* Calculate det([n M]). */
00639     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
00640     loc2 = matr[2] * matr[7] - matr[1] * matr[8];
00641     loc3 = matr[1] * matr[5] - matr[2] * matr[4];
00642     g    = matr[0] * loc1 + matr[3] * loc2 + matr[6] * loc3;
00643     if( g < MSQ_MIN )
00644     {
00645         obj = g;
00646         return false;
00647     }
00648 
00649     /* Calculate norm(M). */
00650     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[3] * matr[3] + matr[4] * matr[4] + matr[6] * matr[6] +
00651         matr[7] * matr[7];
00652 
00653     /* Calculate objective function. */
00654     obj = a * b.raise( f ) * c.raise( g );
00655 
00656     /* Calculate the derivative of the objective function.    */
00657     f = b.value() * obj / f; /* Constant on nabla f      */
00658     g = c.value() * obj / g; /* Constant on nable g      */
00659     f *= 2.0;                /* Modification for nabla f */
00660 
00661     adj_m[0] = d[0] * ( matr[0] * f + loc1 * g );
00662     adj_m[3] = d[0] * ( matr[3] * f + loc2 * g );
00663     adj_m[6] = d[0] * ( matr[6] * f + loc3 * g );
00664 
00665     loc1 = matr[0] * g;
00666     loc2 = matr[3] * g;
00667     loc3 = matr[6] * g;
00668 
00669     adj_m[1] = d[1] * ( matr[1] * f + loc3 * matr[5] - loc2 * matr[8] );
00670     adj_m[4] = d[1] * ( matr[4] * f + loc1 * matr[8] - loc3 * matr[2] );
00671     adj_m[7] = d[1] * ( matr[7] * f + loc2 * matr[2] - loc1 * matr[5] );
00672 
00673     g_obj[0][0] = -adj_m[0] - adj_m[1];
00674     g_obj[1][0] = adj_m[0];
00675     g_obj[2][0] = adj_m[1];
00676 
00677     g_obj[0][1] = -adj_m[3] - adj_m[4];
00678     g_obj[1][1] = adj_m[3];
00679     g_obj[2][1] = adj_m[4];
00680 
00681     g_obj[0][2] = -adj_m[6] - adj_m[7];
00682     g_obj[1][2] = adj_m[6];
00683     g_obj[2][2] = adj_m[7];
00684     return true;
00685 }
00686 
00687 /*****************************************************************************/
00688 /* Hessian requires 253 flops.                                               */
00689 /*   Reductions possible when b == 1, c == 1, or d == 1                      */
00690 /*****************************************************************************/
00691 inline bool h_fcn_2i( double& obj,
00692                       Vector3D g_obj[3],
00693                       Matrix3D h_obj[6],
00694                       const Vector3D x[3],
00695                       const Vector3D& n,
00696                       const double a,
00697                       const Exponent& b,
00698                       const Exponent& c,
00699                       const Vector3D& d )
00700 {
00701     double matr[9], f;
00702     double adj_m[9], g;  // adj_m[2,5,8] not used
00703     double dg[9];        // dg[2,5,8] not used
00704     double loc0, loc1, loc2, loc3, loc4;
00705     double A[12], J_A[6], J_B[9], J_C[9], cross;  // only 2x2 corners used
00706 
00707     const double scale[3] = { d[0] * d[0], d[0] * d[1], d[1] * d[1] };
00708 
00709     /* Calculate M = [A*inv(W) n] */
00710     matr[0] = d[0] * ( x[1][0] - x[0][0] );
00711     matr[1] = d[1] * ( x[2][0] - x[0][0] );
00712     matr[2] = n[0];
00713 
00714     matr[3] = d[0] * ( x[1][1] - x[0][1] );
00715     matr[4] = d[1] * ( x[2][1] - x[0][1] );
00716     matr[5] = n[1];
00717 
00718     matr[6] = d[0] * ( x[1][2] - x[0][2] );
00719     matr[7] = d[1] * ( x[2][2] - x[0][2] );
00720     matr[8] = n[2];
00721 
00722     /* Calculate det([n M]). */
00723     dg[0] = matr[4] * matr[8] - matr[5] * matr[7];
00724     dg[3] = matr[2] * matr[7] - matr[1] * matr[8];
00725     dg[6] = matr[1] * matr[5] - matr[2] * matr[4];
00726     g     = matr[0] * dg[0] + matr[3] * dg[3] + matr[6] * dg[6];
00727     if( g < MSQ_MIN )
00728     {
00729         obj = g;
00730         return false;
00731     }
00732 
00733     /* Calculate norm(M). */
00734     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[3] * matr[3] + matr[4] * matr[4] + matr[6] * matr[6] +
00735         matr[7] * matr[7];
00736 
00737     loc3 = f;
00738     loc4 = g;
00739 
00740     /* Calculate objective function. */
00741     obj = a * b.raise( f ) * c.raise( g );
00742 
00743     /* Calculate the derivative of the objective function.    */
00744     f = b.value() * obj / f; /* Constant on nabla f      */
00745     g = c.value() * obj / g; /* Constant on nable g      */
00746     f *= 2.0;                /* Modification for nabla f */
00747 
00748     dg[1] = matr[5] * matr[6] - matr[3] * matr[8];
00749     dg[4] = matr[0] * matr[8] - matr[2] * matr[6];
00750     dg[7] = matr[2] * matr[3] - matr[0] * matr[5];
00751 
00752     adj_m[0] = d[0] * ( matr[0] * f + dg[0] * g );
00753     adj_m[1] = d[1] * ( matr[1] * f + dg[1] * g );
00754     adj_m[3] = d[0] * ( matr[3] * f + dg[3] * g );
00755     adj_m[4] = d[1] * ( matr[4] * f + dg[4] * g );
00756     adj_m[6] = d[0] * ( matr[6] * f + dg[6] * g );
00757     adj_m[7] = d[1] * ( matr[7] * f + dg[7] * g );
00758 
00759     g_obj[0][0] = -adj_m[0] - adj_m[1];
00760     g_obj[1][0] = adj_m[0];
00761     g_obj[2][0] = adj_m[1];
00762 
00763     g_obj[0][1] = -adj_m[3] - adj_m[4];
00764     g_obj[1][1] = adj_m[3];
00765     g_obj[2][1] = adj_m[4];
00766 
00767     g_obj[0][2] = -adj_m[6] - adj_m[7];
00768     g_obj[1][2] = adj_m[6];
00769     g_obj[2][2] = adj_m[7];
00770 
00771     /* Calculate the hessian of the objective.                   */
00772     loc0  = f;                            /* Constant on nabla^2 f       */
00773     loc1  = g;                            /* Constant on nabla^2 g       */
00774     cross = f * c.value() / loc4;         /* Constant on nabla g nabla f */
00775     f     = f * ( b.value() - 1 ) / loc3; /* Constant on nabla f nabla f */
00776     g     = g * ( c.value() - 1 ) / loc4; /* Constant on nabla g nabla g */
00777     f *= 2.0;                             /* Modification for nabla f    */
00778 
00779     /* First block of rows */
00780     loc3 = matr[0] * f + dg[0] * cross;
00781     loc4 = dg[0] * g + matr[0] * cross;
00782 
00783     J_A[0] = loc0 + loc3 * matr[0] + loc4 * dg[0];
00784     J_A[1] = loc3 * matr[1] + loc4 * dg[1];
00785     J_B[0] = loc3 * matr[3] + loc4 * dg[3];
00786     J_B[1] = loc3 * matr[4] + loc4 * dg[4];
00787     J_C[0] = loc3 * matr[6] + loc4 * dg[6];
00788     J_C[1] = loc3 * matr[7] + loc4 * dg[7];
00789 
00790     loc3 = matr[1] * f + dg[1] * cross;
00791     loc4 = dg[1] * g + matr[1] * cross;
00792 
00793     J_A[3] = loc0 + loc3 * matr[1] + loc4 * dg[1];
00794     J_B[3] = loc3 * matr[3] + loc4 * dg[3];
00795     J_B[4] = loc3 * matr[4] + loc4 * dg[4];
00796     J_C[3] = loc3 * matr[6] + loc4 * dg[6];
00797     J_C[4] = loc3 * matr[7] + loc4 * dg[7];
00798 
00799     /* First diagonal block */
00800     J_A[0] *= scale[0];
00801     J_A[1] *= scale[1];
00802     J_A[3] *= scale[2];
00803 
00804     A[0] = -J_A[0] - J_A[1];
00805     A[4] = -J_A[1] - J_A[3];
00806 
00807     h_obj[0][0][0] = -A[0] - A[4];
00808     h_obj[1][0][0] = A[0];
00809     h_obj[2][0][0] = A[4];
00810 
00811     h_obj[3][0][0] = J_A[0];
00812     h_obj[4][0][0] = J_A[1];
00813 
00814     h_obj[5][0][0] = J_A[3];
00815 
00816     /* First off-diagonal block */
00817     loc2 = matr[8] * loc1;
00818     J_B[1] += loc2;
00819     J_B[3] -= loc2;
00820 
00821     J_B[0] *= scale[0];
00822     J_B[1] *= scale[1];
00823     J_B[3] *= scale[1];
00824     J_B[4] *= scale[2];
00825 
00826     A[0] = -J_B[0] - J_B[3];
00827     A[4] = -J_B[1] - J_B[4];
00828 
00829     h_obj[0][0][1] = -A[0] - A[4];
00830     h_obj[1][0][1] = A[0];
00831     h_obj[2][0][1] = A[4];
00832 
00833     h_obj[1][1][0] = -J_B[0] - J_B[1];
00834     h_obj[3][0][1] = J_B[0];
00835     h_obj[4][0][1] = J_B[1];
00836 
00837     h_obj[2][1][0] = -J_B[3] - J_B[4];
00838     h_obj[4][1][0] = J_B[3];
00839     h_obj[5][0][1] = J_B[4];
00840 
00841     /* Second off-diagonal block */
00842     loc2 = matr[5] * loc1;
00843     J_C[1] -= loc2;
00844     J_C[3] += loc2;
00845 
00846     J_C[0] *= scale[0];
00847     J_C[1] *= scale[1];
00848     J_C[3] *= scale[1];
00849     J_C[4] *= scale[2];
00850 
00851     A[0] = -J_C[0] - J_C[3];
00852     A[4] = -J_C[1] - J_C[4];
00853 
00854     h_obj[0][0][2] = -A[0] - A[4];
00855     h_obj[1][0][2] = A[0];
00856     h_obj[2][0][2] = A[4];
00857 
00858     h_obj[1][2][0] = -J_C[0] - J_C[1];
00859     h_obj[3][0][2] = J_C[0];
00860     h_obj[4][0][2] = J_C[1];
00861 
00862     h_obj[2][2][0] = -J_C[3] - J_C[4];
00863     h_obj[4][2][0] = J_C[3];
00864     h_obj[5][0][2] = J_C[4];
00865 
00866     /* Second block of rows */
00867     loc3 = matr[3] * f + dg[3] * cross;
00868     loc4 = dg[3] * g + matr[3] * cross;
00869 
00870     J_A[0] = loc0 + loc3 * matr[3] + loc4 * dg[3];
00871     J_A[1] = loc3 * matr[4] + loc4 * dg[4];
00872     J_B[0] = loc3 * matr[6] + loc4 * dg[6];
00873     J_B[1] = loc3 * matr[7] + loc4 * dg[7];
00874 
00875     loc3 = matr[4] * f + dg[4] * cross;
00876     loc4 = dg[4] * g + matr[4] * cross;
00877 
00878     J_A[3] = loc0 + loc3 * matr[4] + loc4 * dg[4];
00879     J_B[3] = loc3 * matr[6] + loc4 * dg[6];
00880     J_B[4] = loc3 * matr[7] + loc4 * dg[7];
00881 
00882     /* Second diagonal block */
00883     J_A[0] *= scale[0];
00884     J_A[1] *= scale[1];
00885     J_A[3] *= scale[2];
00886 
00887     A[0] = -J_A[0] - J_A[1];
00888     A[4] = -J_A[1] - J_A[3];
00889 
00890     h_obj[0][1][1] = -A[0] - A[4];
00891     h_obj[1][1][1] = A[0];
00892     h_obj[2][1][1] = A[4];
00893 
00894     h_obj[3][1][1] = J_A[0];
00895     h_obj[4][1][1] = J_A[1];
00896 
00897     h_obj[5][1][1] = J_A[3];
00898 
00899     /* Third off-diagonal block */
00900     loc2 = matr[2] * loc1;
00901     J_B[1] += loc2;
00902     J_B[3] -= loc2;
00903 
00904     J_B[0] *= scale[0];
00905     J_B[1] *= scale[1];
00906     J_B[3] *= scale[1];
00907     J_B[4] *= scale[2];
00908 
00909     A[0] = -J_B[0] - J_B[3];
00910     A[4] = -J_B[1] - J_B[4];
00911 
00912     h_obj[0][1][2] = -A[0] - A[4];
00913     h_obj[1][1][2] = A[0];
00914     h_obj[2][1][2] = A[4];
00915 
00916     h_obj[1][2][1] = -J_B[0] - J_B[1];
00917     h_obj[3][1][2] = J_B[0];
00918     h_obj[4][1][2] = J_B[1];
00919 
00920     h_obj[2][2][1] = -J_B[3] - J_B[4];
00921     h_obj[4][2][1] = J_B[3];
00922     h_obj[5][1][2] = J_B[4];
00923 
00924     /* Third block of rows */
00925     loc3 = matr[6] * f + dg[6] * cross;
00926     loc4 = dg[6] * g + matr[6] * cross;
00927 
00928     J_A[0] = loc0 + loc3 * matr[6] + loc4 * dg[6];
00929     J_A[1] = loc3 * matr[7] + loc4 * dg[7];
00930 
00931     loc3 = matr[7] * f + dg[7] * cross;
00932     loc4 = dg[7] * g + matr[7] * cross;
00933 
00934     J_A[3] = loc0 + loc3 * matr[7] + loc4 * dg[7];
00935 
00936     /* Third diagonal block */
00937     J_A[0] *= scale[0];
00938     J_A[1] *= scale[1];
00939     J_A[3] *= scale[2];
00940 
00941     A[0] = -J_A[0] - J_A[1];
00942     A[4] = -J_A[1] - J_A[3];
00943 
00944     h_obj[0][2][2] = -A[0] - A[4];
00945     h_obj[1][2][2] = A[0];
00946     h_obj[2][2][2] = A[4];
00947 
00948     h_obj[3][2][2] = J_A[0];
00949     h_obj[4][2][2] = J_A[1];
00950 
00951     h_obj[5][2][2] = J_A[3];
00952 
00953     // completes diagonal blocks.
00954     h_obj[0].fill_lower_triangle();
00955     h_obj[3].fill_lower_triangle();
00956     h_obj[5].fill_lower_triangle();
00957     return true;
00958 }
00959 
00960 /*****************************************************************************/
00961 /* The following set of functions reference tetrahedral elements to a        */
00962 /* regular tetrahedron.  They are used when assessing the quality of a       */
00963 /* tetrahedral element.  A zero return value indicates success, while        */
00964 /* a nonzero value indicates failure.                                        */
00965 /*****************************************************************************/
00966 
00967 /*****************************************************************************/
00968 /* Function evaluation requires 62 flops.                                    */
00969 /*   Reductions possible when b == 1 or c == 1                               */
00970 /*****************************************************************************/
00971 inline bool m_fcn_3e( double& obj, const Vector3D x[4], const double a, const Exponent& b, const Exponent& c )
00972 {
00973     double matr[9], f;
00974     double g;
00975 
00976     /* Calculate M = A*inv(W). */
00977     f       = x[1][0] + x[0][0];
00978     matr[0] = x[1][0] - x[0][0];
00979     matr[1] = ( 2.0 * x[2][0] - f ) * isqrt3;
00980     matr[2] = ( 3.0 * x[3][0] - x[2][0] - f ) * isqrt6;
00981 
00982     f       = x[1][1] + x[0][1];
00983     matr[3] = x[1][1] - x[0][1];
00984     matr[4] = ( 2.0 * x[2][1] - f ) * isqrt3;
00985     matr[5] = ( 3.0 * x[3][1] - x[2][1] - f ) * isqrt6;
00986 
00987     f       = x[1][2] + x[0][2];
00988     matr[6] = x[1][2] - x[0][2];
00989     matr[7] = ( 2.0 * x[2][2] - f ) * isqrt3;
00990     matr[8] = ( 3.0 * x[3][2] - x[2][2] - f ) * isqrt6;
00991 
00992     /* Calculate det(M). */
00993     g = matr[0] * ( matr[4] * matr[8] - matr[5] * matr[7] ) + matr[1] * ( matr[5] * matr[6] - matr[3] * matr[8] ) +
00994         matr[2] * ( matr[3] * matr[7] - matr[4] * matr[6] );
00995     if( g < MSQ_MIN )
00996     {
00997         obj = g;
00998         return false;
00999     }
01000 
01001     /* Calculate norm(M). */
01002     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
01003         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
01004 
01005     /* Calculate objective function. */
01006     obj = a * b.raise( f ) * c.raise( g );
01007     return true;
01008 }
01009 
01010 /*****************************************************************************/
01011 /* Gradient evaluation requires 133 flops.                                   */
01012 /*   Reductions possible when b == 1 or c == 1                               */
01013 /*****************************************************************************/
01014 inline bool g_fcn_3e( double& obj,
01015                       Vector3D g_obj[4],
01016                       const Vector3D x[4],
01017                       const double a,
01018                       const Exponent& b,
01019                       const Exponent& c )
01020 {
01021     double matr[9], f;
01022     double adj_m[9], g;
01023     double loc1, loc2, loc3;
01024 
01025     /* Calculate M = A*inv(W). */
01026     f       = x[1][0] + x[0][0];
01027     matr[0] = x[1][0] - x[0][0];
01028     matr[1] = ( 2.0 * x[2][0] - f ) * isqrt3;
01029     matr[2] = ( 3.0 * x[3][0] - x[2][0] - f ) * isqrt6;
01030 
01031     f       = x[1][1] + x[0][1];
01032     matr[3] = x[1][1] - x[0][1];
01033     matr[4] = ( 2.0 * x[2][1] - f ) * isqrt3;
01034     matr[5] = ( 3.0 * x[3][1] - x[2][1] - f ) * isqrt6;
01035 
01036     f       = x[1][2] + x[0][2];
01037     matr[6] = x[1][2] - x[0][2];
01038     matr[7] = ( 2.0 * x[2][2] - f ) * isqrt3;
01039     matr[8] = ( 3.0 * x[3][2] - x[2][2] - f ) * isqrt6;
01040 
01041     /* Calculate det(M). */
01042     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
01043     loc2 = matr[5] * matr[6] - matr[3] * matr[8];
01044     loc3 = matr[3] * matr[7] - matr[4] * matr[6];
01045     g    = matr[0] * loc1 + matr[1] * loc2 + matr[2] * loc3;
01046     if( g < MSQ_MIN )
01047     {
01048         obj = g;
01049         return false;
01050     }
01051 
01052     /* Calculate norm(M). */
01053     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
01054         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
01055 
01056     /* Calculate objective function. */
01057     obj = a * b.raise( f ) * c.raise( g );
01058 
01059     /* Calculate the derivative of the objective function.    */
01060     f = b.value() * obj / f; /* Constant on nabla f      */
01061     g = c.value() * obj / g; /* Constant on nable g      */
01062     f *= 2.0;                /* Modification for nabla f */
01063 
01064     adj_m[0] = matr[0] * f + loc1 * g;
01065     adj_m[1] = matr[1] * f + loc2 * g;
01066     adj_m[2] = matr[2] * f + loc3 * g;
01067 
01068     loc1 = matr[0] * g;
01069     loc2 = matr[1] * g;
01070     loc3 = matr[2] * g;
01071 
01072     adj_m[3] = matr[3] * f + loc3 * matr[7] - loc2 * matr[8];
01073     adj_m[4] = matr[4] * f + loc1 * matr[8] - loc3 * matr[6];
01074     adj_m[5] = matr[5] * f + loc2 * matr[6] - loc1 * matr[7];
01075 
01076     adj_m[6] = matr[6] * f + loc2 * matr[5] - loc3 * matr[4];
01077     adj_m[7] = matr[7] * f + loc3 * matr[3] - loc1 * matr[5];
01078     adj_m[8] = matr[8] * f + loc1 * matr[4] - loc2 * matr[3];
01079 
01080     loc1        = isqrt3 * adj_m[1];
01081     loc2        = isqrt6 * adj_m[2];
01082     loc3        = loc1 + loc2;
01083     g_obj[0][0] = -adj_m[0] - loc3;
01084     g_obj[1][0] = adj_m[0] - loc3;
01085     g_obj[2][0] = 2.0 * loc1 - loc2;
01086     g_obj[3][0] = 3.0 * loc2;
01087 
01088     loc1        = isqrt3 * adj_m[4];
01089     loc2        = isqrt6 * adj_m[5];
01090     loc3        = loc1 + loc2;
01091     g_obj[0][1] = -adj_m[3] - loc3;
01092     g_obj[1][1] = adj_m[3] - loc3;
01093     g_obj[2][1] = 2.0 * loc1 - loc2;
01094     g_obj[3][1] = 3.0 * loc2;
01095 
01096     loc1        = isqrt3 * adj_m[7];
01097     loc2        = isqrt6 * adj_m[8];
01098     loc3        = loc1 + loc2;
01099     g_obj[0][2] = -adj_m[6] - loc3;
01100     g_obj[1][2] = adj_m[6] - loc3;
01101     g_obj[2][2] = 2.0 * loc1 - loc2;
01102     g_obj[3][2] = 3.0 * loc2;
01103     return true;
01104 }
01105 
01106 /*****************************************************************************/
01107 /* Hessian evaluation requires 634 flops.                                    */
01108 /*   Reductions possible when b == 1 or c == 1                               */
01109 /*****************************************************************************/
01110 inline bool h_fcn_3e( double& obj,
01111                       Vector3D g_obj[4],
01112                       Matrix3D h_obj[10],
01113                       const Vector3D x[4],
01114                       const double a,
01115                       const Exponent& b,
01116                       const Exponent& c )
01117 {
01118     double matr[9], f;
01119     double adj_m[9], g;
01120     double dg[9], loc0, loc1, loc2, loc3, loc4;
01121     double A[12], J_A[6], J_B[9], J_C[9], cross;
01122 
01123     /* Calculate M = A*inv(W). */
01124     f       = x[1][0] + x[0][0];
01125     matr[0] = x[1][0] - x[0][0];
01126     matr[1] = ( 2.0 * x[2][0] - f ) * isqrt3;
01127     matr[2] = ( 3.0 * x[3][0] - x[2][0] - f ) * isqrt6;
01128 
01129     f       = x[1][1] + x[0][1];
01130     matr[3] = x[1][1] - x[0][1];
01131     matr[4] = ( 2.0 * x[2][1] - f ) * isqrt3;
01132     matr[5] = ( 3.0 * x[3][1] - x[2][1] - f ) * isqrt6;
01133 
01134     f       = x[1][2] + x[0][2];
01135     matr[6] = x[1][2] - x[0][2];
01136     matr[7] = ( 2.0 * x[2][2] - f ) * isqrt3;
01137     matr[8] = ( 3.0 * x[3][2] - x[2][2] - f ) * isqrt6;
01138 
01139     /* Calculate det(M). */
01140     dg[0] = matr[4] * matr[8] - matr[5] * matr[7];
01141     dg[1] = matr[5] * matr[6] - matr[3] * matr[8];
01142     dg[2] = matr[3] * matr[7] - matr[4] * matr[6];
01143     g     = matr[0] * dg[0] + matr[1] * dg[1] + matr[2] * dg[2];
01144     if( g < MSQ_MIN )
01145     {
01146         obj = g;
01147         return false;
01148     }
01149 
01150     /* Calculate norm(M). */
01151     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
01152         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
01153 
01154     loc3 = f;
01155     loc4 = g;
01156 
01157     /* Calculate objective function. */
01158     obj = a * b.raise( f ) * c.raise( g );
01159 
01160     /* Calculate the derivative of the objective function.    */
01161     f = b.value() * obj / f; /* Constant on nabla f      */
01162     g = c.value() * obj / g; /* Constant on nable g      */
01163     f *= 2.0;                /* Modification for nabla f */
01164 
01165     dg[3] = matr[2] * matr[7] - matr[1] * matr[8];
01166     dg[4] = matr[0] * matr[8] - matr[2] * matr[6];
01167     dg[5] = matr[1] * matr[6] - matr[0] * matr[7];
01168     dg[6] = matr[1] * matr[5] - matr[2] * matr[4];
01169     dg[7] = matr[2] * matr[3] - matr[0] * matr[5];
01170     dg[8] = matr[0] * matr[4] - matr[1] * matr[3];
01171 
01172     adj_m[0] = matr[0] * f + dg[0] * g;
01173     adj_m[1] = matr[1] * f + dg[1] * g;
01174     adj_m[2] = matr[2] * f + dg[2] * g;
01175     adj_m[3] = matr[3] * f + dg[3] * g;
01176     adj_m[4] = matr[4] * f + dg[4] * g;
01177     adj_m[5] = matr[5] * f + dg[5] * g;
01178     adj_m[6] = matr[6] * f + dg[6] * g;
01179     adj_m[7] = matr[7] * f + dg[7] * g;
01180     adj_m[8] = matr[8] * f + dg[8] * g;
01181 
01182     loc0        = isqrt3 * adj_m[1];
01183     loc1        = isqrt6 * adj_m[2];
01184     loc2        = loc0 + loc1;
01185     g_obj[0][0] = -adj_m[0] - loc2;
01186     g_obj[1][0] = adj_m[0] - loc2;
01187     g_obj[2][0] = 2.0 * loc0 - loc1;
01188     g_obj[3][0] = 3.0 * loc1;
01189 
01190     loc0        = isqrt3 * adj_m[4];
01191     loc1        = isqrt6 * adj_m[5];
01192     loc2        = loc0 + loc1;
01193     g_obj[0][1] = -adj_m[3] - loc2;
01194     g_obj[1][1] = adj_m[3] - loc2;
01195     g_obj[2][1] = 2.0 * loc0 - loc1;
01196     g_obj[3][1] = 3.0 * loc1;
01197 
01198     loc0        = isqrt3 * adj_m[7];
01199     loc1        = isqrt6 * adj_m[8];
01200     loc2        = loc0 + loc1;
01201     g_obj[0][2] = -adj_m[6] - loc2;
01202     g_obj[1][2] = adj_m[6] - loc2;
01203     g_obj[2][2] = 2.0 * loc0 - loc1;
01204     g_obj[3][2] = 3.0 * loc1;
01205 
01206     /* Calculate the hessian of the objective.                   */
01207     loc0  = f;                            /* Constant on nabla^2 f       */
01208     loc1  = g;                            /* Constant on nabla^2 g       */
01209     cross = f * c.value() / loc4;         /* Constant on nabla g nabla f */
01210     f     = f * ( b.value() - 1 ) / loc3; /* Constant on nabla f nabla f */
01211     g     = g * ( c.value() - 1 ) / loc4; /* Constant on nabla g nabla g */
01212     f *= 2.0;                             /* Modification for nabla f    */
01213 
01214     /* First block of rows */
01215     loc3 = matr[0] * f + dg[0] * cross;
01216     loc4 = dg[0] * g + matr[0] * cross;
01217 
01218     J_A[0] = loc0 + loc3 * matr[0] + loc4 * dg[0];
01219     J_A[1] = loc3 * matr[1] + loc4 * dg[1];
01220     J_A[2] = loc3 * matr[2] + loc4 * dg[2];
01221     J_B[0] = loc3 * matr[3] + loc4 * dg[3];
01222     J_B[1] = loc3 * matr[4] + loc4 * dg[4];
01223     J_B[2] = loc3 * matr[5] + loc4 * dg[5];
01224     J_C[0] = loc3 * matr[6] + loc4 * dg[6];
01225     J_C[1] = loc3 * matr[7] + loc4 * dg[7];
01226     J_C[2] = loc3 * matr[8] + loc4 * dg[8];
01227 
01228     loc3 = matr[1] * f + dg[1] * cross;
01229     loc4 = dg[1] * g + matr[1] * cross;
01230 
01231     J_A[3] = loc0 + loc3 * matr[1] + loc4 * dg[1];
01232     J_A[4] = loc3 * matr[2] + loc4 * dg[2];
01233     J_B[3] = loc3 * matr[3] + loc4 * dg[3];
01234     J_B[4] = loc3 * matr[4] + loc4 * dg[4];
01235     J_B[5] = loc3 * matr[5] + loc4 * dg[5];
01236     J_C[3] = loc3 * matr[6] + loc4 * dg[6];
01237     J_C[4] = loc3 * matr[7] + loc4 * dg[7];
01238     J_C[5] = loc3 * matr[8] + loc4 * dg[8];
01239 
01240     loc3 = matr[2] * f + dg[2] * cross;
01241     loc4 = dg[2] * g + matr[2] * cross;
01242 
01243     J_A[5] = loc0 + loc3 * matr[2] + loc4 * dg[2];
01244     J_B[6] = loc3 * matr[3] + loc4 * dg[3];
01245     J_B[7] = loc3 * matr[4] + loc4 * dg[4];
01246     J_B[8] = loc3 * matr[5] + loc4 * dg[5];
01247     J_C[6] = loc3 * matr[6] + loc4 * dg[6];
01248     J_C[7] = loc3 * matr[7] + loc4 * dg[7];
01249     J_C[8] = loc3 * matr[8] + loc4 * dg[8];
01250 
01251     /* First diagonal block */
01252     loc2 = isqrt3 * J_A[1];
01253     loc3 = isqrt6 * J_A[2];
01254     loc4 = loc2 + loc3;
01255 
01256     A[0] = -J_A[0] - loc4;
01257     A[1] = J_A[0] - loc4;
01258 
01259     loc2 = isqrt3 * J_A[3];
01260     loc3 = isqrt6 * J_A[4];
01261     loc4 = loc2 + loc3;
01262 
01263     A[4] = -J_A[1] - loc4;
01264     A[5] = J_A[1] - loc4;
01265     A[6] = 2.0 * loc2 - loc3;
01266 
01267     loc2 = isqrt3 * J_A[4];
01268     loc3 = isqrt6 * J_A[5];
01269     loc4 = loc2 + loc3;
01270 
01271     A[8]  = -J_A[2] - loc4;
01272     A[9]  = J_A[2] - loc4;
01273     A[10] = 2.0 * loc2 - loc3;
01274     A[11] = 3.0 * loc3;
01275 
01276     loc2 = isqrt3 * A[4];
01277     loc3 = isqrt6 * A[8];
01278     loc4 = loc2 + loc3;
01279 
01280     h_obj[0][0][0] = -A[0] - loc4;
01281     h_obj[1][0][0] = A[0] - loc4;
01282     h_obj[2][0][0] = 2.0 * loc2 - loc3;
01283     h_obj[3][0][0] = 3.0 * loc3;
01284 
01285     loc2 = isqrt3 * A[5];
01286     loc3 = isqrt6 * A[9];
01287 
01288     h_obj[4][0][0] = A[1] - loc2 - loc3;
01289     h_obj[5][0][0] = 2.0 * loc2 - loc3;
01290     h_obj[6][0][0] = 3.0 * loc3;
01291 
01292     loc3           = isqrt6 * A[10];
01293     h_obj[7][0][0] = tisqrt3 * A[6] - loc3;
01294     h_obj[8][0][0] = 3.0 * loc3;
01295 
01296     h_obj[9][0][0] = tisqrt6 * A[11];
01297 
01298     /* First off-diagonal block */
01299     loc2 = matr[8] * loc1;
01300     J_B[1] += loc2;
01301     J_B[3] -= loc2;
01302 
01303     loc2 = matr[7] * loc1;
01304     J_B[2] -= loc2;
01305     J_B[6] += loc2;
01306 
01307     loc2 = matr[6] * loc1;
01308     J_B[5] += loc2;
01309     J_B[7] -= loc2;
01310 
01311     loc2 = isqrt3 * J_B[3];
01312     loc3 = isqrt6 * J_B[6];
01313     loc4 = loc2 + loc3;
01314 
01315     A[0] = -J_B[0] - loc4;
01316     A[1] = J_B[0] - loc4;
01317     A[2] = 2.0 * loc2 - loc3;
01318     A[3] = 3.0 * loc3;
01319 
01320     loc2 = isqrt3 * J_B[4];
01321     loc3 = isqrt6 * J_B[7];
01322     loc4 = loc2 + loc3;
01323 
01324     A[4] = -J_B[1] - loc4;
01325     A[5] = J_B[1] - loc4;
01326     A[6] = 2.0 * loc2 - loc3;
01327     A[7] = 3.0 * loc3;
01328 
01329     loc2 = isqrt3 * J_B[5];
01330     loc3 = isqrt6 * J_B[8];
01331     loc4 = loc2 + loc3;
01332 
01333     A[8]  = -J_B[2] - loc4;
01334     A[9]  = J_B[2] - loc4;
01335     A[10] = 2.0 * loc2 - loc3;
01336     A[11] = 3.0 * loc3;
01337 
01338     loc2 = isqrt3 * A[4];
01339     loc3 = isqrt6 * A[8];
01340     loc4 = loc2 + loc3;
01341 
01342     h_obj[0][0][1] = -A[0] - loc4;
01343     h_obj[1][0][1] = A[0] - loc4;
01344     h_obj[2][0][1] = 2.0 * loc2 - loc3;
01345     h_obj[3][0][1] = 3.0 * loc3;
01346 
01347     loc2 = isqrt3 * A[5];
01348     loc3 = isqrt6 * A[9];
01349     loc4 = loc2 + loc3;
01350 
01351     h_obj[1][1][0] = -A[1] - loc4;
01352     h_obj[4][0][1] = A[1] - loc4;
01353     h_obj[5][0][1] = 2.0 * loc2 - loc3;
01354     h_obj[6][0][1] = 3.0 * loc3;
01355 
01356     loc2 = isqrt3 * A[6];
01357     loc3 = isqrt6 * A[10];
01358     loc4 = loc2 + loc3;
01359 
01360     h_obj[2][1][0] = -A[2] - loc4;
01361     h_obj[5][1][0] = A[2] - loc4;
01362     h_obj[7][0][1] = 2.0 * loc2 - loc3;
01363     h_obj[8][0][1] = 3.0 * loc3;
01364 
01365     loc2 = isqrt3 * A[7];
01366     loc3 = isqrt6 * A[11];
01367     loc4 = loc2 + loc3;
01368 
01369     h_obj[3][1][0] = -A[3] - loc4;
01370     h_obj[6][1][0] = A[3] - loc4;
01371     h_obj[8][1][0] = 2.0 * loc2 - loc3;
01372     h_obj[9][0][1] = 3.0 * loc3;
01373 
01374     /* Second off-diagonal block */
01375     loc2 = matr[5] * loc1;
01376     J_C[1] -= loc2;
01377     J_C[3] += loc2;
01378 
01379     loc2 = matr[4] * loc1;
01380     J_C[2] += loc2;
01381     J_C[6] -= loc2;
01382 
01383     loc2 = matr[3] * loc1;
01384     J_C[5] -= loc2;
01385     J_C[7] += loc2;
01386 
01387     loc2 = isqrt3 * J_C[3];
01388     loc3 = isqrt6 * J_C[6];
01389     loc4 = loc2 + loc3;
01390 
01391     A[0] = -J_C[0] - loc4;
01392     A[1] = J_C[0] - loc4;
01393     A[2] = 2.0 * loc2 - loc3;
01394     A[3] = 3.0 * loc3;
01395 
01396     loc2 = isqrt3 * J_C[4];
01397     loc3 = isqrt6 * J_C[7];
01398     loc4 = loc2 + loc3;
01399 
01400     A[4] = -J_C[1] - loc4;
01401     A[5] = J_C[1] - loc4;
01402     A[6] = 2.0 * loc2 - loc3;
01403     A[7] = 3.0 * loc3;
01404 
01405     loc2 = isqrt3 * J_C[5];
01406     loc3 = isqrt6 * J_C[8];
01407     loc4 = loc2 + loc3;
01408 
01409     A[8]  = -J_C[2] - loc4;
01410     A[9]  = J_C[2] - loc4;
01411     A[10] = 2.0 * loc2 - loc3;
01412     A[11] = 3.0 * loc3;
01413 
01414     loc2 = isqrt3 * A[4];
01415     loc3 = isqrt6 * A[8];
01416     loc4 = loc2 + loc3;
01417 
01418     h_obj[0][0][2] = -A[0] - loc4;
01419     h_obj[1][0][2] = A[0] - loc4;
01420     h_obj[2][0][2] = 2.0 * loc2 - loc3;
01421     h_obj[3][0][2] = 3.0 * loc3;
01422 
01423     loc2 = isqrt3 * A[5];
01424     loc3 = isqrt6 * A[9];
01425     loc4 = loc2 + loc3;
01426 
01427     h_obj[1][2][0] = -A[1] - loc4;
01428     h_obj[4][0][2] = A[1] - loc4;
01429     h_obj[5][0][2] = 2.0 * loc2 - loc3;
01430     h_obj[6][0][2] = 3.0 * loc3;
01431 
01432     loc2 = isqrt3 * A[6];
01433     loc3 = isqrt6 * A[10];
01434     loc4 = loc2 + loc3;
01435 
01436     h_obj[2][2][0] = -A[2] - loc4;
01437     h_obj[5][2][0] = A[2] - loc4;
01438     h_obj[7][0][2] = 2.0 * loc2 - loc3;
01439     h_obj[8][0][2] = 3.0 * loc3;
01440 
01441     loc2 = isqrt3 * A[7];
01442     loc3 = isqrt6 * A[11];
01443     loc4 = loc2 + loc3;
01444 
01445     h_obj[3][2][0] = -A[3] - loc4;
01446     h_obj[6][2][0] = A[3] - loc4;
01447     h_obj[8][2][0] = 2.0 * loc2 - loc3;
01448     h_obj[9][0][2] = 3.0 * loc3;
01449 
01450     /* Second block of rows */
01451     loc3 = matr[3] * f + dg[3] * cross;
01452     loc4 = dg[3] * g + matr[3] * cross;
01453 
01454     J_A[0] = loc0 + loc3 * matr[3] + loc4 * dg[3];
01455     J_A[1] = loc3 * matr[4] + loc4 * dg[4];
01456     J_A[2] = loc3 * matr[5] + loc4 * dg[5];
01457     J_B[0] = loc3 * matr[6] + loc4 * dg[6];
01458     J_B[1] = loc3 * matr[7] + loc4 * dg[7];
01459     J_B[2] = loc3 * matr[8] + loc4 * dg[8];
01460 
01461     loc3 = matr[4] * f + dg[4] * cross;
01462     loc4 = dg[4] * g + matr[4] * cross;
01463 
01464     J_A[3] = loc0 + loc3 * matr[4] + loc4 * dg[4];
01465     J_A[4] = loc3 * matr[5] + loc4 * dg[5];
01466     J_B[3] = loc3 * matr[6] + loc4 * dg[6];
01467     J_B[4] = loc3 * matr[7] + loc4 * dg[7];
01468     J_B[5] = loc3 * matr[8] + loc4 * dg[8];
01469 
01470     loc3 = matr[5] * f + dg[5] * cross;
01471     loc4 = dg[5] * g + matr[5] * cross;
01472 
01473     J_A[5] = loc0 + loc3 * matr[5] + loc4 * dg[5];
01474     J_B[6] = loc3 * matr[6] + loc4 * dg[6];
01475     J_B[7] = loc3 * matr[7] + loc4 * dg[7];
01476     J_B[8] = loc3 * matr[8] + loc4 * dg[8];
01477 
01478     /* Second diagonal block */
01479     loc2 = isqrt3 * J_A[1];
01480     loc3 = isqrt6 * J_A[2];
01481     loc4 = loc2 + loc3;
01482 
01483     A[0] = -J_A[0] - loc4;
01484     A[1] = J_A[0] - loc4;
01485 
01486     loc2 = isqrt3 * J_A[3];
01487     loc3 = isqrt6 * J_A[4];
01488     loc4 = loc2 + loc3;
01489 
01490     A[4] = -J_A[1] - loc4;
01491     A[5] = J_A[1] - loc4;
01492     A[6] = 2.0 * loc2 - loc3;
01493 
01494     loc2 = isqrt3 * J_A[4];
01495     loc3 = isqrt6 * J_A[5];
01496     loc4 = loc2 + loc3;
01497 
01498     A[8]  = -J_A[2] - loc4;
01499     A[9]  = J_A[2] - loc4;
01500     A[10] = 2.0 * loc2 - loc3;
01501     A[11] = 3.0 * loc3;
01502 
01503     loc2 = isqrt3 * A[4];
01504     loc3 = isqrt6 * A[8];
01505     loc4 = loc2 + loc3;
01506 
01507     h_obj[0][1][1] = -A[0] - loc4;
01508     h_obj[1][1][1] = A[0] - loc4;
01509     h_obj[2][1][1] = 2.0 * loc2 - loc3;
01510     h_obj[3][1][1] = 3.0 * loc3;
01511 
01512     loc2 = isqrt3 * A[5];
01513     loc3 = isqrt6 * A[9];
01514 
01515     h_obj[4][1][1] = A[1] - loc2 - loc3;
01516     h_obj[5][1][1] = 2.0 * loc2 - loc3;
01517     h_obj[6][1][1] = 3.0 * loc3;
01518 
01519     loc3           = isqrt6 * A[10];
01520     h_obj[7][1][1] = tisqrt3 * A[6] - loc3;
01521     h_obj[8][1][1] = 3.0 * loc3;
01522 
01523     h_obj[9][1][1] = tisqrt6 * A[11];
01524 
01525     /* Third off-diagonal block */
01526     loc2 = matr[2] * loc1;
01527     J_B[1] += loc2;
01528     J_B[3] -= loc2;
01529 
01530     loc2 = matr[1] * loc1;
01531     J_B[2] -= loc2;
01532     J_B[6] += loc2;
01533 
01534     loc2 = matr[0] * loc1;
01535     J_B[5] += loc2;
01536     J_B[7] -= loc2;
01537 
01538     loc2 = isqrt3 * J_B[3];
01539     loc3 = isqrt6 * J_B[6];
01540     loc4 = loc2 + loc3;
01541 
01542     A[0] = -J_B[0] - loc4;
01543     A[1] = J_B[0] - loc4;
01544     A[2] = 2.0 * loc2 - loc3;
01545     A[3] = 3.0 * loc3;
01546 
01547     loc2 = isqrt3 * J_B[4];
01548     loc3 = isqrt6 * J_B[7];
01549     loc4 = loc2 + loc3;
01550 
01551     A[4] = -J_B[1] - loc4;
01552     A[5] = J_B[1] - loc4;
01553     A[6] = 2.0 * loc2 - loc3;
01554     A[7] = 3.0 * loc3;
01555 
01556     loc2 = isqrt3 * J_B[5];
01557     loc3 = isqrt6 * J_B[8];
01558     loc4 = loc2 + loc3;
01559 
01560     A[8]  = -J_B[2] - loc4;
01561     A[9]  = J_B[2] - loc4;
01562     A[10] = 2.0 * loc2 - loc3;
01563     A[11] = 3.0 * loc3;
01564 
01565     loc2 = isqrt3 * A[4];
01566     loc3 = isqrt6 * A[8];
01567     loc4 = loc2 + loc3;
01568 
01569     h_obj[0][1][2] = -A[0] - loc4;
01570     h_obj[1][1][2] = A[0] - loc4;
01571     h_obj[2][1][2] = 2.0 * loc2 - loc3;
01572     h_obj[3][1][2] = 3.0 * loc3;
01573 
01574     loc2 = isqrt3 * A[5];
01575     loc3 = isqrt6 * A[9];
01576     loc4 = loc2 + loc3;
01577 
01578     h_obj[1][2][1] = -A[1] - loc4;
01579     h_obj[4][1][2] = A[1] - loc4;
01580     h_obj[5][1][2] = 2.0 * loc2 - loc3;
01581     h_obj[6][1][2] = 3.0 * loc3;
01582 
01583     loc2 = isqrt3 * A[6];
01584     loc3 = isqrt6 * A[10];
01585     loc4 = loc2 + loc3;
01586 
01587     h_obj[2][2][1] = -A[2] - loc4;
01588     h_obj[5][2][1] = A[2] - loc4;
01589     h_obj[7][1][2] = 2.0 * loc2 - loc3;
01590     h_obj[8][1][2] = 3.0 * loc3;
01591 
01592     loc2 = isqrt3 * A[7];
01593     loc3 = isqrt6 * A[11];
01594     loc4 = loc2 + loc3;
01595 
01596     h_obj[3][2][1] = -A[3] - loc4;
01597     h_obj[6][2][1] = A[3] - loc4;
01598     h_obj[8][2][1] = 2.0 * loc2 - loc3;
01599     h_obj[9][1][2] = 3.0 * loc3;
01600 
01601     /* Third block of rows */
01602     loc3 = matr[6] * f + dg[6] * cross;
01603     loc4 = dg[6] * g + matr[6] * cross;
01604 
01605     J_A[0] = loc0 + loc3 * matr[6] + loc4 * dg[6];
01606     J_A[1] = loc3 * matr[7] + loc4 * dg[7];
01607     J_A[2] = loc3 * matr[8] + loc4 * dg[8];
01608 
01609     loc3 = matr[7] * f + dg[7] * cross;
01610     loc4 = dg[7] * g + matr[7] * cross;
01611 
01612     J_A[3] = loc0 + loc3 * matr[7] + loc4 * dg[7];
01613     J_A[4] = loc3 * matr[8] + loc4 * dg[8];
01614 
01615     loc3 = matr[8] * f + dg[8] * cross;
01616     loc4 = dg[8] * g + matr[8] * cross;
01617 
01618     J_A[5] = loc0 + loc3 * matr[8] + loc4 * dg[8];
01619 
01620     /* Third diagonal block */
01621     loc2 = isqrt3 * J_A[1];
01622     loc3 = isqrt6 * J_A[2];
01623     loc4 = loc2 + loc3;
01624 
01625     A[0] = -J_A[0] - loc4;
01626     A[1] = J_A[0] - loc4;
01627 
01628     loc2 = isqrt3 * J_A[3];
01629     loc3 = isqrt6 * J_A[4];
01630     loc4 = loc2 + loc3;
01631 
01632     A[4] = -J_A[1] - loc4;
01633     A[5] = J_A[1] - loc4;
01634     A[6] = 2.0 * loc2 - loc3;
01635 
01636     loc2 = isqrt3 * J_A[4];
01637     loc3 = isqrt6 * J_A[5];
01638     loc4 = loc2 + loc3;
01639 
01640     A[8]  = -J_A[2] - loc4;
01641     A[9]  = J_A[2] - loc4;
01642     A[10] = 2.0 * loc2 - loc3;
01643     A[11] = 3.0 * loc3;
01644 
01645     loc2 = isqrt3 * A[4];
01646     loc3 = isqrt6 * A[8];
01647     loc4 = loc2 + loc3;
01648 
01649     h_obj[0][2][2] = -A[0] - loc4;
01650     h_obj[1][2][2] = A[0] - loc4;
01651     h_obj[2][2][2] = 2.0 * loc2 - loc3;
01652     h_obj[3][2][2] = 3.0 * loc3;
01653 
01654     loc2 = isqrt3 * A[5];
01655     loc3 = isqrt6 * A[9];
01656 
01657     h_obj[4][2][2] = A[1] - loc2 - loc3;
01658     h_obj[5][2][2] = 2.0 * loc2 - loc3;
01659     h_obj[6][2][2] = 3.0 * loc3;
01660 
01661     loc3           = isqrt6 * A[10];
01662     h_obj[7][2][2] = tisqrt3 * A[6] - loc3;
01663     h_obj[8][2][2] = 3.0 * loc3;
01664 
01665     h_obj[9][2][2] = tisqrt6 * A[11];
01666 
01667     // completes diagonal blocks.
01668     h_obj[0].fill_lower_triangle();
01669     h_obj[4].fill_lower_triangle();
01670     h_obj[7].fill_lower_triangle();
01671     h_obj[9].fill_lower_triangle();
01672     return true;
01673 }
01674 
01675 /*****************************************************************************/
01676 /* The following set of functions reference tetrahedral elements to a        */
01677 /* equilateral tetrahedron.  These functions are specialized toward          */
01678 /* obtaining the gradient and Hessian with respect to a single vertex.       */
01679 /*****************************************************************************/
01680 
01681 inline bool g_fcn_3e_v3( double& obj,
01682                          Vector3D& g_obj,
01683                          const Vector3D x[4],
01684                          const double a,
01685                          const Exponent& b,
01686                          const Exponent& c )
01687 {
01688     double matr[9], f, g;
01689     double loc1, loc2, loc3;
01690 
01691     /* Calculate M = A*inv(W). */
01692     f       = x[1][0] + x[0][0];
01693     matr[0] = x[1][0] - x[0][0];
01694     matr[1] = ( 2.0 * x[2][0] - f ) * isqrt3;
01695     matr[2] = ( 3.0 * x[3][0] - x[2][0] - f ) * isqrt6;
01696 
01697     f       = x[1][1] + x[0][1];
01698     matr[3] = x[1][1] - x[0][1];
01699     matr[4] = ( 2.0 * x[2][1] - f ) * isqrt3;
01700     matr[5] = ( 3.0 * x[3][1] - x[2][1] - f ) * isqrt6;
01701 
01702     f       = x[1][2] + x[0][2];
01703     matr[6] = x[1][2] - x[0][2];
01704     matr[7] = ( 2.0 * x[2][2] - f ) * isqrt3;
01705     matr[8] = ( 3.0 * x[3][2] - x[2][2] - f ) * isqrt6;
01706 
01707     /* Calculate det(M). */
01708     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
01709     loc2 = matr[5] * matr[6] - matr[3] * matr[8];
01710     loc3 = matr[3] * matr[7] - matr[4] * matr[6];
01711     g    = matr[0] * loc1 + matr[1] * loc2 + matr[2] * loc3;
01712     if( g < MSQ_MIN )
01713     {
01714         obj = g;
01715         return false;
01716     }
01717 
01718     /* Calculate norm(M). */
01719     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
01720         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
01721 
01722     /* Calculate objective function. */
01723     obj = a * b.raise( f ) * c.raise( g );
01724 
01725     /* Calculate the derivative of the objective function.    */
01726     f = b.value() * obj / f; /* Constant on nabla f      */
01727     g = c.value() * obj / g; /* Constant on nable g      */
01728     f *= 2.0;                /* Modification for nabla f */
01729 
01730     g_obj[0] = tisqrt6 * ( matr[2] * f + loc3 * g );
01731 
01732     loc1 = matr[0] * g;
01733     loc2 = matr[1] * g;
01734 
01735     g_obj[1] = tisqrt6 * ( matr[5] * f + loc2 * matr[6] - loc1 * matr[7] );
01736     g_obj[2] = tisqrt6 * ( matr[8] * f + loc1 * matr[4] - loc2 * matr[3] );
01737     return true;
01738 }
01739 
01740 inline bool g_fcn_3e_v0( double& obj,
01741                          Vector3D& g_obj,
01742                          const Vector3D x[4],
01743                          const double a,
01744                          const Exponent& b,
01745                          const Exponent& c )
01746 {
01747     static Vector3D my_x[4];
01748 
01749     my_x[0] = x[1];
01750     my_x[1] = x[3];
01751     my_x[2] = x[2];
01752     my_x[3] = x[0];
01753     return g_fcn_3e_v3( obj, g_obj, my_x, a, b, c );
01754 }
01755 
01756 inline bool g_fcn_3e_v1( double& obj,
01757                          Vector3D& g_obj,
01758                          const Vector3D x[4],
01759                          const double a,
01760                          const Exponent& b,
01761                          const Exponent& c )
01762 {
01763     static Vector3D my_x[4];
01764 
01765     my_x[0] = x[0];
01766     my_x[1] = x[2];
01767     my_x[2] = x[3];
01768     my_x[3] = x[1];
01769     return g_fcn_3e_v3( obj, g_obj, my_x, a, b, c );
01770 }
01771 
01772 inline bool g_fcn_3e_v2( double& obj,
01773                          Vector3D& g_obj,
01774                          const Vector3D x[4],
01775                          const double a,
01776                          const Exponent& b,
01777                          const Exponent& c )
01778 {
01779     static Vector3D my_x[4];
01780 
01781     my_x[0] = x[1];
01782     my_x[1] = x[0];
01783     my_x[2] = x[3];
01784     my_x[3] = x[2];
01785     return g_fcn_3e_v3( obj, g_obj, my_x, a, b, c );
01786 }
01787 
01788 inline bool h_fcn_3e_v3( double& obj,
01789                          Vector3D& g_obj,
01790                          Matrix3D& h_obj,
01791                          const Vector3D x[4],
01792                          const double a,
01793                          const Exponent& b,
01794                          const Exponent& c )
01795 {
01796     double matr[9], f, g;
01797     double dg[9], loc0, /*loc1,*/ loc3, loc4;
01798     double cross;
01799 
01800     /* Calculate M = A*inv(W). */
01801     f       = x[1][0] + x[0][0];
01802     matr[0] = x[1][0] - x[0][0];
01803     matr[1] = ( 2.0 * x[2][0] - f ) * isqrt3;
01804     matr[2] = ( 3.0 * x[3][0] - x[2][0] - f ) * isqrt6;
01805 
01806     f       = x[1][1] + x[0][1];
01807     matr[3] = x[1][1] - x[0][1];
01808     matr[4] = ( 2.0 * x[2][1] - f ) * isqrt3;
01809     matr[5] = ( 3.0 * x[3][1] - x[2][1] - f ) * isqrt6;
01810 
01811     f       = x[1][2] + x[0][2];
01812     matr[6] = x[1][2] - x[0][2];
01813     matr[7] = ( 2.0 * x[2][2] - f ) * isqrt3;
01814     matr[8] = ( 3.0 * x[3][2] - x[2][2] - f ) * isqrt6;
01815 
01816     /* Calculate det(M). */
01817     dg[0] = matr[4] * matr[8] - matr[5] * matr[7];
01818     dg[1] = matr[5] * matr[6] - matr[3] * matr[8];
01819     dg[2] = matr[3] * matr[7] - matr[4] * matr[6];
01820     g     = matr[0] * dg[0] + matr[1] * dg[1] + matr[2] * dg[2];
01821     if( g < MSQ_MIN )
01822     {
01823         obj = g;
01824         return false;
01825     }
01826 
01827     /* Calculate norm(M). */
01828     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
01829         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
01830 
01831     loc3 = f;
01832     loc4 = g;
01833 
01834     /* Calculate objective function. */
01835     obj = a * b.raise( f ) * c.raise( g );
01836 
01837     /* Calculate the derivative of the objective function.    */
01838     f = b.value() * obj / f; /* Constant on nabla f      */
01839     g = c.value() * obj / g; /* Constant on nable g      */
01840     f *= 2.0;                /* Modification for nabla f */
01841 
01842     dg[5] = matr[1] * matr[6] - matr[0] * matr[7];
01843     dg[8] = matr[0] * matr[4] - matr[1] * matr[3];
01844 
01845     g_obj[0] = tisqrt6 * ( matr[2] * f + dg[2] * g );
01846     g_obj[1] = tisqrt6 * ( matr[5] * f + dg[5] * g );
01847     g_obj[2] = tisqrt6 * ( matr[8] * f + dg[8] * g );
01848 
01849     /* Calculate the hessian of the objective.                   */
01850     loc0 = f; /* Constant on nabla^2 f       */
01851     //  loc1 = g;           /* Constant on nabla^2 g       */
01852     cross = f * c.value() / loc4;         /* Constant on nabla g nabla f */
01853     f     = f * ( b.value() - 1 ) / loc3; /* Constant on nabla f nabla f */
01854     g     = g * ( c.value() - 1 ) / loc4; /* Constant on nabla g nabla g */
01855     f *= 2.0;                             /* Modification for nabla f    */
01856 
01857     /* First block of rows */
01858     loc3 = matr[2] * f + dg[2] * cross;
01859     loc4 = dg[2] * g + matr[2] * cross;
01860 
01861     h_obj[0][0] = 1.5 * ( loc0 + loc3 * matr[2] + loc4 * dg[2] );
01862     h_obj[0][1] = 1.5 * ( loc3 * matr[5] + loc4 * dg[5] );
01863     h_obj[0][2] = 1.5 * ( loc3 * matr[8] + loc4 * dg[8] );
01864 
01865     /* Second block of rows */
01866     loc3 = matr[5] * f + dg[5] * cross;
01867     loc4 = dg[5] * g + matr[5] * cross;
01868 
01869     h_obj[1][1] = 1.5 * ( loc0 + loc3 * matr[5] + loc4 * dg[5] );
01870     h_obj[1][2] = 1.5 * ( loc3 * matr[8] + loc4 * dg[8] );
01871 
01872     /* Third block of rows */
01873     loc3 = matr[8] * f + dg[8] * cross;
01874     loc4 = dg[8] * g + matr[8] * cross;
01875 
01876     h_obj[2][2] = 1.5 * ( loc0 + loc3 * matr[8] + loc4 * dg[8] );
01877 
01878     // completes diagonal block.
01879     h_obj.fill_lower_triangle();
01880     return true;
01881 }
01882 
01883 inline bool h_fcn_3e_v0( double& obj,
01884                          Vector3D& g_obj,
01885                          Matrix3D& h_obj,
01886                          const Vector3D x[4],
01887                          const double a,
01888                          const Exponent& b,
01889                          const Exponent& c )
01890 {
01891     static Vector3D my_x[4];
01892 
01893     my_x[0] = x[1];
01894     my_x[1] = x[3];
01895     my_x[2] = x[2];
01896     my_x[3] = x[0];
01897     return h_fcn_3e_v3( obj, g_obj, h_obj, my_x, a, b, c );
01898 }
01899 
01900 inline bool h_fcn_3e_v1( double& obj,
01901                          Vector3D& g_obj,
01902                          Matrix3D& h_obj,
01903                          const Vector3D x[4],
01904                          const double a,
01905                          const Exponent& b,
01906                          const Exponent& c )
01907 {
01908     static Vector3D my_x[4];
01909 
01910     my_x[0] = x[0];
01911     my_x[1] = x[2];
01912     my_x[2] = x[3];
01913     my_x[3] = x[1];
01914     return h_fcn_3e_v3( obj, g_obj, h_obj, my_x, a, b, c );
01915 }
01916 
01917 inline bool h_fcn_3e_v2( double& obj,
01918                          Vector3D& g_obj,
01919                          Matrix3D& h_obj,
01920                          const Vector3D x[4],
01921                          const double a,
01922                          const Exponent& b,
01923                          const Exponent& c )
01924 {
01925     static Vector3D my_x[4];
01926 
01927     my_x[0] = x[1];
01928     my_x[1] = x[0];
01929     my_x[2] = x[3];
01930     my_x[3] = x[2];
01931     return h_fcn_3e_v3( obj, g_obj, h_obj, my_x, a, b, c );
01932 }
01933 
01934 /*****************************************************************************/
01935 /* The following set of functions reference tetrahedral elements to a        */
01936 /* right tetrahedron.  They are used when assessing the quality of a         */
01937 /* hexahedral element.  A zero return value indicates success, while         */
01938 /* a nonzero value indicates failure.                                        */
01939 /*****************************************************************************/
01940 
01941 /*****************************************************************************/
01942 /* Function evaluation requires 53 flops.                                    */
01943 /*   Reductions possible when b == 1, c == 1, or d == 1                      */
01944 /*****************************************************************************/
01945 inline bool m_fcn_3i( double& obj,
01946                       const Vector3D x[4],
01947                       const double a,
01948                       const Exponent& b,
01949                       const Exponent& c,
01950                       const Vector3D& d )
01951 {
01952     double matr[9], f;
01953     double g;
01954 
01955     /* Calculate M = A*inv(W). */
01956     matr[0] = d[0] * ( x[1][0] - x[0][0] );
01957     matr[1] = d[1] * ( x[2][0] - x[0][0] );
01958     matr[2] = d[2] * ( x[3][0] - x[0][0] );
01959 
01960     matr[3] = d[0] * ( x[1][1] - x[0][1] );
01961     matr[4] = d[1] * ( x[2][1] - x[0][1] );
01962     matr[5] = d[2] * ( x[3][1] - x[0][1] );
01963 
01964     matr[6] = d[0] * ( x[1][2] - x[0][2] );
01965     matr[7] = d[1] * ( x[2][2] - x[0][2] );
01966     matr[8] = d[2] * ( x[3][2] - x[0][2] );
01967 
01968     /* Calculate det(M). */
01969     g = matr[0] * ( matr[4] * matr[8] - matr[5] * matr[7] ) + matr[1] * ( matr[5] * matr[6] - matr[3] * matr[8] ) +
01970         matr[2] * ( matr[3] * matr[7] - matr[4] * matr[6] );
01971     if( g < MSQ_MIN )
01972     {
01973         obj = g;
01974         return false;
01975     }
01976 
01977     /* Calculate norm(M). */
01978     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
01979         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
01980 
01981     /* Calculate objective function. */
01982     obj = a * b.raise( f ) * c.raise( g );
01983     return true;
01984 }
01985 
01986 /*****************************************************************************/
01987 /* Gradient evaluation requires 115 flops.                                   */
01988 /*   Reductions possible when b == 1, c == 1, or d == 1                      */
01989 /*****************************************************************************/
01990 inline bool g_fcn_3i( double& obj,
01991                       Vector3D g_obj[4],
01992                       const Vector3D x[4],
01993                       const double a,
01994                       const Exponent& b,
01995                       const Exponent& c,
01996                       const Vector3D& d )
01997 {
01998     double matr[9], f;
01999     double adj_m[9], g;
02000     double loc1, loc2, loc3;
02001 
02002     /* Calculate M = A*inv(W). */
02003     matr[0] = d[0] * ( x[1][0] - x[0][0] );
02004     matr[1] = d[1] * ( x[2][0] - x[0][0] );
02005     matr[2] = d[2] * ( x[3][0] - x[0][0] );
02006 
02007     matr[3] = d[0] * ( x[1][1] - x[0][1] );
02008     matr[4] = d[1] * ( x[2][1] - x[0][1] );
02009     matr[5] = d[2] * ( x[3][1] - x[0][1] );
02010 
02011     matr[6] = d[0] * ( x[1][2] - x[0][2] );
02012     matr[7] = d[1] * ( x[2][2] - x[0][2] );
02013     matr[8] = d[2] * ( x[3][2] - x[0][2] );
02014 
02015     /* Calculate det(M). */
02016     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
02017     loc2 = matr[5] * matr[6] - matr[3] * matr[8];
02018     loc3 = matr[3] * matr[7] - matr[4] * matr[6];
02019     g    = matr[0] * loc1 + matr[1] * loc2 + matr[2] * loc3;
02020     if( g < MSQ_MIN )
02021     {
02022         obj = g;
02023         return false;
02024     }
02025 
02026     /* Calculate norm(M). */
02027     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
02028         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
02029 
02030     /* Calculate objective function. */
02031     obj = a * b.raise( f ) * c.raise( g );
02032 
02033     /* Calculate the derivative of the objective function.    */
02034     f = b.value() * obj / f; /* Constant on nabla f      */
02035     g = c.value() * obj / g; /* Constant on nable g      */
02036     f *= 2.0;                /* Modification for nabla f */
02037 
02038     adj_m[0] = d[0] * ( matr[0] * f + loc1 * g );
02039     adj_m[1] = d[1] * ( matr[1] * f + loc2 * g );
02040     adj_m[2] = d[2] * ( matr[2] * f + loc3 * g );
02041 
02042     loc1 = matr[0] * g;
02043     loc2 = matr[1] * g;
02044     loc3 = matr[2] * g;
02045 
02046     adj_m[3] = d[0] * ( matr[3] * f + loc3 * matr[7] - loc2 * matr[8] );
02047     adj_m[4] = d[1] * ( matr[4] * f + loc1 * matr[8] - loc3 * matr[6] );
02048     adj_m[5] = d[2] * ( matr[5] * f + loc2 * matr[6] - loc1 * matr[7] );
02049 
02050     adj_m[6] = d[0] * ( matr[6] * f + loc2 * matr[5] - loc3 * matr[4] );
02051     adj_m[7] = d[1] * ( matr[7] * f + loc3 * matr[3] - loc1 * matr[5] );
02052     adj_m[8] = d[2] * ( matr[8] * f + loc1 * matr[4] - loc2 * matr[3] );
02053 
02054     g_obj[0][0] = -adj_m[0] - adj_m[1] - adj_m[2];
02055     g_obj[1][0] = adj_m[0];
02056     g_obj[2][0] = adj_m[1];
02057     g_obj[3][0] = adj_m[2];
02058 
02059     g_obj[0][1] = -adj_m[3] - adj_m[4] - adj_m[5];
02060     g_obj[1][1] = adj_m[3];
02061     g_obj[2][1] = adj_m[4];
02062     g_obj[3][1] = adj_m[5];
02063 
02064     g_obj[0][2] = -adj_m[6] - adj_m[7] - adj_m[8];
02065     g_obj[1][2] = adj_m[6];
02066     g_obj[2][2] = adj_m[7];
02067     g_obj[3][2] = adj_m[8];
02068     return true;
02069 }
02070 
02071 /*****************************************************************************/
02072 /* Hessian evaluation requires 469 flops.                                    */
02073 /*   Reductions possible when b == 1, c == 1, or d == 1                      */
02074 /*****************************************************************************/
02075 inline int h_fcn_3i( double& obj,
02076                      Vector3D g_obj[4],
02077                      Matrix3D h_obj[10],
02078                      const Vector3D x[4],
02079                      const double a,
02080                      const Exponent& b,
02081                      const Exponent& c,
02082                      const Vector3D& d )
02083 {
02084     double matr[9], f;
02085     double adj_m[9], g;
02086     double dg[9], loc0, loc1, loc2, loc3, loc4;
02087     double A[3], J_A[6], J_B[9], J_C[9], cross;
02088 
02089     const double scale[6] = { d[0] * d[0], d[0] * d[1], d[0] * d[2], d[1] * d[1], d[1] * d[2], d[2] * d[2] };
02090 
02091     /* Calculate M = A*inv(W). */
02092     matr[0] = d[0] * ( x[1][0] - x[0][0] );
02093     matr[1] = d[1] * ( x[2][0] - x[0][0] );
02094     matr[2] = d[2] * ( x[3][0] - x[0][0] );
02095 
02096     matr[3] = d[0] * ( x[1][1] - x[0][1] );
02097     matr[4] = d[1] * ( x[2][1] - x[0][1] );
02098     matr[5] = d[2] * ( x[3][1] - x[0][1] );
02099 
02100     matr[6] = d[0] * ( x[1][2] - x[0][2] );
02101     matr[7] = d[1] * ( x[2][2] - x[0][2] );
02102     matr[8] = d[2] * ( x[3][2] - x[0][2] );
02103 
02104     /* Calculate det(M). */
02105     dg[0] = matr[4] * matr[8] - matr[5] * matr[7];
02106     dg[1] = matr[5] * matr[6] - matr[3] * matr[8];
02107     dg[2] = matr[3] * matr[7] - matr[4] * matr[6];
02108     g     = matr[0] * dg[0] + matr[1] * dg[1] + matr[2] * dg[2];
02109     if( g < MSQ_MIN )
02110     {
02111         obj = g;
02112         return false;
02113     }
02114 
02115     /* Calculate norm(M). */
02116     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
02117         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
02118 
02119     loc3 = f;
02120     loc4 = g;
02121 
02122     /* Calculate objective function. */
02123     obj = a * b.raise( f ) * c.raise( g );
02124 
02125     /* Calculate the derivative of the objective function.    */
02126     f = b.value() * obj / f; /* Constant on nabla f      */
02127     g = c.value() * obj / g; /* Constant on nable g      */
02128     f *= 2.0;                /* Modification for nabla f */
02129 
02130     dg[3] = matr[2] * matr[7] - matr[1] * matr[8];
02131     dg[4] = matr[0] * matr[8] - matr[2] * matr[6];
02132     dg[5] = matr[1] * matr[6] - matr[0] * matr[7];
02133     dg[6] = matr[1] * matr[5] - matr[2] * matr[4];
02134     dg[7] = matr[2] * matr[3] - matr[0] * matr[5];
02135     dg[8] = matr[0] * matr[4] - matr[1] * matr[3];
02136 
02137     adj_m[0] = d[0] * ( matr[0] * f + dg[0] * g );
02138     adj_m[1] = d[1] * ( matr[1] * f + dg[1] * g );
02139     adj_m[2] = d[2] * ( matr[2] * f + dg[2] * g );
02140     adj_m[3] = d[0] * ( matr[3] * f + dg[3] * g );
02141     adj_m[4] = d[1] * ( matr[4] * f + dg[4] * g );
02142     adj_m[5] = d[2] * ( matr[5] * f + dg[5] * g );
02143     adj_m[6] = d[0] * ( matr[6] * f + dg[6] * g );
02144     adj_m[7] = d[1] * ( matr[7] * f + dg[7] * g );
02145     adj_m[8] = d[2] * ( matr[8] * f + dg[8] * g );
02146 
02147     g_obj[0][0] = -adj_m[0] - adj_m[1] - adj_m[2];
02148     g_obj[1][0] = adj_m[0];
02149     g_obj[2][0] = adj_m[1];
02150     g_obj[3][0] = adj_m[2];
02151 
02152     g_obj[0][1] = -adj_m[3] - adj_m[4] - adj_m[5];
02153     g_obj[1][1] = adj_m[3];
02154     g_obj[2][1] = adj_m[4];
02155     g_obj[3][1] = adj_m[5];
02156 
02157     g_obj[0][2] = -adj_m[6] - adj_m[7] - adj_m[8];
02158     g_obj[1][2] = adj_m[6];
02159     g_obj[2][2] = adj_m[7];
02160     g_obj[3][2] = adj_m[8];
02161 
02162     /* Calculate the hessian of the objective.                   */
02163     loc0  = f;                            /* Constant on nabla^2 f       */
02164     loc1  = g;                            /* Constant on nabla^2 g       */
02165     cross = f * c.value() / loc4;         /* Constant on nabla g nabla f */
02166     f     = f * ( b.value() - 1 ) / loc3; /* Constant on nabla f nabla f */
02167     g     = g * ( c.value() - 1 ) / loc4; /* Constant on nabla g nabla g */
02168     f *= 2.0;                             /* Modification for nabla f    */
02169 
02170     /* First block of rows */
02171     loc3 = matr[0] * f + dg[0] * cross;
02172     loc4 = dg[0] * g + matr[0] * cross;
02173 
02174     J_A[0] = loc0 + loc3 * matr[0] + loc4 * dg[0];
02175     J_A[1] = loc3 * matr[1] + loc4 * dg[1];
02176     J_A[2] = loc3 * matr[2] + loc4 * dg[2];
02177     J_B[0] = loc3 * matr[3] + loc4 * dg[3];
02178     J_B[1] = loc3 * matr[4] + loc4 * dg[4];
02179     J_B[2] = loc3 * matr[5] + loc4 * dg[5];
02180     J_C[0] = loc3 * matr[6] + loc4 * dg[6];
02181     J_C[1] = loc3 * matr[7] + loc4 * dg[7];
02182     J_C[2] = loc3 * matr[8] + loc4 * dg[8];
02183 
02184     loc3 = matr[1] * f + dg[1] * cross;
02185     loc4 = dg[1] * g + matr[1] * cross;
02186 
02187     J_A[3] = loc0 + loc3 * matr[1] + loc4 * dg[1];
02188     J_A[4] = loc3 * matr[2] + loc4 * dg[2];
02189     J_B[3] = loc3 * matr[3] + loc4 * dg[3];
02190     J_B[4] = loc3 * matr[4] + loc4 * dg[4];
02191     J_B[5] = loc3 * matr[5] + loc4 * dg[5];
02192     J_C[3] = loc3 * matr[6] + loc4 * dg[6];
02193     J_C[4] = loc3 * matr[7] + loc4 * dg[7];
02194     J_C[5] = loc3 * matr[8] + loc4 * dg[8];
02195 
02196     loc3 = matr[2] * f + dg[2] * cross;
02197     loc4 = dg[2] * g + matr[2] * cross;
02198 
02199     J_A[5] = loc0 + loc3 * matr[2] + loc4 * dg[2];
02200     J_B[6] = loc3 * matr[3] + loc4 * dg[3];
02201     J_B[7] = loc3 * matr[4] + loc4 * dg[4];
02202     J_B[8] = loc3 * matr[5] + loc4 * dg[5];
02203     J_C[6] = loc3 * matr[6] + loc4 * dg[6];
02204     J_C[7] = loc3 * matr[7] + loc4 * dg[7];
02205     J_C[8] = loc3 * matr[8] + loc4 * dg[8];
02206 
02207     /* First diagonal block */
02208     J_A[0] *= scale[0];
02209     J_A[1] *= scale[1];
02210     J_A[2] *= scale[2];
02211     J_A[3] *= scale[3];
02212     J_A[4] *= scale[4];
02213     J_A[5] *= scale[5];
02214 
02215     A[0] = -J_A[0] - J_A[1] - J_A[2];
02216     A[1] = -J_A[1] - J_A[3] - J_A[4];
02217     A[2] = -J_A[2] - J_A[4] - J_A[5];
02218 
02219     h_obj[0][0][0] = -A[0] - A[1] - A[2];
02220     h_obj[1][0][0] = A[0];
02221     h_obj[2][0][0] = A[1];
02222     h_obj[3][0][0] = A[2];
02223 
02224     h_obj[4][0][0] = J_A[0];
02225     h_obj[5][0][0] = J_A[1];
02226     h_obj[6][0][0] = J_A[2];
02227 
02228     h_obj[7][0][0] = J_A[3];
02229     h_obj[8][0][0] = J_A[4];
02230 
02231     h_obj[9][0][0] = J_A[5];
02232 
02233     /* First off-diagonal block */
02234     loc2 = matr[8] * loc1;
02235     J_B[1] += loc2;
02236     J_B[3] -= loc2;
02237 
02238     loc2 = matr[7] * loc1;
02239     J_B[2] -= loc2;
02240     J_B[6] += loc2;
02241 
02242     loc2 = matr[6] * loc1;
02243     J_B[5] += loc2;
02244     J_B[7] -= loc2;
02245 
02246     J_B[0] *= scale[0];
02247     J_B[1] *= scale[1];
02248     J_B[2] *= scale[2];
02249     J_B[3] *= scale[1];
02250     J_B[4] *= scale[3];
02251     J_B[5] *= scale[4];
02252     J_B[6] *= scale[2];
02253     J_B[7] *= scale[4];
02254     J_B[8] *= scale[5];
02255 
02256     A[0] = -J_B[0] - J_B[3] - J_B[6];
02257     A[1] = -J_B[1] - J_B[4] - J_B[7];
02258     A[2] = -J_B[2] - J_B[5] - J_B[8];
02259 
02260     h_obj[0][0][1] = -A[0] - A[1] - A[2];
02261     h_obj[1][0][1] = A[0];
02262     h_obj[2][0][1] = A[1];
02263     h_obj[3][0][1] = A[2];
02264 
02265     h_obj[1][1][0] = -J_B[0] - J_B[1] - J_B[2];
02266     h_obj[4][0][1] = J_B[0];
02267     h_obj[5][0][1] = J_B[1];
02268     h_obj[6][0][1] = J_B[2];
02269 
02270     h_obj[2][1][0] = -J_B[3] - J_B[4] - J_B[5];
02271     h_obj[5][1][0] = J_B[3];
02272     h_obj[7][0][1] = J_B[4];
02273     h_obj[8][0][1] = J_B[5];
02274 
02275     h_obj[3][1][0] = -J_B[6] - J_B[7] - J_B[8];
02276     h_obj[6][1][0] = J_B[6];
02277     h_obj[8][1][0] = J_B[7];
02278     h_obj[9][0][1] = J_B[8];
02279 
02280     /* Second off-diagonal block */
02281     loc2 = matr[5] * loc1;
02282     J_C[1] -= loc2;
02283     J_C[3] += loc2;
02284 
02285     loc2 = matr[4] * loc1;
02286     J_C[2] += loc2;
02287     J_C[6] -= loc2;
02288 
02289     loc2 = matr[3] * loc1;
02290     J_C[5] -= loc2;
02291     J_C[7] += loc2;
02292 
02293     J_C[0] *= scale[0];
02294     J_C[1] *= scale[1];
02295     J_C[2] *= scale[2];
02296     J_C[3] *= scale[1];
02297     J_C[4] *= scale[3];
02298     J_C[5] *= scale[4];
02299     J_C[6] *= scale[2];
02300     J_C[7] *= scale[4];
02301     J_C[8] *= scale[5];
02302 
02303     A[0] = -J_C[0] - J_C[3] - J_C[6];
02304     A[1] = -J_C[1] - J_C[4] - J_C[7];
02305     A[2] = -J_C[2] - J_C[5] - J_C[8];
02306 
02307     h_obj[0][0][2] = -A[0] - A[1] - A[2];
02308     h_obj[1][0][2] = A[0];
02309     h_obj[2][0][2] = A[1];
02310     h_obj[3][0][2] = A[2];
02311 
02312     h_obj[1][2][0] = -J_C[0] - J_C[1] - J_C[2];
02313     h_obj[4][0][2] = J_C[0];
02314     h_obj[5][0][2] = J_C[1];
02315     h_obj[6][0][2] = J_C[2];
02316 
02317     h_obj[2][2][0] = -J_C[3] - J_C[4] - J_C[5];
02318     h_obj[5][2][0] = J_C[3];
02319     h_obj[7][0][2] = J_C[4];
02320     h_obj[8][0][2] = J_C[5];
02321 
02322     h_obj[3][2][0] = -J_C[6] - J_C[7] - J_C[8];
02323     h_obj[6][2][0] = J_C[6];
02324     h_obj[8][2][0] = J_C[7];
02325     h_obj[9][0][2] = J_C[8];
02326 
02327     /* Second block of rows */
02328     loc3 = matr[3] * f + dg[3] * cross;
02329     loc4 = dg[3] * g + matr[3] * cross;
02330 
02331     J_A[0] = loc0 + loc3 * matr[3] + loc4 * dg[3];
02332     J_A[1] = loc3 * matr[4] + loc4 * dg[4];
02333     J_A[2] = loc3 * matr[5] + loc4 * dg[5];
02334     J_B[0] = loc3 * matr[6] + loc4 * dg[6];
02335     J_B[1] = loc3 * matr[7] + loc4 * dg[7];
02336     J_B[2] = loc3 * matr[8] + loc4 * dg[8];
02337 
02338     loc3 = matr[4] * f + dg[4] * cross;
02339     loc4 = dg[4] * g + matr[4] * cross;
02340 
02341     J_A[3] = loc0 + loc3 * matr[4] + loc4 * dg[4];
02342     J_A[4] = loc3 * matr[5] + loc4 * dg[5];
02343     J_B[3] = loc3 * matr[6] + loc4 * dg[6];
02344     J_B[4] = loc3 * matr[7] + loc4 * dg[7];
02345     J_B[5] = loc3 * matr[8] + loc4 * dg[8];
02346 
02347     loc3 = matr[5] * f + dg[5] * cross;
02348     loc4 = dg[5] * g + matr[5] * cross;
02349 
02350     J_A[5] = loc0 + loc3 * matr[5] + loc4 * dg[5];
02351     J_B[6] = loc3 * matr[6] + loc4 * dg[6];
02352     J_B[7] = loc3 * matr[7] + loc4 * dg[7];
02353     J_B[8] = loc3 * matr[8] + loc4 * dg[8];
02354 
02355     /* Second diagonal block */
02356     J_A[0] *= scale[0];
02357     J_A[1] *= scale[1];
02358     J_A[2] *= scale[2];
02359     J_A[3] *= scale[3];
02360     J_A[4] *= scale[4];
02361     J_A[5] *= scale[5];
02362 
02363     A[0] = -J_A[0] - J_A[1] - J_A[2];
02364     A[1] = -J_A[1] - J_A[3] - J_A[4];
02365     A[2] = -J_A[2] - J_A[4] - J_A[5];
02366 
02367     h_obj[0][1][1] = -A[0] - A[1] - A[2];
02368     h_obj[1][1][1] = A[0];
02369     h_obj[2][1][1] = A[1];
02370     h_obj[3][1][1] = A[2];
02371 
02372     h_obj[4][1][1] = J_A[0];
02373     h_obj[5][1][1] = J_A[1];
02374     h_obj[6][1][1] = J_A[2];
02375 
02376     h_obj[7][1][1] = J_A[3];
02377     h_obj[8][1][1] = J_A[4];
02378 
02379     h_obj[9][1][1] = J_A[5];
02380 
02381     /* Third off-diagonal block */
02382     loc2 = matr[2] * loc1;
02383     J_B[1] += loc2;
02384     J_B[3] -= loc2;
02385 
02386     loc2 = matr[1] * loc1;
02387     J_B[2] -= loc2;
02388     J_B[6] += loc2;
02389 
02390     loc2 = matr[0] * loc1;
02391     J_B[5] += loc2;
02392     J_B[7] -= loc2;
02393 
02394     J_B[0] *= scale[0];
02395     J_B[1] *= scale[1];
02396     J_B[2] *= scale[2];
02397     J_B[3] *= scale[1];
02398     J_B[4] *= scale[3];
02399     J_B[5] *= scale[4];
02400     J_B[6] *= scale[2];
02401     J_B[7] *= scale[4];
02402     J_B[8] *= scale[5];
02403 
02404     A[0] = -J_B[0] - J_B[3] - J_B[6];
02405     A[1] = -J_B[1] - J_B[4] - J_B[7];
02406     A[2] = -J_B[2] - J_B[5] - J_B[8];
02407 
02408     h_obj[0][1][2] = -A[0] - A[1] - A[2];
02409     h_obj[1][1][2] = A[0];
02410     h_obj[2][1][2] = A[1];
02411     h_obj[3][1][2] = A[2];
02412 
02413     h_obj[1][2][1] = -J_B[0] - J_B[1] - J_B[2];
02414     h_obj[4][1][2] = J_B[0];
02415     h_obj[5][1][2] = J_B[1];
02416     h_obj[6][1][2] = J_B[2];
02417 
02418     h_obj[2][2][1] = -J_B[3] - J_B[4] - J_B[5];
02419     h_obj[5][2][1] = J_B[3];
02420     h_obj[7][1][2] = J_B[4];
02421     h_obj[8][1][2] = J_B[5];
02422 
02423     h_obj[3][2][1] = -J_B[6] - J_B[7] - J_B[8];
02424     h_obj[6][2][1] = J_B[6];
02425     h_obj[8][2][1] = J_B[7];
02426     h_obj[9][1][2] = J_B[8];
02427 
02428     /* Third block of rows */
02429     loc3 = matr[6] * f + dg[6] * cross;
02430     loc4 = dg[6] * g + matr[6] * cross;
02431 
02432     J_A[0] = loc0 + loc3 * matr[6] + loc4 * dg[6];
02433     J_A[1] = loc3 * matr[7] + loc4 * dg[7];
02434     J_A[2] = loc3 * matr[8] + loc4 * dg[8];
02435 
02436     loc3 = matr[7] * f + dg[7] * cross;
02437     loc4 = dg[7] * g + matr[7] * cross;
02438 
02439     J_A[3] = loc0 + loc3 * matr[7] + loc4 * dg[7];
02440     J_A[4] = loc3 * matr[8] + loc4 * dg[8];
02441 
02442     loc3 = matr[8] * f + dg[8] * cross;
02443     loc4 = dg[8] * g + matr[8] * cross;
02444 
02445     J_A[5] = loc0 + loc3 * matr[8] + loc4 * dg[8];
02446 
02447     /* Third diagonal block */
02448     J_A[0] *= scale[0];
02449     J_A[1] *= scale[1];
02450     J_A[2] *= scale[2];
02451     J_A[3] *= scale[3];
02452     J_A[4] *= scale[4];
02453     J_A[5] *= scale[5];
02454 
02455     A[0] = -J_A[0] - J_A[1] - J_A[2];
02456     A[1] = -J_A[1] - J_A[3] - J_A[4];
02457     A[2] = -J_A[2] - J_A[4] - J_A[5];
02458 
02459     h_obj[0][2][2] = -A[0] - A[1] - A[2];
02460     h_obj[1][2][2] = A[0];
02461     h_obj[2][2][2] = A[1];
02462     h_obj[3][2][2] = A[2];
02463 
02464     h_obj[4][2][2] = J_A[0];
02465     h_obj[5][2][2] = J_A[1];
02466     h_obj[6][2][2] = J_A[2];
02467 
02468     h_obj[7][2][2] = J_A[3];
02469     h_obj[8][2][2] = J_A[4];
02470 
02471     h_obj[9][2][2] = J_A[5];
02472 
02473     // completes diagonal blocks.
02474     h_obj[0].fill_lower_triangle();
02475     h_obj[4].fill_lower_triangle();
02476     h_obj[7].fill_lower_triangle();
02477     h_obj[9].fill_lower_triangle();
02478     return true;
02479 }
02480 
02481 /*********************************************************************
02482  * Reference tetrahedral elements to halves of an ideal pyramid.
02483  * Vertices should be ordered such that the edge between the 2nd and
02484  * 3rd vertices is the one longer edge in the reference tetrahedron
02485  * (the diagonal of the base of the pyramid of which the tetrahedron
02486  * is one half of).
02487  *      1  0  1/2                     1  0 -1/sqrt(2)
02488  * W =  0  1  1/2           inv(W) =  0  1 -1/sqrt(2)
02489  *      0  0  1/sqrt(2)               0  0  sqrt(2)
02490  *
02491  *********************************************************************/
02492 inline bool m_fcn_3p( double& obj, const Vector3D x[4], const double a, const Exponent& b, const Exponent& c )
02493 {
02494     const double h = 0.5; /* h = 1 / (2*height) */
02495 
02496     double matr[9], f;
02497     double g;
02498 
02499     /* Calculate M = A*inv(W). */
02500     matr[0] = x[1][0] - x[0][0];
02501     matr[1] = x[2][0] - x[0][0];
02502     matr[2] = ( 2.0 * x[3][0] - x[1][0] - x[2][0] ) * h;
02503 
02504     matr[3] = x[1][1] - x[0][1];
02505     matr[4] = x[2][1] - x[0][1];
02506     matr[5] = ( 2.0 * x[3][1] - x[1][1] - x[2][1] ) * h;
02507 
02508     matr[6] = x[1][2] - x[0][2];
02509     matr[7] = x[2][2] - x[0][2];
02510     matr[8] = ( 2.0 * x[3][2] - x[1][2] - x[2][2] ) * h;
02511 
02512     /* Calculate det(M). */
02513     g = matr[0] * ( matr[4] * matr[8] - matr[5] * matr[7] ) + matr[1] * ( matr[5] * matr[6] - matr[3] * matr[8] ) +
02514         matr[2] * ( matr[3] * matr[7] - matr[4] * matr[6] );
02515     if( g < MSQ_MIN )
02516     {
02517         obj = g;
02518         return false;
02519     }
02520 
02521     /* Calculate norm(M). */
02522     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
02523         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
02524 
02525     /* Calculate objective function. */
02526     obj = a * b.raise( f ) * c.raise( g );
02527     return true;
02528 }
02529 
02530 inline bool g_fcn_3p( double& obj,
02531                       Vector3D g_obj[4],
02532                       const Vector3D x[4],
02533                       const double a,
02534                       const Exponent& b,
02535                       const Exponent& c )
02536 {
02537     const double h  = 0.5; /* h = 1 / (2*height) */
02538     const double th = 1.0; /* h = 1 / (height)   */
02539 
02540     double matr[9], f;
02541     double adj_m[9], g;
02542     double loc1, loc2, loc3;
02543 
02544     /* Calculate M = A*inv(W). */
02545     matr[0] = x[1][0] - x[0][0];
02546     matr[1] = x[2][0] - x[0][0];
02547     matr[2] = ( 2.0 * x[3][0] - x[1][0] - x[2][0] ) * h;
02548 
02549     matr[3] = x[1][1] - x[0][1];
02550     matr[4] = x[2][1] - x[0][1];
02551     matr[5] = ( 2.0 * x[3][1] - x[1][1] - x[2][1] ) * h;
02552 
02553     matr[6] = x[1][2] - x[0][2];
02554     matr[7] = x[2][2] - x[0][2];
02555     matr[8] = ( 2.0 * x[3][2] - x[1][2] - x[2][2] ) * h;
02556 
02557     /* Calculate det(M). */
02558     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
02559     loc2 = matr[5] * matr[6] - matr[3] * matr[8];
02560     loc3 = matr[3] * matr[7] - matr[4] * matr[6];
02561     g    = matr[0] * loc1 + matr[1] * loc2 + matr[2] * loc3;
02562     if( g < MSQ_MIN )
02563     {
02564         obj = g;
02565         return false;
02566     }
02567 
02568     /* Calculate norm(M). */
02569     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
02570         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
02571 
02572     /* Calculate objective function. */
02573     obj = a * b.raise( f ) * c.raise( g );
02574 
02575     /* Calculate the derivative of the objective function.    */
02576     f = b.value() * obj / f; /* Constant on nabla f      */
02577     g = c.value() * obj / g; /* Constant on nable g      */
02578     f *= 2.0;                /* Modification for nabla f */
02579 
02580     adj_m[0] = matr[0] * f + loc1 * g;
02581     adj_m[1] = matr[1] * f + loc2 * g;
02582     adj_m[2] = matr[2] * f + loc3 * g;
02583 
02584     loc1 = matr[0] * g;
02585     loc2 = matr[1] * g;
02586     loc3 = matr[2] * g;
02587 
02588     adj_m[3] = matr[3] * f + loc3 * matr[7] - loc2 * matr[8];
02589     adj_m[4] = matr[4] * f + loc1 * matr[8] - loc3 * matr[6];
02590     adj_m[5] = matr[5] * f + loc2 * matr[6] - loc1 * matr[7];
02591 
02592     adj_m[6] = matr[6] * f + loc2 * matr[5] - loc3 * matr[4];
02593     adj_m[7] = matr[7] * f + loc3 * matr[3] - loc1 * matr[5];
02594     adj_m[8] = matr[8] * f + loc1 * matr[4] - loc2 * matr[3];
02595 
02596     g_obj[0][0] = -adj_m[0] - adj_m[1];
02597     g_obj[1][0] = adj_m[0] - h * adj_m[2];
02598     g_obj[2][0] = adj_m[1] - h * adj_m[2];
02599     g_obj[3][0] = th * adj_m[2];
02600 
02601     g_obj[0][1] = -adj_m[3] - adj_m[4];
02602     g_obj[1][1] = adj_m[3] - h * adj_m[5];
02603     g_obj[2][1] = adj_m[4] - h * adj_m[5];
02604     g_obj[3][1] = th * adj_m[5];
02605 
02606     g_obj[0][2] = -adj_m[6] - adj_m[7];
02607     g_obj[1][2] = adj_m[6] - h * adj_m[8];
02608     g_obj[2][2] = adj_m[7] - h * adj_m[8];
02609     g_obj[3][2] = th * adj_m[8];
02610     return true;
02611 }
02612 
02613 inline bool h_fcn_3p( double& obj,
02614                       Vector3D g_obj[4],
02615                       Matrix3D h_obj[10],
02616                       const Vector3D x[4],
02617                       const double a,
02618                       const Exponent& b,
02619                       const Exponent& c )
02620 {
02621     const double h  = 0.5; /* h = 1 / (2*height) */
02622     const double th = 1.0; /* h = 1 / (height)   */
02623 
02624     double matr[9], f;
02625     double adj_m[9], g;
02626     double dg[9], loc0, loc1, loc2, loc3, loc4;
02627     double A[12], J_A[6], J_B[9], J_C[9], cross;
02628 
02629     /* Calculate M = A*inv(W). */
02630     matr[0] = x[1][0] - x[0][0];
02631     matr[1] = x[2][0] - x[0][0];
02632     matr[2] = ( 2.0 * x[3][0] - x[1][0] - x[2][0] ) * h;
02633 
02634     matr[3] = x[1][1] - x[0][1];
02635     matr[4] = x[2][1] - x[0][1];
02636     matr[5] = ( 2.0 * x[3][1] - x[1][1] - x[2][1] ) * h;
02637 
02638     matr[6] = x[1][2] - x[0][2];
02639     matr[7] = x[2][2] - x[0][2];
02640     matr[8] = ( 2.0 * x[3][2] - x[1][2] - x[2][2] ) * h;
02641 
02642     /* Calculate det(M). */
02643     dg[0] = matr[4] * matr[8] - matr[5] * matr[7];
02644     dg[1] = matr[5] * matr[6] - matr[3] * matr[8];
02645     dg[2] = matr[3] * matr[7] - matr[4] * matr[6];
02646     g     = matr[0] * dg[0] + matr[1] * dg[1] + matr[2] * dg[2];
02647     if( g < MSQ_MIN )
02648     {
02649         obj = g;
02650         return false;
02651     }
02652 
02653     dg[3] = matr[2] * matr[7] - matr[1] * matr[8];
02654     dg[4] = matr[0] * matr[8] - matr[2] * matr[6];
02655     dg[5] = matr[1] * matr[6] - matr[0] * matr[7];
02656     dg[6] = matr[1] * matr[5] - matr[2] * matr[4];
02657     dg[7] = matr[2] * matr[3] - matr[0] * matr[5];
02658     dg[8] = matr[0] * matr[4] - matr[1] * matr[3];
02659 
02660     /* Calculate norm(M). */
02661     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
02662         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
02663 
02664     loc3 = f;
02665     loc4 = g;
02666 
02667     /* Calculate objective function. */
02668     obj = a * b.raise( f ) * c.raise( g );
02669 
02670     /* Calculate the derivative of the objective function.    */
02671     f = b.value() * obj / f; /* Constant on nabla f      */
02672     g = c.value() * obj / g; /* Constant on nable g      */
02673     f *= 2.0;                /* Modification for nabla f */
02674 
02675     adj_m[0] = matr[0] * f + dg[0] * g;
02676     adj_m[1] = matr[1] * f + dg[1] * g;
02677     adj_m[2] = matr[2] * f + dg[2] * g;
02678     adj_m[3] = matr[3] * f + dg[3] * g;
02679     adj_m[4] = matr[4] * f + dg[4] * g;
02680     adj_m[5] = matr[5] * f + dg[5] * g;
02681     adj_m[6] = matr[6] * f + dg[6] * g;
02682     adj_m[7] = matr[7] * f + dg[7] * g;
02683     adj_m[8] = matr[8] * f + dg[8] * g;
02684 
02685     g_obj[0][0] = -adj_m[0] - adj_m[1];
02686     g_obj[1][0] = adj_m[0] - h * adj_m[2];
02687     g_obj[2][0] = adj_m[1] - h * adj_m[2];
02688     g_obj[3][0] = th * adj_m[2];
02689 
02690     g_obj[0][1] = -adj_m[3] - adj_m[4];
02691     g_obj[1][1] = adj_m[3] - h * adj_m[5];
02692     g_obj[2][1] = adj_m[4] - h * adj_m[5];
02693     g_obj[3][1] = th * adj_m[5];
02694 
02695     g_obj[0][2] = -adj_m[6] - adj_m[7];
02696     g_obj[1][2] = adj_m[6] - h * adj_m[8];
02697     g_obj[2][2] = adj_m[7] - h * adj_m[8];
02698     g_obj[3][2] = th * adj_m[8];
02699 
02700     /* Calculate the hessian of the objective.                   */
02701     loc0  = f;                            /* Constant on nabla^2 f       */
02702     loc1  = g;                            /* Constant on nabla^2 g       */
02703     cross = f * c.value() / loc4;         /* Constant on nabla g nabla f */
02704     f     = f * ( b.value() - 1 ) / loc3; /* Constant on nabla f nabla f */
02705     g     = g * ( c.value() - 1 ) / loc4; /* Constant on nabla g nabla g */
02706     f *= 2.0;                             /* Modification for nabla f    */
02707 
02708     /* First block of rows */
02709     loc3 = matr[0] * f + dg[0] * cross;
02710     loc4 = dg[0] * g + matr[0] * cross;
02711 
02712     J_A[0] = loc0 + loc3 * matr[0] + loc4 * dg[0];
02713     J_A[1] = loc3 * matr[1] + loc4 * dg[1];
02714     J_A[2] = loc3 * matr[2] + loc4 * dg[2];
02715     J_B[0] = loc3 * matr[3] + loc4 * dg[3];
02716     J_B[1] = loc3 * matr[4] + loc4 * dg[4];
02717     J_B[2] = loc3 * matr[5] + loc4 * dg[5];
02718     J_C[0] = loc3 * matr[6] + loc4 * dg[6];
02719     J_C[1] = loc3 * matr[7] + loc4 * dg[7];
02720     J_C[2] = loc3 * matr[8] + loc4 * dg[8];
02721 
02722     loc3 = matr[1] * f + dg[1] * cross;
02723     loc4 = dg[1] * g + matr[1] * cross;
02724 
02725     J_A[3] = loc0 + loc3 * matr[1] + loc4 * dg[1];
02726     J_A[4] = loc3 * matr[2] + loc4 * dg[2];
02727     J_B[3] = loc3 * matr[3] + loc4 * dg[3];
02728     J_B[4] = loc3 * matr[4] + loc4 * dg[4];
02729     J_B[5] = loc3 * matr[5] + loc4 * dg[5];
02730     J_C[3] = loc3 * matr[6] + loc4 * dg[6];
02731     J_C[4] = loc3 * matr[7] + loc4 * dg[7];
02732     J_C[5] = loc3 * matr[8] + loc4 * dg[8];
02733 
02734     loc3 = matr[2] * f + dg[2] * cross;
02735     loc4 = dg[2] * g + matr[2] * cross;
02736 
02737     J_A[5] = loc0 + loc3 * matr[2] + loc4 * dg[2];
02738     J_B[6] = loc3 * matr[3] + loc4 * dg[3];
02739     J_B[7] = loc3 * matr[4] + loc4 * dg[4];
02740     J_B[8] = loc3 * matr[5] + loc4 * dg[5];
02741     J_C[6] = loc3 * matr[6] + loc4 * dg[6];
02742     J_C[7] = loc3 * matr[7] + loc4 * dg[7];
02743     J_C[8] = loc3 * matr[8] + loc4 * dg[8];
02744 
02745     /* First diagonal block */
02746     A[0] = -J_A[0] - J_A[1];
02747     A[1] = J_A[0] - h * J_A[2];
02748     A[2] = J_A[1] - h * J_A[2];
02749     A[3] = th * J_A[2];
02750 
02751     A[4] = -J_A[1] - J_A[3];
02752     A[5] = J_A[1] - h * J_A[4];
02753     A[6] = J_A[3] - h * J_A[4];
02754     A[7] = th * J_A[4];
02755 
02756     A[8]  = -J_A[2] - J_A[4];
02757     A[9]  = J_A[2] - h * J_A[5];
02758     A[10] = J_A[4] - h * J_A[5];
02759     A[11] = th * J_A[5];
02760 
02761     h_obj[0][0][0] = -A[0] - A[4];
02762     h_obj[1][0][0] = A[0] - h * A[8];
02763     h_obj[2][0][0] = A[4] - h * A[8];
02764     h_obj[3][0][0] = th * A[8];
02765 
02766     h_obj[4][0][0] = A[1] - h * A[9];
02767     h_obj[5][0][0] = A[5] - h * A[9];
02768     h_obj[6][0][0] = th * A[9];
02769 
02770     h_obj[7][0][0] = A[6] - h * A[10];
02771     h_obj[8][0][0] = th * A[10];
02772 
02773     h_obj[9][0][0] = th * A[11];
02774 
02775     /* First off-diagonal block */
02776     loc2 = matr[8] * loc1;
02777     J_B[1] += loc2;
02778     J_B[3] -= loc2;
02779 
02780     loc2 = matr[7] * loc1;
02781     J_B[2] -= loc2;
02782     J_B[6] += loc2;
02783 
02784     loc2 = matr[6] * loc1;
02785     J_B[5] += loc2;
02786     J_B[7] -= loc2;
02787 
02788     A[0] = -J_B[0] - J_B[1];
02789     A[1] = J_B[0] - h * J_B[2];
02790     A[2] = J_B[1] - h * J_B[2];
02791     A[3] = th * J_B[2];
02792 
02793     A[4] = -J_B[3] - J_B[4];
02794     A[5] = J_B[3] - h * J_B[5];
02795     A[6] = J_B[4] - h * J_B[5];
02796     A[7] = th * J_B[5];
02797 
02798     A[8]  = -J_B[6] - J_B[7];
02799     A[9]  = J_B[6] - h * J_B[8];
02800     A[10] = J_B[7] - h * J_B[8];
02801     A[11] = th * J_B[8];
02802 
02803     h_obj[0][0][1] = -A[0] - A[4];
02804     h_obj[1][1][0] = A[0] - h * A[8];
02805     h_obj[2][1][0] = A[4] - h * A[8];
02806     h_obj[3][1][0] = th * A[8];
02807 
02808     h_obj[1][0][1] = -A[1] - A[5];
02809     h_obj[4][0][1] = A[1] - h * A[9];
02810     h_obj[5][1][0] = A[5] - h * A[9];
02811     h_obj[6][1][0] = th * A[9];
02812 
02813     h_obj[2][0][1] = -A[2] - A[6];
02814     h_obj[5][0][1] = A[2] - h * A[10];
02815     h_obj[7][0][1] = A[6] - h * A[10];
02816     h_obj[8][1][0] = th * A[10];
02817 
02818     h_obj[3][0][1] = -A[3] - A[7];
02819     h_obj[6][0][1] = A[3] - h * A[11];
02820     h_obj[8][0][1] = A[7] - h * A[11];
02821     h_obj[9][0][1] = th * A[11];
02822 
02823     /* Second off-diagonal block */
02824     loc2 = matr[5] * loc1;
02825     J_C[1] -= loc2;
02826     J_C[3] += loc2;
02827 
02828     loc2 = matr[4] * loc1;
02829     J_C[2] += loc2;
02830     J_C[6] -= loc2;
02831 
02832     loc2 = matr[3] * loc1;
02833     J_C[5] -= loc2;
02834     J_C[7] += loc2;
02835 
02836     A[0] = -J_C[0] - J_C[1];
02837     A[1] = J_C[0] - h * J_C[2];
02838     A[2] = J_C[1] - h * J_C[2];
02839     A[3] = th * J_C[2];
02840 
02841     A[4] = -J_C[3] - J_C[4];
02842     A[5] = J_C[3] - h * J_C[5];
02843     A[6] = J_C[4] - h * J_C[5];
02844     A[7] = th * J_C[5];
02845 
02846     A[8]  = -J_C[6] - J_C[7];
02847     A[9]  = J_C[6] - h * J_C[8];
02848     A[10] = J_C[7] - h * J_C[8];
02849     A[11] = th * J_C[8];
02850 
02851     h_obj[0][0][2] = -A[0] - A[4];
02852     h_obj[1][2][0] = A[0] - h * A[8];
02853     h_obj[2][2][0] = A[4] - h * A[8];
02854     h_obj[3][2][0] = th * A[8];
02855 
02856     h_obj[1][0][2] = -A[1] - A[5];
02857     h_obj[4][0][2] = A[1] - h * A[9];
02858     h_obj[5][2][0] = A[5] - h * A[9];
02859     h_obj[6][2][0] = th * A[9];
02860 
02861     h_obj[2][0][2] = -A[2] - A[6];
02862     h_obj[5][0][2] = A[2] - h * A[10];
02863     h_obj[7][0][2] = A[6] - h * A[10];
02864     h_obj[8][2][0] = th * A[10];
02865 
02866     h_obj[3][0][2] = -A[3] - A[7];
02867     h_obj[6][0][2] = A[3] - h * A[11];
02868     h_obj[8][0][2] = A[7] - h * A[11];
02869     h_obj[9][0][2] = th * A[11];
02870 
02871     /* Second block of rows */
02872     loc3 = matr[3] * f + dg[3] * cross;
02873     loc4 = dg[3] * g + matr[3] * cross;
02874 
02875     J_A[0] = loc0 + loc3 * matr[3] + loc4 * dg[3];
02876     J_A[1] = loc3 * matr[4] + loc4 * dg[4];
02877     J_A[2] = loc3 * matr[5] + loc4 * dg[5];
02878     J_B[0] = loc3 * matr[6] + loc4 * dg[6];
02879     J_B[1] = loc3 * matr[7] + loc4 * dg[7];
02880     J_B[2] = loc3 * matr[8] + loc4 * dg[8];
02881 
02882     loc3 = matr[4] * f + dg[4] * cross;
02883     loc4 = dg[4] * g + matr[4] * cross;
02884 
02885     J_A[3] = loc0 + loc3 * matr[4] + loc4 * dg[4];
02886     J_A[4] = loc3 * matr[5] + loc4 * dg[5];
02887     J_B[3] = loc3 * matr[6] + loc4 * dg[6];
02888     J_B[4] = loc3 * matr[7] + loc4 * dg[7];
02889     J_B[5] = loc3 * matr[8] + loc4 * dg[8];
02890 
02891     loc3 = matr[5] * f + dg[5] * cross;
02892     loc4 = dg[5] * g + matr[5] * cross;
02893 
02894     J_A[5] = loc0 + loc3 * matr[5] + loc4 * dg[5];
02895     J_B[6] = loc3 * matr[6] + loc4 * dg[6];
02896     J_B[7] = loc3 * matr[7] + loc4 * dg[7];
02897     J_B[8] = loc3 * matr[8] + loc4 * dg[8];
02898 
02899     /* Second diagonal block */
02900     A[0] = -J_A[0] - J_A[1];
02901     A[1] = J_A[0] - h * J_A[2];
02902     A[2] = J_A[1] - h * J_A[2];
02903     A[3] = th * J_A[2];
02904 
02905     A[4] = -J_A[1] - J_A[3];
02906     A[5] = J_A[1] - h * J_A[4];
02907     A[6] = J_A[3] - h * J_A[4];
02908     A[7] = th * J_A[4];
02909 
02910     A[8]  = -J_A[2] - J_A[4];
02911     A[9]  = J_A[2] - h * J_A[5];
02912     A[10] = J_A[4] - h * J_A[5];
02913     A[11] = th * J_A[5];
02914 
02915     h_obj[0][1][1] = -A[0] - A[4];
02916     h_obj[1][1][1] = A[0] - h * A[8];
02917     h_obj[2][1][1] = A[4] - h * A[8];
02918     h_obj[3][1][1] = th * A[8];
02919 
02920     h_obj[4][1][1] = A[1] - h * A[9];
02921     h_obj[5][1][1] = A[5] - h * A[9];
02922     h_obj[6][1][1] = th * A[9];
02923 
02924     h_obj[7][1][1] = A[6] - h * A[10];
02925     h_obj[8][1][1] = th * A[10];
02926 
02927     h_obj[9][1][1] = th * A[11];
02928 
02929     /* Third off-diagonal block */
02930     loc2 = matr[2] * loc1;
02931     J_B[1] += loc2;
02932     J_B[3] -= loc2;
02933 
02934     loc2 = matr[1] * loc1;
02935     J_B[2] -= loc2;
02936     J_B[6] += loc2;
02937 
02938     loc2 = matr[0] * loc1;
02939     J_B[5] += loc2;
02940     J_B[7] -= loc2;
02941 
02942     A[0] = -J_B[0] - J_B[1];
02943     A[1] = J_B[0] - h * J_B[2];
02944     A[2] = J_B[1] - h * J_B[2];
02945     A[3] = th * J_B[2];
02946 
02947     A[4] = -J_B[3] - J_B[4];
02948     A[5] = J_B[3] - h * J_B[5];
02949     A[6] = J_B[4] - h * J_B[5];
02950     A[7] = th * J_B[5];
02951 
02952     A[8]  = -J_B[6] - J_B[7];
02953     A[9]  = J_B[6] - h * J_B[8];
02954     A[10] = J_B[7] - h * J_B[8];
02955     A[11] = th * J_B[8];
02956 
02957     h_obj[0][1][2] = -A[0] - A[4];
02958     h_obj[1][2][1] = A[0] - h * A[8];
02959     h_obj[2][2][1] = A[4] - h * A[8];
02960     h_obj[3][2][1] = th * A[8];
02961 
02962     h_obj[1][1][2] = -A[1] - A[5];
02963     h_obj[4][1][2] = A[1] - h * A[9];
02964     h_obj[5][2][1] = A[5] - h * A[9];
02965     h_obj[6][2][1] = th * A[9];
02966 
02967     h_obj[2][1][2] = -A[2] - A[6];
02968     h_obj[5][1][2] = A[2] - h * A[10];
02969     h_obj[7][1][2] = A[6] - h * A[10];
02970     h_obj[8][2][1] = th * A[10];
02971 
02972     h_obj[3][1][2] = -A[3] - A[7];
02973     h_obj[6][1][2] = A[3] - h * A[11];
02974     h_obj[8][1][2] = A[7] - h * A[11];
02975     h_obj[9][1][2] = th * A[11];
02976 
02977     /* Third block of rows */
02978     loc3 = matr[6] * f + dg[6] * cross;
02979     loc4 = dg[6] * g + matr[6] * cross;
02980 
02981     J_A[0] = loc0 + loc3 * matr[6] + loc4 * dg[6];
02982     J_A[1] = loc3 * matr[7] + loc4 * dg[7];
02983     J_A[2] = loc3 * matr[8] + loc4 * dg[8];
02984 
02985     loc3 = matr[7] * f + dg[7] * cross;
02986     loc4 = dg[7] * g + matr[7] * cross;
02987 
02988     J_A[3] = loc0 + loc3 * matr[7] + loc4 * dg[7];
02989     J_A[4] = loc3 * matr[8] + loc4 * dg[8];
02990 
02991     loc3 = matr[8] * f + dg[8] * cross;
02992     loc4 = dg[8] * g + matr[8] * cross;
02993 
02994     J_A[5] = loc0 + loc3 * matr[8] + loc4 * dg[8];
02995 
02996     /* Third diagonal block */
02997     A[0] = -J_A[0] - J_A[1];
02998     A[1] = J_A[0] - h * J_A[2];
02999     A[2] = J_A[1] - h * J_A[2];
03000     A[3] = th * J_A[2];
03001 
03002     A[4] = -J_A[1] - J_A[3];
03003     A[5] = J_A[1] - h * J_A[4];
03004     A[6] = J_A[3] - h * J_A[4];
03005     A[7] = th * J_A[4];
03006 
03007     A[8]  = -J_A[2] - J_A[4];
03008     A[9]  = J_A[2] - h * J_A[5];
03009     A[10] = J_A[4] - h * J_A[5];
03010     A[11] = th * J_A[5];
03011 
03012     h_obj[0][2][2] = -A[0] - A[4];
03013     h_obj[1][2][2] = A[0] - h * A[8];
03014     h_obj[2][2][2] = A[4] - h * A[8];
03015     h_obj[3][2][2] = th * A[8];
03016 
03017     h_obj[4][2][2] = A[1] - h * A[9];
03018     h_obj[5][2][2] = A[5] - h * A[9];
03019     h_obj[6][2][2] = th * A[9];
03020 
03021     h_obj[7][2][2] = A[6] - h * A[10];
03022     h_obj[8][2][2] = th * A[10];
03023 
03024     h_obj[9][2][2] = th * A[11];
03025 
03026 #if 0
03027   int i, j, k, l;
03028   double   nobj;
03029   Vector3D nx[4];
03030   Vector3D ng_obj[4];
03031 
03032   for (i = 0; i < 4; ++i) {
03033     nx[i] = x[i];
03034     ng_obj[i] = 0.0;
03035   }
03036 
03037   m_fcn_3p(obj, x, a, b, c);
03038   for (i = 0; i < 4; ++i) {
03039     for (j = 0; j < 3; ++j) {
03040       nx[i][j] += 1e-6;
03041       m_fcn_3p(nobj, nx, a, b, c);
03042       nx[i][j] = x[i][j];
03043 
03044       ng_obj[i][j] = (nobj - obj) / 1e-6;
03045       std::cout << i << " " << j << " " << g_obj[i][j] << " " << ng_obj[i][j] << std::endl;
03046     }
03047   }
03048   std::cout << std::endl;
03049 
03050   for (i = 0; i < 4; ++i) {
03051     for (j = 0; j < 3; ++j) {
03052       nx[i][j] += 1e-6;
03053       g_fcn_3p(nobj, ng_obj, nx, a, b, c);
03054       nx[i][j] = x[i][j];
03055 
03056       printf("%d %d", i, j);
03057       for (k = 0; k < 4; ++k) {
03058     for (l = 0; l < 3; ++l) {
03059       printf(" % 5.4e", (ng_obj[k][l] - g_obj[k][l]) / 1e-6);
03060     }
03061       }
03062       printf("\n");
03063     }
03064   }
03065 
03066   for (i = 0; i < 10; ++i) {
03067     std::cout << i << std::endl << h_obj[i] << std::endl << std::endl;
03068   }
03069 #endif
03070 
03071     // completes diagonal blocks.
03072     h_obj[0].fill_lower_triangle();
03073     h_obj[4].fill_lower_triangle();
03074     h_obj[7].fill_lower_triangle();
03075     h_obj[9].fill_lower_triangle();
03076     return true;
03077 }
03078 
03079 /*********************************************************************
03080  * Reference tetrahedral elements to corners of an ideal wedge element.
03081  * Vertices should be ordered such that the first three vertices form
03082  * the ideally-equaliteral face of the tetrahedron (the end of the
03083  * wedge) and the first and fourth vertices form the tetrahedral edge
03084  * orthogonal to the ideally-equaliteral face (the lateral edge of the
03085  * edge.)
03086  *      1  1/2        0                     1  -1/sqrt(3)  0
03087  * W =  0  sqrt(3)/2  0           inv(W) =  0   2/sqrt(3)  0
03088  *      0  0          1                     0   0          1
03089  *
03090  *********************************************************************/
03091 inline bool m_fcn_3w( double& obj, const Vector3D x[4], const double a, const Exponent& b, const Exponent& c )
03092 {
03093     double matr[9], f, g;
03094     double loc1, loc2, loc3;
03095 
03096     /* Calculate M = A*inv(W). */
03097     matr[0] = x[1][0] - x[0][0];
03098     matr[1] = isqrt3 * ( 2 * x[2][0] - x[1][0] - x[0][0] );
03099     matr[2] = x[3][0] - x[0][0];
03100 
03101     matr[3] = x[1][1] - x[0][1];
03102     matr[4] = isqrt3 * ( 2 * x[2][1] - x[1][1] - x[0][1] );
03103     matr[5] = x[3][1] - x[0][1];
03104 
03105     matr[6] = x[1][2] - x[0][2];
03106     matr[7] = isqrt3 * ( 2 * x[2][2] - x[1][2] - x[0][2] );
03107     matr[8] = x[3][2] - x[0][2];
03108 
03109     /* Calculate det(M). */
03110     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
03111     loc2 = matr[5] * matr[6] - matr[3] * matr[8];
03112     loc3 = matr[3] * matr[7] - matr[4] * matr[6];
03113     g    = matr[0] * loc1 + matr[1] * loc2 + matr[2] * loc3;
03114     if( g < MSQ_MIN )
03115     {
03116         obj = g;
03117         return false;
03118     }
03119 
03120     /* Calculate norm(M). */
03121     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
03122         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
03123 
03124     /* Calculate objective function. */
03125     obj = a * b.raise( f ) * c.raise( g );
03126     return true;
03127 }
03128 
03129 inline bool g_fcn_3w( double& obj,
03130                       Vector3D g_obj[4],
03131                       const Vector3D x[4],
03132                       const double a,
03133                       const Exponent& b,
03134                       const Exponent& c )
03135 {
03136     double matr[9], f;
03137     double adj_m[9], g;
03138     double loc1, loc2, loc3;
03139 
03140     /* Calculate M = A*inv(W). */
03141     matr[0] = x[1][0] - x[0][0];
03142     matr[1] = isqrt3 * ( 2 * x[2][0] - x[1][0] - x[0][0] );
03143     matr[2] = x[3][0] - x[0][0];
03144 
03145     matr[3] = x[1][1] - x[0][1];
03146     matr[4] = isqrt3 * ( 2 * x[2][1] - x[1][1] - x[0][1] );
03147     matr[5] = x[3][1] - x[0][1];
03148 
03149     matr[6] = x[1][2] - x[0][2];
03150     matr[7] = isqrt3 * ( 2 * x[2][2] - x[1][2] - x[0][2] );
03151     matr[8] = x[3][2] - x[0][2];
03152 
03153     /* Calculate det(M). */
03154     loc1 = matr[4] * matr[8] - matr[5] * matr[7];
03155     loc2 = matr[5] * matr[6] - matr[3] * matr[8];
03156     loc3 = matr[3] * matr[7] - matr[4] * matr[6];
03157     g    = matr[0] * loc1 + matr[1] * loc2 + matr[2] * loc3;
03158     if( g < MSQ_MIN )
03159     {
03160         obj = g;
03161         return false;
03162     }
03163 
03164     /* Calculate norm(M). */
03165     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
03166         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
03167 
03168     /* Calculate objective function. */
03169     obj = a * b.raise( f ) * c.raise( g );
03170 
03171     /* Calculate the derivative of the objective function.    */
03172     f = b.value() * obj / f; /* Constant on nabla f      */
03173     g = c.value() * obj / g; /* Constant on nable g      */
03174     f *= 2.0;                /* Modification for nabla f */
03175 
03176     adj_m[0] = matr[0] * f + loc1 * g;
03177     adj_m[1] = matr[1] * f + loc2 * g;
03178     adj_m[2] = matr[2] * f + loc3 * g;
03179 
03180     loc1 = matr[0] * g;
03181     loc2 = matr[1] * g;
03182     loc3 = matr[2] * g;
03183 
03184     adj_m[3] = matr[3] * f + loc3 * matr[7] - loc2 * matr[8];
03185     adj_m[4] = matr[4] * f + loc1 * matr[8] - loc3 * matr[6];
03186     adj_m[5] = matr[5] * f + loc2 * matr[6] - loc1 * matr[7];
03187 
03188     adj_m[6] = matr[6] * f + loc2 * matr[5] - loc3 * matr[4];
03189     adj_m[7] = matr[7] * f + loc3 * matr[3] - loc1 * matr[5];
03190     adj_m[8] = matr[8] * f + loc1 * matr[4] - loc2 * matr[3];
03191 
03192     g_obj[0][0] = -adj_m[0] - isqrt3 * adj_m[1] - adj_m[2];
03193     g_obj[1][0] = adj_m[0] - isqrt3 * adj_m[1];
03194     g_obj[2][0] = tisqrt3 * adj_m[1];
03195     g_obj[3][0] = adj_m[2];
03196 
03197     g_obj[0][1] = -adj_m[3] - isqrt3 * adj_m[4] - adj_m[5];
03198     g_obj[1][1] = adj_m[3] - isqrt3 * adj_m[4];
03199     g_obj[2][1] = tisqrt3 * adj_m[4];
03200     g_obj[3][1] = adj_m[5];
03201 
03202     g_obj[0][2] = -adj_m[6] - isqrt3 * adj_m[7] - adj_m[8];
03203     g_obj[1][2] = adj_m[6] - isqrt3 * adj_m[7];
03204     g_obj[2][2] = tisqrt3 * adj_m[7];
03205     g_obj[3][2] = adj_m[8];
03206 
03207     return true;
03208 }
03209 
03210 inline bool h_fcn_3w( double& obj,
03211                       Vector3D g_obj[4],
03212                       Matrix3D h_obj[10],
03213                       const Vector3D x[4],
03214                       const double a,
03215                       const Exponent& b,
03216                       const Exponent& c )
03217 {
03218     double matr[9], f;
03219     double adj_m[9], g;
03220     double dg[9], loc0, loc1, loc2, loc3, loc4;
03221     double A[12], J_A[6], J_B[9], J_C[9], cross;
03222 
03223     /* Calculate M = A*inv(W). */
03224     matr[0] = x[1][0] - x[0][0];
03225     matr[1] = isqrt3 * ( 2 * x[2][0] - x[1][0] - x[0][0] );
03226     matr[2] = x[3][0] - x[0][0];
03227 
03228     matr[3] = x[1][1] - x[0][1];
03229     matr[4] = isqrt3 * ( 2 * x[2][1] - x[1][1] - x[0][1] );
03230     matr[5] = x[3][1] - x[0][1];
03231 
03232     matr[6] = x[1][2] - x[0][2];
03233     matr[7] = isqrt3 * ( 2 * x[2][2] - x[1][2] - x[0][2] );
03234     matr[8] = x[3][2] - x[0][2];
03235 
03236     /* Calculate det(M). */
03237     dg[0] = matr[4] * matr[8] - matr[5] * matr[7];
03238     dg[1] = matr[5] * matr[6] - matr[3] * matr[8];
03239     dg[2] = matr[3] * matr[7] - matr[4] * matr[6];
03240     g     = matr[0] * dg[0] + matr[1] * dg[1] + matr[2] * dg[2];
03241     if( g < MSQ_MIN )
03242     {
03243         obj = g;
03244         return false;
03245     }
03246 
03247     dg[3] = matr[2] * matr[7] - matr[1] * matr[8];
03248     dg[4] = matr[0] * matr[8] - matr[2] * matr[6];
03249     dg[5] = matr[1] * matr[6] - matr[0] * matr[7];
03250     dg[6] = matr[1] * matr[5] - matr[2] * matr[4];
03251     dg[7] = matr[2] * matr[3] - matr[0] * matr[5];
03252     dg[8] = matr[0] * matr[4] - matr[1] * matr[3];
03253 
03254     /* Calculate norm(M). */
03255     f = matr[0] * matr[0] + matr[1] * matr[1] + matr[2] * matr[2] + matr[3] * matr[3] + matr[4] * matr[4] +
03256         matr[5] * matr[5] + matr[6] * matr[6] + matr[7] * matr[7] + matr[8] * matr[8];
03257 
03258     loc3 = f;
03259     loc4 = g;
03260 
03261     /* Calculate objective function. */
03262     obj = a * b.raise( f ) * c.raise( g );
03263 
03264     /* Calculate the derivative of the objective function.    */
03265     f = b.value() * obj / f; /* Constant on nabla f      */
03266     g = c.value() * obj / g; /* Constant on nable g      */
03267     f *= 2.0;                /* Modification for nabla f */
03268 
03269     adj_m[0] = matr[0] * f + dg[0] * g;
03270     adj_m[1] = matr[1] * f + dg[1] * g;
03271     adj_m[2] = matr[2] * f + dg[2] * g;
03272     adj_m[3] = matr[3] * f + dg[3] * g;
03273     adj_m[4] = matr[4] * f + dg[4] * g;
03274     adj_m[5] = matr[5] * f + dg[5] * g;
03275     adj_m[6] = matr[6] * f + dg[6] * g;
03276     adj_m[7] = matr[7] * f + dg[7] * g;
03277     adj_m[8] = matr[8] * f + dg[8] * g;
03278 
03279     g_obj[0][0] = -adj_m[0] - isqrt3 * adj_m[1] - adj_m[2];
03280     g_obj[1][0] = adj_m[0] - isqrt3 * adj_m[1];
03281     g_obj[2][0] = tisqrt3 * adj_m[1];
03282     g_obj[3][0] = adj_m[2];
03283 
03284     g_obj[0][1] = -adj_m[3] - isqrt3 * adj_m[4] - adj_m[5];
03285     g_obj[1][1] = adj_m[3] - isqrt3 * adj_m[4];
03286     g_obj[2][1] = tisqrt3 * adj_m[4];
03287     g_obj[3][1] = adj_m[5];
03288 
03289     g_obj[0][2] = -adj_m[6] - isqrt3 * adj_m[7] - adj_m[8];
03290     g_obj[1][2] = adj_m[6] - isqrt3 * adj_m[7];
03291     g_obj[2][2] = tisqrt3 * adj_m[7];
03292     g_obj[3][2] = adj_m[8];
03293 
03294     /* Calculate the hessian of the objective.                   */
03295     loc0  = f;                            /* Constant on nabla^2 f       */
03296     loc1  = g;                            /* Constant on nabla^2 g       */
03297     cross = f * c.value() / loc4;         /* Constant on nabla g nabla f */
03298     f     = f * ( b.value() - 1 ) / loc3; /* Constant on nabla f nabla f */
03299     g     = g * ( c.value() - 1 ) / loc4; /* Constant on nabla g nabla g */
03300     f *= 2.0;                             /* Modification for nabla f    */
03301 
03302     /* First block of rows */
03303     loc3 = matr[0] * f + dg[0] * cross;
03304     loc4 = dg[0] * g + matr[0] * cross;
03305 
03306     J_A[0] = loc0 + loc3 * matr[0] + loc4 * dg[0];
03307     J_A[1] = loc3 * matr[1] + loc4 * dg[1];
03308     J_A[2] = loc3 * matr[2] + loc4 * dg[2];
03309     J_B[0] = loc3 * matr[3] + loc4 * dg[3];
03310     J_B[1] = loc3 * matr[4] + loc4 * dg[4];
03311     J_B[2] = loc3 * matr[5] + loc4 * dg[5];
03312     J_C[0] = loc3 * matr[6] + loc4 * dg[6];
03313     J_C[1] = loc3 * matr[7] + loc4 * dg[7];
03314     J_C[2] = loc3 * matr[8] + loc4 * dg[8];
03315 
03316     loc3 = matr[1] * f + dg[1] * cross;
03317     loc4 = dg[1] * g + matr[1] * cross;
03318 
03319     J_A[3] = loc0 + loc3 * matr[1] + loc4 * dg[1];
03320     J_A[4] = loc3 * matr[2] + loc4 * dg[2];
03321     J_B[3] = loc3 * matr[3] + loc4 * dg[3];
03322     J_B[4] = loc3 * matr[4] + loc4 * dg[4];
03323     J_B[5] = loc3 * matr[5] + loc4 * dg[5];
03324     J_C[3] = loc3 * matr[6] + loc4 * dg[6];
03325     J_C[4] = loc3 * matr[7] + loc4 * dg[7];
03326     J_C[5] = loc3 * matr[8] + loc4 * dg[8];
03327 
03328     loc3 = matr[2] * f + dg[2] * cross;
03329     loc4 = dg[2] * g + matr[2] * cross;
03330 
03331     J_A[5] = loc0 + loc3 * matr[2] + loc4 * dg[2];
03332     J_B[6] = loc3 * matr[3] + loc4 * dg[3];
03333     J_B[7] = loc3 * matr[4] + loc4 * dg[4];
03334     J_B[8] = loc3 * matr[5] + loc4 * dg[5];
03335     J_C[6] = loc3 * matr[6] + loc4 * dg[6];
03336     J_C[7] = loc3 * matr[7] + loc4 * dg[7];
03337     J_C[8] = loc3 * matr[8] + loc4 * dg[8];
03338 
03339     /* First diagonal block */
03340     A[0] = -J_A[0] - isqrt3 * J_A[1] - J_A[2];
03341     A[1] = J_A[0] - isqrt3 * J_A[1];
03342     // A[2]  =          tisqrt3*J_A[1];
03343     // A[3]  =                           J_A[2];
03344 
03345     A[4] = -J_A[1] - isqrt3 * J_A[3] - J_A[4];
03346     A[5] = J_A[1] - isqrt3 * J_A[3];
03347     A[6] = tisqrt3 * J_A[3];
03348     // A[7]  =                           J_A[4];
03349 
03350     A[8]  = -J_A[2] - isqrt3 * J_A[4] - J_A[5];
03351     A[9]  = J_A[2] - isqrt3 * J_A[4];
03352     A[10] = tisqrt3 * J_A[4];
03353     A[11] = J_A[5];
03354 
03355     h_obj[0][0][0] = -A[0] - isqrt3 * A[4] - A[8];
03356     h_obj[1][0][0] = A[0] - isqrt3 * A[4];
03357     h_obj[2][0][0] = tisqrt3 * A[4];
03358     h_obj[3][0][0] = A[8];
03359 
03360     h_obj[4][0][0] = A[1] - isqrt3 * A[5];
03361     h_obj[5][0][0] = tisqrt3 * A[5];
03362     h_obj[6][0][0] = A[9];
03363 
03364     h_obj[7][0][0] = tisqrt3 * A[6];
03365     h_obj[8][0][0] = A[10];
03366 
03367     h_obj[9][0][0] = A[11];
03368 
03369     /* First off-diagonal block */
03370     loc2 = matr[8] * loc1;
03371     J_B[1] += loc2;
03372     J_B[3] -= loc2;
03373 
03374     loc2 = matr[7] * loc1;
03375     J_B[2] -= loc2;
03376     J_B[6] += loc2;
03377 
03378     loc2 = matr[6] * loc1;
03379     J_B[5] += loc2;
03380     J_B[7] -= loc2;
03381 
03382     A[0] = -J_B[0] - isqrt3 * J_B[1] - J_B[2];
03383     A[1] = J_B[0] - isqrt3 * J_B[1];
03384     A[2] = tisqrt3 * J_B[1];
03385     A[3] = J_B[2];
03386 
03387     A[4] = -J_B[3] - isqrt3 * J_B[4] - J_B[5];
03388     A[5] = J_B[3] - isqrt3 * J_B[4];
03389     A[6] = tisqrt3 * J_B[4];
03390     A[7] = J_B[5];
03391 
03392     A[8]  = -J_B[6] - isqrt3 * J_B[7] - J_B[8];
03393     A[9]  = J_B[6] - isqrt3 * J_B[7];
03394     A[10] = tisqrt3 * J_B[7];
03395     A[11] = J_B[8];
03396 
03397     h_obj[0][0][1] = -A[0] - isqrt3 * A[4] - A[8];
03398     h_obj[1][1][0] = A[0] - isqrt3 * A[4];
03399     h_obj[2][1][0] = tisqrt3 * A[4];
03400     h_obj[3][1][0] = A[8];
03401 
03402     h_obj[1][0][1] = -A[1] - isqrt3 * A[5] - A[9];
03403     h_obj[4][0][1] = A[1] - isqrt3 * A[5];
03404     h_obj[5][1][0] = tisqrt3 * A[5];
03405     h_obj[6][1][0] = A[9];
03406 
03407     h_obj[2][0][1] = -A[2] - isqrt3 * A[6] - A[10];
03408     h_obj[5][0][1] = A[2] - isqrt3 * A[6];
03409     h_obj[7][0][1] = tisqrt3 * A[6];
03410     h_obj[8][1][0] = A[10];
03411 
03412     h_obj[3][0][1] = -A[3] - isqrt3 * A[7] - A[11];
03413     h_obj[6][0][1] = A[3] - isqrt3 * A[7];
03414     h_obj[8][0][1] = tisqrt3 * A[7];
03415     h_obj[9][0][1] = A[11];
03416 
03417     /* Second off-diagonal block */
03418     loc2 = matr[5] * loc1;
03419     J_C[1] -= loc2;
03420     J_C[3] += loc2;
03421 
03422     loc2 = matr[4] * loc1;
03423     J_C[2] += loc2;
03424     J_C[6] -= loc2;
03425 
03426     loc2 = matr[3] * loc1;
03427     J_C[5] -= loc2;
03428     J_C[7] += loc2;
03429 
03430     A[0] = -J_C[0] - isqrt3 * J_C[1] - J_C[2];
03431     A[1] = J_C[0] - isqrt3 * J_C[1];
03432     A[2] = tisqrt3 * J_C[1];
03433     A[3] = J_C[2];
03434 
03435     A[4] = -J_C[3] - isqrt3 * J_C[4] - J_C[5];
03436     A[5] = J_C[3] - isqrt3 * J_C[4];
03437     A[6] = tisqrt3 * J_C[4];
03438     A[7] = J_C[5];
03439 
03440     A[8]  = -J_C[6] - isqrt3 * J_C[7] - J_C[8];
03441     A[9]  = J_C[6] - isqrt3 * J_C[7];
03442     A[10] = tisqrt3 * J_C[7];
03443     A[11] = J_C[8];
03444 
03445     h_obj[0][0][2] = -A[0] - isqrt3 * A[4] - A[8];
03446     h_obj[1][2][0] = A[0] - isqrt3 * A[4];
03447     h_obj[2][2][0] = tisqrt3 * A[4];
03448     h_obj[3][2][0] = A[8];
03449 
03450     h_obj[1][0][2] = -A[1] - isqrt3 * A[5] - A[9];
03451     h_obj[4][0][2] = A[1] - isqrt3 * A[5];
03452     h_obj[5][2][0] = tisqrt3 * A[5];
03453     h_obj[6][2][0] = A[9];
03454 
03455     h_obj[2][0][2] = -A[2] - isqrt3 * A[6] - A[10];
03456     h_obj[5][0][2] = A[2] - isqrt3 * A[6];
03457     h_obj[7][0][2] = tisqrt3 * A[6];
03458     h_obj[8][2][0] = A[10];
03459 
03460     h_obj[3][0][2] = -A[3] - isqrt3 * A[7] - A[11];
03461     h_obj[6][0][2] = A[3] - isqrt3 * A[7];
03462     h_obj[8][0][2] = tisqrt3 * A[7];
03463     h_obj[9][0][2] = A[11];
03464 
03465     /* Second block of rows */
03466     loc3 = matr[3] * f + dg[3] * cross;
03467     loc4 = dg[3] * g + matr[3] * cross;
03468 
03469     J_A[0] = loc0 + loc3 * matr[3] + loc4 * dg[3];
03470     J_A[1] = loc3 * matr[4] + loc4 * dg[4];
03471     J_A[2] = loc3 * matr[5] + loc4 * dg[5];
03472     J_B[0] = loc3 * matr[6] + loc4 * dg[6];
03473     J_B[1] = loc3 * matr[7] + loc4 * dg[7];
03474     J_B[2] = loc3 * matr[8] + loc4 * dg[8];
03475 
03476     loc3 = matr[4] * f + dg[4] * cross;
03477     loc4 = dg[4] * g + matr[4] * cross;
03478 
03479     J_A[3] = loc0 + loc3 * matr[4] + loc4 * dg[4];
03480     J_A[4] = loc3 * matr[5] + loc4 * dg[5];
03481     J_B[3] = loc3 * matr[6] + loc4 * dg[6];
03482     J_B[4] = loc3 * matr[7] + loc4 * dg[7];
03483     J_B[5] = loc3 * matr[8] + loc4 * dg[8];
03484 
03485     loc3 = matr[5] * f + dg[5] * cross;
03486     loc4 = dg[5] * g + matr[5] * cross;
03487 
03488     J_A[5] = loc0 + loc3 * matr[5] + loc4 * dg[5];
03489     J_B[6] = loc3 * matr[6] + loc4 * dg[6];
03490     J_B[7] = loc3 * matr[7] + loc4 * dg[7];
03491     J_B[8] = loc3 * matr[8] + loc4 * dg[8];
03492 
03493     /* Second diagonal block */
03494     A[0] = -J_A[0] - isqrt3 * J_A[1] - J_A[2];
03495     A[1] = J_A[0] - isqrt3 * J_A[1];
03496     // A[2]  =          tisqrt3*J_A[1];
03497     // A[3]  =                           J_A[2];
03498 
03499     A[4] = -J_A[1] - isqrt3 * J_A[3] - J_A[4];
03500     A[5] = J_A[1] - isqrt3 * J_A[3];
03501     A[6] = tisqrt3 * J_A[3];
03502     // A[7]  =                           J_A[4];
03503 
03504     A[8]  = -J_A[2] - isqrt3 * J_A[4] - J_A[5];
03505     A[9]  = J_A[2] - isqrt3 * J_A[4];
03506     A[10] = tisqrt3 * J_A[4];
03507     A[11] = J_A[5];
03508 
03509     h_obj[0][1][1] = -A[0] - isqrt3 * A[4] - A[8];
03510     h_obj[1][1][1] = A[0] - isqrt3 * A[4];
03511     h_obj[2][1][1] = tisqrt3 * A[4];
03512     h_obj[3][1][1] = A[8];
03513 
03514     h_obj[4][1][1] = A[1] - isqrt3 * A[5];
03515     h_obj[5][1][1] = tisqrt3 * A[5];
03516     h_obj[6][1][1] = A[9];
03517 
03518     h_obj[7][1][1] = tisqrt3 * A[6];
03519     h_obj[8][1][1] = A[10];
03520 
03521     h_obj[9][1][1] = A[11];
03522 
03523     /* Third off-diagonal block */
03524     loc2 = matr[2] * loc1;
03525     J_B[1] += loc2;
03526     J_B[3] -= loc2;
03527 
03528     loc2 = matr[1] * loc1;
03529     J_B[2] -= loc2;
03530     J_B[6] += loc2;
03531 
03532     loc2 = matr[0] * loc1;
03533     J_B[5] += loc2;
03534     J_B[7] -= loc2;
03535 
03536     A[0] = -J_B[0] - isqrt3 * J_B[1] - J_B[2];
03537     A[1] = J_B[0] - isqrt3 * J_B[1];
03538     A[2] = tisqrt3 * J_B[1];
03539     A[3] = J_B[2];
03540 
03541     A[4] = -J_B[3] - isqrt3 * J_B[4] - J_B[5];
03542     A[5] = J_B[3] - isqrt3 * J_B[4];
03543     A[6] = tisqrt3 * J_B[4];
03544     A[7] = J_B[5];
03545 
03546     A[8]  = -J_B[6] - isqrt3 * J_B[7] - J_B[8];
03547     A[9]  = J_B[6] - isqrt3 * J_B[7];
03548     A[10] = tisqrt3 * J_B[7];
03549     A[11] = J_B[8];
03550 
03551     h_obj[0][1][2] = -A[0] - isqrt3 * A[4] - A[8];
03552     h_obj[1][2][1] = A[0] - isqrt3 * A[4];
03553     h_obj[2][2][1] = tisqrt3 * A[4];
03554     h_obj[3][2][1] = A[8];
03555 
03556     h_obj[1][1][2] = -A[1] - isqrt3 * A[5] - A[9];
03557     h_obj[4][1][2] = A[1] - isqrt3 * A[5];
03558     h_obj[5][2][1] = tisqrt3 * A[5];
03559     h_obj[6][2][1] = A[9];
03560 
03561     h_obj[2][1][2] = -A[2] - isqrt3 * A[6] - A[10];
03562     h_obj[5][1][2] = A[2] - isqrt3 * A[6];
03563     h_obj[7][1][2] = tisqrt3 * A[6];
03564     h_obj[8][2][1] = A[10];
03565 
03566     h_obj[3][1][2] = -A[3] - isqrt3 * A[7] - A[11];
03567     h_obj[6][1][2] = A[3] - isqrt3 * A[7];
03568     h_obj[8][1][2] = tisqrt3 * A[7];
03569     h_obj[9][1][2] = A[11];
03570 
03571     /* Third block of rows */
03572     loc3 = matr[6] * f + dg[6] * cross;
03573     loc4 = dg[6] * g + matr[6] * cross;
03574 
03575     J_A[0] = loc0 + loc3 * matr[6] + loc4 * dg[6];
03576     J_A[1] = loc3 * matr[7] + loc4 * dg[7];
03577     J_A[2] = loc3 * matr[8] + loc4 * dg[8];
03578 
03579     loc3 = matr[7] * f + dg[7] * cross;
03580     loc4 = dg[7] * g + matr[7] * cross;
03581 
03582     J_A[3] = loc0 + loc3 * matr[7] + loc4 * dg[7];
03583     J_A[4] = loc3 * matr[8] + loc4 * dg[8];
03584 
03585     loc3 = matr[8] * f + dg[8] * cross;
03586     loc4 = dg[8] * g + matr[8] * cross;
03587 
03588     J_A[5] = loc0 + loc3 * matr[8] + loc4 * dg[8];
03589 
03590     /* Third diagonal block */
03591     A[0] = -J_A[0] - isqrt3 * J_A[1] - J_A[2];
03592     A[1] = J_A[0] - isqrt3 * J_A[1];
03593     // A[2]  =          tisqrt3*J_A[1];
03594     // A[3]  =                           J_A[2];
03595 
03596     A[4] = -J_A[1] - isqrt3 * J_A[3] - J_A[4];
03597     A[5] = J_A[1] - isqrt3 * J_A[3];
03598     A[6] = tisqrt3 * J_A[3];
03599     // A[7]  =                           J_A[4];
03600 
03601     A[8]  = -J_A[2] - isqrt3 * J_A[4] - J_A[5];
03602     A[9]  = J_A[2] - isqrt3 * J_A[4];
03603     A[10] = tisqrt3 * J_A[4];
03604     A[11] = J_A[5];
03605 
03606     h_obj[0][2][2] = -A[0] - isqrt3 * A[4] - A[8];
03607     h_obj[1][2][2] = A[0] - isqrt3 * A[4];
03608     h_obj[2][2][2] = tisqrt3 * A[4];
03609     h_obj[3][2][2] = A[8];
03610 
03611     h_obj[4][2][2] = A[1] - isqrt3 * A[5];
03612     h_obj[5][2][2] = tisqrt3 * A[5];
03613     h_obj[6][2][2] = A[9];
03614 
03615     h_obj[7][2][2] = tisqrt3 * A[6];
03616     h_obj[8][2][2] = A[10];
03617 
03618     h_obj[9][2][2] = A[11];
03619 
03620     // completes diagonal blocks.
03621     h_obj[0].fill_lower_triangle();
03622     h_obj[4].fill_lower_triangle();
03623     h_obj[7].fill_lower_triangle();
03624     h_obj[9].fill_lower_triangle();
03625 
03626     return true;
03627 }
03628 
03629 }  // namespace MBMesquite
03630 
03631 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines