00001 #include <cmath>
00002
00003 #include "colvarmodule.h"
00004 #include "colvarvalue.h"
00005 #include "colvarparse.h"
00006 #include "colvar.h"
00007 #include "colvarcomp.h"
00008
00009
00011
00013
00014 colvar::alpha_angles::alpha_angles (std::string const &conf)
00015 : cvc (conf)
00016 {
00017 if (cvm::debug())
00018 cvm::log ("Initializing alpha_angles object.\n");
00019
00020 function_type = "alpha_angles";
00021 x.type (colvarvalue::type_scalar);
00022
00023 std::string segment_id;
00024 get_keyval (conf, "psfSegID", segment_id, std::string ("MAIN"));
00025
00026 std::vector<int> residues;
00027 {
00028 std::string residues_conf = "";
00029 key_lookup (conf, "residueRange", residues_conf);
00030 if (residues_conf.size()) {
00031 std::istringstream is (residues_conf);
00032 int initial, final;
00033 char dash;
00034 if ( (is >> initial) && (initial > 0) &&
00035 (is >> dash) && (dash == '-') &&
00036 (is >> final) && (final > 0) ) {
00037 for (int rnum = initial; rnum <= final; rnum++) {
00038 residues.push_back (rnum);
00039 }
00040 }
00041 } else {
00042 cvm::fatal_error ("Error: no residues defined in \"residueRange\".\n");
00043 }
00044 }
00045
00046 if (residues.size() < 5) {
00047 cvm::fatal_error ("Error: not enough residues defined in \"residueRange\".\n");
00048 }
00049
00050 std::string const &sid = segment_id;
00051 std::vector<int> const &r = residues;
00052
00053
00054 get_keyval (conf, "hBondCoeff", hb_coeff, 0.5);
00055 if ( (hb_coeff < 0.0) || (hb_coeff > 1.0) ) {
00056 cvm::fatal_error ("Error: hBondCoeff must be defined between 0 and 1.\n");
00057 }
00058
00059
00060 get_keyval (conf, "angleRef", theta_ref, 88.0);
00061 get_keyval (conf, "angleTol", theta_tol, 15.0);
00062
00063 if (hb_coeff < 1.0) {
00064
00065 for (size_t i = 0; i < residues.size()-2; i++) {
00066 theta.push_back (new colvar::angle (cvm::atom (r[i ], "CA", sid),
00067 cvm::atom (r[i+1], "CA", sid),
00068 cvm::atom (r[i+2], "CA", sid)));
00069 }
00070
00071 } else {
00072 cvm::log ("The hBondCoeff specified will disable the Calpha-Calpha-Calpha angle terms.\n");
00073 }
00074
00075 {
00076 cvm::real r0;
00077 size_t en, ed;
00078 get_keyval (conf, "hBondCutoff", r0, (3.3 * cvm::unit_angstrom()));
00079 get_keyval (conf, "hBondExpNumer", en, 6);
00080 get_keyval (conf, "hBondExpDenom", ed, 8);
00081
00082 if (hb_coeff > 0.0) {
00083
00084 for (size_t i = 0; i < residues.size()-4; i++) {
00085 hb.push_back (new colvar::h_bond (cvm::atom (r[i ], "O", sid),
00086 cvm::atom (r[i+4], "N", sid),
00087 r0, en, ed));
00088 }
00089
00090 } else {
00091 cvm::log ("The hBondCoeff specified will disable the hydrogen bond terms.\n");
00092 }
00093 }
00094
00095 if (cvm::debug())
00096 cvm::log ("Done initializing alpha_angles object.\n");
00097 }
00098
00099
00100 colvar::alpha_angles::alpha_angles()
00101 : cvc ()
00102 {
00103 function_type = "alpha_angles";
00104 x.type (colvarvalue::type_scalar);
00105 }
00106
00107 colvar::alpha_angles::~alpha_angles()
00108 {
00109 while (theta.size() != 0) {
00110 delete theta.back();
00111 theta.pop_back();
00112 }
00113 while (hb.size() != 0) {
00114 delete hb.back();
00115 hb.pop_back();
00116 }
00117 }
00118
00119 void colvar::alpha_angles::calc_value()
00120 {
00121 x.real_value = 0.0;
00122
00123 if (theta.size()) {
00124
00125 cvm::real const theta_norm =
00126 (1.0-hb_coeff) / cvm::real (theta.size());
00127
00128 for (size_t i = 0; i < theta.size(); i++) {
00129
00130 (theta[i])->calc_value();
00131
00132 cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
00133 cvm::real const f = ( (1.0 - std::pow (t, (int) 2)) /
00134 (1.0 - std::pow (t, (int) 4)) );
00135
00136 x.real_value += theta_norm * f;
00137
00138 if (cvm::debug())
00139 cvm::log ("Calpha-Calpha angle no. "+cvm::to_str (i+1)+" in \""+
00140 this->name+"\" has a value of "+
00141 (cvm::to_str ((theta[i])->value().real_value))+
00142 " degrees, f = "+cvm::to_str (f)+".\n");
00143 }
00144 }
00145
00146 if (hb.size()) {
00147
00148 cvm::real const hb_norm =
00149 hb_coeff / cvm::real (hb.size());
00150
00151 for (size_t i = 0; i < hb.size(); i++) {
00152 (hb[i])->calc_value();
00153 x.real_value += hb_norm * (hb[i])->value().real_value;
00154 if (cvm::debug())
00155 cvm::log ("Hydrogen bond no. "+cvm::to_str (i+1)+" in \""+
00156 this->name+"\" has a value of "+
00157 (cvm::to_str ((hb[i])->value().real_value))+".\n");
00158 }
00159 }
00160 }
00161
00162
00163 void colvar::alpha_angles::calc_gradients()
00164 {
00165 for (size_t i = 0; i < theta.size(); i++)
00166 (theta[i])->calc_gradients();
00167
00168 for (size_t i = 0; i < hb.size(); i++)
00169 (hb[i])->calc_gradients();
00170 }
00171
00172
00173 void colvar::alpha_angles::apply_force (colvarvalue const &force)
00174 {
00175
00176 if (theta.size()) {
00177
00178 cvm::real const theta_norm =
00179 (1.0-hb_coeff) / cvm::real (theta.size());
00180
00181 for (size_t i = 0; i < theta.size(); i++) {
00182
00183 cvm::real const t = ((theta[i])->value().real_value-theta_ref)/theta_tol;
00184 cvm::real const f = ( (1.0 - std::pow (t, (int) 2)) /
00185 (1.0 - std::pow (t, (int) 4)) );
00186
00187 cvm::real const dfdt =
00188 1.0/(1.0 - std::pow (t, (int) 4)) *
00189 ( (-2.0 * t) + (-1.0*f)*(-4.0 * std::pow (t, (int) 3)) );
00190
00191 (theta[i])->apply_force (theta_norm *
00192 dfdt * (1.0/theta_tol) *
00193 force.real_value );
00194 }
00195 }
00196
00197 if (hb.size()) {
00198
00199 cvm::real const hb_norm =
00200 hb_coeff / cvm::real (hb.size());
00201
00202 for (size_t i = 0; i < hb.size(); i++) {
00203 (hb[i])->apply_force (0.5 * hb_norm * force.real_value);
00204 }
00205 }
00206 }
00207
00208
00210
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 colvar::dihedPC::dihedPC (std::string const &conf)
00222 : cvc (conf)
00223 {
00224 if (cvm::debug())
00225 cvm::log ("Initializing dihedral PC object.\n");
00226
00227 function_type = "dihedPC";
00228 x.type (colvarvalue::type_scalar);
00229
00230 std::string segment_id;
00231 get_keyval (conf, "psfSegID", segment_id, std::string ("MAIN"));
00232
00233 std::vector<int> residues;
00234 {
00235 std::string residues_conf = "";
00236 key_lookup (conf, "residueRange", residues_conf);
00237 if (residues_conf.size()) {
00238 std::istringstream is (residues_conf);
00239 int initial, final;
00240 char dash;
00241 if ( (is >> initial) && (initial > 0) &&
00242 (is >> dash) && (dash == '-') &&
00243 (is >> final) && (final > 0) ) {
00244 for (int rnum = initial; rnum <= final; rnum++) {
00245 residues.push_back (rnum);
00246 }
00247 }
00248 } else {
00249 cvm::fatal_error ("Error: no residues defined in \"residueRange\".\n");
00250 }
00251 }
00252
00253 if (residues.size() < 2) {
00254 cvm::fatal_error ("Error: dihedralPC requires at least two residues.\n");
00255 }
00256
00257 std::string const &sid = segment_id;
00258 std::vector<int> const &r = residues;
00259
00260 std::string vecFileName;
00261 int vecNumber;
00262 if (get_keyval (conf, "vectorFile", vecFileName, vecFileName)) {
00263 get_keyval (conf, "vectorNumber", vecNumber, 0);
00264 if (vecNumber < 1)
00265 cvm::fatal_error ("A positive value of vectorNumber is required.");
00266
00267 std::ifstream vecFile;
00268 vecFile.open (vecFileName.c_str());
00269 if (!vecFile.good())
00270 cvm::fatal_error ("Error opening dihedral PCA vector file " + vecFileName + " for reading");
00271
00272
00273 bool eigenvectors_as_columns = true;
00274
00275 if (eigenvectors_as_columns) {
00276
00277 std::string line;
00278 cvm::real c;
00279 while (vecFile.good()) {
00280 getline(vecFile, line);
00281 if (line.length() < 2) break;
00282 std::istringstream ls (line);
00283 for (int i=0; i<vecNumber; i++) ls >> c;
00284 coeffs.push_back(c);
00285 }
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 vecFile.close();
00308
00309 } else {
00310 get_keyval (conf, "vector", coeffs, coeffs);
00311 }
00312
00313 if ( coeffs.size() != 4 * (residues.size() - 1)) {
00314 cvm::fatal_error ("Error: wrong number of coefficients: " +
00315 cvm::to_str(coeffs.size()) + ". Expected " +
00316 cvm::to_str(4 * (residues.size() - 1)) +
00317 " (4 coeffs per residue, minus one residue).\n");
00318 }
00319
00320 for (size_t i = 0; i < residues.size()-1; i++) {
00321
00322 theta.push_back (new colvar::dihedral (cvm::atom (r[i ], "N", sid),
00323 cvm::atom (r[i ], "CA", sid),
00324 cvm::atom (r[i ], "C", sid),
00325 cvm::atom (r[i+1], "N", sid)));
00326
00327 theta.push_back (new colvar::dihedral (cvm::atom (r[i ], "C", sid),
00328 cvm::atom (r[i+1], "N", sid),
00329 cvm::atom (r[i+1], "CA", sid),
00330 cvm::atom (r[i+1], "C", sid)));
00331 }
00332
00333 if (cvm::debug())
00334 cvm::log ("Done initializing dihedPC object.\n");
00335 }
00336
00337
00338 colvar::dihedPC::dihedPC()
00339 : cvc ()
00340 {
00341 function_type = "dihedPC";
00342 x.type (colvarvalue::type_scalar);
00343 }
00344
00345
00346 colvar::dihedPC::~dihedPC()
00347 {
00348 while (theta.size() != 0) {
00349 delete theta.back();
00350 theta.pop_back();
00351 }
00352 }
00353
00354
00355 void colvar::dihedPC::calc_value()
00356 {
00357 x.real_value = 0.0;
00358 for (size_t i = 0; i < theta.size(); i++) {
00359 theta[i]->calc_value();
00360 cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
00361 x.real_value += coeffs[2*i ] * std::cos(t)
00362 + coeffs[2*i+1] * std::sin(t);
00363 }
00364 }
00365
00366
00367 void colvar::dihedPC::calc_gradients()
00368 {
00369 for (size_t i = 0; i < theta.size(); i++) {
00370 theta[i]->calc_gradients();
00371 }
00372 }
00373
00374
00375 void colvar::dihedPC::apply_force (colvarvalue const &force)
00376 {
00377 for (size_t i = 0; i < theta.size(); i++) {
00378 cvm::real const t = (PI / 180.) * theta[i]->value().real_value;
00379 cvm::real const dcosdt = - (PI / 180.) * std::sin(t);
00380 cvm::real const dsindt = (PI / 180.) * std::cos(t);
00381
00382 theta[i]->apply_force((coeffs[2*i ] * dcosdt +
00383 coeffs[2*i+1] * dsindt) * force);
00384 }
00385 }