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

colvarcomp.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 "colvar.h"
00015 #include "colvarcomp.h"
00016 
00017 
00018 
00019 colvar::cvc::cvc()
00020 {
00021   description = "uninitialized colvar component";
00022   b_try_scalable = true;
00023   sup_coeff = 1.0;
00024   sup_np = 1;
00025   period = 0.0;
00026   wrap_center = 0.0;
00027   width = 0.0;
00028   cvc::init_dependencies();
00029 }
00030 
00031 
00032 colvar::cvc::cvc(std::string const &conf)
00033 {
00034   description = "uninitialized colvar component";
00035   b_try_scalable = true;
00036   sup_coeff = 1.0;
00037   sup_np = 1;
00038   period = 0.0;
00039   wrap_center = 0.0;
00040   width = 0.0;
00041   init_dependencies();
00042   colvar::cvc::init(conf);
00043 }
00044 
00045 
00046 int colvar::cvc::set_function_type(std::string const &type)
00047 {
00048   function_type = type;
00049   if (function_types.size() == 0) {
00050     function_types.push_back(function_type);
00051   } else {
00052     if (function_types.back() != function_type) {
00053       function_types.push_back(function_type);
00054     }
00055   }
00056   for (size_t i = function_types.size()-1; i > 0; i--) {
00057     cvm::main()->cite_feature(function_types[i]+" colvar component"+
00058                               " (derived from "+function_types[i-1]+")");
00059   }
00060   cvm::main()->cite_feature(function_types[0]+" colvar component");
00061   return COLVARS_OK;
00062 }
00063 
00064 
00065 int colvar::cvc::init(std::string const &conf)
00066 {
00067   if (cvm::debug())
00068     cvm::log("Initializing cvc base object.\n");
00069 
00070   std::string const old_name(name);
00071 
00072   if (name.size() > 0) {
00073     cvm::log("Updating configuration for component \""+name+"\"\n");
00074   }
00075 
00076   if (get_keyval(conf, "name", name, name)) {
00077     if (name.size() > 0) {
00078       description = "cvc \"" + name + "\" of type " + function_type;
00079     } else {
00080       description = "unnamed cvc";
00081     }
00082     if ((name != old_name) && (old_name.size() > 0)) {
00083       cvm::error("Error: cannot rename component \""+old_name+
00084                  "\" after initialization (new name = \""+name+"\")",
00085                  COLVARS_INPUT_ERROR);
00086       name = old_name;
00087     }
00088   }
00089 
00090   get_keyval(conf, "componentCoeff", sup_coeff, sup_coeff);
00091   get_keyval(conf, "componentExp", sup_np, sup_np);
00092   if (sup_coeff != 1.0 || sup_np != 1) {
00093     cvm::main()->cite_feature("Linear and polynomial combination of colvar components");
00094   }
00095   // TODO these could be condensed into get_keyval()
00096   register_param("componentCoeff", reinterpret_cast<void *>(&sup_coeff));
00097   register_param("componentExp", reinterpret_cast<void *>(&sup_np));
00098 
00099   get_keyval(conf, "period", period, period);
00100   get_keyval(conf, "wrapAround", wrap_center, wrap_center);
00101   // TODO when init() is called after all constructors, check periodic flag
00102   register_param("period", reinterpret_cast<void *>(&period));
00103   register_param("wrapAround", reinterpret_cast<void *>(&wrap_center));
00104 
00105   get_keyval_feature(this, conf, "debugGradients",
00106                      f_cvc_debug_gradient, false, parse_silent);
00107 
00108   bool b_no_PBC = !is_enabled(f_cvc_pbc_minimum_image); // Enabled by default
00109   get_keyval(conf, "forceNoPBC", b_no_PBC, b_no_PBC);
00110   if (b_no_PBC) {
00111     disable(f_cvc_pbc_minimum_image);
00112   } else {
00113     enable(f_cvc_pbc_minimum_image);
00114   }
00115 
00116   // Attempt scalable calculations when in parallel? (By default yes, if available)
00117   get_keyval(conf, "scalable", b_try_scalable, b_try_scalable);
00118 
00119   if (cvm::debug())
00120     cvm::log("Done initializing cvc base object.\n");
00121 
00122   return cvm::get_error();
00123 }
00124 
00125 
00126 int colvar::cvc::init_total_force_params(std::string const &conf)
00127 {
00128   if (cvm::get_error()) return COLVARS_ERROR;
00129 
00130   if (get_keyval_feature(this, conf, "oneSiteSystemForce",
00131                          f_cvc_one_site_total_force, is_enabled(f_cvc_one_site_total_force))) {
00132     cvm::log("Warning: keyword \"oneSiteSystemForce\" is deprecated: "
00133              "please use \"oneSiteTotalForce\" instead.\n");
00134   }
00135   if (get_keyval_feature(this, conf, "oneSiteTotalForce",
00136                          f_cvc_one_site_total_force, is_enabled(f_cvc_one_site_total_force))) {
00137     cvm::log("Computing total force on group 1 only\n");
00138   }
00139 
00140   if (! is_enabled(f_cvc_one_site_total_force)) {
00141     // check whether any of the other atom groups is dummy
00142     std::vector<cvm::atom_group *>::iterator agi = atom_groups.begin();
00143     agi++;
00144     for ( ; agi != atom_groups.end(); agi++) {
00145       if ((*agi)->b_dummy) {
00146         provide(f_cvc_inv_gradient, false);
00147         provide(f_cvc_Jacobian, false);
00148       }
00149     }
00150   }
00151 
00152   return COLVARS_OK;
00153 }
00154 
00155 
00156 cvm::atom_group *colvar::cvc::parse_group(std::string const &conf,
00157                                           char const *group_key,
00158                                           bool optional)
00159 {
00160   cvm::atom_group *group = NULL;
00161   std::string group_conf;
00162 
00163   if (key_lookup(conf, group_key, &group_conf)) {
00164     group = new cvm::atom_group(group_key);
00165 
00166     if (b_try_scalable) {
00167       if (is_available(f_cvc_scalable_com)
00168           && is_enabled(f_cvc_com_based)
00169           && !is_enabled(f_cvc_debug_gradient)) {
00170         disable(f_cvc_explicit_gradient);
00171         enable(f_cvc_scalable_com);
00172         // The CVC makes the feature available;
00173         // the atom group will enable it unless it needs to compute a rotational fit
00174         group->provide(f_ag_scalable_com);
00175       }
00176 
00177       // TODO check for other types of parallelism here
00178     }
00179 
00180     if (group_conf.size() == 0) {
00181       cvm::error("Error: atom group \""+group->key+
00182                  "\" is set, but has no definition.\n",
00183                  COLVARS_INPUT_ERROR);
00184       return group;
00185     }
00186 
00187     cvm::increase_depth();
00188     if (group->parse(group_conf) == COLVARS_OK) {
00189       register_atom_group(group);
00190     }
00191     group->check_keywords(group_conf, group_key);
00192     if (cvm::get_error()) {
00193       cvm::error("Error parsing definition for atom group \""+
00194                  std::string(group_key)+"\".", COLVARS_INPUT_ERROR);
00195     }
00196     cvm::decrease_depth();
00197 
00198   } else {
00199     if (! optional) {
00200       cvm::error("Error: definition for atom group \""+
00201                  std::string(group_key)+"\" not found.\n");
00202     }
00203   }
00204 
00205   return group;
00206 }
00207 
00208 
00209 int colvar::cvc::init_dependencies() {
00210   size_t i;
00211   // Initialize static array once and for all
00212   if (features().size() == 0) {
00213     for (i = 0; i < colvardeps::f_cvc_ntot; i++) {
00214       modify_features().push_back(new feature);
00215     }
00216 
00217     init_feature(f_cvc_active, "active", f_type_dynamic);
00218 //     The dependency below may become useful if we use dynamic atom groups
00219 //     require_feature_children(f_cvc_active, f_ag_active);
00220 
00221     init_feature(f_cvc_scalar, "scalar", f_type_static);
00222 
00223     init_feature(f_cvc_periodic, "periodic", f_type_static);
00224 
00225     init_feature(f_cvc_width, "defined_width", f_type_static);
00226 
00227     init_feature(f_cvc_lower_boundary, "defined_lower_boundary", f_type_static);
00228 
00229     init_feature(f_cvc_upper_boundary, "defined_upper_boundary", f_type_static);
00230 
00231     init_feature(f_cvc_gradient, "gradient", f_type_dynamic);
00232 
00233     init_feature(f_cvc_explicit_gradient, "explicit_gradient", f_type_static);
00234     require_feature_children(f_cvc_explicit_gradient, f_ag_explicit_gradient);
00235 
00236     init_feature(f_cvc_inv_gradient, "inverse_gradient", f_type_dynamic);
00237     require_feature_self(f_cvc_inv_gradient, f_cvc_gradient);
00238 
00239     init_feature(f_cvc_debug_gradient, "debug_gradient", f_type_user);
00240     require_feature_self(f_cvc_debug_gradient, f_cvc_gradient);
00241     require_feature_self(f_cvc_debug_gradient, f_cvc_explicit_gradient);
00242 
00243     init_feature(f_cvc_Jacobian, "Jacobian_derivative", f_type_dynamic);
00244     require_feature_self(f_cvc_Jacobian, f_cvc_inv_gradient);
00245 
00246     // Compute total force on first site only to avoid unwanted
00247     // coupling to other colvars (see e.g. Ciccotti et al., 2005)
00248     init_feature(f_cvc_one_site_total_force, "total_force_from_one_group", f_type_user);
00249     require_feature_self(f_cvc_one_site_total_force, f_cvc_com_based);
00250 
00251     init_feature(f_cvc_com_based, "function_of_centers_of_mass", f_type_static);
00252 
00253     init_feature(f_cvc_pbc_minimum_image, "use_minimum-image_with_PBCs", f_type_user);
00254 
00255     init_feature(f_cvc_scalable, "scalable_calculation", f_type_dynamic);
00256     require_feature_self(f_cvc_scalable_com, f_cvc_scalable);
00257     // CVC cannot compute atom-level gradients on rank 0 if colvar computation is distributed
00258     exclude_feature_self(f_cvc_scalable, f_cvc_explicit_gradient);
00259 
00260     init_feature(f_cvc_scalable_com, "scalable_calculation_of_centers_of_mass", f_type_static);
00261     require_feature_self(f_cvc_scalable_com, f_cvc_com_based);
00262     // CVC cannot compute atom-level gradients if computed on atom group COM
00263     exclude_feature_self(f_cvc_scalable_com, f_cvc_explicit_gradient);
00264 
00265     init_feature(f_cvc_collect_atom_ids, "collect_atom_ids", f_type_dynamic);
00266     require_feature_children(f_cvc_collect_atom_ids, f_ag_collect_atom_ids);
00267 
00268     // TODO only enable this when f_ag_scalable can be turned on for a pre-initialized group
00269     // require_feature_children(f_cvc_scalable, f_ag_scalable);
00270     // require_feature_children(f_cvc_scalable_com, f_ag_scalable_com);
00271 
00272     // check that everything is initialized
00273     for (i = 0; i < colvardeps::f_cvc_ntot; i++) {
00274       if (is_not_set(i)) {
00275         cvm::error("Uninitialized feature " + cvm::to_str(i) + " in " + description);
00276       }
00277     }
00278   }
00279 
00280   // Initialize feature_states for each instance
00281   // default as available, not enabled
00282   // except dynamic features which default as unavailable
00283   feature_states.reserve(f_cvc_ntot);
00284   for (i = 0; i < colvardeps::f_cvc_ntot; i++) {
00285     bool avail = is_dynamic(i) ? false : true;
00286     feature_states.push_back(feature_state(avail, false));
00287   }
00288 
00289   // Features that are implemented by all cvcs by default
00290   // Each cvc specifies what other features are available
00291   feature_states[f_cvc_active].available = true;
00292   feature_states[f_cvc_gradient].available = true;
00293   feature_states[f_cvc_collect_atom_ids].available = true;
00294 
00295   // CVCs are enabled from the start - get disabled based on flags
00296   enable(f_cvc_active);
00297 
00298   // Explicit gradients are implemented in most CVCs. Exceptions must be specified explicitly.
00299   enable(f_cvc_explicit_gradient);
00300 
00301   // Use minimum-image distances by default
00302   enable(f_cvc_pbc_minimum_image);
00303 
00304   // Features that are implemented by default if their requirements are
00305   feature_states[f_cvc_one_site_total_force].available = true;
00306 
00307   // Features That are implemented only for certain simulation engine configurations
00308   feature_states[f_cvc_scalable_com].available = (cvm::proxy->scalable_group_coms() == COLVARS_OK);
00309   feature_states[f_cvc_scalable].available = feature_states[f_cvc_scalable_com].available;
00310 
00311   return COLVARS_OK;
00312 }
00313 
00314 
00315 int colvar::cvc::setup()
00316 {
00317   description = "cvc " + name;
00318   return COLVARS_OK;
00319 }
00320 
00321 
00322 colvar::cvc::~cvc()
00323 {
00324   free_children_deps();
00325   remove_all_children();
00326   for (size_t i = 0; i < atom_groups.size(); i++) {
00327     if (atom_groups[i] != NULL) delete atom_groups[i];
00328   }
00329 }
00330 
00331 
00332 void colvar::cvc::init_as_distance()
00333 {
00334   x.type(colvarvalue::type_scalar);
00335   enable(f_cvc_lower_boundary);
00336   lower_boundary.type(colvarvalue::type_scalar);
00337   lower_boundary.real_value = 0.0;
00338   register_param("lowerBoundary", reinterpret_cast<void *>(&lower_boundary));
00339 }
00340 
00341 
00342 void colvar::cvc::init_as_angle()
00343 {
00344   x.type(colvarvalue::type_scalar);
00345   init_scalar_boundaries(0.0, 180.0);
00346 }
00347 
00348 
00349 void colvar::cvc::init_as_periodic_angle()
00350 {
00351   x.type(colvarvalue::type_scalar);
00352   enable(f_cvc_periodic);
00353   period = 360.0;
00354   init_scalar_boundaries(-180.0, 180.0);
00355 }
00356 
00357 
00358 void colvar::cvc::init_scalar_boundaries(cvm::real lb, cvm::real ub)
00359 {
00360   enable(f_cvc_lower_boundary);
00361   lower_boundary.type(colvarvalue::type_scalar);
00362   lower_boundary.real_value = lb;
00363   enable(f_cvc_upper_boundary);
00364   upper_boundary.type(colvarvalue::type_scalar);
00365   upper_boundary.real_value = ub;
00366   register_param("lowerBoundary", reinterpret_cast<void *>(&lower_boundary));
00367   register_param("upperBoundary", reinterpret_cast<void *>(&upper_boundary));
00368 }
00369 
00370 
00371 void colvar::cvc::register_atom_group(cvm::atom_group *ag)
00372 {
00373   atom_groups.push_back(ag);
00374   add_child(ag);
00375 }
00376 
00377 
00378 colvarvalue const *colvar::cvc::get_param_grad(std::string const &param_name)
00379 {
00380   colvarvalue const *ptr =
00381     reinterpret_cast<colvarvalue const *>(get_param_grad_ptr(param_name));
00382   return ptr != NULL ? ptr : NULL;
00383 }
00384 
00385 
00386 int colvar::cvc::set_param(std::string const &param_name,
00387                            void const *new_value)
00388 {
00389   if (param_map.count(param_name) > 0) {
00390 
00391     // TODO When we can use C++11, make this a proper function map
00392     if (param_name.compare("componentCoeff") == 0) {
00393       sup_coeff = *(reinterpret_cast<cvm::real const *>(new_value));
00394     }
00395     if (param_name.compare("componentExp") == 0) {
00396       sup_np = *(reinterpret_cast<int const *>(new_value));
00397     }
00398     if (is_enabled(f_cvc_periodic)) {
00399       if (param_name.compare("period") == 0) {
00400         period = *(reinterpret_cast<cvm::real const *>(new_value));
00401       }
00402       if (param_name.compare("wrapAround") == 0) {
00403         wrap_center = *(reinterpret_cast<cvm::real const *>(new_value));
00404       }
00405     }
00406   }
00407 
00408   return colvarparams::set_param(param_name, new_value);
00409 }
00410 
00411 
00412 void colvar::cvc::read_data()
00413 {
00414   size_t ig;
00415   for (ig = 0; ig < atom_groups.size(); ig++) {
00416     cvm::atom_group &atoms = *(atom_groups[ig]);
00417     atoms.reset_atoms_data();
00418     atoms.read_positions();
00419     atoms.calc_required_properties();
00420     // each atom group will take care of its own fitting_group, if defined
00421   }
00422 
00424 //   if (tasks[task_output_velocity] && !tasks[task_fdiff_velocity]) {
00425 //     for (i = 0; i < cvcs.size(); i++) {
00426 //       for (ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
00427 //         cvcs[i]->atom_groups[ig]->read_velocities();
00428 //       }
00429 //     }
00430 //   }
00431 }
00432 
00433 
00434 std::vector<std::vector<int> > colvar::cvc::get_atom_lists()
00435 {
00436   std::vector<std::vector<int> > lists;
00437 
00438   std::vector<cvm::atom_group *>::iterator agi = atom_groups.begin();
00439   for ( ; agi != atom_groups.end(); ++agi) {
00440     (*agi)->create_sorted_ids();
00441     lists.push_back((*agi)->sorted_ids());
00442     if ((*agi)->is_enabled(f_ag_fitting_group) && (*agi)->is_enabled(f_ag_fit_gradients)) {
00443       cvm::atom_group &fg = *((*agi)->fitting_group);
00444       fg.create_sorted_ids();
00445       lists.push_back(fg.sorted_ids());
00446     }
00447   }
00448   return lists;
00449 }
00450 
00451 
00452 void colvar::cvc::collect_gradients(std::vector<int> const &atom_ids, std::vector<cvm::rvector> &atomic_gradients)
00453 {
00454   // Coefficient: d(a * x^n) = a * n * x^(n-1) * dx
00455   cvm::real coeff = sup_coeff * cvm::real(sup_np) *
00456     cvm::integer_power(value().real_value, sup_np-1);
00457 
00458   for (size_t j = 0; j < atom_groups.size(); j++) {
00459 
00460     cvm::atom_group &ag = *(atom_groups[j]);
00461 
00462     // If necessary, apply inverse rotation to get atomic
00463     // gradient in the laboratory frame
00464     if (ag.is_enabled(f_ag_rotate)) {
00465       cvm::rotation const rot_inv = ag.rot.inverse();
00466 
00467       for (size_t k = 0; k < ag.size(); k++) {
00468         size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
00469                                     ag[k].id) - atom_ids.begin();
00470         atomic_gradients[a] += coeff * rot_inv.rotate(ag[k].grad);
00471       }
00472 
00473     } else {
00474 
00475       for (size_t k = 0; k < ag.size(); k++) {
00476         size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
00477                                     ag[k].id) - atom_ids.begin();
00478         atomic_gradients[a] += coeff * ag[k].grad;
00479       }
00480     }
00481     if (ag.is_enabled(f_ag_fitting_group) && ag.is_enabled(f_ag_fit_gradients)) {
00482       cvm::atom_group const &fg = *(ag.fitting_group);
00483       for (size_t k = 0; k < fg.size(); k++) {
00484         size_t a = std::lower_bound(atom_ids.begin(), atom_ids.end(),
00485                                     fg[k].id) - atom_ids.begin();
00486         // fit gradients are in the unrotated (simulation) frame
00487         atomic_gradients[a] += coeff * fg.fit_gradients[k];
00488       }
00489     }
00490   }
00491 }
00492 
00493 
00494 void colvar::cvc::calc_force_invgrads()
00495 {
00496   cvm::error("Error: calculation of inverse gradients is not implemented "
00497              "for colvar components of type \""+function_type+"\".\n",
00498              COLVARS_NOT_IMPLEMENTED);
00499 }
00500 
00501 
00502 void colvar::cvc::calc_Jacobian_derivative()
00503 {
00504   cvm::error("Error: calculation of inverse gradients is not implemented "
00505              "for colvar components of type \""+function_type+"\".\n",
00506              COLVARS_NOT_IMPLEMENTED);
00507 }
00508 
00509 
00510 void colvar::cvc::calc_fit_gradients()
00511 {
00512   for (size_t ig = 0; ig < atom_groups.size(); ig++) {
00513     atom_groups[ig]->calc_fit_gradients();
00514   }
00515 }
00516 
00517 
00518 void colvar::cvc::debug_gradients()
00519 {
00520   // this function should work for any scalar cvc:
00521   // the only difference will be the name of the atom group (here, "group")
00522   // NOTE: this assumes that groups for this cvc are non-overlapping,
00523   // since atom coordinates are modified only within the current group
00524 
00525   cvm::log("Debugging gradients for " + description);
00526 
00527   for (size_t ig = 0; ig < atom_groups.size(); ig++) {
00528     cvm::atom_group *group = atom_groups[ig];
00529     if (group->b_dummy) continue;
00530 
00531     cvm::rotation const rot_0 = group->rot;
00532     cvm::rotation const rot_inv = group->rot.inverse();
00533 
00534     cvm::real x_0 = x.real_value;
00535     if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_0 = x[0];
00536 
00537     // cvm::log("gradients     = "+cvm::to_str (gradients)+"\n");
00538 
00539     cvm::atom_group *group_for_fit = group->fitting_group ? group->fitting_group : group;
00540     cvm::atom_pos fit_gradient_sum, gradient_sum;
00541 
00542     // print the values of the fit gradients
00543     if (group->is_enabled(f_ag_center) || group->is_enabled(f_ag_rotate)) {
00544       if (group->is_enabled(f_ag_fit_gradients)) {
00545         size_t j;
00546 
00547         // fit_gradients are in the simulation frame: we should print them in the rotated frame
00548         cvm::log("Fit gradients:\n");
00549         for (j = 0; j < group_for_fit->fit_gradients.size(); j++) {
00550           cvm::log((group->fitting_group ? std::string("refPosGroup") : group->key) +
00551                   "[" + cvm::to_str(j) + "] = " +
00552                   (group->is_enabled(f_ag_rotate) ?
00553                     cvm::to_str(rot_0.rotate(group_for_fit->fit_gradients[j])) :
00554                     cvm::to_str(group_for_fit->fit_gradients[j])));
00555         }
00556       }
00557     }
00558 
00559     // debug the gradients
00560     for (size_t ia = 0; ia < group->size(); ia++) {
00561 
00562       // tests are best conducted in the unrotated (simulation) frame
00563       cvm::rvector const atom_grad = (group->is_enabled(f_ag_rotate) ?
00564                                       rot_inv.rotate((*group)[ia].grad) :
00565                                       (*group)[ia].grad);
00566       gradient_sum += atom_grad;
00567 
00568       for (size_t id = 0; id < 3; id++) {
00569         // (re)read original positions
00570         group->read_positions();
00571         // change one coordinate
00572         (*group)[ia].pos[id] += cvm::debug_gradients_step_size;
00573         group->calc_required_properties();
00574         calc_value();
00575         cvm::real x_1 = x.real_value;
00576         if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_1 = x[0];
00577         cvm::log("Atom "+cvm::to_str(ia)+", component "+cvm::to_str(id)+":\n");
00578         cvm::log("dx(actual) = "+cvm::to_str(x_1 - x_0,
00579                               21, 14)+"\n");
00580         cvm::real const dx_pred = (group->fit_gradients.size()) ?
00581           (cvm::debug_gradients_step_size * (atom_grad[id] + group->fit_gradients[ia][id])) :
00582           (cvm::debug_gradients_step_size * atom_grad[id]);
00583         cvm::log("dx(interp) = "+cvm::to_str(dx_pred,
00584                               21, 14)+"\n");
00585         cvm::log("|dx(actual) - dx(interp)|/|dx(actual)| = "+
00586                   cvm::to_str(cvm::fabs(x_1 - x_0 - dx_pred) /
00587                               cvm::fabs(x_1 - x_0), 12, 5)+"\n");
00588       }
00589     }
00590 
00591     if ((group->is_enabled(f_ag_fit_gradients)) && (group->fitting_group != NULL)) {
00592       cvm::atom_group *ref_group = group->fitting_group;
00593       group->read_positions();
00594       group->calc_required_properties();
00595 
00596       for (size_t ia = 0; ia < ref_group->size(); ia++) {
00597 
00598         // fit gradients are in the unrotated (simulation) frame
00599         cvm::rvector const atom_grad = ref_group->fit_gradients[ia];
00600         fit_gradient_sum += atom_grad;
00601 
00602         for (size_t id = 0; id < 3; id++) {
00603           // (re)read original positions
00604           group->read_positions();
00605           ref_group->read_positions();
00606           // change one coordinate
00607           (*ref_group)[ia].pos[id] += cvm::debug_gradients_step_size;
00608           group->calc_required_properties();
00609           calc_value();
00610 
00611           cvm::real const x_1 = x.real_value;
00612           cvm::log("refPosGroup atom "+cvm::to_str(ia)+", component "+cvm::to_str (id)+":\n");
00613           cvm::log("dx(actual) = "+cvm::to_str (x_1 - x_0,
00614                                 21, 14)+"\n");
00615 
00616           cvm::real const dx_pred = cvm::debug_gradients_step_size * atom_grad[id];
00617 
00618           cvm::log("dx(interp) = "+cvm::to_str (dx_pred,
00619                                 21, 14)+"\n");
00620           cvm::log ("|dx(actual) - dx(interp)|/|dx(actual)| = "+
00621                     cvm::to_str(cvm::fabs (x_1 - x_0 - dx_pred) /
00622                                 cvm::fabs (x_1 - x_0),
00623                                 12, 5)+
00624                     ".\n");
00625         }
00626       }
00627     }
00628 
00629     cvm::log("Gradient sum: " +  cvm::to_str(gradient_sum) +
00630           "  Fit gradient sum: " + cvm::to_str(fit_gradient_sum) +
00631           "  Total " + cvm::to_str(gradient_sum + fit_gradient_sum));
00632   }
00633   return;
00634 }
00635 
00636 
00637 cvm::real colvar::cvc::dist2(colvarvalue const &x1,
00638                              colvarvalue const &x2) const
00639 {
00640   return x1.dist2(x2);
00641 }
00642 
00643 
00644 colvarvalue colvar::cvc::dist2_lgrad(colvarvalue const &x1,
00645                                      colvarvalue const &x2) const
00646 {
00647   return x1.dist2_grad(x2);
00648 }
00649 
00650 
00651 colvarvalue colvar::cvc::dist2_rgrad(colvarvalue const &x1,
00652                                      colvarvalue const &x2) const
00653 {
00654   return x2.dist2_grad(x1);
00655 }
00656 
00657 
00658 void colvar::cvc::wrap(colvarvalue & /* x_unwrapped */) const
00659 {
00660   return;
00661 }
00662 
00663 
00664 
00665 // Static members
00666 
00667 std::vector<colvardeps::feature *> colvar::cvc::cvc_features;

Generated on Thu Apr 25 02:42:13 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002