MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov, 00024 pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov 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