Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
atom_tree_minimize.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file core/optimization/atom_tree_minimize.cc
11 /// @brief Atom tree minimization functions
12 /// @author Phil Bradley
13 
14 
15 // Unit headers
17 
18 // Package headers
22 
23 // Project headers
25 #include <core/pose/Pose.hh>
28 #include <core/scoring/Energies.hh>
32 // AUTO-REMOVED #include <core/scoring/NeighborList.hh>
33 // AUTO-REMOVED #include <core/scoring/hbonds/hbonds.hh>
34 // AUTO-REMOVED #include <core/scoring/hbonds/HBondSet.hh>
35 
36 // // ObjexxFCL headers
37 // #include <ObjexxFCL/FArray1A.hh>
38 // AUTO-REMOVED #include <ObjexxFCL/FArray2D.hh>
39 // #include <ObjexxFCL/FArray3A.hh>
40 // #include <ObjexxFCL/Fmath.hh>
41 #include <ObjexxFCL/format.hh>
42 // #include <ObjexxFCL/string.functions.hh>
43 
44 // // Numeric headers
45 #include <numeric/constants.hh>
46 // AUTO-REMOVED #include <numeric/conversions.hh>
47 // #include <numeric/xyzVector.hh>
48 // #include <numeric/xyz.functions.hh>
49 
50 // // Utility headers
51 // #include <utility/exit.hh>
52 
53 // // C++ headers
54 // #include <algorithm>
55 // #include <cmath>
56 // #include <cstdlib>
57 // #include <iostream>
58 
59 #include <basic/Tracer.hh>
60 
63 #include <utility/vector1.hh>
64 
65 using basic::T;
66 using basic::Error;
67 using basic::Warning;
68 
69 using namespace ObjexxFCL::fmt;
70 
71 namespace core {
72 namespace optimization {
73 
74 static basic::Tracer TR("core.optimization");
75 
76 /////////////////////////////////////////////////////////////////////////////
77 /// @detailed
78 ///car note that this calculates the deriv for all torsion angles even
79 ///car those that are fixed. Because of the way that the derivative is
80 ///car calculated, I don't believe this is a significant slow down (ie
81 ///car have to run over all the atom pairs twice, regardless of the number
82 ///car of torsion angles)
83 ///
84 ///car multiple neighborlists:
85 ///car cendist centroid distances in current structure, cutoff for vdw
86 ///car dis2_tether centroid distances in tether structure, cutoff for tether
87 ///
88 ///db computes the derivative of E with respect to each
89 ///db of the torsion angles. Using the chain rule, we have
90 ///db
91 ///db dE/d phi = dE/dr * dr/dphi
92 ///db
93 ///db dr/dphi = Eab x (V-Vb) . (V' - V)/|V-V'|
94 ///db
95 ///db (the first cross product is the displacement of V upon a rotation dphi
96 ///db around the unit vector Eab, Vb is the coordinates of the second atom in
97 ///db the bond)
98 ///db
99 ///car dE/dR = 2r (for vdw at least)
100 ///db since | V-V'| = r,
101 ///db
102 ///db dE/ dphi = 2 Eab x (V-Vb) . (V' - V)
103 ///db
104 ///db note that Eab and Vb are different for each torsion angle, but V'
105 ///db and V are the same. rearranging:
106 ///db
107 ///db = - 2 Eab X Vb . (V' - V) - 2 Eab . (V' x V).
108 ///db
109 ///db now we need the averages over all Vi of the difference and the
110 ///db crossproduct of V and V'.
111 ///
112 ///car below, Eab x Vb is 'vec'
113 ///car Eab is 'unit'
114 ///car (V'-V) is 'f2'
115 ///car 'F2tot' = f2*dE_dR (cumulative)
116 ///car (V' X V) is 'f1' ('F1_xxxE' is cumulative for potential xxx)
117 ///car eval_dE_dR actually returns dE_dR/r
118 ///
119 ///car if two atoms are fixed relatively in cartesian space, then dr/dphi = 0
120 ///car and there is no contribution to the derivative
121 ///
122 
123 void
125  pose::Pose & pose,
126  MinimizerMap & min_map,
127  scoring::ScoreFunction const & scorefxn,
128  Multivec const & vars,
129  Multivec & dE_dvars
130 )
131 {
132 
133  dE_dvars.resize( min_map.nangles() );
134 
135  // clear all the F1's and F2's
136  min_map.zero_torsion_vectors();
137 
138 
139  // puts the degrees of freedom from vars into pose
140  min_map.copy_dofs_to_pose( pose, vars );
141 
142 
143  /////////////////////////////////////////////////////////////////////////////
144  // do some pre-computation prior to looping over the torsions
145 
146  // this will stash necessary information in the pose's energies object
147  //
148  scorefxn.setup_for_derivatives( pose );
149 
150  /////////////////////////////////////////////////////////////////////////////
151  // get derivative of all atom pair potentials
152  // this includes fa_pair and hbonds
153  //
154  // this call fills the F1's and F2's with contributions from their
155  // immediately downstream atoms
156  atom_tree_get_atompairE_deriv( pose, min_map, scorefxn );
157 
158 
159  /////////////////////////////////////////////////////////////////////////////
160  // this should only be done once, after all torsion F1,F2's have
161  // been filled in
162  //
163  // this sums all the F1,F2 contributions down the tree from leaves to root
164  min_map.link_torsion_vectors();
165 
166 
167  /////////////////////////////////////////////////////////////////////////////
168  // now loop over the torsions in the map
169  int imap( 1 ); // for indexing into de_dvars( imap )
170  for ( MinimizerMap::iterator it=min_map.begin(), ite=min_map.end();
171  it != ite; ++it, ++imap ) {
172 
173  DOF_Node const & dof_node( **it );
174  kinematics::tree::Atom const & atom( pose.atom_tree().atom( dof_node.atom_id() ) );
175  /////////////////////////////////////////////////////////////////
176  // derivatives of this particular degree of freedom
177  //
178  // eg rama,Paa,dunbrack,and torsional constraints
179  Real sfxn_dof_deriv = scorefxn.eval_dof_derivative( dof_node.dof_id(), dof_node.torsion_id(), pose );
180  Real scale = min_map.torsion_scale_factor( dof_node );
181 
182  dE_dvars[ imap ] = torsional_derivative_from_cartesian_derivatives( atom, dof_node, sfxn_dof_deriv, scale );
183 
184  } // loop over map
185 
186 
187  scorefxn.finalize_after_derivatives( pose );
188 
189 }
190 
191 /// @details Refactored from atom_tree_dfunc above for use in alternate minimization contexts
192 Real
194  kinematics::tree::Atom const & atom,
195  optimization::DOF_Node const & dof_node,
196  Real dof_deriv, // derivatives applied directly to this DOF, if any
197  Real torsion_scale_factor
198 )
199 {
200  using namespace id;
201 
202  // NOTE: deriv is in the units of the degree of freedom as
203  // represented internally, without any scale factors applied
204  // ie the units returned by pose.get_atom_tree_torsion(...)
205  //
206  //
207  // type -- units
208  // -------------------
209  // PHI -- radians
210  // THETA -- radians
211  // D -- angstroms
212  // RB1-3 -- angstroms
213  // RB4-6 -- degrees (!)
214 
215  Real deriv = 0.0;
216 
217  // this function determines the axis and center of rotation/translation
218  Vector axis, end_pos;
219  DOF_Type const type( dof_node.type() );
220  atom.get_dof_axis_and_end_pos( axis, end_pos, type );
221 
222 
223  // convert combined F1,F2 to an angular derivative
224  // using Abe Go trick
225  //
226  if ( type == PHI || type == THETA || type == RB4 || type == RB5 ||
227  type == RB6 ) {
228  // rotation about an axis
229  // note: assumes we are dealing with RADIANS
230  // scale factor below handles the fact that RB4-6 are degrees
231  Real scale_factor( ( type == PHI || type == THETA ) ? 1 : numeric::constants::d::deg2rad );
232 
233  if ( type == THETA ) {
234  // need to think about this more carefully
235  using numeric::constants::f::pi; // silly -- why not numeric::constants::d?
236  Real const theta( atom.dof( type ) );
237  int const theta_mod
238  ( ( static_cast< int >( std::floor( theta/pi )))%2);
239  if ( theta_mod == 1 || theta_mod == -1 ) {
240  scale_factor *= -1.0f;
241  }
242  }
243 
244  deriv -= scale_factor * ( dot( axis, dof_node.F1() ) +
245  dot( cross( axis, end_pos ), dof_node.F2() ) );
246  } else {
247  // translation along an axis
248  deriv += dot( axis, dof_node.F2() );
249  }
250 
251  deriv += dof_deriv;
252 
253  deriv /= torsion_scale_factor;
254 
255  return deriv;
256 }
257 
258 ///////////////////////////////////////////////////////////////////////////////
259 
260 /// @details First evaluate all derivatives for the residue- and residue-pair decomposable
261 /// terms, using the minimization graph as a guide. Then, evaluate any further derivatives
262 /// for those terms that are not residue- or residue-pair decomposable
263 void
265  pose::Pose & pose,
266  MinimizerMap & min_map,
267  scoring::ScoreFunction const & scorefxn
268 )
269 {
270  using namespace scoring;
271 
272  assert( pose.energies().minimization_graph() );
274 
275  for ( Size ii = 1; ii <= pose.total_residue(); ++ii ) {
276  MinimizationNode const & minnode = * mingraph->get_minimization_node( ii );
277  /// 1. eval intra-residue derivatives
278  eval_atom_derivatives_for_minnode( minnode, pose.residue( ii ), pose, scorefxn.weights(), min_map.atom_derivatives( ii ) );
279  }
280 
281  /// 2. eval inter-residue derivatives
283  edgeit = mingraph->const_edge_list_begin(), edgeit_end = mingraph->const_edge_list_end();
284  edgeit != edgeit_end; ++edgeit ) {
285  MinimizationEdge const & minedge = static_cast< MinimizationEdge const & > ( (**edgeit) );
286  Size const rsd1ind = minedge.get_first_node_ind();
287  Size const rsd2ind = minedge.get_second_node_ind();
288  conformation::Residue const & rsd1( pose.residue( rsd1ind ));
289  conformation::Residue const & rsd2( pose.residue( rsd2ind ));
290  ResSingleMinimizationData const & r1_min_data( mingraph->get_minimization_node( rsd1ind )->res_min_data() );
291  ResSingleMinimizationData const & r2_min_data( mingraph->get_minimization_node( rsd2ind )->res_min_data() );
292 
293  eval_atom_derivatives_for_minedge( minedge, rsd1, rsd2,
294  r1_min_data, r2_min_data, pose, scorefxn.weights(),
295  min_map.atom_derivatives( rsd1ind ), min_map.atom_derivatives( rsd2ind ));
296  }
297 
298  for ( MinimizerMap::iterator iter = min_map.begin(), iter_e = min_map.end();
299  iter != iter_e; ++iter ) {
300  DOF_Node & dof_node( **iter );
301 
302  // loop through atoms first moved by this torsion
303  for ( DOF_Node::AtomIDs::const_iterator it1=dof_node.atoms().begin(),
304  it1e = dof_node.atoms().end(); it1 != it1e; ++it1 ) {
305  id::AtomID const & atom_id( *it1 );
306  dof_node.F1() += min_map.atom_derivatives( atom_id.rsd() )[ atom_id.atomno() ].f1();
307  dof_node.F2() += min_map.atom_derivatives( atom_id.rsd() )[ atom_id.atomno() ].f2();
308  scorefxn.eval_npd_atom_derivative( atom_id, pose, min_map.domain_map(), dof_node.F1(), dof_node.F2() );
309  } // atom1
310  } // tor
311 }
312 
313 
314 SimpleDerivCheckResult
316  Multifunc const & func,
317  Multivec const & start_vars,
318  Multivec const & dE_dvars,
319  bool send_to_stdout,
320  bool verbose,
321  Size nsteps /* = 5 */
322 )
323 {
324 
325  /////////////////////////////////////////////////////////////////////////////
326  // NUMERICAL DERIVATIVE CHECK
327  /////////////////////////////////////////////////////////////////////////////
328  // how to analyze this:
329  //
330  // in gnuplot, look at numerical vs analytical derivs:
331  // plot '< grep "^core.optimization: ratio" a3.log ' u 4:5,x
332  //
333  // also sort by deriv_dev lines:
334  //
335  // by magnitude of deviation
336  // grep deriv_dev a3.log | sort -g +6
337  //
338  // or by ratio of deviation to actual
339  //
340  // grep deriv_dev a3.log | sort -g +7
341 
342  Size const nangles( start_vars.size() );
343 
344 
345  Real const increment = 0.0005; // PB -- 3/02
346  Size const n_increment = nsteps;
347  utility::vector1< Multivec > dE_dvars_numeric( n_increment );
348 
349  SimpleDerivCheckResult num_deriv_result(nangles, n_increment);
350 
351  for ( Size i=1; i<= n_increment; ++i ) {
352  dE_dvars_numeric[i].resize( nangles, 0.0 );
353  }
354  ///ObjexxFCL::FArray2D< Real > dE_dvars_numeric( nangles, n_increment );
355 
356  Multivec vars( start_vars );
357 
358  Real const f00 = func( vars );
359 
360  for ( Size ii = 1; ii <= vars.size(); ++ii ) {
361  Real deriv_dev = 10000.0;
362  for ( Size j = 1,factor=1; j <= n_increment; ++j ) {
363  factor*=2;
364 
365  vars[ii] = start_vars[ii] + factor * increment;
366  Real const f11 = func( vars );
367 
368  //std::cout << "Vars, f11:";
369  //for ( Size jj = 1; jj <= vars.size(); ++jj ) std::cout << " " << vars[ jj ];
370  //std::cout << " " << f11 << std::endl;
371 
372  vars[ii] = start_vars[ii] - factor * increment;
373  Real const f22 = func( vars );
374 
375  //std::cout << "Vars, f22:";
376  //for ( Size jj = 1; jj <= vars.size(); ++jj ) std::cout << " " << vars[ jj ];
377  //std::cout << " " << f22 << std::endl;
378 
379 
380  Real const deriv = ( f11 - f22 ) / ( factor * 2 * increment );
381 
382  //std::cout << "Numeric deriv " << deriv << " anayltic: " << dE_dvars[ ii ] << std::endl;
383 
384  dE_dvars_numeric[j][ii] = deriv;
385 
386  deriv_dev = std::min( deriv_dev, std::abs( deriv - dE_dvars[ii] ) );
387 
388  vars[ii] = start_vars[ii];
389 
390  Real const ratio( std::abs( dE_dvars[ii] ) < 0.001 ? 0.0 : deriv / dE_dvars[ii] );
391 
392  if ( std::abs(dE_dvars[ii]) > 0.001 || std::abs(deriv) > 0.001 ) {
393  DerivCheckDataPoint dp( deriv, dE_dvars[ii], ratio, f11, f00, f22, start_vars[ ii ] );
394  num_deriv_result.step_data( ii, j, dp );
395 
396  if ( verbose && send_to_stdout ) {
397  // if you change this output, please also change the comments
398  // at the beginning of this section
399  static bool ratio_header_output( false );
400  if ( !ratio_header_output ) {
401  ratio_header_output = true;
402  TR << "ratio" <<
403  A( 4, "inc" ) <<
404  A( 10, "numeric" ) <<
405  A( 10, "analytic" ) <<
406  A( 10, "ratio" ) <<
407  A( 10, "f11" ) <<
408  A( 10, "f00" ) <<
409  A( 10, "f22" ) <<
410  A( 10, "vars[ii]" ) << std::endl;
411  }
412 
413  TR << "ratio" <<
414  I( 4, j ) <<
415  F( 10, 4, deriv ) << // column 4
416  F( 10, 4, dE_dvars[ii] ) << // column 5
417  F( 10, 4, ratio ) <<
418  F( 10, 4, f11 ) <<
419  F( 10, 4, f00 ) <<
420  F( 10, 4, f22 ) <<
421  F( 10, 4, start_vars[ii] ) << std::endl;
422  }
423 
424  }
425  }
426  if ( true ) {
427 
428  Real const ratio( std::abs( dE_dvars[ii] ) < 0.001 ? 0.0 :
429  deriv_dev / std::abs( dE_dvars[ii] ) );
430 
431  num_deriv_result.rel_deriv_dev( ii, ratio );
432  num_deriv_result.abs_deriv_dev( ii, deriv_dev );
433 
434  if ( verbose && send_to_stdout ) {
435  // if you change this output, please also change the comments
436  // at the beginning of this section
437  TR << "deriv_dev:" << SS(ii) << SS(nangles) << SS(f00) <<
438  SS( dE_dvars[ii] ) << SS( deriv_dev ) << SS(ratio) << std::endl;
439  }
440  }
441  }
442 
443  // calculate magnitudes, dot products of gradient vectors
444  utility::vector1< Real > norm_numeric(n_increment,0.0), dot(n_increment,0.0);
445  Real norm(0.0);
446  for ( Size i=1; i<= nangles; ++i ) {
447  norm += dE_dvars[i] * dE_dvars[i];
448  for ( Size j=1; j<= n_increment; ++j ) {
449  dot[j] += dE_dvars[i] * dE_dvars_numeric[j][i];
450  norm_numeric[j] += dE_dvars_numeric[j][i] * dE_dvars_numeric[j][i];
451  }
452  }
453  norm = std::sqrt( norm );
454 
455  Real const too_small( 0.0001 );
456 
457  num_deriv_result.best_cos_theta( -10.0 );
458  num_deriv_result.best_abs_log_norm_ratio( 200.0 );
459  num_deriv_result.best_norm_analytic( 999.9 );
460  num_deriv_result.best_norm_numeric( 999.9 );
461 
462  for ( Size j=1; j<= n_increment; ++j ) {
463  norm_numeric[j] = std::sqrt( norm_numeric[j] );
464 
465  // handle strange cases
466  Real log_norm_ratio;
467  if ( norm < too_small && norm_numeric[j] < too_small ) {
468  log_norm_ratio = 1.0;
469  } else if ( norm < 0.125 * too_small ) {
470  log_norm_ratio = 100.0;
471  } else if ( norm_numeric[j] < 0.125 * too_small ) {
472  log_norm_ratio = -100.0;
473  } else {
474  log_norm_ratio = std::log( norm_numeric[j] / norm );
475  }
476 
477  Real const cos_theta( dot[j] / ( norm * norm_numeric[j]) );
478 
479  if ( send_to_stdout ) {
480  TR <<
481  " norm: " << j << ' ' << F(12,4,norm) <<
482  " norm_numeric: " << F(12,4,norm_numeric[j]) <<
483  " cos_theta: " << F(7,4,cos_theta) <<
484  " log_norm_ratio: " << F(9,4,log_norm_ratio) << std::endl;
485  }
486 
487  num_deriv_result.best_cos_theta( std::max( num_deriv_result.best_cos_theta(), cos_theta ) );
488  if ( std::abs( log_norm_ratio ) < num_deriv_result.best_abs_log_norm_ratio() ) {
489  num_deriv_result.best_abs_log_norm_ratio( std::abs( log_norm_ratio ) ) ;
490  num_deriv_result.best_norm_analytic( norm );
491  num_deriv_result.best_norm_numeric( norm_numeric[j] );
492  }
493  }
494  if ( send_to_stdout ) {
495  TR << "best : cos_theta " << num_deriv_result.best_cos_theta()
496  << " log_norm_ratio: " << num_deriv_result.best_abs_log_norm_ratio()
497  << " norm " << num_deriv_result.best_norm_analytic()
498  << " norm numeric: " << num_deriv_result.best_norm_numeric() << std::endl;
499  }
500  //deriv_check_result->add_deriv_data( min_debug );
501  return num_deriv_result;
502 }
503 
504 ///////////////////////////////////////////////////////////////////////////////
505 
506 void
508  MinimizerMap const & min_map,
509  Multifunc const & func,
510  Multivec const & start_vars,
511  Multivec const & dE_dvars,
512  NumericalDerivCheckResultOP deriv_check_result,
513  bool const verbose // = true
514 )
515 {
516  /////////////////////////////////////////////////////////////////////////////
517  // NUMERICAL DERIVATIVE CHECK
518  /////////////////////////////////////////////////////////////////////////////
519  // how to analyze this:
520  //
521  // in gnuplot, look at numerical vs analytical derivs:
522  // plot '< grep "^core.optimization: ratio" a3.log ' u 11:12,x
523  //
524  // also sort by deriv_dev lines:
525  //
526  // by magnitude of deviation
527  // grep deriv_dev a3.log | sort -g +8
528  //
529  // or by ratio of deviation to actual
530  //
531  // grep deriv_dev a3.log | sort -g +9
532 
533  Size const nangles( min_map.nangles() );
534 
535  bool const write_to_stdout( ! deriv_check_result || deriv_check_result->send_to_stdout() );
536 
537  Real const increment = 0.0005; // PB -- 3/02
538  Size const n_increment = 5;
539  utility::vector1< Multivec > dE_dvars_numeric( n_increment );
540  for ( Size i=1; i<= n_increment; ++i ) {
541  dE_dvars_numeric[i].resize( nangles, 0.0 );
542  }
543  //FArray2D_Real dE_dvars_numeric( nangles, n_increment );
544 
545  // setup for saving diagnostics
546  NumDerivCheckDataOP min_debug;
547  if ( deriv_check_result ) min_debug = new NumDerivCheckData( nangles, n_increment );
548 
549 // min_debug->nangles = nangles;
550 // if ( nangles > int( min_debug->abs_deriv_dev.size1() ) ) {
551 // min_debug->abs_deriv_dev.dimension( nangles );
552 // min_debug->rel_deriv_dev.dimension( nangles );
553 // }
554 
555  Multivec vars( start_vars );
556 
557  Real const f00 = func( vars );
558  Size ii( 1 ); // for indexing into dE_dvars[ ii ]
559 
560  for ( MinimizerMap::const_iterator iter= min_map.begin(),
561  iter_end= min_map.end(); iter != iter_end; ++iter, ++ii ) {
562  DOF_Node const & dof_node( **iter );
563 
564  Real deriv_dev = 10000.0;
565  for ( Size j = 1,factor=1; j <= n_increment; ++j ) {
566  factor*=2;
567 
568  vars[ii] = start_vars[ii] + factor * increment;
569  Real const f11 = func( vars );
570 
571  vars[ii] = start_vars[ii] - factor * increment;
572  Real const f22 = func( vars );
573 
574  Real const deriv = ( f11 - f22 ) / ( factor * 2 * increment );
575 
576  dE_dvars_numeric[j][ii] = deriv;
577 
578  deriv_dev = std::min( deriv_dev, std::abs( deriv - dE_dvars[ii] ) );
579 
580  vars[ii] = start_vars[ii];
581 
582  Real const ratio( std::abs( dE_dvars[ii] ) < 0.001 ? 0.0 :
583  deriv / dE_dvars[ii] );
584 
585  if ( std::abs(dE_dvars[ii]) > 0.001 || std::abs(deriv) > 0.001 ) {
586  id::DOF_ID parent_id( id::BOGUS_DOF_ID );
587  if ( dof_node.parent() ) {
588  parent_id = dof_node.parent()->dof_id();
589  }
590  DOF_DataPoint dp( dof_node.dof_id(), parent_id, dof_node.atoms().size(),
591  deriv, dE_dvars[ii], ratio, f11, f00, f22, start_vars[ ii ] );
592  if ( min_debug ) min_debug->dof_step_data( ii, j, dp );
593  if ( verbose && write_to_stdout ) {
594  // if you change this output, please also change the comments
595  // at the beginning of this section
596  static bool ratio_header_output( false );
597  if ( !ratio_header_output ) {
598  ratio_header_output = true;
599  TR << "ratio" <<
600  A( 4, "inc" ) <<
601  A( 4, "rsd" ) <<
602  A( 4, "typ" ) <<
603  A( 4, "atm" ) <<
604  A( 5, "prsd" ) <<
605  A( 5, "ptyp" ) <<
606  A( 5, "patm" ) <<
607  A( 5, "natm" ) <<
608  A( 10, "numeric" ) <<
609  A( 10, "analytic" ) <<
610  A( 10, "ratio" ) <<
611  A( 10, "f11" ) <<
612  A( 10, "f00" ) <<
613  A( 10, "f22" ) <<
614  A( 10, "vars[ii]" ) << std::endl;
615  }
616 
617 
618  TR << "ratio" <<
619  I( 4, j ) <<
620  I( 4, dof_node.rsd() ) <<
621  I( 4, dof_node.type() ) <<
622  I( 4, dof_node.atomno() ) <<
623  I( 5, parent_id.rsd() ) <<
624  I( 5, parent_id.type() ) <<
625  I( 5, parent_id.atomno() ) <<
626  I( 5, dof_node.atoms().size()) <<
627  F( 10, 4, deriv ) << // column 11
628  F( 10, 4, dE_dvars[ii] ) << // column 12
629  F( 10, 4, ratio ) <<
630  F( 10, 4, f11 ) <<
631  F( 10, 4, f00 ) <<
632  F( 10, 4, f22 ) <<
633  F( 10, 4, start_vars[ii] ) << std::endl;
634  }
635 
636  }
637  }
638  if ( true ) {
639 
640  Real const ratio( std::abs( dE_dvars[ii] ) < 0.001 ? 0.0 :
641  deriv_dev / std::abs( dE_dvars[ii] ) );
642 
643  if ( min_debug ) min_debug->rel_deriv_dev( ii, ratio );
644  if ( min_debug ) min_debug->abs_deriv_dev( ii, deriv_dev );
645 
646  if ( verbose && write_to_stdout ) {
647  // if you change this output, please also change the comments
648  // at the beginning of this section
649  TR << "deriv_dev:" << SS(ii) << SS(nangles) << SS(f00) <<
650  SS( dof_node.type() ) << SS( dof_node.atomno() ) <<
651  SS( dof_node.rsd() ) <<
652  SS( dE_dvars[ii] ) << SS( deriv_dev ) << SS(ratio) << std::endl;
653  }
654  }
655  }
656 
657  // calculate magnitudes, dot products of gradient vectors
658  utility::vector1< Real > norm_numeric(n_increment,0.0), dot(n_increment,0.0);
659  Real norm(0.0);
660  for ( Size i=1; i<= nangles; ++i ) {
661  norm += dE_dvars[i] * dE_dvars[i];
662  for ( Size j=1; j<= n_increment; ++j ) {
663  dot[j] += dE_dvars[i] * dE_dvars_numeric[j][i];
664  norm_numeric[j] += dE_dvars_numeric[j][i] * dE_dvars_numeric[j][i];
665  }
666  }
667  norm = std::sqrt( norm );
668 
669  Real lbest_cos_theta( -10.0 );
670  Real lbest_abs_log_norm_ratio( 200.0 );
671  Real lbest_norm_analytic( 999.9 );
672  Real lbest_norm_numeric( 999.9 );
673 
674  for ( Size j=1; j<= n_increment; ++j ) {
675  norm_numeric[j] = std::sqrt( norm_numeric[j] );
676 
677  // handle strange cases
678  Real log_norm_ratio;
679  if ( norm < 0.001 && norm_numeric[j] < 0.001 ) {
680  log_norm_ratio = 1.0;
681  } else if ( norm < 0.001 ) {
682  log_norm_ratio = 100.0;
683  } else if ( norm_numeric[j] < 0.001 ) {
684  log_norm_ratio = -100.0;
685  } else {
686  log_norm_ratio = std::log( norm_numeric[j] / norm );
687  }
688 
689  Real const cos_theta( dot[j] / ( norm * norm_numeric[j]) );
690 
691  if ( write_to_stdout ) {
692  TR <<
693  " norm: " << j << ' ' << F(12,4,norm) <<
694  " norm_numeric: " << F(12,4,norm_numeric[j]) <<
695  " cos_theta: " << F(7,4,cos_theta) <<
696  " log_norm_ratio: " << F(9,4,log_norm_ratio) << std::endl;
697  }
698 
699  lbest_cos_theta = std::max( lbest_cos_theta, cos_theta );
700  if ( std::abs( log_norm_ratio ) < lbest_abs_log_norm_ratio ) {
701  lbest_abs_log_norm_ratio = std::abs( log_norm_ratio );
702  lbest_norm_analytic = norm;
703  lbest_norm_numeric = norm_numeric[j];
704  }
705  }
706 
707  if ( min_debug ) min_debug->best_cos_theta( lbest_cos_theta );
708  if ( min_debug ) min_debug->best_abs_log_norm_ratio( lbest_abs_log_norm_ratio );
709  if ( min_debug ) min_debug->best_norm_analytic( lbest_norm_analytic );
710  if ( min_debug ) min_debug->best_norm_numeric( lbest_norm_numeric );
711 
712  if ( deriv_check_result ) deriv_check_result->add_deriv_data( min_debug );
713 }
714 
715 
716 } // namespace optimization
717 } // namespace core
718 // { // dont want to modify the pose if we can avoid it
719 // Size const nangles( min_map.nangles() );
720 // Multivec tmp_vars( nangles );
721 // min_map.copy_dofs_from_pose( pose, tmp_vars );
722 // Real dev(0.0);
723 // for ( Size i=1; i<= nangles; ++i ) {
724 // dev += std::abs( tmp_vars[i] - vars[i] );
725 // }
726 // std::cout << "[ DEBUG ] vars dev in atom_tree_dfunc: " << dev << std::endl;
727 // if ( dev > 1e-2 ) {
728 // min_map.copy_dofs_to_pose( pose, vars );
729 // scorefxn( pose );
730 // }
731 // }