MOAB: Mesh Oriented datABase
(version 5.3.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, PatchSet* user_set, 00092 MsqError& err ) 00093 { 00094 bool rval1, rval2; 00095 rval1 = objFunc1->initialize_block_coordinate_descent( mesh_and_domain, settings, user_set, err ); 00096 MSQ_ERRZERO( err ); 00097 rval2 = objFunc2->initialize_block_coordinate_descent( mesh_and_domain, settings, user_set, err ); 00098 return !MSQ_CHKERR( err ) && rval1 && rval2; 00099 } 00100 00101 bool CompositeOFMultiply::evaluate( EvalType type, PatchData& pd, double& value_out, bool free, MsqError& err ) 00102 { 00103 double value_2; 00104 bool ok; 00105 00106 ok = objFunc1->evaluate( type, pd, value_out, free, err ); 00107 if( MSQ_CHKERR( err ) || !ok ) return false; 00108 ok = objFunc2->evaluate( type, pd, value_2, free, err ); 00109 if( MSQ_CHKERR( err ) || !ok ) return false; 00110 00111 value_out *= value_2; 00112 return true; 00113 } 00114 00115 bool CompositeOFMultiply::evaluate_with_gradient( EvalType type, PatchData& pd, double& value_out, 00116 std::vector< Vector3D >& grad_out, MsqError& err ) 00117 { 00118 double value_2; 00119 bool ok; 00120 00121 ok = objFunc1->evaluate_with_gradient( type, pd, value_out, grad_out, err ); 00122 if( MSQ_CHKERR( err ) || !ok ) return false; 00123 ok = objFunc2->evaluate_with_gradient( type, pd, value_2, mGradient, err ); 00124 if( MSQ_CHKERR( err ) || !ok ) return false; 00125 00126 assert( grad_out.size() == pd.num_free_vertices() ); 00127 assert( mGradient.size() == pd.num_free_vertices() ); 00128 00129 std::vector< Vector3D >::iterator i = grad_out.begin(), j = mGradient.begin(); 00130 while( i != grad_out.end() ) 00131 { 00132 *i *= value_2; 00133 *j *= value_out; 00134 *i += *j; 00135 ++i; 00136 ++j; 00137 } 00138 value_out *= value_2; 00139 return true; 00140 } 00141 00142 bool CompositeOFMultiply::evaluate_with_Hessian_diagonal( EvalType type, PatchData& pd, double& value_out, 00143 std::vector< Vector3D >& grad_out, 00144 std::vector< SymMatrix3D >& diag_out, MsqError& err ) 00145 { 00146 double value_2; 00147 bool valid; 00148 00149 valid = objFunc1->evaluate_with_Hessian_diagonal( type, pd, value_out, grad_out, diag_out, err ); 00150 if( MSQ_CHKERR( err ) || !valid ) return false; 00151 valid = objFunc2->evaluate_with_Hessian_diagonal( type, pd, value_2, mGradient, mDiagonal, err ); 00152 if( MSQ_CHKERR( err ) || !valid ) return false; 00153 00154 for( size_t i = 0; i < pd.num_free_vertices(); ++i ) 00155 { 00156 diag_out[i] *= value_2; 00157 mDiagonal[i] *= value_out; 00158 diag_out[i] += mDiagonal[i]; 00159 diag_out[i] += outer_plus_transpose( grad_out[i], mGradient[i] ); 00160 00161 grad_out[i] *= value_2; 00162 mGradient[i] *= value_out; 00163 grad_out[i] += mGradient[i]; 00164 } 00165 00166 value_out *= value_2; 00167 return true; 00168 } 00169 00170 bool CompositeOFMultiply::evaluate_with_Hessian( EvalType, PatchData&, double&, std::vector< Vector3D >&, MsqHessian&, 00171 MsqError& err ) 00172 { 00173 MSQ_SETERR( err ) 00174 ( "Mesquite is not capable of representing the dense " 00175 "Hessian of the product of two objective fuctions. " 00176 "Either choose a solver that does not require the " 00177 "Hessian of the objective function or do not use the " 00178 "CompositeOFMultiple objective function .", 00179 MsqError::INVALID_STATE ); 00180 return false; 00181 } 00182 00183 int CompositeOFMultiply::min_patch_layers() const 00184 { 00185 const int v1 = objFunc1->min_patch_layers(); 00186 const int v2 = objFunc2->min_patch_layers(); 00187 return v1 > v2 ? v1 : v2; 00188 } 00189 00190 } // namespace MBMesquite