MOAB: Mesh Oriented datABase  (version 5.4.1)
CompositeOFMultiply.cpp
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 /*!
00028   \file    CompositeOFMultiply.cpp
00029   \brief
00030 
00031   This Objective Function combines two Objective Functions by mulitplication
00032   \author Michael Brewer
00033   \date   2002-01-23
00034 */
00035 #include <cmath>
00036 #include "CompositeOFMultiply.hpp"
00037 #include "MsqTimer.hpp"
00038 #include "PatchData.hpp"
00039 
00040 namespace MBMesquite
00041 {
00042 
00043 /*!
00044 Sets the QualityMetric pointer to the metric associated with Obj1 and Obj2
00045 if Obj1 and Obj2 are associated with the same metric.  Otherwise, it sets
00046 the QualityMetric pointer to NULL.  The new
00047 ObjectiveFunction's negateFlag is set to negative one only if both Obj1 and
00048 Obj2's negateFlag are negative one (because obj1 and obj2's evaluate function
00049 multiply their return values by negative one if their respective
00050 function needs to be maximized.  If both of these functions needed to
00051 be maximized, then the negative ones will have cancelled out).  Otherwise,
00052 the negateFlag is set to one.  Defaults to the analytical gradient.
00053   \param Obj1 (ObjectiveFunction*)
00054   \param Obj2 (ObjectiveFunction*)
00055  */
00056 CompositeOFMultiply::CompositeOFMultiply( ObjectiveFunction* Obj1, ObjectiveFunction* Obj2, bool delete_OFs )
00057     : deleteObjFuncs( delete_OFs )
00058 {
00059     objFunc1 = Obj1;
00060     objFunc2 = Obj2;
00061 }
00062 
00063 // Michael:  need to clean up here
00064 CompositeOFMultiply::~CompositeOFMultiply()
00065 {
00066     if( deleteObjFuncs )
00067     {
00068         delete objFunc1;
00069         delete objFunc2;
00070     }
00071 }
00072 
00073 ObjectiveFunction* CompositeOFMultiply::clone() const
00074 {
00075     return new CompositeOFMultiply( objFunc1->clone(), objFunc2->clone(), true );
00076 }
00077 
00078 void CompositeOFMultiply::clear()
00079 {
00080     objFunc1->clear();
00081     objFunc2->clear();
00082 }
00083 
00084 void CompositeOFMultiply::initialize_queue( MeshDomainAssoc* mesh_and_domain, const Settings* settings, MsqError& err )
00085 {
00086     objFunc1->initialize_queue( mesh_and_domain, settings, err );MSQ_ERRRTN( err );
00087     objFunc2->initialize_queue( mesh_and_domain, settings, err );MSQ_ERRRTN( err );
00088 }
00089 
00090 bool CompositeOFMultiply::initialize_block_coordinate_descent( MeshDomainAssoc* mesh_and_domain,
00091                                                                const Settings* settings,
00092                                                                PatchSet* user_set,
00093                                                                MsqError& err )
00094 {
00095     bool rval1, rval2;
00096     rval1 = objFunc1->initialize_block_coordinate_descent( mesh_and_domain, settings, user_set, err );
00097     MSQ_ERRZERO( err );
00098     rval2 = objFunc2->initialize_block_coordinate_descent( mesh_and_domain, settings, user_set, err );
00099     return !MSQ_CHKERR( err ) && rval1 && rval2;
00100 }
00101 
00102 bool CompositeOFMultiply::evaluate( EvalType type, PatchData& pd, double& value_out, bool free, MsqError& err )
00103 {
00104     double value_2;
00105     bool ok;
00106 
00107     ok = objFunc1->evaluate( type, pd, value_out, free, err );
00108     if( MSQ_CHKERR( err ) || !ok ) return false;
00109     ok = objFunc2->evaluate( type, pd, value_2, free, err );
00110     if( MSQ_CHKERR( err ) || !ok ) return false;
00111 
00112     value_out *= value_2;
00113     return true;
00114 }
00115 
00116 bool CompositeOFMultiply::evaluate_with_gradient( EvalType type,
00117                                                   PatchData& pd,
00118                                                   double& value_out,
00119                                                   std::vector< Vector3D >& grad_out,
00120                                                   MsqError& err )
00121 {
00122     double value_2;
00123     bool ok;
00124 
00125     ok = objFunc1->evaluate_with_gradient( type, pd, value_out, grad_out, err );
00126     if( MSQ_CHKERR( err ) || !ok ) return false;
00127     ok = objFunc2->evaluate_with_gradient( type, pd, value_2, mGradient, err );
00128     if( MSQ_CHKERR( err ) || !ok ) return false;
00129 
00130     assert( grad_out.size() == pd.num_free_vertices() );
00131     assert( mGradient.size() == pd.num_free_vertices() );
00132 
00133     std::vector< Vector3D >::iterator i = grad_out.begin(), j = mGradient.begin();
00134     while( i != grad_out.end() )
00135     {
00136         *i *= value_2;
00137         *j *= value_out;
00138         *i += *j;
00139         ++i;
00140         ++j;
00141     }
00142     value_out *= value_2;
00143     return true;
00144 }
00145 
00146 bool CompositeOFMultiply::evaluate_with_Hessian_diagonal( EvalType type,
00147                                                           PatchData& pd,
00148                                                           double& value_out,
00149                                                           std::vector< Vector3D >& grad_out,
00150                                                           std::vector< SymMatrix3D >& diag_out,
00151                                                           MsqError& err )
00152 {
00153     double value_2;
00154     bool valid;
00155 
00156     valid = objFunc1->evaluate_with_Hessian_diagonal( type, pd, value_out, grad_out, diag_out, err );
00157     if( MSQ_CHKERR( err ) || !valid ) return false;
00158     valid = objFunc2->evaluate_with_Hessian_diagonal( type, pd, value_2, mGradient, mDiagonal, err );
00159     if( MSQ_CHKERR( err ) || !valid ) return false;
00160 
00161     for( size_t i = 0; i < pd.num_free_vertices(); ++i )
00162     {
00163         diag_out[i] *= value_2;
00164         mDiagonal[i] *= value_out;
00165         diag_out[i] += mDiagonal[i];
00166         diag_out[i] += outer_plus_transpose( grad_out[i], mGradient[i] );
00167 
00168         grad_out[i] *= value_2;
00169         mGradient[i] *= value_out;
00170         grad_out[i] += mGradient[i];
00171     }
00172 
00173     value_out *= value_2;
00174     return true;
00175 }
00176 
00177 bool CompositeOFMultiply::evaluate_with_Hessian( EvalType,
00178                                                  PatchData&,
00179                                                  double&,
00180                                                  std::vector< Vector3D >&,
00181                                                  MsqHessian&,
00182                                                  MsqError& err )
00183 {
00184     MSQ_SETERR( err )
00185     ( "Mesquite is not capable of representing the dense "
00186       "Hessian of the product of two objective fuctions. "
00187       "Either choose a solver that does not require the "
00188       "Hessian of the objective function or do not use the "
00189       "CompositeOFMultiple objective function .",
00190       MsqError::INVALID_STATE );
00191     return false;
00192 }
00193 
00194 int CompositeOFMultiply::min_patch_layers() const
00195 {
00196     const int v1 = objFunc1->min_patch_layers();
00197     const int v2 = objFunc2->min_patch_layers();
00198     return v1 > v2 ? v1 : v2;
00199 }
00200 
00201 }  // namespace MBMesquite
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines