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