From 2fcd26f6c41bc6637ab5f5a8f9a4408135d29daf Mon Sep 17 00:00:00 2001 From: sjplimp Date: Fri, 17 Jun 2016 23:07:51 +0000 Subject: [PATCH] git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@15200 f3b2605a-c512-4ea7-a41b-209d697bcdaa --- lib/colvars/colvar.cpp | 368 ++++++++++-------- lib/colvars/colvar.h | 15 +- lib/colvars/colvaratoms.cpp | 72 ++-- lib/colvars/colvaratoms.h | 8 +- lib/colvars/colvarbias.cpp | 2 +- lib/colvars/colvarbias.h | 2 +- lib/colvars/colvarbias_abf.cpp | 16 +- lib/colvars/colvarbias_histogram.cpp | 2 +- lib/colvars/colvarbias_meta.cpp | 10 +- lib/colvars/colvarbias_meta.h | 2 +- lib/colvars/colvarbias_restraint.cpp | 2 +- lib/colvars/colvarbias_restraint.h | 2 +- lib/colvars/colvarcomp.cpp | 17 +- lib/colvars/colvarcomp.h | 21 +- lib/colvars/colvarcomp_angles.cpp | 2 +- lib/colvars/colvarcomp_coordnums.cpp | 41 +- lib/colvars/colvarcomp_distances.cpp | 18 +- lib/colvars/colvarcomp_protein.cpp | 2 +- lib/colvars/colvarcomp_rotations.cpp | 2 +- lib/colvars/colvardeps.cpp | 16 +- lib/colvars/colvardeps.h | 4 +- lib/colvars/colvargrid.cpp | 2 +- lib/colvars/colvargrid.h | 2 +- lib/colvars/colvarmodule.cpp | 2 +- lib/colvars/colvarmodule.h | 7 +- lib/colvars/colvarparse.cpp | 560 ++++++++++++++++----------- lib/colvars/colvarparse.h | 156 ++++++-- lib/colvars/colvarproxy.h | 2 +- lib/colvars/colvarscript.cpp | 5 + lib/colvars/colvarscript.h | 2 +- lib/colvars/colvartypes.h | 2 +- lib/colvars/colvarvalue.cpp | 2 +- lib/colvars/colvarvalue.h | 2 +- 33 files changed, 824 insertions(+), 544 deletions(-) diff --git a/lib/colvars/colvar.cpp b/lib/colvars/colvar.cpp index 761855f52d..eec49d1fad 100644 --- a/lib/colvars/colvar.cpp +++ b/lib/colvars/colvar.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvarvalue.h" @@ -19,11 +19,11 @@ bool compare(colvar::cvc *i, colvar::cvc *j) { colvar::colvar(std::string const &conf) : colvarparse(conf) { - size_t i; cvm::log("Initializing a new collective variable.\n"); + int error_code = COLVARS_OK; get_keyval(conf, "name", this->name, - (std::string("colvar")+cvm::to_str(cvm::colvars.size()+1))); + (std::string("colvar")+cvm::to_str(cvm::colvars.size()+1))); if (cvm::colvar_by_name(this->name) != NULL) { cvm::error("Error: this colvar cannot have the same name, \""+this->name+ @@ -43,141 +43,9 @@ colvar::colvar(std::string const &conf) kinetic_energy = 0.0; potential_energy = 0.0; - // read the configuration and set up corresponding instances, for - // each type of component implemented -#define initialize_components(def_desc,def_config_key,def_class_name) \ - { \ - size_t def_count = 0; \ - std::string def_conf = ""; \ - size_t pos = 0; \ - while ( this->key_lookup(conf, \ - def_config_key, \ - def_conf, \ - pos) ) { \ - if (!def_conf.size()) continue; \ - cvm::log("Initializing " \ - "a new \""+std::string(def_config_key)+"\" component"+ \ - (cvm::debug() ? ", with configuration:\n"+def_conf \ - : ".\n")); \ - cvm::increase_depth(); \ - cvc *cvcp = new colvar::def_class_name(def_conf); \ - if (cvcp != NULL) { \ - cvcs.push_back(cvcp); \ - cvcp->check_keywords(def_conf, def_config_key); \ - if (cvm::get_error()) { \ - cvm::error("Error: in setting up component \"" \ - def_config_key"\".\n"); \ - return; \ - } \ - cvm::decrease_depth(); \ - } else { \ - cvm::error("Error: in allocating component \"" \ - def_config_key"\".\n", \ - MEMORY_ERROR); \ - return; \ - } \ - if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) { \ - if ( (cvcp->function_type != std::string("distance_z")) && \ - (cvcp->function_type != std::string("dihedral")) && \ - (cvcp->function_type != std::string("spin_angle")) ) { \ - cvm::error("Error: invalid use of period and/or " \ - "wrapAround in a \""+ \ - std::string(def_config_key)+ \ - "\" component.\n"+ \ - "Period: "+cvm::to_str(cvcp->period) + \ - " wrapAround: "+cvm::to_str(cvcp->wrap_center), \ - INPUT_ERROR); \ - return; \ - } \ - } \ - if ( ! cvcs.back()->name.size()){ \ - std::ostringstream s; \ - s << def_config_key << std::setfill('0') << std::setw(4) << ++def_count;\ - cvcs.back()->name = s.str(); \ - /* pad cvc number for correct ordering when sorting by name */\ - } \ - cvcs.back()->setup(); \ - if (cvm::debug()) \ - cvm::log("Done initializing a \""+ \ - std::string(def_config_key)+ \ - "\" component"+ \ - (cvm::debug() ? \ - ", named \""+cvcs.back()->name+"\"" \ - : "")+".\n"); \ - def_conf = ""; \ - if (cvm::debug()) \ - cvm::log("Parsed "+cvm::to_str(cvcs.size())+ \ - " components at this time.\n"); \ - } \ - } + cvm::combine_errors(error_code, init_components(conf)); - - initialize_components("distance", "distance", distance); - initialize_components("distance vector", "distanceVec", distance_vec); - initialize_components("Cartesian coordinates", "cartesian", cartesian); - initialize_components("distance vector " - "direction", "distanceDir", distance_dir); - initialize_components("distance projection " - "on an axis", "distanceZ", distance_z); - initialize_components("distance projection " - "on a plane", "distanceXY", distance_xy); - initialize_components("average distance weighted by inverse power", - "distanceInv", distance_inv); - initialize_components("N1xN2-long vector of pairwise distances", - "distancePairs", distance_pairs); - - initialize_components("coordination " - "number", "coordNum", coordnum); - initialize_components("self-coordination " - "number", "selfCoordNum", selfcoordnum); - - initialize_components("angle", "angle", angle); - initialize_components("dipole angle", "dipoleAngle", dipole_angle); - initialize_components("dihedral", "dihedral", dihedral); - - initialize_components("hydrogen bond", "hBond", h_bond); - - // initialize_components ("alpha helix", "alphaDihedrals", alpha_dihedrals); - initialize_components("alpha helix", "alpha", alpha_angles); - - initialize_components("dihedral principal " - "component", "dihedralPC", dihedPC); - - initialize_components("orientation", "orientation", orientation); - initialize_components("orientation " - "angle", "orientationAngle",orientation_angle); - initialize_components("orientation " - "projection", "orientationProj",orientation_proj); - initialize_components("tilt", "tilt", tilt); - initialize_components("spin angle", "spinAngle", spin_angle); - - initialize_components("RMSD", "rmsd", rmsd); - - // initialize_components ("logarithm of MSD", "logmsd", logmsd); - - initialize_components("radius of " - "gyration", "gyration", gyration); - initialize_components("moment of " - "inertia", "inertia", inertia); - initialize_components("moment of inertia around an axis", - "inertiaZ", inertia_z); - initialize_components("eigenvector", "eigenvector", eigenvector); - - if (!cvcs.size()) { - cvm::error("Error: no valid components were provided " - "for this collective variable.\n", - INPUT_ERROR); - return; - } - - n_active_cvcs = cvcs.size(); - - cvm::log("All components initialized.\n"); - - // Store list of children cvcs for dependency checking purposes - for (i = 0; i < cvcs.size(); i++) { - add_child(cvcs[i]); - } + size_t i; // Setup colvar as scripted function of components if (get_keyval(conf, "scriptedFunction", scripted_function, @@ -540,6 +408,215 @@ colvar::colvar(std::string const &conf) } + + +// read the configuration and set up corresponding instances, for +// each type of component implemented +template int colvar::init_components_type(std::string const &conf, + char const *def_desc, + char const *def_config_key) +{ + size_t def_count = 0; + std::string def_conf = ""; + size_t pos = 0; + while ( this->key_lookup(conf, + def_config_key, + def_conf, + pos) ) { + if (!def_conf.size()) continue; + cvm::log("Initializing " + "a new \""+std::string(def_config_key)+"\" component"+ + (cvm::debug() ? ", with configuration:\n"+def_conf + : ".\n")); + cvm::increase_depth(); + cvc *cvcp = new def_class_name(def_conf); + if (cvcp != NULL) { + cvcs.push_back(cvcp); + cvcp->check_keywords(def_conf, def_config_key); + if (cvm::get_error()) { + cvm::error("Error: in setting up component \""+ + std::string(def_config_key)+"\".\n", INPUT_ERROR); + return INPUT_ERROR; + } + cvm::decrease_depth(); + } else { + cvm::error("Error: in allocating component \""+ + std::string(def_config_key)+"\".\n", + MEMORY_ERROR); + return MEMORY_ERROR; + } + + if ( (cvcp->period != 0.0) || (cvcp->wrap_center != 0.0) ) { + if ( (cvcp->function_type != std::string("distance_z")) && + (cvcp->function_type != std::string("dihedral")) && + (cvcp->function_type != std::string("spin_angle")) ) { + cvm::error("Error: invalid use of period and/or " + "wrapAround in a \""+ + std::string(def_config_key)+ + "\" component.\n"+ + "Period: "+cvm::to_str(cvcp->period) + + " wrapAround: "+cvm::to_str(cvcp->wrap_center), + INPUT_ERROR); + return INPUT_ERROR; + } + } + + if ( ! cvcs.back()->name.size()) { + std::ostringstream s; + s << def_config_key << std::setfill('0') << std::setw(4) << ++def_count; + cvcs.back()->name = s.str(); + /* pad cvc number for correct ordering when sorting by name */ + } + + cvcs.back()->setup(); + if (cvm::debug()) { + cvm::log("Done initializing a \""+ + std::string(def_config_key)+ + "\" component"+ + (cvm::debug() ? + ", named \""+cvcs.back()->name+"\"" + : "")+".\n"); + } + def_conf = ""; + if (cvm::debug()) { + cvm::log("Parsed "+cvm::to_str(cvcs.size())+ + " components at this time.\n"); + } + } + + return COLVARS_OK; +} + + +int colvar::init_components(std::string const &conf) +{ + int error_code = COLVARS_OK; + + cvm::combine_errors(error_code, + init_components_type(conf, + "distance", "distance")); + cvm::combine_errors(error_code, + init_components_type(conf, + "distance vector", "distanceVec")); + cvm::combine_errors(error_code, + init_components_type(conf, + "Cartesian coordinates", "cartesian")); + cvm::combine_errors(error_code, + init_components_type(conf, + "distance vector " + "direction", "distanceDir")); + cvm::combine_errors(error_code, + init_components_type(conf, + "distance projection " + "on an axis", "distanceZ")); + cvm::combine_errors(error_code, + init_components_type(conf, + "distance projection " + "on a plane", "distanceXY")); + cvm::combine_errors(error_code, + init_components_type(conf, + "average distance " + "weighted by inverse power", + "distanceInv")); + cvm::combine_errors(error_code, + init_components_type(conf, + "N1xN2-long vector " + "of pairwise distances", + "distancePairs")); + + cvm::combine_errors(error_code, + init_components_type(conf, + "coordination " + "number", "coordNum")); + cvm::combine_errors(error_code, + init_components_type(conf, + "self-coordination " + "number", "selfCoordNum")); + + cvm::combine_errors(error_code, + init_components_type(conf, + "angle", "angle")); + cvm::combine_errors(error_code, + init_components_type(conf, + "dipole angle", "dipoleAngle")); + cvm::combine_errors(error_code, + init_components_type(conf, + "dihedral", "dihedral")); + + cvm::combine_errors(error_code, + init_components_type(conf, + "hydrogen bond", "hBond")); + + // cvm::combine_errors(error_code, init_components_type(conf, "alpha helix", "alphaDihedrals")); + cvm::combine_errors(error_code, + init_components_type(conf, + "alpha helix", "alpha")); + + cvm::combine_errors(error_code, + init_components_type(conf, + "dihedral " + "principal component", "dihedralPC")); + + cvm::combine_errors(error_code, + init_components_type(conf, + "orientation", "orientation")); + cvm::combine_errors(error_code, + init_components_type(conf, + "orientation " + "angle", "orientationAngle")); + cvm::combine_errors(error_code, + init_components_type(conf, + "orientation " + "projection", "orientationProj")); + cvm::combine_errors(error_code, + init_components_type(conf, + "tilt", "tilt")); + cvm::combine_errors(error_code, + init_components_type(conf, + "spin angle", "spinAngle")); + + cvm::combine_errors(error_code, + init_components_type(conf, + "RMSD", "rmsd")); + + // cvm::combine_errors(error_code, init_components_type (conf,"logarithm of MSD", "logmsd")); + + cvm::combine_errors(error_code, + init_components_type(conf, + "radius of " + "gyration", "gyration")); + cvm::combine_errors(error_code, + init_components_type(conf, + "moment of " + "inertia", "inertia")); + cvm::combine_errors(error_code, + init_components_type(conf, + "moment of inertia around an axis", + "inertiaZ")); + cvm::combine_errors(error_code, + init_components_type(conf, + "eigenvector", "eigenvector")); + + if (!cvcs.size() || (error_code != COLVARS_OK)) { + cvm::error("Error: no valid components were provided " + "for this collective variable.\n", + INPUT_ERROR); + return INPUT_ERROR; + } + + n_active_cvcs = cvcs.size(); + + cvm::log("All components initialized.\n"); + + // Store list of children cvcs for dependency checking purposes + for (size_t i = 0; i < cvcs.size(); i++) { + add_child(cvcs[i]); + } + + return COLVARS_OK; +} + + int colvar::refresh_deps() { // If enabled features are changed upstream, the features below should be refreshed @@ -959,18 +1036,7 @@ int colvar::calc_cvc_sys_forces(int first_cvc, size_t num_cvcs) size_t const cvc_max_count = num_cvcs ? num_cvcs : num_active_cvcs(); size_t i, cvc_count; - if (is_enabled(f_cv_system_force) && !is_enabled(f_cv_extended_Lagrangian)) { - // If extended Lagrangian is enabled, system force calculation is trivial - // and done together with integration of the extended coordinate. - - if (is_enabled(f_cv_scripted)) { - // TODO see if this could reasonably be done in a generic way - // from generic inverse gradients - cvm::error("System force is not implemented for " - "scripted colvars.", COLVARS_NOT_IMPLEMENTED); - return COLVARS_NOT_IMPLEMENTED; - } - + if (is_enabled(f_cv_system_force_calc)) { if (cvm::debug()) cvm::log("Calculating system force of colvar \""+this->name+"\".\n"); @@ -1001,9 +1067,7 @@ int colvar::calc_cvc_sys_forces(int first_cvc, size_t num_cvcs) int colvar::collect_cvc_sys_forces() { - if (is_enabled(f_cv_system_force) && !is_enabled(f_cv_extended_Lagrangian)) { - // If extended Lagrangian is enabled, system force calculation is trivial - // and done together with integration of the extended coordinate. + if (is_enabled(f_cv_system_force_calc)) { ft.reset(); if (cvm::step_relative() > 0) { diff --git a/lib/colvars/colvar.h b/lib/colvars/colvar.h index 9e4b448a83..5f2fce35e0 100644 --- a/lib/colvars/colvar.h +++ b/lib/colvars/colvar.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVAR_H #define COLVAR_H @@ -220,7 +220,18 @@ public: /// Constructor colvar(std::string const &conf); - /// Get ready for a run and possibly re-initialize internal data + /// Parse the CVC configuration and allocate their data + int init_components(std::string const &conf); + +private: + /// Parse the CVC configuration for all components of a certain type + template int init_components_type(std::string const &conf, + char const *def_desc, + char const *def_config_key); + +public: + + /// Get ready for a run and re-initialize internal data if needed void setup(); /// Destructor diff --git a/lib/colvars/colvaratoms.cpp b/lib/colvars/colvaratoms.cpp index 7f11abd311..b77576e896 100644 --- a/lib/colvars/colvaratoms.cpp +++ b/lib/colvars/colvaratoms.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvarparse.h" @@ -96,9 +96,9 @@ cvm::atom_group::~atom_group() index = -1; } - if (ref_pos_group) { - delete ref_pos_group; - ref_pos_group = NULL; + if (fitting_group) { + delete fitting_group; + fitting_group = NULL; } } @@ -183,7 +183,7 @@ int cvm::atom_group::init() b_rotate = false; b_user_defined_fit = false; b_fit_gradients = false; - ref_pos_group = NULL; + fitting_group = NULL; noforce = false; @@ -598,23 +598,31 @@ int cvm::atom_group::parse_fitting_options(std::string const &group_conf) cvm::error("Error: centerReference or rotateReference " "cannot be defined for a dummy atom.\n"); + bool b_ref_pos_group = false; if (key_lookup(group_conf, "refPositionsGroup")) { + b_ref_pos_group = true; + cvm::log("Warning: keyword \"refPositionsGroup\" is deprecated: please use \"fittingGroup\" instead.\n"); + } + + if (b_ref_pos_group || key_lookup(group_conf, "fittingGroup")) { // instead of this group, define another group to compute the fit - if (ref_pos_group) { + if (fitting_group) { cvm::error("Error: the atom group \""+ key+"\" has already a reference group " "for the rototranslational fit, which was communicated by the " - "colvar component. You should not use refPositionsGroup " + "colvar component. You should not use fittingGroup " "in this case.\n"); } cvm::log("Within atom group \""+key+"\":\n"); - ref_pos_group = new atom_group(group_conf, "refPositionsGroup"); + fitting_group = b_ref_pos_group ? + new atom_group(group_conf, "refPositionsGroup") : + new atom_group(group_conf, "fittingGroup"); - // regardless of the configuration, fit gradients must be calculated by refPositionsGroup - ref_pos_group->b_fit_gradients = this->b_fit_gradients; + // regardless of the configuration, fit gradients must be calculated by fittingGroup + fitting_group->b_fit_gradients = this->b_fit_gradients; } - atom_group *group_for_fit = ref_pos_group ? ref_pos_group : this; + atom_group *group_for_fit = fitting_group ? fitting_group : this; get_keyval(group_conf, "refPositions", ref_pos, ref_pos); @@ -678,7 +686,7 @@ int cvm::atom_group::parse_fitting_options(std::string const &group_conf) "\" will be aligned to a fixed orientation given by the reference positions provided. " "If the internal structure of the group changes too much (i.e. its RMSD is comparable " "to its radius of gyration), the optimal rotation and its gradients may become discontinuous. " - "If that happens, use refPositionsGroup (or a different definition for it if already defined) " + "If that happens, use fittingGroup (or a different definition for it if already defined) " "to align the coordinates.\n"); // initialize rot member data rot.request_group1_gradients(group_for_fit->size()); @@ -741,8 +749,8 @@ void cvm::atom_group::read_positions() ai->read_position(); } - if (ref_pos_group) - ref_pos_group->read_positions(); + if (fitting_group) + fitting_group->read_positions(); } @@ -754,8 +762,8 @@ int cvm::atom_group::calc_required_properties() if (!is_enabled(f_ag_scalable)) { if (b_center || b_rotate) { - if (ref_pos_group) { - ref_pos_group->calc_center_of_geometry(); + if (fitting_group) { + fitting_group->calc_center_of_geometry(); } calc_apply_roto_translation(); @@ -763,8 +771,8 @@ int cvm::atom_group::calc_required_properties() // update COM and COG after fitting calc_center_of_geometry(); calc_center_of_mass(); - if (ref_pos_group) { - ref_pos_group->calc_center_of_geometry(); + if (fitting_group) { + fitting_group->calc_center_of_geometry(); } } } @@ -779,25 +787,25 @@ void cvm::atom_group::calc_apply_roto_translation() { // store the laborarory-frame COGs for when they are needed later cog_orig = this->center_of_geometry(); - if (ref_pos_group) { - ref_pos_group->cog_orig = ref_pos_group->center_of_geometry(); + if (fitting_group) { + fitting_group->cog_orig = fitting_group->center_of_geometry(); } if (b_center) { // center on the origin first - cvm::atom_pos const rpg_cog = ref_pos_group ? - ref_pos_group->center_of_geometry() : this->center_of_geometry(); + cvm::atom_pos const rpg_cog = fitting_group ? + fitting_group->center_of_geometry() : this->center_of_geometry(); apply_translation(-1.0 * rpg_cog); - if (ref_pos_group) { - ref_pos_group->apply_translation(-1.0 * rpg_cog); + if (fitting_group) { + fitting_group->apply_translation(-1.0 * rpg_cog); } } if (b_rotate) { // rotate the group (around the center of geometry if b_center is // true, around the origin otherwise) - rot.calc_optimal_rotation(ref_pos_group ? - ref_pos_group->positions() : + rot.calc_optimal_rotation(fitting_group ? + fitting_group->positions() : this->positions(), ref_pos); @@ -805,8 +813,8 @@ void cvm::atom_group::calc_apply_roto_translation() for (ai = this->begin(); ai != this->end(); ai++) { ai->pos = rot.rotate(ai->pos); } - if (ref_pos_group) { - for (ai = ref_pos_group->begin(); ai != ref_pos_group->end(); ai++) { + if (fitting_group) { + for (ai = fitting_group->begin(); ai != fitting_group->end(); ai++) { ai->pos = rot.rotate(ai->pos); } } @@ -815,8 +823,8 @@ void cvm::atom_group::calc_apply_roto_translation() if (b_center) { // align with the center of geometry of ref_pos apply_translation(ref_pos_cog); - if (ref_pos_group) { - ref_pos_group->apply_translation(ref_pos_cog); + if (fitting_group) { + fitting_group->apply_translation(ref_pos_cog); } } // update of COM and COG is done from the calling routine @@ -953,7 +961,7 @@ void cvm::atom_group::calc_fit_gradients() if (cvm::debug()) cvm::log("Calculating fit gradients.\n"); - atom_group *group_for_fit = ref_pos_group ? ref_pos_group : this; + atom_group *group_for_fit = fitting_group ? fitting_group : this; if (b_center) { // add the center of geometry contribution to the gradients @@ -1141,7 +1149,7 @@ void cvm::atom_group::apply_colvar_force(cvm::real const &force) if ((b_center || b_rotate) && b_fit_gradients) { - atom_group *group_for_fit = ref_pos_group ? ref_pos_group : this; + atom_group *group_for_fit = fitting_group ? fitting_group : this; // Fit gradients are already calculated in "laboratory" frame for (size_t j = 0; j < group_for_fit->size(); j++) { diff --git a/lib/colvars/colvaratoms.h b/lib/colvars/colvaratoms.h index ea346b1415..440afd57cb 100644 --- a/lib/colvars/colvaratoms.h +++ b/lib/colvars/colvaratoms.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARATOMS_H #define COLVARATOMS_H @@ -299,7 +299,7 @@ public: /// \brief If b_center or b_rotate is true, use this group to /// define the transformation (default: this group itself) - atom_group *ref_pos_group; + atom_group *fitting_group; /// Total mass of the atom group cvm::real total_mass; @@ -346,8 +346,8 @@ public: { for (cvm::atom_iter ai = atoms.begin(); ai != atoms.end(); ai++) ai->reset_data(); - if (ref_pos_group) - ref_pos_group->reset_atoms_data(); + if (fitting_group) + fitting_group->reset_atoms_data(); } /// \brief Recompute all mutable quantities that are required to compute CVCs diff --git a/lib/colvars/colvarbias.cpp b/lib/colvars/colvarbias.cpp index 94d74e47d4..93f227bd17 100644 --- a/lib/colvars/colvarbias.cpp +++ b/lib/colvars/colvarbias.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvarvalue.h" diff --git a/lib/colvars/colvarbias.h b/lib/colvars/colvarbias.h index 58688a47bf..12e50bceaa 100644 --- a/lib/colvars/colvarbias.h +++ b/lib/colvars/colvarbias.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARBIAS_H #define COLVARBIAS_H diff --git a/lib/colvars/colvarbias_abf.cpp b/lib/colvars/colvarbias_abf.cpp index cc549578ce..0005aac837 100644 --- a/lib/colvars/colvarbias_abf.cpp +++ b/lib/colvars/colvarbias_abf.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvar.h" @@ -8,8 +8,11 @@ colvarbias_abf::colvarbias_abf(std::string const &conf, char const *key) : colvarbias(conf, key), + force(NULL), gradients(NULL), - samples(NULL) + samples(NULL), + last_gradients(NULL), + last_samples(NULL) { // TODO relax this in case of VMD plugin if (cvm::temperature() == 0.0) @@ -60,10 +63,10 @@ colvarbias_abf::colvarbias_abf(std::string const &conf, char const *key) if (update_bias) { // Request calculation of system force (which also checks for availability) - enable(f_cvb_get_system_force); + if(enable(f_cvb_get_system_force)) return; } if (apply_bias) { - enable(f_cvb_apply_force); + if(enable(f_cvb_apply_force)) return; } for (size_t i = 0; i < colvars.size(); i++) { @@ -151,7 +154,10 @@ colvarbias_abf::~colvarbias_abf() last_gradients = NULL; } - delete [] force; + if (force) { + delete [] force; + force = NULL; + } if (cvm::n_abf_biases > 0) cvm::n_abf_biases -= 1; diff --git a/lib/colvars/colvarbias_histogram.cpp b/lib/colvars/colvarbias_histogram.cpp index ea91a5a55b..7432fafe5f 100644 --- a/lib/colvars/colvarbias_histogram.cpp +++ b/lib/colvars/colvarbias_histogram.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvar.h" diff --git a/lib/colvars/colvarbias_meta.cpp b/lib/colvars/colvarbias_meta.cpp index 46c0884e11..bc4f37a0b1 100644 --- a/lib/colvars/colvarbias_meta.cpp +++ b/lib/colvars/colvarbias_meta.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include #include @@ -41,10 +41,10 @@ colvarbias_meta::colvarbias_meta(std::string const &conf, char const *key) if (cvm::n_abf_biases > 0) cvm::log("Warning: running ABF and metadynamics together is not recommended unless applyBias is off for ABF.\n"); - get_keyval(conf, "hillWeight", hill_weight, 0.01); - if (hill_weight == 0.0) - cvm::log("Warning: hillWeight has been set to zero, " - "this bias will have no effect.\n"); + get_keyval(conf, "hillWeight", hill_weight, 0.0); + if (hill_weight <= 0.0) { + cvm::error("Error: hillWeight must be provided, and a positive number.\n", INPUT_ERROR); + } get_keyval(conf, "newHillFrequency", new_hill_freq, 1000); diff --git a/lib/colvars/colvarbias_meta.h b/lib/colvars/colvarbias_meta.h index 2de1e2bade..f61e70b168 100644 --- a/lib/colvars/colvarbias_meta.h +++ b/lib/colvars/colvarbias_meta.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARBIAS_META_H #define COLVARBIAS_META_H diff --git a/lib/colvars/colvarbias_restraint.cpp b/lib/colvars/colvarbias_restraint.cpp index 6812c670f7..369ed2d2ee 100644 --- a/lib/colvars/colvarbias_restraint.cpp +++ b/lib/colvars/colvarbias_restraint.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvarvalue.h" diff --git a/lib/colvars/colvarbias_restraint.h b/lib/colvars/colvarbias_restraint.h index fb751bc10e..006ab0f1e2 100644 --- a/lib/colvars/colvarbias_restraint.h +++ b/lib/colvars/colvarbias_restraint.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARBIAS_RESTRAINT_H #define COLVARBIAS_RESTRAINT_H diff --git a/lib/colvars/colvarcomp.cpp b/lib/colvars/colvarcomp.cpp index cd0ffe8b65..eec43d0963 100644 --- a/lib/colvars/colvarcomp.cpp +++ b/lib/colvars/colvarcomp.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvarvalue.h" @@ -68,6 +68,7 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf, group->key = group_key; if (b_try_scalable) { + // TODO rewrite this logic in terms of dependencies if (is_available(f_cvc_scalable_com) && is_available(f_cvc_com_based)) { enable(f_cvc_scalable_com); enable(f_cvc_scalable); @@ -109,10 +110,6 @@ int colvar::cvc::setup() add_child((cvm::deps *) atom_groups[i]); } - if (b_try_scalable && is_available(f_cvc_scalable)) { - enable(f_cvc_scalable); - } - return COLVARS_OK; } @@ -134,7 +131,7 @@ void colvar::cvc::read_data() atoms.reset_atoms_data(); atoms.read_positions(); atoms.calc_required_properties(); - // each atom group will take care of its own ref_pos_group, if defined + // each atom group will take care of its own fitting_group, if defined } //// Don't try to get atom velocities, as no back-end currently implements it @@ -179,7 +176,7 @@ void colvar::cvc::debug_gradients(cvm::atom_group *group) // cvm::log("gradients = "+cvm::to_str (gradients)+"\n"); - cvm::atom_group *group_for_fit = group->ref_pos_group ? group->ref_pos_group : group; + cvm::atom_group *group_for_fit = group->fitting_group ? group->fitting_group : group; cvm::atom_pos fit_gradient_sum, gradient_sum; // print the values of the fit gradients @@ -190,7 +187,7 @@ void colvar::cvc::debug_gradients(cvm::atom_group *group) // fit_gradients are in the simulation frame: we should print them in the rotated frame cvm::log("Fit gradients:\n"); for (j = 0; j < group_for_fit->fit_gradients.size(); j++) { - cvm::log((group->ref_pos_group ? std::string("refPosGroup") : group->key) + + cvm::log((group->fitting_group ? std::string("refPosGroup") : group->key) + "[" + cvm::to_str(j) + "] = " + (group->b_rotate ? cvm::to_str(rot_0.rotate(group_for_fit->fit_gradients[j])) : @@ -231,8 +228,8 @@ void colvar::cvc::debug_gradients(cvm::atom_group *group) } } - if ((group->b_fit_gradients) && (group->ref_pos_group != NULL)) { - cvm::atom_group *ref_group = group->ref_pos_group; + if ((group->b_fit_gradients) && (group->fitting_group != NULL)) { + cvm::atom_group *ref_group = group->fitting_group; group->read_positions(); group->calc_required_properties(); diff --git a/lib/colvars/colvarcomp.h b/lib/colvars/colvarcomp.h index 923b2c6bd1..1ed3c38924 100644 --- a/lib/colvars/colvarcomp.h +++ b/lib/colvars/colvarcomp.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARCOMP_H #define COLVARCOMP_H @@ -293,12 +293,7 @@ inline void colvar::cvc::wrap(colvarvalue &x) const /// \brief Colvar component: distance between the centers of mass of /// two groups (colvarvalue::type_scalar type, range [0:*)) -/// -/// This class also serves as the template for many collective -/// variables with two atom groups: in this case, the -/// distance::distance() constructor should be called on the same -/// configuration string, to make the same member data and functions -/// available to the derived object + class colvar::distance : public colvar::cvc { @@ -315,7 +310,7 @@ protected: /// coupling to other colvars (see e.g. Ciccotti et al., 2005) bool b_1site_force; public: - distance(std::string const &conf, bool twogroups = true); + distance(std::string const &conf); distance(); virtual inline ~distance() {} virtual void calc_value(); @@ -764,9 +759,13 @@ public: /// \brief Colvar component: coordination number between two groups /// (colvarvalue::type_scalar type, range [0:N1*N2]) class colvar::coordnum - : public colvar::distance + : public colvar::cvc { protected: + /// First atom group + cvm::atom_group *group1; + /// Second atom group + cvm::atom_group *group2; /// \brief "Cutoff" for isotropic calculation (default) cvm::real r0; /// \brief "Cutoff vector" for anisotropic calculation @@ -819,9 +818,11 @@ public: /// \brief Colvar component: self-coordination number within a group /// (colvarvalue::type_scalar type, range [0:N*(N-1)/2]) class colvar::selfcoordnum - : public colvar::distance + : public colvar::cvc { protected: + /// First atom group + cvm::atom_group *group1; /// \brief "Cutoff" for isotropic calculation (default) cvm::real r0; /// Integer exponent of the function numerator diff --git a/lib/colvars/colvarcomp_angles.cpp b/lib/colvars/colvarcomp_angles.cpp index 1f825a17c4..a4bf53feb7 100644 --- a/lib/colvars/colvarcomp_angles.cpp +++ b/lib/colvars/colvarcomp_angles.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvar.h" diff --git a/lib/colvars/colvarcomp_coordnums.cpp b/lib/colvars/colvarcomp_coordnums.cpp index 2d4a20d542..390cdc1e59 100644 --- a/lib/colvars/colvarcomp_coordnums.cpp +++ b/lib/colvars/colvarcomp_coordnums.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include @@ -71,31 +71,29 @@ cvm::real colvar::coordnum::switching_function(cvm::rvector const &r0_vec, } - colvar::coordnum::coordnum(std::string const &conf) - : distance(conf), b_anisotropic(false), b_group2_center_only(false) + : cvc(conf), b_anisotropic(false), b_group2_center_only(false) { function_type = "coordnum"; x.type(colvarvalue::type_scalar); - // group1 and group2 are already initialized by distance() + group1 = parse_group(conf, "group1"); + group2 = parse_group(conf, "group2"); + if (group1->b_dummy) cvm::fatal_error("Error: only group2 is allowed to be a dummy atom\n"); + bool const b_isotropic = get_keyval(conf, "cutoff", r0, + cvm::real(4.0 * cvm::unit_angstrom())); - // need to specify this explicitly because the distance() constructor - // has set it to true - feature_states[f_cvc_inv_gradient]->available = false; + if (get_keyval(conf, "cutoff3", r0_vec, cvm::rvector(4.0 * cvm::unit_angstrom(), + 4.0 * cvm::unit_angstrom(), + 4.0 * cvm::unit_angstrom()))) { + if (b_isotropic) { + cvm::error("Error: cannot specify \"cutoff\" and \"cutoff3\" at the same time.\n", + INPUT_ERROR); + } - bool const b_scale = get_keyval(conf, "cutoff", r0, - cvm::real(4.0 * cvm::unit_angstrom())); - - if (get_keyval(conf, "cutoff3", r0_vec, - cvm::rvector(4.0, 4.0, 4.0), parse_silent)) { - - if (b_scale) - cvm::fatal_error("Error: cannot specify \"scale\" and " - "\"scale3\" at the same time.\n"); b_anisotropic = true; // remove meaningless negative signs if (r0_vec.x < 0.0) r0_vec.x *= -1.0; @@ -107,7 +105,7 @@ colvar::coordnum::coordnum(std::string const &conf) get_keyval(conf, "expDenom", ed, int(12)); if ( (en%2) || (ed%2) ) { - cvm::fatal_error("Error: odd exponents provided, can only use even ones.\n"); + cvm::error("Error: odd exponents provided, can only use even ones.\n", INPUT_ERROR); } get_keyval(conf, "group2CenterOnly", b_group2_center_only, group2->b_dummy); @@ -289,17 +287,12 @@ void colvar::h_bond::apply_force(colvarvalue const &force) colvar::selfcoordnum::selfcoordnum(std::string const &conf) - : distance(conf, false) + : cvc(conf) { function_type = "selfcoordnum"; x.type(colvarvalue::type_scalar); - // group1 is already initialized by distance() - - // need to specify this explicitly because the distance() constructor - // has set it to true - feature_states[f_cvc_inv_gradient]->available = false; - + group1 = parse_group(conf, "group1"); get_keyval(conf, "cutoff", r0, cvm::real(4.0 * cvm::unit_angstrom())); get_keyval(conf, "expNumer", en, int(6) ); diff --git a/lib/colvars/colvarcomp_distances.cpp b/lib/colvars/colvarcomp_distances.cpp index a38fa7b91f..ff6b03e2c5 100644 --- a/lib/colvars/colvarcomp_distances.cpp +++ b/lib/colvars/colvarcomp_distances.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include @@ -10,10 +10,7 @@ -// "twogroup" flag defaults to true; set to false by selfCoordNum -// (only distance-derived component based on only one group) - -colvar::distance::distance(std::string const &conf, bool twogroups) +colvar::distance::distance(std::string const &conf) : cvc(conf) { function_type = "distance"; @@ -24,13 +21,12 @@ colvar::distance::distance(std::string const &conf, bool twogroups) if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { cvm::log("Computing distance using absolute positions (not minimal-image)"); } - if (twogroups && get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) { + if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) { cvm::log("Computing system force on group 1 only"); } group1 = parse_group(conf, "group1"); - if (twogroups) { - group2 = parse_group(conf, "group2"); - } + group2 = parse_group(conf, "group2"); + x.type(colvarvalue::type_scalar); } @@ -789,7 +785,7 @@ colvar::rmsd::rmsd(std::string const &conf) } bool b_Jacobian_derivative = true; - if (atoms->ref_pos_group != NULL && b_Jacobian_derivative) { + if (atoms->fitting_group != NULL && b_Jacobian_derivative) { cvm::log("The option \"refPositionsGroup\" (alternative group for fitting) was enabled: " "Jacobian derivatives of the RMSD will not be calculated.\n"); b_Jacobian_derivative = false; @@ -798,7 +794,7 @@ colvar::rmsd::rmsd(std::string const &conf) // the following is a simplified version of the corresponding atom group options; // we need this because the reference coordinates defined inside the atom group - // may be used only for fitting, and even more so if ref_pos_group is used + // may be used only for fitting, and even more so if fitting_group is used if (get_keyval(conf, "refPositions", ref_pos, ref_pos)) { cvm::log("Using reference positions from configuration file to calculate the variable.\n"); if (ref_pos.size() != atoms->size()) { diff --git a/lib/colvars/colvarcomp_protein.cpp b/lib/colvars/colvarcomp_protein.cpp index a12fab1c19..e5db3a4b50 100644 --- a/lib/colvars/colvarcomp_protein.cpp +++ b/lib/colvars/colvarcomp_protein.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include diff --git a/lib/colvars/colvarcomp_rotations.cpp b/lib/colvars/colvarcomp_rotations.cpp index b318b0f7be..a3cbbb2908 100644 --- a/lib/colvars/colvarcomp_rotations.cpp +++ b/lib/colvars/colvarcomp_rotations.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include diff --git a/lib/colvars/colvardeps.cpp b/lib/colvars/colvardeps.cpp index 7df4d14539..b5d9e09270 100644 --- a/lib/colvars/colvardeps.cpp +++ b/lib/colvars/colvardeps.cpp @@ -196,7 +196,7 @@ int cvm::deps::enable(int feature_id, void cvm::deps::init_cvb_requires() { int i; if (features().size() == 0) { - for (i = 0; i < f_cv_ntot; i++) { + for (i = 0; i < f_cvb_ntot; i++) { features().push_back(new feature); } } @@ -362,11 +362,15 @@ void cvm::deps::init_cvc_requires() { f_description(f_cvc_Jacobian, "Jacobian"); f_req_self(f_cvc_Jacobian, f_cvc_inv_gradient); - f_description(f_cvc_scalable, "scalable calculation"); - f_description(f_cvc_scalable_com, "scalable calculation of centers of mass"); + f_description(f_cvc_com_based, "depends on group centers of mass"); + f_description(f_cvc_scalable, "scalable calculation"); f_req_self(f_cvc_scalable, f_cvc_scalable_com); + f_description(f_cvc_scalable_com, "scalable calculation of centers of mass"); + f_req_self(f_cvc_scalable_com, f_cvc_com_based); + + // TODO only enable this when f_ag_scalable can be turned on for a pre-initialized group // f_req_children(f_cvc_scalable, f_ag_scalable); // f_req_children(f_cvc_scalable_com, f_ag_scalable_com); @@ -380,9 +384,9 @@ void cvm::deps::init_cvc_requires() { } // Features that are implemented by all cvcs by default + // Each cvc specifies what other features are available feature_states[f_cvc_active]->available = true; feature_states[f_cvc_gradient]->available = true; - // Each cvc specifies what other features are available feature_states[f_cvc_scalable_com]->available = (proxy->scalable_group_coms() == COLVARS_OK); feature_states[f_cvc_scalable]->available = feature_states[f_cvc_scalable_com]->available; } @@ -399,7 +403,7 @@ void cvm::deps::init_ag_requires() { f_description(f_ag_active, "active"); f_description(f_ag_center, "translational fit"); f_description(f_ag_rotate, "rotational fit"); - f_description(f_ag_ref_pos_group, "reference positions group"); + f_description(f_ag_fitting_group, "reference positions group"); f_description(f_ag_fit_gradient_group, "fit gradient for main group"); f_description(f_ag_fit_gradient_ref, "fit gradient for reference group"); f_description(f_ag_atom_forces, "atomic forces"); @@ -413,7 +417,7 @@ void cvm::deps::init_ag_requires() { // f_description(f_ag_min_msd_fit, "minimum MSD fit") // f_req_self(f_ag_min_msd_fit, f_ag_center) // f_req_self(f_ag_min_msd_fit, f_ag_rotate) -// f_req_exclude(f_ag_min_msd_fit, f_ag_ref_pos_group) +// f_req_exclude(f_ag_min_msd_fit, f_ag_fitting_group) } // Initialize feature_states for each instance diff --git a/lib/colvars/colvardeps.h b/lib/colvars/colvardeps.h index d9d3cbfe57..926746f45a 100644 --- a/lib/colvars/colvardeps.h +++ b/lib/colvars/colvardeps.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" @@ -238,7 +238,7 @@ public: f_ag_active, f_ag_center, f_ag_rotate, - f_ag_ref_pos_group, + f_ag_fitting_group, /// Perform a standard minimum msd fit for given atoms /// ie. not using refpositionsgroup // f_ag_min_msd_fit, diff --git a/lib/colvars/colvargrid.cpp b/lib/colvars/colvargrid.cpp index 522d866409..3b07a0b3d5 100644 --- a/lib/colvars/colvargrid.cpp +++ b/lib/colvars/colvargrid.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include "colvarmodule.h" #include "colvarvalue.h" diff --git a/lib/colvars/colvargrid.h b/lib/colvars/colvargrid.h index 4cf05b0ddb..c42894c60a 100644 --- a/lib/colvars/colvargrid.h +++ b/lib/colvars/colvargrid.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARGRID_H #define COLVARGRID_H diff --git a/lib/colvars/colvarmodule.cpp b/lib/colvars/colvarmodule.cpp index 2988c63594..20739f5e62 100644 --- a/lib/colvars/colvarmodule.cpp +++ b/lib/colvars/colvarmodule.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include #include diff --git a/lib/colvars/colvarmodule.h b/lib/colvars/colvarmodule.h index 8c220baaf4..de95a8b95a 100644 --- a/lib/colvars/colvarmodule.h +++ b/lib/colvars/colvarmodule.h @@ -1,16 +1,19 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARMODULE_H #define COLVARMODULE_H #ifndef COLVARS_VERSION -#define COLVARS_VERSION "2016-05-23" +#define COLVARS_VERSION "2016-06-14" #endif #ifndef COLVARS_DEBUG #define COLVARS_DEBUG false #endif +/*! \mainpage Main page + */ + /// \file colvarmodule.h /// \brief Collective variables main module /// diff --git a/lib/colvars/colvarparse.cpp b/lib/colvars/colvarparse.cpp index 42d7b6e01d..ce87265b86 100644 --- a/lib/colvars/colvarparse.cpp +++ b/lib/colvars/colvarparse.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- + #include #include @@ -17,235 +17,280 @@ size_t colvarparse::dummy_pos = 0; // definition of single-value keyword parsers -#define _get_keyval_scalar_string_(TYPE) \ - \ - bool colvarparse::get_keyval(std::string const &conf, \ - char const *key, \ - TYPE &value, \ - TYPE const &def_value, \ - Parse_Mode const parse_mode) \ - { \ - std::string data; \ - bool b_found = false, b_found_any = false; \ - size_t save_pos = 0, found_count = 0; \ - \ - do { \ - std::string data_this = ""; \ - b_found = key_lookup(conf, key, data_this, save_pos); \ - if (b_found) { \ - if (!b_found_any) \ - b_found_any = true; \ - found_count++; \ - data = data_this; \ - } \ - } while (b_found); \ - \ - if (found_count > 1) \ - cvm::log("Warning: found more than one instance of \""+ \ - std::string(key)+"\".\n"); \ - \ - if (data.size()) { \ - std::istringstream is(data); \ - TYPE x(def_value); \ - if (is >> x) { \ - value = x; \ - } else { \ - cvm::error("Error: in parsing \""+ \ - std::string(key)+"\".\n", INPUT_ERROR); \ - } \ - if (parse_mode != parse_silent) { \ - cvm::log("# "+std::string(key)+" = "+ \ - cvm::to_str(value)+"\n"); \ - } \ - } else { \ - \ - if (b_found_any) { \ - cvm::error("Error: improper or missing value " \ - "for \""+std::string(key)+"\".\n", INPUT_ERROR); \ - } \ - value = def_value; \ - if (parse_mode != parse_silent) { \ - cvm::log("# "+std::string(key)+" = \""+ \ - cvm::to_str(def_value)+"\" [default]\n"); \ - } \ - } \ - \ - return b_found_any; \ +template bool colvarparse::_get_keyval_scalar_(std::string const &conf, + char const *key, + TYPE &value, + TYPE const &def_value, + Parse_Mode const parse_mode) +{ + std::string data; + bool b_found = false, b_found_any = false; + size_t save_pos = 0, found_count = 0; + + do { + std::string data_this = ""; + b_found = key_lookup(conf, key, data_this, save_pos); + if (b_found) { + if (!b_found_any) + b_found_any = true; + found_count++; + data = data_this; + } + } while (b_found); + + if (found_count > 1) + cvm::log("Warning: found more than one instance of \""+ + std::string(key)+"\".\n"); + + if (data.size()) { + std::istringstream is(data); + TYPE x(def_value); + if (is >> x) { + value = x; + } else { + cvm::error("Error: in parsing \""+ + std::string(key)+"\".\n", INPUT_ERROR); + } + if (parse_mode != parse_silent) { + cvm::log("# "+std::string(key)+" = "+ + cvm::to_str(value)+"\n"); + } + } else { + + if (b_found_any) { + cvm::error("Error: improper or missing value " + "for \""+std::string(key)+"\".\n", INPUT_ERROR); + } + value = def_value; + if (parse_mode != parse_silent) { + cvm::log("# "+std::string(key)+" = "+ + cvm::to_str(def_value)+" [default]\n"); + } } + return b_found_any; +} -#define _get_keyval_scalar_(TYPE) \ - \ - bool colvarparse::get_keyval(std::string const &conf, \ - char const *key, \ - TYPE &value, \ - TYPE const &def_value, \ - Parse_Mode const parse_mode) \ - { \ - std::string data; \ - bool b_found = false, b_found_any = false; \ - size_t save_pos = 0, found_count = 0; \ - \ - do { \ - std::string data_this = ""; \ - b_found = key_lookup(conf, key, data_this, save_pos); \ - if (b_found) { \ - if (!b_found_any) \ - b_found_any = true; \ - found_count++; \ - data = data_this; \ - } \ - } while (b_found); \ - \ - if (found_count > 1) \ - cvm::log("Warning: found more than one instance of \""+ \ - std::string(key)+"\".\n"); \ - \ - if (data.size()) { \ - std::istringstream is(data); \ - size_t data_count = 0; \ - TYPE x(def_value); \ - while (is >> x) { \ - value = x; \ - data_count++; \ - } \ - if (data_count == 0) \ - cvm::error("Error: in parsing \""+ \ - std::string(key)+"\".\n", INPUT_ERROR); \ - if (data_count > 1) { \ - cvm::error("Error: multiple values " \ - "are not allowed for keyword \""+ \ - std::string(key)+"\".\n", INPUT_ERROR); \ - } \ - if (parse_mode != parse_silent) { \ - cvm::log("# "+std::string(key)+" = "+ \ - cvm::to_str(value)+"\n"); \ - } \ - } else { \ - \ - if (b_found_any) { \ - cvm::error("Error: improper or missing value " \ - "for \""+std::string(key)+"\".\n", INPUT_ERROR); \ - } \ - value = def_value; \ - if (parse_mode != parse_silent) { \ - cvm::log("# "+std::string(key)+" = "+ \ - cvm::to_str(def_value)+" [default]\n"); \ - } \ - } \ - \ - return b_found_any; \ + +bool colvarparse::_get_keyval_scalar_string_(std::string const &conf, + char const *key, + std::string &value, + std::string const &def_value, + Parse_Mode const parse_mode) +{ + std::string data; + bool b_found = false, b_found_any = false; + size_t save_pos = 0, found_count = 0; + + do { + std::string data_this = ""; + b_found = key_lookup(conf, key, data_this, save_pos); + if (b_found) { + if (!b_found_any) + b_found_any = true; + found_count++; + data = data_this; + } + } while (b_found); + + if (found_count > 1) + cvm::log("Warning: found more than one instance of \""+ + std::string(key)+"\".\n"); + + if (data.size()) { + std::istringstream is(data); + size_t data_count = 0; + std::string x(def_value); + while (is >> x) { + value = x; + data_count++; + } + if (data_count == 0) + cvm::error("Error: in parsing \""+ + std::string(key)+"\".\n", INPUT_ERROR); + if (data_count > 1) { + cvm::error("Error: multiple values " + "are not allowed for keyword \""+ + std::string(key)+"\".\n", INPUT_ERROR); + } + if (parse_mode != parse_silent) { + cvm::log("# "+std::string(key)+" = \""+ + cvm::to_str(value)+"\"\n"); + } + } else { + + if (b_found_any) { + cvm::error("Error: improper or missing value " + "for \""+std::string(key)+"\".\n", INPUT_ERROR); + } + value = def_value; + if (parse_mode != parse_silent) { + cvm::log("# "+std::string(key)+" = \""+ + cvm::to_str(def_value)+"\" [default]\n"); + } } - -// definition of multiple-value keyword parsers - -#define _get_keyval_vector_(TYPE) \ - \ - bool colvarparse::get_keyval(std::string const &conf, \ - char const *key, \ - std::vector &values, \ - std::vector const &def_values, \ - Parse_Mode const parse_mode) \ - { \ - std::string data; \ - bool b_found = false, b_found_any = false; \ - size_t save_pos = 0, found_count = 0; \ - \ - do { \ - std::string data_this = ""; \ - b_found = key_lookup(conf, key, data_this, save_pos); \ - if (b_found) { \ - if (!b_found_any) \ - b_found_any = true; \ - found_count++; \ - data = data_this; \ - } \ - } while (b_found); \ - \ - if (found_count > 1) \ - cvm::log("Warning: found more than one instance of \""+ \ - std::string(key)+"\".\n"); \ - \ - if (data.size()) { \ - std::istringstream is(data); \ - \ - if (values.size() == 0) { \ - \ - std::vector x; \ - if (def_values.size()) \ - x = def_values; \ - else \ - x.assign(1, TYPE()); \ - \ - for (size_t i = 0; \ - ( is >> x[ ((i> x) { \ - values[i] = x; \ - } else { \ - cvm::error("Error: in parsing \""+ \ - std::string(key)+"\".\n", INPUT_ERROR); \ - } \ - } \ - } \ - \ - if (parse_mode != parse_silent) { \ - cvm::log("# "+std::string(key)+" = "+ \ - cvm::to_str(values)+"\n"); \ - } \ - \ - } else { \ - \ - if (b_found_any) { \ - cvm::error("Error: improper or missing values for \""+ \ - std::string(key)+"\".\n", INPUT_ERROR); \ - } \ - \ - for (size_t i = 0; i < values.size(); i++) \ - values[i] = def_values[ (i > def_values.size()) ? 0 : i ]; \ - \ - if (parse_mode != parse_silent) { \ - cvm::log("# "+std::string(key)+" = "+ \ - cvm::to_str(def_values)+" [default]\n"); \ - } \ - } \ - \ - return b_found_any; \ - } - - -// single-value keyword parsers - -_get_keyval_scalar_(int); -_get_keyval_scalar_(size_t); -_get_keyval_scalar_(long); -_get_keyval_scalar_string_(std::string); -_get_keyval_scalar_(cvm::real); -_get_keyval_scalar_(cvm::rvector); -_get_keyval_scalar_(cvm::quaternion); -_get_keyval_scalar_(colvarvalue); + return b_found_any; +} // multiple-value keyword parsers -_get_keyval_vector_(int); -_get_keyval_vector_(size_t); -_get_keyval_vector_(long); -_get_keyval_vector_(std::string); -_get_keyval_vector_(cvm::real); -_get_keyval_vector_(cvm::rvector); -_get_keyval_vector_(cvm::quaternion); -_get_keyval_vector_(colvarvalue); +template bool colvarparse::_get_keyval_vector_(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + std::string data; + bool b_found = false, b_found_any = false; + size_t save_pos = 0, found_count = 0; + do { + std::string data_this = ""; + b_found = key_lookup(conf, key, data_this, save_pos); + if (b_found) { + if (!b_found_any) + b_found_any = true; + found_count++; + data = data_this; + } + } while (b_found); + + if (found_count > 1) + cvm::log("Warning: found more than one instance of \""+ + std::string(key)+"\".\n"); + + if (data.size()) { + std::istringstream is(data); + + if (values.size() == 0) { + + std::vector x; + if (def_values.size()) + x = def_values; + else + x.assign(1, TYPE()); + + for (size_t i = 0; + ( is >> x[ ((i> x) { + values[i] = x; + } else { + cvm::error("Error: in parsing \""+ + std::string(key)+"\".\n", INPUT_ERROR); + } + } + } + + if (parse_mode != parse_silent) { + cvm::log("# "+std::string(key)+" = "+ + cvm::to_str(values)+"\n"); + } + + } else { + + if (b_found_any) { + cvm::error("Error: improper or missing values for \""+ + std::string(key)+"\".\n", INPUT_ERROR); + } + + for (size_t i = 0; i < values.size(); i++) + values[i] = def_values[ (i > def_values.size()) ? 0 : i ]; + + if (parse_mode != parse_silent) { + cvm::log("# "+std::string(key)+" = "+ + cvm::to_str(def_values)+" [default]\n"); + } + } + + return b_found_any; +} + + +// single-value keyword parsers + + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + int &value, + int const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_(conf, key, value, def_value, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + size_t &value, + size_t const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_(conf, key, value, def_value, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + long &value, + long const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_(conf, key, value, def_value, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::string &value, + std::string const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_string_(conf, key, value, def_value, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + cvm::real &value, + cvm::real const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_(conf, key, value, def_value, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + cvm::rvector &value, + cvm::rvector const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_(conf, key, value, def_value, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + cvm::quaternion &value, + cvm::quaternion const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_(conf, key, value, def_value, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + colvarvalue &value, + colvarvalue const &def_value, + Parse_Mode const parse_mode) +{ + return _get_keyval_scalar_(conf, key, value, def_value, parse_mode); +} bool colvarparse::get_keyval(std::string const &conf, @@ -309,6 +354,81 @@ bool colvarparse::get_keyval(std::string const &conf, } +// multiple-value keyword parsers + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + +bool colvarparse::get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode) +{ + return _get_keyval_vector_(conf, key, values, def_values, parse_mode); +} + + void colvarparse::add_keyword(char const *key) { for (std::list::iterator ki = allowed_keywords.begin(); diff --git a/lib/colvars/colvarparse.h b/lib/colvars/colvarparse.h index b635711f9c..6ebe413679 100644 --- a/lib/colvars/colvarparse.h +++ b/lib/colvars/colvarparse.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARPARSE_H #define COLVARPARSE_H @@ -64,7 +64,7 @@ public: inline const std::string& get_config() { - return config_string; + return config_string; } /// How a keyword is parsed in a string @@ -104,40 +104,113 @@ public: /// functions, or insert this type in the \link colvarvalue \endlink /// wrapper class (colvarvalue.h). -#define _get_keyval_scalar_proto_(_type_,_def_value_) \ - bool get_keyval(std::string const &conf, \ - char const *key, \ - _type_ &value, \ - _type_ const &def_value = _def_value_, \ - Parse_Mode const parse_mode = parse_normal) + bool get_keyval(std::string const &conf, + char const *key, + int &value, + int const &def_value = (int)0, + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + size_t &value, + size_t const &def_value = (size_t)0, + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + long &value, + long const &def_value = 0, + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::string &value, + std::string const &def_value = std::string(""), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + cvm::real &value, + cvm::real const &def_value = (cvm::real)0.0, + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + cvm::rvector &value, + cvm::rvector const &def_value = cvm::rvector(), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + cvm::quaternion &value, + cvm::quaternion const &def_value = cvm::quaternion(), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + colvarvalue &value, + colvarvalue const &def_value = colvarvalue(colvarvalue::type_notset), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + bool &value, + bool const &def_value = false, + Parse_Mode const parse_mode = parse_normal); - _get_keyval_scalar_proto_(int, (int)0); - _get_keyval_scalar_proto_(size_t, (size_t)0); - _get_keyval_scalar_proto_(long, 0); - _get_keyval_scalar_proto_(std::string, std::string("")); - _get_keyval_scalar_proto_(cvm::real, (cvm::real)0.0); - _get_keyval_scalar_proto_(cvm::rvector, cvm::rvector()); - _get_keyval_scalar_proto_(cvm::quaternion, cvm::quaternion()); - _get_keyval_scalar_proto_(colvarvalue, colvarvalue(colvarvalue::type_notset)); - _get_keyval_scalar_proto_(bool, false); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, (int)0), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, (size_t)0), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, (long)0), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, std::string("")), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, (cvm::real)0.0), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, cvm::rvector()), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, cvm::quaternion()), + Parse_Mode const parse_mode = parse_normal); + bool get_keyval(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values = std::vector(0, colvarvalue(colvarvalue::type_notset)), + Parse_Mode const parse_mode = parse_normal); -#define _get_keyval_vector_proto_(_type_,_def_value_) \ - bool get_keyval(std::string const &conf, \ - char const *key, \ - std::vector<_type_> &values, \ - std::vector<_type_> const &def_values = \ - std::vector<_type_> (0, static_cast<_type_>(_def_value_)), \ - Parse_Mode const parse_mode = parse_normal) +protected: - _get_keyval_vector_proto_(int, 0); - _get_keyval_vector_proto_(size_t, 0); - _get_keyval_vector_proto_(long, 0); - _get_keyval_vector_proto_(std::string, std::string("")); - _get_keyval_vector_proto_(cvm::real, 0.0); - _get_keyval_vector_proto_(cvm::rvector, cvm::rvector()); - _get_keyval_vector_proto_(cvm::quaternion, cvm::quaternion()); - _get_keyval_vector_proto_(colvarvalue, colvarvalue(colvarvalue::type_notset)); + // Templates + template bool _get_keyval_scalar_(std::string const &conf, + char const *key, + TYPE &value, + TYPE const &def_value, + Parse_Mode const parse_mode); + bool _get_keyval_scalar_string_(std::string const &conf, + char const *key, + std::string &value, + std::string const &def_value, + Parse_Mode const parse_mode); + template bool _get_keyval_vector_(std::string const &conf, + char const *key, + std::vector &values, + std::vector const &def_values, + Parse_Mode const parse_mode); +public: /// \brief Check that all the keywords within "conf" are in the list /// of allowed keywords; this will invoke strip_values() first and @@ -184,17 +257,16 @@ public: static std::string const white_space; /// \brief Low-level function for parsing configuration strings; - /// automatically adds the requested keywords to the list of valid + /// automatically adds the requested keyword to the list of valid /// ones. \param conf the content of the configuration file or one - /// of its blocks \param key the keyword to search in "conf" \param + /// of its blocks \param key the keyword to search within "conf" \param /// data (optional) holds the string provided after "key", if any /// \param save_pos (optional) stores the position of the keyword - /// within "conf", useful when doing multiple calls \param - /// save_delimiters (optional) + /// within "conf", useful when doing multiple calls bool key_lookup(std::string const &conf, - char const *key, - std::string &data = dummy_string, - size_t &save_pos = dummy_pos); + char const *key, + std::string &data = dummy_string, + size_t &save_pos = dummy_pos); /// Used as a default argument by key_lookup static std::string dummy_string; @@ -204,12 +276,12 @@ public: /// \brief Works as std::getline() but also removes everything /// between a comment character and the following newline static std::istream & getline_nocomments(std::istream &is, - std::string &s, - char const delim = '\n'); + std::string &s, + char const delim = '\n'); /// Check if the content of the file has matching braces bool brace_check(std::string const &conf, - size_t const start_pos = 0); + size_t const start_pos = 0); }; diff --git a/lib/colvars/colvarproxy.h b/lib/colvars/colvarproxy.h index b80b575729..0d29a7297d 100644 --- a/lib/colvars/colvarproxy.h +++ b/lib/colvars/colvarproxy.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARPROXY_H #define COLVARPROXY_H diff --git a/lib/colvars/colvarscript.cpp b/lib/colvars/colvarscript.cpp index cabb520248..091162fc18 100644 --- a/lib/colvars/colvarscript.cpp +++ b/lib/colvars/colvarscript.cpp @@ -295,6 +295,11 @@ int colvarscript::proc_colvar(int argc, char const *argv[]) { return COLVARS_OK; } + if (subcmd == "state") { + cv->print_state(); + return COLVARS_OK; + } + result = "Syntax error\n" + help_string(); return COLVARSCRIPT_ERROR; } diff --git a/lib/colvars/colvarscript.h b/lib/colvars/colvarscript.h index ccd3ff82c5..7778c3757f 100644 --- a/lib/colvars/colvarscript.h +++ b/lib/colvars/colvarscript.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARSCRIPT_H #define COLVARSCRIPT_H diff --git a/lib/colvars/colvartypes.h b/lib/colvars/colvartypes.h index fcc26c0b98..65259c7220 100644 --- a/lib/colvars/colvartypes.h +++ b/lib/colvars/colvartypes.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARTYPES_H #define COLVARTYPES_H diff --git a/lib/colvars/colvarvalue.cpp b/lib/colvars/colvarvalue.cpp index 17f81ec73a..d009e12f31 100644 --- a/lib/colvars/colvarvalue.cpp +++ b/lib/colvars/colvarvalue.cpp @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #include #include diff --git a/lib/colvars/colvarvalue.h b/lib/colvars/colvarvalue.h index 24af824081..6f63bd64a2 100644 --- a/lib/colvars/colvarvalue.h +++ b/lib/colvars/colvarvalue.h @@ -1,4 +1,4 @@ -/// -*- c++ -*- +// -*- c++ -*- #ifndef COLVARVALUE_H #define COLVARVALUE_H