MOAB: Mesh Oriented datABase
(version 5.2.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 <math.h> 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, const Settings* settings, 00089 PatchSet* user_set, MsqError& err ) 00090 { 00091 bool rval1, rval2; 00092 rval1 = objFunc1->initialize_block_coordinate_descent( mesh_and_domain, settings, user_set, err ); 00093 MSQ_ERRZERO( err ); 00094 rval2 = objFunc2->initialize_block_coordinate_descent( mesh_and_domain, settings, user_set, err ); 00095 return !MSQ_CHKERR( err ) && rval1 && rval2; 00096 } 00097 00098 bool CompositeOFAdd::evaluate( EvalType type, PatchData& pd, double& value_out, bool free, MsqError& err ) 00099 { 00100 double value_2; 00101 bool ok; 00102 00103 ok = objFunc1->evaluate( type, pd, value_out, free, err ); 00104 if( MSQ_CHKERR( err ) || !ok ) return false; 00105 ok = objFunc2->evaluate( type, pd, value_2, free, err ); 00106 if( MSQ_CHKERR( err ) || !ok ) return false; 00107 00108 value_out += value_2; 00109 return true; 00110 } 00111 00112 bool CompositeOFAdd::evaluate_with_gradient( EvalType type, PatchData& pd, double& value_out, 00113 std::vector< Vector3D >& grad_out, MsqError& err ) 00114 { 00115 double value_2; 00116 bool ok; 00117 00118 ok = objFunc1->evaluate_with_gradient( type, pd, value_out, grad_out, err ); 00119 if( MSQ_CHKERR( err ) || !ok ) return false; 00120 ok = objFunc2->evaluate_with_gradient( type, pd, value_2, mGradient, err ); 00121 if( MSQ_CHKERR( err ) || !ok ) return false; 00122 00123 assert( grad_out.size() == pd.num_free_vertices() ); 00124 assert( mGradient.size() == pd.num_free_vertices() ); 00125 00126 std::vector< Vector3D >::iterator i = grad_out.begin(), j = mGradient.begin(); 00127 while( i != grad_out.end() ) 00128 { 00129 *i += *j; 00130 ++i; 00131 ++j; 00132 } 00133 value_out += value_2; 00134 return true; 00135 } 00136 00137 bool CompositeOFAdd::evaluate_with_Hessian_diagonal( EvalType type, PatchData& pd, double& value_out, 00138 std::vector< Vector3D >& grad_out, 00139 std::vector< SymMatrix3D >& diag_out, MsqError& err ) 00140 { 00141 double value_2; 00142 bool valid; 00143 00144 valid = objFunc1->evaluate_with_Hessian_diagonal( type, pd, value_out, grad_out, diag_out, err ); 00145 if( MSQ_CHKERR( err ) || !valid ) return false; 00146 valid = objFunc2->evaluate_with_Hessian_diagonal( type, pd, value_2, mGradient, mDiagonal, err ); 00147 if( MSQ_CHKERR( err ) || !valid ) return false; 00148 00149 for( size_t i = 0; i < pd.num_free_vertices(); ++i ) 00150 { 00151 grad_out[i] += mGradient[i]; 00152 diag_out[i] += mDiagonal[i]; 00153 } 00154 00155 value_out += value_2; 00156 return true; 00157 } 00158 00159 bool CompositeOFAdd::evaluate_with_Hessian( EvalType type, PatchData& pd, double& value_out, 00160 std::vector< Vector3D >& grad_out, MsqHessian& Hessian_out, MsqError& err ) 00161 { 00162 double value_2; 00163 bool ok; 00164 00165 mHessian.initialize( Hessian_out ); 00166 00167 ok = objFunc1->evaluate_with_Hessian( type, pd, value_out, grad_out, Hessian_out, err ); 00168 if( MSQ_CHKERR( err ) || !ok ) return false; 00169 ok = objFunc2->evaluate_with_Hessian( type, pd, value_2, mGradient, mHessian, err ); 00170 if( MSQ_CHKERR( err ) || !ok ) return false; 00171 00172 value_out += value_2; 00173 00174 assert( grad_out.size() == pd.num_free_vertices() ); 00175 assert( mGradient.size() == pd.num_free_vertices() ); 00176 00177 for( size_t i = 0; i < pd.num_free_vertices(); ++i ) 00178 grad_out[i] += mGradient[i]; 00179 Hessian_out.add( mHessian ); 00180 return true; 00181 } 00182 00183 int CompositeOFAdd::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