Changeset f433ec for src/Dynamics/BondVectors.cpp
- Timestamp:
- Apr 10, 2018, 6:43:30 AM (7 years ago)
- Branches:
- AutomationFragmentation_failures, Candidate_v1.6.1, ChemicalSpaceEvaluator, Exclude_Hydrogens_annealWithBondGraph, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_contraction-expansion, Gui_displays_atomic_force_velocity, PythonUI_with_named_parameters, StoppableMakroAction, TremoloParser_IncreasedPrecision
- Children:
- 07d4b1
- Parents:
- 7b4e67
- git-author:
- Frederik Heber <frederik.heber@…> (07/18/17 22:24:12)
- git-committer:
- Frederik Heber <frederik.heber@…> (04/10/18 06:43:30)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Dynamics/BondVectors.cpp
r7b4e67 rf433ec 45 45 #include "CodePatterns/Assert.hpp" 46 46 #include "CodePatterns/Log.hpp" 47 48 #include <levmar.h> 47 49 48 50 #include "Atom/atom.hpp" … … 111 113 } 112 114 115 struct WeightsMinimization { 116 117 static void evaluate(double *p, double *x, int m, int n, void *data) 118 { 119 // current weights in p, output to x 120 double *matrix = static_cast<double*>(data); 121 for(size_t i=0;i<(size_t)n;++i) { 122 x[i] = 0.; 123 for(size_t j=0;j<(size_t)n;++j) 124 x[i] += p[j]*matrix[i*n+j]; 125 // x[i] = .5*x[i]*x[i]; 126 } 127 } 128 129 static void evaluate_derivative(double *p, double *jac, int m, int n, void *data) 130 { 131 // current weights in p, output to x 132 double *matrix = static_cast<double*>(data); 133 // // tmp = (Bx - 1) 134 // double *tmp = new double[n]; 135 // for(size_t i=0;i<(size_t)n;++i) { 136 // tmp[i] = -1.; 137 // for(size_t j=0;j<(size_t)n;++j) 138 // tmp[i] += p[j]*matrix[i*n+j]; 139 // } 140 // // tmp(i) * B_(ij) 141 // for(size_t i=0;i<(size_t)n;++i) 142 // for(size_t j=0;j<(size_t)n;++j) 143 // jac[i*n+j] = tmp[i]*matrix[i*n+j]; 144 // delete[] tmp ; 145 for(size_t i=0;i<(size_t)n;++i) 146 for(size_t j=0;j<(size_t)n;++j) 147 jac[i*n+j] = matrix[i*n+j]; 148 } 149 150 static double* getMatrixFromBondVectors( 151 const std::vector<Vector> &_bondvectors 152 ) 153 { 154 const size_t n = _bondvectors.size(); 155 double *matrix = new double[n*n]; 156 size_t i=0; 157 for (std::vector<Vector>::const_iterator iter = _bondvectors.begin(); 158 iter != _bondvectors.end(); ++iter, ++i) { 159 size_t j=0; 160 for (std::vector<Vector>::const_iterator otheriter = _bondvectors.begin(); 161 otheriter != _bondvectors.end(); ++otheriter, ++j) { 162 // only magnitude is important not the sign 163 matrix[i*n+j] = fabs((*iter).ScalarProduct(*otheriter)); 164 } 165 } 166 167 return matrix; 168 } 169 }; 170 171 172 BondVectors::weights_t BondVectors::getWeightsForAtomAtStep( 173 const atom &_walker, 174 const std::vector<Vector> &_bondvectors, 175 const size_t &_step) const 176 { 177 // let levmar optimize 178 register int i, j; 179 int ret; 180 double *p; 181 double *x; 182 int n=_bondvectors.size(); 183 double opts[LM_OPTS_SZ], info[LM_INFO_SZ]; 184 185 double *matrix = WeightsMinimization::getMatrixFromBondVectors(_bondvectors); 186 187 weights_t weights(n, 0.); 188 189 // minim. options [\tau, \epsilon1, \epsilon2, \epsilon3]. Respectively the scale factor for initial \mu, 190 // * stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2. 191 opts[0]=LM_INIT_MU; opts[1]=1E-15; opts[2]=1E-15; opts[3]=1E-20; 192 opts[4]= LM_DIFF_DELTA; // relevant only if the Jacobian is approximated using finite differences; specifies forward differencing 193 //opts[4]=-LM_DIFF_DELTA; // specifies central differencing to approximate Jacobian; more accurate but more expensive to compute! 194 195 // prepare initial values for weights 196 p = new double[n]; 197 for (i=0;i<n;++i) 198 p[i] = 1.; 199 // prepare output value, i.e. the row sums 200 x = new double[n]; 201 for (i=0;i<n;++i) 202 x[i] = 1.; 203 204 { 205 double *work, *covar; 206 work=(double *)malloc((LM_DIF_WORKSZ(n, n)+n*n)*sizeof(double)); 207 if(!work){ 208 ELOG(0, "BondVectors::getWeightsForAtomAtStep() - memory allocation request failed."); 209 return weights; 210 } 211 covar=work+LM_DIF_WORKSZ(n, n); 212 213 // give this pointer as additional data to construct function pointer in 214 // LevMarCallback and call 215 double *lb = new double[n]; 216 double *ub = new double[n]; 217 for (i=0;i<n;++i) { 218 lb[i] = 1./(double)n; 219 ub[i] = 1.; 220 } 221 ret=dlevmar_bc_der( 222 &WeightsMinimization::evaluate, 223 &WeightsMinimization::evaluate_derivative, 224 p, x, n, n, lb, ub, NULL, 1000, opts, info, work, covar, matrix); // no Jacobian, caller allocates work memory, covariance estimated 225 delete[] lb; 226 delete[] ub; 227 228 if (0) 229 { 230 std::stringstream covar_msg; 231 covar_msg << "Covariance of the fit:\n"; 232 for(i=0; i<n; ++i){ 233 for(j=0; j<n; ++j) 234 covar_msg << covar[i*n+j] << " "; 235 covar_msg << std::endl; 236 } 237 covar_msg << std::endl; 238 LOG(1, "INFO: " << covar_msg.str()); 239 } 240 241 free(work); 242 } 243 244 if (DoLog(4)) { 245 std::stringstream result_msg; 246 result_msg << "Levenberg-Marquardt returned " << ret << " in " << info[5] << " iter, reason " << info[6] << "\nSolution: "; 247 for(i=0; i<n; ++i) 248 result_msg << p[i] << " "; 249 result_msg << "\n\nMinimization info:\n"; 250 std::vector<std::string> infonames(LM_INFO_SZ); 251 infonames[0] = std::string("||e||_2 at initial p"); 252 infonames[1] = std::string("||e||_2"); 253 infonames[2] = std::string("||J^T e||_inf"); 254 infonames[3] = std::string("||Dp||_2"); 255 infonames[4] = std::string("mu/max[J^T J]_ii"); 256 infonames[5] = std::string("# iterations"); 257 infonames[6] = std::string("reason for termination"); 258 infonames[7] = std::string(" # function evaluations"); 259 infonames[8] = std::string(" # Jacobian evaluations"); 260 infonames[9] = std::string(" # linear systems solved"); 261 for(i=0; i<LM_INFO_SZ; ++i) 262 result_msg << infonames[i] << ": " << info[i] << " "; 263 result_msg << std::endl; 264 LOG(4, "DEBUG: " << result_msg.str()); 265 } 266 267 std::copy(p, p+n, weights.begin()); 268 LOG(4, "DEBUG: Weights for atom #" << _walker.getId() << ": " << weights); 269 270 delete[] p; 271 delete[] x; 272 delete[] matrix; 273 274 return weights; 275 } 276 113 277 BondVectors::weights_t BondVectors::getWeightsForAtomAtStep( 114 278 const atom &_walker, … … 118 282 getAtomsBondVectorsAtStep(_walker, _step); 119 283 120 weights_t weights; 121 for (std::vector<Vector>::const_iterator iter = BondVectors.begin(); 122 iter != BondVectors.end(); ++iter) { 284 return getWeightsForAtomAtStep(_walker, BondVectors, _step); 285 } 286 287 Vector BondVectors::getRemnantGradientForAtomAtStep( 288 const atom &_walker, 289 const std::vector<Vector> _BondVectors, 290 const BondVectors::weights_t &_weights, 291 const size_t &_step, 292 forcestore_t _forcestore) const 293 { 294 const Vector &walkerGradient = _walker.getAtomicForceAtStep(_step); 295 BondVectors::weights_t::const_iterator weightiter = _weights.begin(); 296 std::vector<Vector>::const_iterator vectoriter = _BondVectors.begin(); 297 const BondList& ListOfBonds = _walker.getListOfBonds(); 298 299 Vector forcesum; 300 for(BondList::const_iterator bonditer = ListOfBonds.begin(); 301 bonditer != ListOfBonds.end(); ++bonditer, ++weightiter, ++vectoriter) { 302 const bond::ptr ¤t_bond = *bonditer; 303 const Vector &BondVector = *vectoriter; 304 305 const double temp = (*weightiter)*walkerGradient.ScalarProduct(BondVector); 306 _forcestore(_walker, current_bond, _step, temp); 307 LOG(4, "DEBUG: BondVector " << BondVector << " receives projected force of " 308 << temp); 309 forcesum += temp * BondVector; 310 } 311 ASSERT( weightiter == _weights.end(), 312 "BondVectors::getRemnantGradientForAtomAtStep() - weightiter is not at end when it should be."); 313 ASSERT( vectoriter == _BondVectors.end(), 314 "BondVectors::getRemnantGradientForAtomAtStep() - vectoriter is not at end when it should be."); 315 316 return walkerGradient-forcesum; 317 } 318 319 bool BondVectors::getCheckWeightSumForAtomAtStep( 320 const atom &_walker, 321 const std::vector<Vector> _BondVectors, 322 const BondVectors::weights_t &_weights, 323 const size_t &_step) const 324 { 325 bool status = true; 326 for (std::vector<Vector>::const_iterator iter = _BondVectors.begin(); 327 iter != _BondVectors.end(); ++iter) { 123 328 std::vector<double> scps; 124 scps.reserve( BondVectors.size());329 scps.reserve(_BondVectors.size()); 125 330 std::transform( 126 BondVectors.begin(), BondVectors.end(), 127 std::back_inserter(scps), 128 boost::bind(static_cast< double (*)(double) >(&fabs), 129 boost::bind(&Vector::ScalarProduct, boost::cref(*iter), _1)) 130 ); 131 const double scp_sum = std::accumulate(scps.begin(), scps.end(), 0.); 132 ASSERT( (scp_sum-1.) > -MYEPSILON, 133 "ForceAnnealing() - sum of weights must be equal or larger one but is " 134 +toString(scp_sum)); 135 weights.push_back( 1./scp_sum ); 136 } 137 LOG(4, "DEBUG: Weights for atom #" << _walker.getId() << ": " << weights); 138 139 // for testing we check whether all weighted scalar products now come out as 1. 140 #ifndef NDEBUG 141 for (std::vector<Vector>::const_iterator iter = BondVectors.begin(); 142 iter != BondVectors.end(); ++iter) { 143 std::vector<double> scps; 144 scps.reserve(BondVectors.size()); 145 std::transform( 146 BondVectors.begin(), BondVectors.end(), 147 weights.begin(), 331 _BondVectors.begin(), _BondVectors.end(), 332 _weights.begin(), 148 333 std::back_inserter(scps), 149 334 boost::bind(static_cast< double (*)(double) >(&fabs), … … 153 338 ); 154 339 const double scp_sum = std::accumulate(scps.begin(), scps.end(), 0.); 155 ASSERT( fabs(scp_sum - 1.) < MYEPSILON, 156 "ForceAnnealing::operator() - for BondVector "+toString(*iter) 157 +" we have weighted scalar product of "+toString(scp_sum)+" != 1."); 158 } 159 #endif 160 return weights; 161 } 340 if (fabs(scp_sum -1.) > MYEPSILON) 341 status = false; 342 } 343 344 return status; 345 }
Note:
See TracChangeset
for help on using the changeset viewer.