Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

colvarcomp_protein.C

Go to the documentation of this file.
00001 // -*- c++ -*-
00002 
00003 // This file is part of the Collective Variables module (Colvars).
00004 // The original version of Colvars and its updates are located at:
00005 // https://github.com/Colvars/colvars
00006 // Please update all Colvars source files before making any changes.
00007 // If you wish to distribute your changes, please submit them to the
00008 // Colvars repository at GitHub.
00009 
00010 #include <algorithm>
00011 
00012 #include "colvarmodule.h"
00013 #include "colvarvalue.h"
00014 #include "colvarparse.h"
00015 #include "colvar.h"
00016 #include "colvarcomp.h"
00017 
00018 
00019 colvar::alpha_angles::alpha_angles(std::string const &conf)
00020   : cvc(conf)
00021 {
00022   set_function_type("alpha");
00023   enable(f_cvc_explicit_gradient);
00024   x.type(colvarvalue::type_scalar);
00025 
00026   colvarproxy *proxy = cvm::main()->proxy;
00027 
00028   std::string segment_id;
00029   get_keyval(conf, "psfSegID", segment_id, std::string("MAIN"));
00030 
00031   std::vector<int> residues;
00032   {
00033     std::string residues_conf = "";
00034     key_lookup(conf, "residueRange", &residues_conf);
00035     if (residues_conf.size()) {
00036       std::istringstream is(residues_conf);
00037       int initial, final;
00038       char dash;
00039       if ( (is >> initial) && (initial > 0) &&
00040            (is >> dash) && (dash == '-') &&
00041            (is >> final) && (final > 0) ) {
00042         for (int rnum = initial; rnum <= final; rnum++) {
00043           residues.push_back(rnum);
00044         }
00045       }
00046     } else {
00047       cvm::error("Error: no residues defined in \"residueRange\".\n");
00048       return;
00049     }
00050   }
00051 
00052   if (residues.size() < 5) {
00053     cvm::error("Error: not enough residues defined in \"residueRange\".\n");
00054     return;
00055   }
00056 
00057   std::string const &sid    = segment_id;
00058   std::vector<int> const &r = residues;
00059 
00060 
00061   get_keyval(conf, "hBondCoeff", hb_coeff, 0.5);
00062   if ( (hb_coeff < 0.0) || (hb_coeff > 1.0) ) {
00063     cvm::error("Error: hBondCoeff must be defined between 0 and 1.\n");
00064     return;
00065   }
00066 
00067 
00068   get_keyval(conf, "angleRef", theta_ref, 88.0);
00069   get_keyval(conf, "angleTol", theta_tol, 15.0);
00070 
00071   if (hb_coeff < 1.0) {
00072 
00073     for (size_t i = 0; i < residues.size()-2; i++) {
00074       theta.push_back(new colvar::angle(cvm::atom(r[i  ], "CA", sid),
00075                                         cvm::atom(r[i+1], "CA", sid),
00076                                         cvm::atom(r[i+2], "CA", sid)));
00077       register_atom_group(theta.back()->atom_groups[0]);
00078       register_atom_group(theta.back()->atom_groups[1]);
00079       register_atom_group(theta.back()->atom_groups[2]);
00080     }
00081 
00082   } else {
00083     cvm::log("The hBondCoeff specified will disable the Calpha-Calpha-Calpha angle terms.\n");
00084   }
00085 
00086   {
00087     cvm::real r0;
00088     size_t en, ed;
00089     get_keyval(conf, "hBondCutoff",   r0, proxy->angstrom_to_internal(3.3));
00090     get_keyval(conf, "hBondExpNumer", en, 6);
00091     get_keyval(conf, "hBondExpDenom", ed, 8);
00092 
00093     if (hb_coeff > 0.0) {
00094 
00095       for (size_t i = 0; i < residues.size()-4; i++) {
00096         hb.push_back(new colvar::h_bond(cvm::atom(r[i  ], "O",  sid),
00097                                         cvm::atom(r[i+4], "N",  sid),
00098                                         r0, en, ed));
00099         register_atom_group(hb.back()->atom_groups[0]);
00100       }
00101 
00102     } else {
00103       cvm::log("The hBondCoeff specified will disable the hydrogen bond terms.\n");
00104     }
00105   }
00106 }
00107 
00108 
00109 colvar::alpha_angles::alpha_angles()
00110   : cvc()
00111 {
00112   set_function_type("alphaAngles");
00113   enable(f_cvc_explicit_gradient);
00114   x.type(colvarvalue::type_scalar);
00115 }
00116 
00117 
00118 colvar::alpha_angles::~alpha_angles()
00119 {
00120   while (theta.size() != 0) {
00121     delete theta.back();
00122     theta.pop_back();
00123   }
00124   while (hb.size() != 0) {
00125     delete hb.back();
00126     hb.pop_back();
00127   }
00128   // Our references to atom groups have become invalid now that children cvcs are deleted
00129   atom_groups.clear();
00130 }
00131 
00132 
00133 void colvar::alpha_angles::calc_value()
00134 {
00135   x.real_value = 0.0;
00136 
00137   if (theta.size()) {
00138 
00139     cvm::real const theta_norm =
00140       (1.0-hb_coeff) / cvm::real(theta.size());
00141 
00142     for (size_t i = 0; i < theta.size(); i++) {
00143 
00144       (theta[i])->calc_value();
00145 
00146       cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
00147       cvm::real const f = ( (1.0 - (t*t)) /
00148                             (1.0 - (t*t*t*t)) );
00149 
00150       x.real_value += theta_norm * f;
00151 
00152       if (cvm::debug())
00153         cvm::log("Calpha-Calpha angle no. "+cvm::to_str(i+1)+" in \""+
00154                   this->name+"\" has a value of "+
00155                   (cvm::to_str((theta[i])->value().real_value))+
00156                   " degrees, f = "+cvm::to_str(f)+".\n");
00157     }
00158   }
00159 
00160   if (hb.size()) {
00161 
00162     cvm::real const hb_norm =
00163       hb_coeff / cvm::real(hb.size());
00164 
00165     for (size_t i = 0; i < hb.size(); i++) {
00166       (hb[i])->calc_value();
00167       x.real_value += hb_norm * (hb[i])->value().real_value;
00168       if (cvm::debug())
00169         cvm::log("Hydrogen bond no. "+cvm::to_str(i+1)+" in \""+
00170                   this->name+"\" has a value of "+
00171                   (cvm::to_str((hb[i])->value().real_value))+".\n");
00172     }
00173   }
00174 }
00175 
00176 
00177 void colvar::alpha_angles::calc_gradients()
00178 {
00179   size_t i;
00180   for (i = 0; i < theta.size(); i++)
00181     (theta[i])->calc_gradients();
00182 
00183   for (i = 0; i < hb.size(); i++)
00184     (hb[i])->calc_gradients();
00185 }
00186 
00187 
00188 void colvar::alpha_angles::collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients)
00189 {
00190   cvm::real cvc_coeff = sup_coeff * cvm::real(sup_np) * cvm::integer_power(value().real_value, sup_np-1);
00191 
00192   if (theta.size()) {
00193     cvm::real const theta_norm = (1.0-hb_coeff) / cvm::real(theta.size());
00194 
00195     for (size_t i = 0; i < theta.size(); i++) {
00196       cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
00197       cvm::real const f = ( (1.0 - (t*t)) /
00198                             (1.0 - (t*t*t*t)) );
00199       cvm::real const dfdt =
00200         1.0/(1.0 - (t*t*t*t)) *
00201         ( (-2.0 * t) + (-1.0*f)*(-4.0 * (t*t*t)) );
00202 
00203       // Coefficient of this CVC's gradient in the colvar gradient, times coefficient of this
00204       // angle's gradient in the CVC's gradient
00205       cvm::real const coeff = cvc_coeff * theta_norm * dfdt * (1.0/theta_tol);
00206 
00207       for (size_t j = 0; j < theta[i]->atom_groups.size(); j++) {
00208         cvm::atom_group &ag = *(theta[i]->atom_groups[j]);
00209         for (size_t k = 0; k < ag.size(); k++) {
00210           size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
00211                                       ag[k].id) - atom_ids.begin();
00212           atomic_gradients[a] += coeff * ag[k].grad;
00213         }
00214       }
00215     }
00216   }
00217 
00218   if (hb.size()) {
00219 
00220     cvm::real const hb_norm = hb_coeff / cvm::real(hb.size());
00221 
00222     for (size_t i = 0; i < hb.size(); i++) {
00223       // Coefficient of this CVC's gradient in the colvar gradient, times coefficient of this
00224       // hbond's gradient in the CVC's gradient
00225       cvm::real const coeff = cvc_coeff * 0.5 * hb_norm;
00226 
00227       for (size_t j = 0; j < hb[i]->atom_groups.size(); j++) {
00228         cvm::atom_group &ag = *(hb[i]->atom_groups[j]);
00229         for (size_t k = 0; k < ag.size(); k++) {
00230           size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
00231                                       ag[k].id) - atom_ids.begin();
00232           atomic_gradients[a] += coeff * ag[k].grad;
00233         }
00234       }
00235     }
00236   }
00237 }
00238 
00239 
00240 void colvar::alpha_angles::apply_force(colvarvalue const &force)
00241 {
00242 
00243   if (theta.size()) {
00244 
00245     cvm::real const theta_norm =
00246       (1.0-hb_coeff) / cvm::real(theta.size());
00247 
00248     for (size_t i = 0; i < theta.size(); i++) {
00249 
00250       cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
00251       cvm::real const f = ( (1.0 - (t*t)) /
00252                             (1.0 - (t*t*t*t)) );
00253 
00254       cvm::real const dfdt =
00255         1.0/(1.0 - (t*t*t*t)) *
00256         ( (-2.0 * t) + (-1.0*f)*(-4.0 * (t*t*t)) );
00257 
00258       (theta[i])->apply_force(theta_norm *
00259                                dfdt * (1.0/theta_tol) *
00260                                force.real_value );
00261     }
00262   }
00263 
00264   if (hb.size()) {
00265 
00266     cvm::real const hb_norm =
00267       hb_coeff / cvm::real(hb.size());
00268 
00269     for (size_t i = 0; i < hb.size(); i++) {
00270       (hb[i])->apply_force(0.5 * hb_norm * force.real_value);
00271     }
00272   }
00273 }
00274 
00275 
00276 simple_scalar_dist_functions(alpha_angles)
00277 
00278 
00279 
00281 // dihedral principal component
00283 
00284 colvar::dihedPC::dihedPC(std::string const &conf)
00285   : cvc(conf)
00286 {
00287   if (cvm::debug())
00288     cvm::log("Initializing dihedral PC object.\n");
00289 
00290   set_function_type("dihedPC");
00291   // Supported through references to atom groups of children cvcs
00292   enable(f_cvc_explicit_gradient);
00293   x.type(colvarvalue::type_scalar);
00294 
00295   std::string segment_id;
00296   get_keyval(conf, "psfSegID", segment_id, std::string("MAIN"));
00297 
00298   std::vector<int> residues;
00299   {
00300     std::string residues_conf = "";
00301     key_lookup(conf, "residueRange", &residues_conf);
00302     if (residues_conf.size()) {
00303       std::istringstream is(residues_conf);
00304       int initial, final;
00305       char dash;
00306       if ( (is >> initial) && (initial > 0) &&
00307            (is >> dash) && (dash == '-') &&
00308            (is >> final) && (final > 0) ) {
00309         for (int rnum = initial; rnum <= final; rnum++) {
00310           residues.push_back(rnum);
00311         }
00312       }
00313     } else {
00314       cvm::error("Error: no residues defined in \"residueRange\".\n");
00315       return;
00316     }
00317   }
00318 
00319   if (residues.size() < 2) {
00320     cvm::error("Error: dihedralPC requires at least two residues.\n");
00321     return;
00322   }
00323 
00324   std::string const &sid    = segment_id;
00325   std::vector<int> const &r = residues;
00326 
00327   std::string vecFileName;
00328   int         vecNumber;
00329   if (get_keyval(conf, "vectorFile", vecFileName, vecFileName)) {
00330     get_keyval(conf, "vectorNumber", vecNumber, 0);
00331     if (vecNumber < 1) {
00332       cvm::error("A positive value of vectorNumber is required.");
00333       return;
00334     }
00335 
00336     std::istream &vecFile =
00337       cvm::main()->proxy->input_stream(vecFileName,
00338                                        "dihedral PCA vector file");
00339     if (!vecFile) {
00340       return;
00341     }
00342 
00343     // TODO: adapt to different formats by setting this flag
00344     bool eigenvectors_as_columns = true;
00345 
00346     if (eigenvectors_as_columns) {
00347       // Carma-style dPCA file
00348       std::string line;
00349       cvm::real c;
00350       while (vecFile.good()) {
00351         getline(vecFile, line);
00352         if (line.length() < 2) break;
00353         std::istringstream ls(line);
00354         for (int i=0; i<vecNumber; i++) ls >> c;
00355         coeffs.push_back(c);
00356       }
00357     }
00358 /*  TODO Uncomment this when different formats are recognized
00359     else {
00360       // Eigenvectors as lines
00361       // Skip to the right line
00362       for (int i = 1; i<vecNumber; i++)
00363         vecFile.ignore(999999, '\n');
00364 
00365       if (!vecFile.good()) {
00366         cvm::error("Error reading dihedral PCA vector file " + vecFileName);
00367       }
00368 
00369       std::string line;
00370       getline(vecFile, line);
00371       std::istringstream ls(line);
00372       cvm::real c;
00373       while (ls.good()) {
00374         ls >> c;
00375         coeffs.push_back(c);
00376       }
00377     }
00378  */
00379     cvm::main()->proxy->close_input_stream(vecFileName);
00380 
00381   } else {
00382     get_keyval(conf, "vector", coeffs, coeffs);
00383   }
00384 
00385   if ( coeffs.size() != 4 * (residues.size() - 1)) {
00386     cvm::error("Error: wrong number of coefficients: " +
00387         cvm::to_str(coeffs.size()) + ". Expected " +
00388         cvm::to_str(4 * (residues.size() - 1)) +
00389         " (4 coeffs per residue, minus one residue).\n");
00390     return;
00391   }
00392 
00393   for (size_t i = 0; i < residues.size()-1; i++) {
00394     // Psi
00395     theta.push_back(new colvar::dihedral(cvm::atom(r[i  ], "N", sid),
00396                                          cvm::atom(r[i  ], "CA", sid),
00397                                          cvm::atom(r[i  ], "C", sid),
00398                                          cvm::atom(r[i+1], "N", sid)));
00399     register_atom_group(theta.back()->atom_groups[0]);
00400     register_atom_group(theta.back()->atom_groups[1]);
00401     register_atom_group(theta.back()->atom_groups[2]);
00402     register_atom_group(theta.back()->atom_groups[3]);
00403     // Phi (next res)
00404     theta.push_back(new colvar::dihedral(cvm::atom(r[i  ], "C", sid),
00405                                          cvm::atom(r[i+1], "N", sid),
00406                                          cvm::atom(r[i+1], "CA", sid),
00407                                          cvm::atom(r[i+1], "C", sid)));
00408     register_atom_group(theta.back()->atom_groups[0]);
00409     register_atom_group(theta.back()->atom_groups[1]);
00410     register_atom_group(theta.back()->atom_groups[2]);
00411     register_atom_group(theta.back()->atom_groups[3]);
00412   }
00413 
00414   if (cvm::debug())
00415     cvm::log("Done initializing dihedPC object.\n");
00416 }
00417 
00418 
00419 colvar::dihedPC::dihedPC()
00420   : cvc()
00421 {
00422   set_function_type("dihedPC");
00423   // Supported through references to atom groups of children cvcs
00424   enable(f_cvc_explicit_gradient);
00425   x.type(colvarvalue::type_scalar);
00426 }
00427 
00428 
00429 colvar::dihedPC::~dihedPC()
00430 {
00431   while (theta.size() != 0) {
00432     delete theta.back();
00433     theta.pop_back();
00434   }
00435   // Our references to atom groups have become invalid now that children cvcs are deleted
00436   atom_groups.clear();
00437 }
00438 
00439 
00440 void colvar::dihedPC::calc_value()
00441 {
00442   x.real_value = 0.0;
00443   for (size_t i = 0; i < theta.size(); i++) {
00444     theta[i]->calc_value();
00445     cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
00446     x.real_value += coeffs[2*i  ] * cvm::cos(t)
00447                   + coeffs[2*i+1] * cvm::sin(t);
00448   }
00449 }
00450 
00451 
00452 void colvar::dihedPC::calc_gradients()
00453 {
00454   for (size_t i = 0; i < theta.size(); i++) {
00455     theta[i]->calc_gradients();
00456   }
00457 }
00458 
00459 
00460 void colvar::dihedPC::collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients)
00461 {
00462   cvm::real cvc_coeff = sup_coeff * cvm::real(sup_np) * cvm::integer_power(value().real_value, sup_np-1);
00463   for (size_t i = 0; i < theta.size(); i++) {
00464     cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
00465     cvm::real const dcosdt = - (PI / 180.) * cvm::sin(t);
00466     cvm::real const dsindt =   (PI / 180.) * cvm::cos(t);
00467     // Coefficient of this dihedPC's gradient in the colvar gradient, times coefficient of this
00468     // dihedral's gradient in the dihedPC's gradient
00469     cvm::real const coeff = cvc_coeff * (coeffs[2*i] * dcosdt + coeffs[2*i+1] * dsindt);
00470 
00471     for (size_t j = 0; j < theta[i]->atom_groups.size(); j++) {
00472       cvm::atom_group &ag = *(theta[i]->atom_groups[j]);
00473       for (size_t k = 0; k < ag.size(); k++) {
00474         size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
00475                                     ag[k].id) - atom_ids.begin();
00476         atomic_gradients[a] += coeff * ag[k].grad;
00477       }
00478     }
00479   }
00480 }
00481 
00482 
00483 void colvar::dihedPC::apply_force(colvarvalue const &force)
00484 {
00485   for (size_t i = 0; i < theta.size(); i++) {
00486     cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
00487     cvm::real const dcosdt = - (PI / 180.) * cvm::sin(t);
00488     cvm::real const dsindt =   (PI / 180.) * cvm::cos(t);
00489 
00490     theta[i]->apply_force((coeffs[2*i  ] * dcosdt +
00491                            coeffs[2*i+1] * dsindt) * force);
00492   }
00493 }
00494 
00495 
00496 simple_scalar_dist_functions(dihedPC)

Generated on Wed Oct 9 02:42:14 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002