Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DDGBindOptEData.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 protocols/optimize_weights/DGBindOptEData.cc
11 /// @brief Implementation of the OptEPositionData class that handles interface ddG optimization
12 /// @author Ron Jacak
13 
14 #ifdef USEMPI
15 #include <mpi.h>
16 #endif
17 
18 // Unit headers
21 #include <ObjexxFCL/format.hh>
22 #include <utility/vector1.functions.hh> // to get arg_min
23 #include <basic/Tracer.hh>
24 
25 // option key includes
26 // AUTO-REMOVED #include <basic/options/keys/optE.OptionKeys.gen.hh>
27 
28 #include <utility/vector1.hh>
29 #include <basic/options/keys/OptionKeys.hh>
30 
31 
32 
33 using namespace core;
34 using namespace core::scoring;
35 using namespace ObjexxFCL::fmt;
36 
37 namespace protocols {
38 namespace optimize_weights {
39 
40 static basic::Tracer TR("DDGBindOptEData");
41 
43 
44 ///
45 /// @begin DDGBindOptEData::DDGBindOptEData()
46 ///
47 /// @brief
48 /// Initialize all of the member variables to 0.
49 ///
50 DDGBindOptEData::DDGBindOptEData():
51  experimental_ddG_bind_(0.0)
52 {}
53 
54 ///
55 /// @begin DDGBindOptEData::~DDGBindOptEData()
56 ///
58 
59 
60 ///
61 /// @begin DDGBindOptEData::get_score()
62 ///
63 Real
65  optimization::Multivec const & component_weights,
66  optimization::Multivec const & vars,
67  optimization::Multivec & dE_dvars,
68  Size const num_energy_dofs,
69  int const num_ref_dofs,
70  int const num_total_dofs,
71  EnergyMap const & fixed_terms,
72  ScoreTypes const & free_score_list,
73  ScoreTypes const & fixed_score_list
74 ) const
75 {
76  return process_score( TR, false, component_weights, vars, dE_dvars, num_energy_dofs, num_ref_dofs, num_total_dofs, fixed_terms, free_score_list, fixed_score_list );
77 }
78 
79 ///
80 /// @begin DDGBindOptEData::print_score()
81 ///
82 void
84  std::ostream & ostr,
85  optimization::Multivec const & component_weights,
86  optimization::Multivec const & vars,
87  optimization::Multivec & dE_dvars,
88  Size const num_energy_dofs,
89  int const num_ref_dofs,
90  int const num_total_dofs,
91  EnergyMap const & fixed_terms,
92  ScoreTypes const & free_score_list,
93  ScoreTypes const & fixed_score_list
94 ) const
95 {
96  process_score( ostr, true, component_weights, vars, dE_dvars, num_energy_dofs, num_ref_dofs, num_total_dofs, fixed_terms, free_score_list, fixed_score_list );
97 }
98 
99 
100 ///
101 /// @begin DDGBindOptEData::process_score()
102 ///
103 /// @brief
104 /// One method to do the score processing which takes a boolean dictating whether to print to an ostream or not. With this function, changes
105 /// to how scoring works only need to be made in one place as opposed to two (when get_score() and print_score() both had scoring logic in them).
106 /// Avoiding code duplication is good.
107 ///
108 Real
110  std::ostream & ostr,
111  bool print,
112  optimization::Multivec const & component_weights,
113  optimization::Multivec const & vars,
114  optimization::Multivec & dE_dvars,
115  /// Basically, turn over all the private data from OptEMultiFunc
116  Size const num_energy_dofs,
117  int const num_ref_dofs,
118  int const,
119  EnergyMap const & fixed_terms,
120  ScoreTypes const & /* score_list */,
121  ScoreTypes const & fixed_score_list
122 ) const
123 {
124  using namespace core;
125  using namespace core::optimization;
126  using namespace basic::options;
127  using namespace basic::options::OptionKeys;
128  using namespace utility;
129 
130  // if there are no structures to go through, return immediately
131  if ( wt_complexes_.size() == 0 || mutant_complexes_.size() == 0 ||
132  wt_unbounds_.size() == 0 || mutant_unbounds_.size() == 0 ) return 0.0;
133 
134 
135  // these vectors are sized to the number of structures there are for each of the four types of structures
136  // they'll be used to determine which structure has the best energy
137  utility::vector1< Real > wt_complexes_energies( wt_complexes_.size(), 0.0 );
138  utility::vector1< Real > mutant_complexes_energies( mutant_complexes_.size(), 0.0 );
139  utility::vector1< Real > wt_unbounds_energies( wt_unbounds_.size(), 0.0 );
140  utility::vector1< Real > mutant_unbounds_energies( mutant_unbounds_.size(), 0.0 );
141 
142  // go through and come up with a total score for each structure in the 4 types of structues
143  //
144  // wt_complexes_ is a vector1 of SingleStructureData (SSD) objects. this for loop iterates over each free weight and
145  // takes the unweighted energy for the current free term in wt_complexes_[jj] and multiplies it by the weight in vars.
146  // The SSD objects have a vector1 of Reals accessible by free_data() and fixed_data() member functions. These store
147  // the total unweighted energies by score type for the entire pose.
148 
149  for ( Size ii = 1; ii <= num_energy_dofs; ++ii ) {
150  for ( Size jj = 1; jj <= wt_complexes_.size(); ++jj ) {
151  // cap the fa_rep term at some value - this at least keeps it around for most of the mutants; this is how it would be done for wt_complexes
152  //#ifdef CAP_FA_REP
153  // if ( ( score_list[ ii ] == fa_rep ) && ( vars[ ii ] * wts_[ jj ]->free_data()[ ii ] > 10 ) ) { wt_energies[ jj ] += 10; }
154  // else
155  //#endif
156  wt_complexes_energies[ jj ] += vars[ ii ] * wt_complexes_[ jj ]->free_data()[ ii ];
157  }
158  for ( Size jj = 1; jj <= mutant_complexes_.size(); ++jj ) {
159  mutant_complexes_energies[ jj ] += vars[ ii ] * mutant_complexes_[ jj ]->free_data()[ ii ]; }
160  for ( Size jj = 1; jj <= wt_unbounds_.size(); ++jj ) {
161  wt_unbounds_energies[ jj ] += vars[ ii ] * wt_unbounds_[ jj ]->free_data()[ ii ]; }
162  for ( Size jj = 1; jj <= mutant_unbounds_.size(); ++jj ) {
163  mutant_unbounds_energies[ jj ] += vars[ ii ] * mutant_unbounds_[ jj ]->free_data()[ ii ]; }
164  }
165 
166  for ( Size ii = 1; ii <= fixed_score_list.size(); ++ii ) {
167  for ( Size jj = 1; jj <= wt_complexes_.size(); ++jj ) {
168  //#ifdef CAP_FA_REP
169  // if ( ( fixed_score_list[ ii ] == fa_rep ) && ( fixed_terms[ fixed_score_list[ ii ] ] * wts_[ jj ]->fixed_data()[ ii ] > 10 ) ) { wt_energies[ jj ] += 10; }
170  // else
171  //#endif
172  wt_complexes_energies[ jj ] += fixed_terms[ fixed_score_list[ ii ] ] * wt_complexes_[ jj ]->fixed_data()[ ii ];
173  }
174  for ( Size jj = 1; jj <= mutant_complexes_.size(); ++jj ) {
175  mutant_complexes_energies[ jj ] += fixed_terms[ fixed_score_list[ ii ] ] * mutant_complexes_[ jj ]->fixed_data()[ ii ]; }
176  for ( Size jj = 1; jj <= wt_unbounds_.size(); ++jj ) {
177  wt_unbounds_energies[ jj ] += fixed_terms[ fixed_score_list[ ii ] ] * wt_unbounds_[ jj ]->fixed_data()[ ii ]; }
178  for ( Size jj = 1; jj <= mutant_unbounds_.size(); ++jj ) {
179  mutant_unbounds_energies[ jj ] += fixed_terms[ fixed_score_list[ ii ] ] * mutant_unbounds_[ jj ]->fixed_data()[ ii ]; }
180  }
181 
182  // num_energy_dofs is the number of free, non-reference energy parameters in the run; num_ref_dofs are the reference energies
183  // but only add in the reference energy if they're being optimized in this optE run (not always the case)
184  if ( num_ref_dofs != 0 ) {
185  for ( Size ii = 1; ii <= mutations_.size(); ++ii ) {
186  for ( Size jj = 1; jj <= wt_complexes_.size(); ++jj ) { wt_complexes_energies[ jj ] += vars[ num_energy_dofs + mutations_[ ii ].second.first ]; }
187  for ( Size jj = 1; jj <= mutant_complexes_.size(); ++jj ) { mutant_complexes_energies[ jj ] += vars[ num_energy_dofs + mutations_[ ii ].second.second ]; }
188  for ( Size jj = 1; jj <= wt_unbounds_.size(); ++jj ) { wt_unbounds_energies[ jj ] += vars[ num_energy_dofs + mutations_[ ii ].second.first ]; }
189  for ( Size jj = 1; jj <= mutant_unbounds_.size(); ++jj ) { mutant_unbounds_energies[ jj ] += vars[ num_energy_dofs + mutations_[ ii ].second.second ]; }
190  }
191  }
192 
193  //TR << "process_score(): weighted structure energies, wt complexes: [ ";
194  //for ( Size jj = 1; jj <= wt_complexes_.size(); ++jj ) { TR << F(6,1,wt_complexes_energies[ jj ]) << ", "; }
195  //TR << "]" << std::endl;
196 
197  // This is where we branch on how the score is calculated. The simplest approach is to take the minimum energy
198  // of all the wts and all the muts and subtract them to get the ddG. The mean-based approach uses the difference
199  // of the average of all muts and average of all wts. Finally, the boltzmann approach calculates a boltzmann
200  // probability for the wts and muts to get a score.
201  // The two latter ways have never been implemented for this.
202 
203  // Do things the old-fashioned way: best energy mut - best energy wt
204 
205  // the next four lines just get the index to the best energy in each vector
206  Size const best_wt_complex_index = arg_min( wt_complexes_energies );
207  Size const best_mutant_complex_index = arg_min( mutant_complexes_energies );
208  Size const best_wt_unbounds_index = arg_min( wt_unbounds_energies );
209  Size const best_mutant_unbounds_index = arg_min( mutant_unbounds_energies );
210 
211  Real const best_wt_complex_energy = wt_complexes_energies[ best_wt_complex_index ];
212  Real const best_mutant_complex_energy = mutant_complexes_energies[ best_mutant_complex_index ];
213  Real const best_wt_unbounds_energy = wt_unbounds_energies[ best_wt_unbounds_index ];
214  Real const best_mutant_unbounds_energy = mutant_unbounds_energies[ best_mutant_unbounds_index ];
215 
216  Real dG_bind_wt = best_wt_complex_energy - best_wt_unbounds_energy;
217  Real dG_bind_mutant = best_mutant_complex_energy - best_mutant_unbounds_energy;
218 
219  Real predicted_ddG_bind = dG_bind_mutant - dG_bind_wt;
220  Real ddG_bind_diff = predicted_ddG_bind - experimental_ddG_bind_;
221  Real ddG_bind_diff_sq = ddG_bind_diff * ddG_bind_diff;
222 
223  // It might be good to adjust the slope here in the same way that Ian Davis was doing for dG bind calculations.
224  // PdbBind 2007 core set
225  // Linear regression of components of interface_delta gave an intercept between -3 and -4;
226  // including this allows a better overall fit to the real binding energy.
227  //Real const TdS = 3.5; // kcal/mol
228  //Real const pred_dG = (boundE - unboundE) - TdS;
229  //Real const diff_dG = pred_dG - deltaG_bind_;
230  //Real const sq_err = diff_dG * diff_dG;
231 
232  if ( print ) {
233  ostr << "DDGBind " << A( 20, tag() ) << X(1) << "pred: " << F(6,2,predicted_ddG_bind) << " exp: " << F(6,2,experimental_ddG_bind_)
234  << " diff^2: " << F(7,2,ddG_bind_diff_sq )
235  << " cmptwt_diff^2: " << F(7,2,component_weights[ ddG_bind_correlation ]*ddG_bind_diff_sq)
236  << std::endl;
237 
238  TR << "process_score(): "
239  << "wt bound[ " << best_wt_complex_energy << " ] - wt unbound[ " << best_wt_unbounds_energy << " ] = " << dG_bind_wt
240  << ", mut bound[ " << best_mutant_complex_energy << " ] - mut unbound[ " << best_mutant_unbounds_energy << " ] = " << dG_bind_mutant
241  << ", predicted[ " << predicted_ddG_bind << " ] - experimental[ " << experimental_ddG_bind_ << " ] = error[ " << ddG_bind_diff << " ], "
242  << "error^2[ " << ddG_bind_diff_sq << " ], "
243  << "weighted error^2[ " << component_weights[ ddG_bind_correlation ] * ddG_bind_diff_sq << " ]" << ", tag: " << this->tag()
244  << std::endl;
245 
246  } else {
247 
248  for( core::Size e_dof = 1; e_dof <= num_energy_dofs; ++e_dof ) {
249  // may want to deal with really bad repulsive energy cases here somehow
250  dE_dvars[ e_dof ] += 2 * component_weights[ ddG_bind_correlation ] * ddG_bind_diff *
251  ( mutant_complexes_[ best_mutant_complex_index ]->free_data()[ e_dof ]
252  - mutant_unbounds_[ best_mutant_unbounds_index ]->free_data()[ e_dof ] ) -
253  ( wt_complexes_[ best_wt_complex_index ]->free_data()[ e_dof ]
254  - wt_unbounds_[ best_wt_unbounds_index ]->free_data()[ e_dof ] );
255  }
256  if ( num_ref_dofs != 0 ) {
257  for ( Size ii = 1; ii <= mutations_.size(); ++ii ) {
258  dE_dvars[ num_energy_dofs + mutations_[ ii ].second.second ] += 2 * component_weights[ ddG_bind_correlation ] * ddG_bind_diff;
259  dE_dvars[ num_energy_dofs + mutations_[ ii ].second.first ] -= 2 * component_weights[ ddG_bind_correlation ] * ddG_bind_diff;
260  }
261  }
262  }
263 
264  return component_weights[ ddG_bind_correlation ] * ddG_bind_diff_sq;
265 
266 }
267 
268 
269 ///
270 /// @begin DDGBindOptEData::type()
271 ///
274  return ddG_bind_correlation;
275 }
276 
277 
278 ///
279 /// @begin DDGBindOptEData::range()
280 ///
281 /// @details
282 /// Determine the upper and lower bounds on the unweighted component energy terms at this "position" and deposit them in the passed-in
283 /// EnergyMap objects. Called by the IterativeOptE driver class to print extra information to the minimization data file.
284 ///
285 void
286 DDGBindOptEData::range( ScoreTypes const & free_score_list, ScoreTypes const & fixed_score_list, EnergyMap & lower_bound, EnergyMap & upper_bound ) const {
287 
288  for ( Size ii = 1; ii <= wt_complexes_.size(); ++ii ) {
289  update_range( wt_complexes_[ ii ], free_score_list, fixed_score_list, lower_bound, upper_bound );
290  }
291  for ( Size ii = 1; ii <= mutant_complexes_.size(); ++ii ) {
292  update_range( mutant_complexes_[ ii ], free_score_list, fixed_score_list, lower_bound, upper_bound );
293  }
294  for ( Size ii = 1; ii <= wt_unbounds_.size(); ++ii ) {
295  update_range( wt_unbounds_[ ii ], free_score_list, fixed_score_list, lower_bound, upper_bound );
296  }
297  for ( Size ii = 1; ii <= mutant_unbounds_.size(); ++ii ) {
298  update_range( mutant_unbounds_[ ii ], free_score_list, fixed_score_list, lower_bound, upper_bound );
299  }
300 }
301 
302 
303 ///
304 /// @begin DDGBindOptEData::size()
305 ///
308  return wt_complexes_.size() + mutant_complexes_.size() + wt_unbounds_.size() + mutant_unbounds_.size();
309 }
310 
311 ///
312 /// @begin DDGBindOptEData::memory_use()
313 ///
314 /// Only used for user feedback. Nothing in the code uses the result from this to allocate memory.
315 ///
318 
319  Size total = sizeof( DDGBindOptEData ) +
320  sizeof( SingleStructureData ) * wt_complexes_.size() +
321  sizeof( SingleStructureData ) * mutant_complexes_.size() +
322  sizeof( SingleStructureData ) * wt_unbounds_.size() +
323  sizeof( SingleStructureData ) * mutant_unbounds_.size();
324 
325  if ( wt_complexes_.size() > 0 ) {
326  total += sizeof( Real ) * ( wt_complexes_[ 1 ]->free_data().size() + wt_complexes_[ 1 ]->fixed_data().size() ) * wt_complexes_.size();
327  }
328  if ( mutant_complexes_.size() > 0 ) {
329  total += sizeof( Real ) * ( mutant_complexes_[ 1 ]->free_data().size() + mutant_complexes_[ 1 ]->fixed_data().size() ) * mutant_complexes_.size();
330  }
331  if ( wt_unbounds_.size() > 0 ) {
332  total += sizeof( Real ) * ( wt_unbounds_[ 1 ]->free_data().size() + wt_unbounds_[ 1 ]->fixed_data().size() ) * wt_unbounds_.size();
333  }
334  if ( mutant_unbounds_.size() > 0 ) {
335  total += sizeof( Real ) * ( mutant_unbounds_[ 1 ]->free_data().size() + mutant_unbounds_[ 1 ]->fixed_data().size() ) * mutant_unbounds_.size();
336  }
337 
338  return total;
339 }
340 
341 
342 #ifdef USEMPI
343 ///
344 /// @begin DDGBindOptEData::send_to_node()
345 ///
346 void
347 DDGBindOptEData::send_to_node( int const destination_node, int const tag ) const {
348 
349  /// 1. Experimental DDG, wt_aa, mut_aa
350  Real experimental_ddG_bind = experimental_ddG_bind_; // stupid const pointer
351  MPI_Send( & experimental_ddG_bind, 1, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
352 
353  Size n_mutations = mutations_.size();
354  MPI_Send( & n_mutations, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
355 
356  for ( Size ii = 1; ii <= mutations_.size(); ++ii ) {
357  Size position = mutations_[ ii ].first;
358  MPI_Send( & position, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
359  int wt_aa( mutations_[ ii ].second.first ), mut_aa( mutations_[ ii ].second.second );
360  MPI_Send( & wt_aa, 1, MPI_INT, destination_node, tag, MPI_COMM_WORLD );
361  MPI_Send( & mut_aa, 1, MPI_INT, destination_node, tag, MPI_COMM_WORLD );
362  }
363 
364  // 2a. n wt complexes
365  Size n_wt_complexes = wt_complexes_.size();
366  //TR << "sending n wt complexes to node " << destination_node << ": " << n_wt_complexes << std::endl;
367  MPI_Send( & n_wt_complexes, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
368 
369  /// 2b. n mut complexes
370  Size n_mut_complexes = mutant_complexes_.size();
371  //TR << "sending n mut complexes to node " << destination_node << ": " << n_mut_complexes << std::endl;
372  MPI_Send( & n_mut_complexes, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
373 
374  // 2c. n wt unbounds
375  Size n_wt_unbounds = wt_unbounds_.size();
376  //TR << "sending n wt unbounds to node " << destination_node << ": " << n_wt_unbounds << std::endl;
377  MPI_Send( & n_wt_unbounds, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
378 
379  /// 2d. n mut unbounds
380  Size n_mut_unbounds = mutant_unbounds_.size();
381  //TR << "sending n mut unbounds to node " << destination_node << ": " << n_mut_unbounds << std::endl;
382  MPI_Send( & n_mut_unbounds, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
383 
384  if ( n_wt_complexes == 0 || n_mut_complexes == 0 || n_wt_unbounds == 0 || n_mut_unbounds == 0 )
385  return;
386 
387  /// 3. n free weights
388  Size n_free = wt_complexes_[ 1 ]->free_data().size();
389  //TR << "sending n_free to node " << destination_node << ": " << n_free << std::endl;
390  MPI_Send( & n_free, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
391 
392  /// 4. n fixed weights
393  Size n_fixed = wt_complexes_[ 1 ]->fixed_data().size();
394  //TR << "sending n_fixed to node " << destination_node << ": " << n_fixed << std::endl;
395  MPI_Send( & n_fixed, 1, MPI_UNSIGNED_LONG, destination_node, tag, MPI_COMM_WORLD );
396 
397 
398  /// --------- wt complexes ---------
399  Real * free_data = new Real[ n_free * n_wt_complexes ];
400  Real * fixed_data = new Real[ n_fixed * n_wt_complexes ];
401  for ( Size ii = 1; ii <= n_wt_complexes; ++ ii ) {
402  for ( Size jj = 1; jj <= n_free; ++jj ) {
403  free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ] = wt_complexes_[ ii ]->free_data()[ jj ];
404  }
405  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
406  fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ] = wt_complexes_[ ii ]->fixed_data()[ jj ];
407  }
408  }
409  //TR << "sending wt complexes free_data to node " << destination_node << ": " << free_data << std::endl;
410  /// 5. wt complexes free data
411  MPI_Send( free_data, n_wt_complexes * n_free, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
412 
413  //TR << "sending wt complexes fixed_data to node " << destination_node << ": " << fixed_data << std::endl;
414  /// 6. wt complexes fixed data
415  MPI_Send( fixed_data, n_wt_complexes * n_fixed, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
416 
417  delete [] free_data;
418  delete [] fixed_data;
419 
420  /// --------- mut complexes ---------
421  free_data = new Real[ n_free * n_mut_complexes ];
422  fixed_data = new Real[ n_fixed * n_mut_complexes ];
423  for ( Size ii = 1; ii <= n_mut_complexes; ++ ii ) {
424  for ( Size jj = 1; jj <= n_free; ++jj ) {
425  free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ] = mutant_complexes_[ ii ]->free_data()[ jj ];
426  }
427  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
428  fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ] = mutant_complexes_[ ii ]->fixed_data()[ jj ];
429  }
430  }
431  /// 7. mut complexes free data
432  //TR << "sending mut complexes free_data to node " << destination_node << ": " << free_data << std::endl;
433  MPI_Send( free_data, n_mut_complexes * n_free, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
434 
435  /// 8. mut complexes fixed data
436  //TR << "sending mut complexes fixed_data to node " << destination_node << ": " << fixed_data << std::endl;
437  MPI_Send( fixed_data, n_mut_complexes * n_fixed, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
438 
439  delete [] free_data;
440  delete [] fixed_data;
441 
442  /// --------- wt unbounds ---------
443  free_data = new Real[ n_free * n_wt_unbounds ];
444  fixed_data = new Real[ n_fixed * n_wt_unbounds ];
445  for ( Size ii = 1; ii <= n_wt_unbounds; ++ ii ) {
446  for ( Size jj = 1; jj <= n_free; ++jj ) {
447  free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ] = wt_unbounds_[ ii ]->free_data()[ jj ];
448  }
449  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
450  fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ] = wt_unbounds_[ ii ]->fixed_data()[ jj ];
451  }
452  }
453  //TR << "sending wt unbounds free_data to node " << destination_node << ": " << free_data << std::endl;
454  /// 9. wt unbounds free data
455  MPI_Send( free_data, n_wt_unbounds * n_free, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
456 
457  //TR << "sending wt unbounds fixed_data to node " << destination_node << ": " << fixed_data << std::endl;
458  /// 10. fixed data
459  MPI_Send( fixed_data, n_wt_unbounds * n_fixed, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
460 
461  delete [] free_data;
462  delete [] fixed_data;
463 
464  /// --------- mut unbounds ---------
465  free_data = new Real[ n_free * n_mut_unbounds ];
466  fixed_data = new Real[ n_fixed * n_mut_unbounds ];
467  for ( Size ii = 1; ii <= n_mut_unbounds; ++ ii ) {
468  for ( Size jj = 1; jj <= n_free; ++jj ) {
469  free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ] = mutant_unbounds_[ ii ]->free_data()[ jj ];
470  }
471  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
472  fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ] = mutant_unbounds_[ ii ]->fixed_data()[ jj ];
473  }
474  }
475  /// 11. mut unbounds free data
476  //TR << "sending mut unbounds free_data to node " << destination_node << ": " << free_data << std::endl;
477  MPI_Send( free_data, n_mut_unbounds * n_free, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
478 
479  /// 12. mut unbounds fixed data
480  //TR << "sending mut unbounds fixed_data to node " << destination_node << ": " << fixed_data << std::endl;
481  MPI_Send( fixed_data, n_mut_unbounds * n_fixed, MPI_DOUBLE, destination_node, tag, MPI_COMM_WORLD );
482 
483  delete [] free_data;
484  delete [] fixed_data;
485 
486  OptEPositionData::send_to_node( destination_node, tag );
487 
488 }
489 
490 
491 ///
492 /// @begin DDGBindOptEData::receive_from_node()
493 ///
494 void
495 DDGBindOptEData::receive_from_node( int const source_node, int const tag )
496 {
497  MPI_Status stat;
498  //TR << "receive_from_node(): receiving data from node... " << source_node << std::endl;
499 
500  /// 1. Experimental DDG, wt_aa, mut_aa
501  MPI_Recv( &experimental_ddG_bind_, 1, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
502  //TR << "receive_from_node(): rec'd exp ddGbind: " << experimental_ddG_bind_ << std::endl;
503 
504  Size n_mutations;
505  MPI_Recv( & n_mutations, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
506  mutations_.resize( n_mutations );
507  //TR << "receive_from_node(): rec'd n_mutations: " << n_mutations << std::endl;
508 
509  for ( Size ii = 1; ii <= mutations_.size(); ++ii ) {
510  Size position( 0 );
511  MPI_Recv( & position, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
512  //TR << "receive_from_node(): rec'd position: " << position << std::endl;
513  int wt_aa(0), mut_aa(0);
514  MPI_Recv( & wt_aa, 1, MPI_INT, source_node, tag, MPI_COMM_WORLD, &stat );
515  MPI_Recv( & mut_aa, 1, MPI_INT, source_node, tag, MPI_COMM_WORLD, &stat );
516  //TR << "receive_from_node(): rec'd wt_aa and mut_aa: " << wt_aa << ", " << mut_aa << std::endl;
517  core::chemical::AA wt_aa_ = static_cast< core::chemical::AA > ( wt_aa );
518  core::chemical::AA mut_aa_ = static_cast< core::chemical::AA > ( mut_aa );
519  mutations_[ ii ] = std::make_pair( position, std::make_pair( wt_aa_, mut_aa_ ) );
520  }
521 
522  /// 2a. n wt complexes
523  Size n_wt_complexes( 0 );
524  MPI_Recv( & n_wt_complexes, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
525  //TR << "receive_from_node(): rec'd n_wt_complexes: " << n_wt_complexes << std::endl;
526 
527  /// 2b. n mut complexes
528  Size n_mut_complexes( 0 );
529  MPI_Recv( & n_mut_complexes, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
530  //TR << "receive_from_node(): rec'd n_mut_complexes: " << n_mut_complexes << std::endl;
531 
532  /// 2c. n wt unbounds
533  Size n_wt_unbounds( 0 );
534  MPI_Recv( & n_wt_unbounds, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
535  //TR << "receive_from_node(): rec'd n_wt_unbounds: " << n_wt_unbounds << std::endl;
536 
537  /// 2d. n mut unbounds
538  Size n_mut_unbounds( 0 );
539  MPI_Recv( & n_mut_unbounds, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
540  //TR << "receive_from_node(): rec'd n_mut_unbounds: " << n_mut_unbounds << std::endl;
541 
542  if ( n_wt_complexes == 0 || n_mut_complexes == 0 || n_wt_unbounds == 0 || n_mut_unbounds == 0 ) return;
543  wt_complexes_.reserve( n_wt_complexes );
544  mutant_complexes_.reserve( n_mut_complexes );
545  wt_unbounds_.reserve( n_wt_unbounds );
546  mutant_unbounds_.reserve( n_mut_unbounds );
547 
548  /// 3. n free weights
549  Size n_free( 0 );
550  MPI_Recv( & n_free, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
551  //TR << "receive_from_node(): rec'd n_free: " << n_free << std::endl;
552 
553  /// 4. n fixed weights
554  Size n_fixed( 0 );
555  MPI_Recv( & n_fixed, 1, MPI_UNSIGNED_LONG, source_node, tag, MPI_COMM_WORLD, &stat );
556  //TR << "receive_from_node(): rec'd n_fixed: " << n_fixed << std::endl;
557 
558 
559  /// --------- wt complexes ---------
560  Real * free_data = new Real[ n_free * n_wt_complexes ];
561  Real * fixed_data = new Real[ n_fixed * n_wt_complexes ];
562 
563  /// 5. wt complexes free data
564  MPI_Recv( free_data, n_wt_complexes * n_free, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
565 
566  /// 6. wt complexes fixed data
567  MPI_Recv( fixed_data, n_wt_complexes * n_fixed, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
568 
569  utility::vector1< Real > free_data_v( n_free );
570  utility::vector1< Real > fixed_data_v( n_fixed );
571  for ( Size ii = 1; ii <= n_wt_complexes; ++ ii ) {
572  for ( Size jj = 1; jj <= n_free; ++jj ) {
573  free_data_v[ jj ] = free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ];
574  }
575  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
576  fixed_data_v[ jj ] = fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ];
577  }
578  wt_complexes_.push_back( new SingleStructureData( free_data_v, fixed_data_v ) );
579  }
580  delete [] free_data; free_data = 0; free_data_v.resize(0);
581  delete [] fixed_data; fixed_data = 0; fixed_data_v.resize(0);
582 
583  /// --------- mut complexes ---------
584  free_data = new Real[ n_free * n_mut_complexes ];
585  fixed_data = new Real[ n_fixed * n_mut_complexes ];
586 
587  /// 7. free data
588  MPI_Recv( free_data, n_mut_complexes * n_free, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
589 
590  /// 8. fixed data
591  MPI_Recv( fixed_data, n_mut_complexes * n_fixed, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
592 
593  free_data_v.resize( n_free );
594  fixed_data_v.resize( n_fixed );
595  for ( Size ii = 1; ii <= n_mut_complexes; ++ ii ) {
596  for ( Size jj = 1; jj <= n_free; ++jj ) {
597  free_data_v[ jj ] = free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ];
598  }
599  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
600  fixed_data_v[ jj ] = fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ];
601  }
602  mutant_complexes_.push_back( new SingleStructureData( free_data_v, fixed_data_v ) );
603  }
604  delete [] free_data; free_data = 0; free_data_v.resize(0);
605  delete [] fixed_data; fixed_data = 0; fixed_data_v.resize(0);
606 
607  /// --------- wt unbounds ---------
608  free_data = new Real[ n_free * n_wt_unbounds ];
609  fixed_data = new Real[ n_fixed * n_wt_unbounds ];
610 
611  /// 5. wt unbounds free data
612  MPI_Recv( free_data, n_wt_unbounds * n_free, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
613 
614  /// 6. wt complexes fixed data
615  MPI_Recv( fixed_data, n_wt_unbounds * n_fixed, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
616 
617  free_data_v.resize( n_free );
618  fixed_data_v.resize( n_fixed );
619  for ( Size ii = 1; ii <= n_wt_unbounds; ++ ii ) {
620  for ( Size jj = 1; jj <= n_free; ++jj ) {
621  free_data_v[ jj ] = free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ];
622  }
623  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
624  fixed_data_v[ jj ] = fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ];
625  }
626  wt_unbounds_.push_back( new SingleStructureData( free_data_v, fixed_data_v ) );
627  }
628  delete [] free_data; free_data = 0; free_data_v.resize(0);
629  delete [] fixed_data; fixed_data = 0; fixed_data_v.resize(0);
630 
631  /// --------- mut unbounds ---------
632  free_data = new Real[ n_free * n_mut_unbounds ];
633  fixed_data = new Real[ n_fixed * n_mut_unbounds ];
634 
635  /// 7. free data
636  MPI_Recv( free_data, n_mut_unbounds * n_free, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
637 
638  /// 8. fixed data
639  MPI_Recv( fixed_data, n_mut_unbounds * n_fixed, MPI_DOUBLE, source_node, tag, MPI_COMM_WORLD, &stat );
640 
641  free_data_v.resize( n_free );
642  fixed_data_v.resize( n_fixed );
643  for ( Size ii = 1; ii <= n_mut_unbounds; ++ ii ) {
644  for ( Size jj = 1; jj <= n_free; ++jj ) {
645  free_data_v[ jj ] = free_data[ ( ii - 1 ) * n_free + ( jj - 1 ) ];
646  }
647  for ( Size jj = 1; jj <= n_fixed; ++jj ) {
648  fixed_data_v[ jj ] = fixed_data[ ( ii - 1 ) * n_fixed + ( jj - 1 ) ];
649  }
650  mutant_unbounds_.push_back( new SingleStructureData( free_data_v, fixed_data_v ) );
651  }
652  delete [] free_data; free_data = 0; free_data_v.resize(0);
653  delete [] fixed_data; fixed_data = 0; fixed_data_v.resize(0);
654 
655  //std::cout << "receive_from_node(): receiving tag information from slave node." << std::endl;
656  OptEPositionData::receive_from_node( source_node, tag );
657 
658 }
659 #endif
660 
661 
662 /// @begin DDGBindOptEData::set_experimental_ddg_bind()
663 ///
664 void
666  experimental_ddG_bind_ = exp_ddg_bind;
667 }
668 
669 /// @begin DDGBindOptEData::add_mutation()
670 ///
671 void
672 DDGBindOptEData::add_mutation( std::pair< Size, std::pair < AA, AA > > mutation ) {
673  mutations_.push_back( mutation );
674 }
675 
676 /// @begin DDGBindOptEData::add_wt_complex()
677 ///
678 void
680  wt_complexes_.push_back( wt );
681 }
682 
683 /// @begin DDGBindOptEData::add_mutant_complex()
684 ///
685 void
687  mutant_complexes_.push_back( mut );
688 }
689 
690 /// @begin DDGBindOptEData::add_wt_unbounds()
691 ///
692 void
694  wt_unbounds_.push_back( wt );
695 }
696 
697 /// @begin DDGBindOptEData::add_mutant_unbounds()
698 ///
699 void
701  mutant_unbounds_.push_back( mut );
702 }
703 
704 
705 
706 } // namespace optimize_weights
707 } // namespace protocols