colvar::cartesian::cartesian(std::string const &conf) : cvc(conf) { b_inverse_gradients = false; b_Jacobian_derivative = false; function_type = "cartesian"; parse_group(conf, "atoms", atoms); atom_groups.push_back(&atoms); bool use_x, use_y, use_z; get_keyval(conf, "useX", use_x, true); get_keyval(conf, "useY", use_y, true); get_keyval(conf, "useZ", use_z, true); axes.clear(); if (use_x) axes.push_back(0); if (use_y) axes.push_back(1); if (use_z) axes.push_back(2); if (axes.size() == 0) { cvm::error("Error: a \"cartesian\" component was defined with all three axes disabled.\n"); } x.type(colvarvalue::type_vector); x.vector1d_value.resize(atoms.size() * axes.size()); }
colvar::cartesian::cartesian(std::string const &conf) : cvc(conf) { function_type = "cartesian"; atoms = parse_group(conf, "atoms"); bool use_x, use_y, use_z; get_keyval(conf, "useX", use_x, true); get_keyval(conf, "useY", use_y, true); get_keyval(conf, "useZ", use_z, true); axes.clear(); if (use_x) axes.push_back(0); if (use_y) axes.push_back(1); if (use_z) axes.push_back(2); if (axes.size() == 0) { cvm::error("Error: a \"cartesian\" component was defined with all three axes disabled.\n"); return; } x.type(colvarvalue::type_vector); enable(f_cvc_implicit_gradient); x.vector1d_value.resize(atoms->size() * axes.size()); }
colvar::h_bond::h_bond(std::string const &conf) : cvc(conf) { if (cvm::debug()) cvm::log("Initializing h_bond object.\n"); function_type = "h_bond"; x.type(colvarvalue::type_scalar); int a_num, d_num; get_keyval(conf, "acceptor", a_num, -1); get_keyval(conf, "donor", d_num, -1); if ( (a_num == -1) || (d_num == -1) ) { cvm::fatal_error("Error: either acceptor or donor undefined.\n"); } cvm::atom acceptor = cvm::atom(a_num); cvm::atom donor = cvm::atom(d_num); atom_groups.push_back(new cvm::atom_group); atom_groups[0]->add_atom(acceptor); atom_groups[0]->add_atom(donor); get_keyval(conf, "cutoff", r0, (3.3 * cvm::unit_angstrom())); get_keyval(conf, "expNumer", en, 6); get_keyval(conf, "expDenom", ed, 8); if ( (en%2) || (ed%2) ) { cvm::fatal_error("Error: odd exponents provided, can only use even ones.\n"); } if (cvm::debug()) cvm::log("Done initializing h_bond object.\n"); }
colvar::distance_z::distance_z(std::string const &conf) : cvc(conf) { function_type = "distance_z"; b_inverse_gradients = true; b_Jacobian_derivative = true; x.type(colvarvalue::type_scalar); // TODO detect PBC from MD engine (in simple cases) // and then update period in real time if (period != 0.0) b_periodic = true; if ((wrap_center != 0.0) && (period == 0.0)) { cvm::error("Error: wrapAround was defined in a distanceZ component," " but its period has not been set.\n"); return; } parse_group(conf, "main", main); parse_group(conf, "ref", ref1); atom_groups.push_back(&main); atom_groups.push_back(&ref1); // this group is optional parse_group(conf, "ref2", ref2, true); if (ref2.size()) { atom_groups.push_back(&ref2); cvm::log("Using axis joining the centers of mass of groups \"ref\" and \"ref2\""); fixed_axis = false; if (key_lookup(conf, "axis")) cvm::log("Warning: explicit axis definition will be ignored!"); } else { if (get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0))) { if (axis.norm2() == 0.0) { cvm::error("Axis vector is zero!"); return; } if (axis.norm2() != 1.0) { axis = axis.unit(); cvm::log("The normalized axis is: "+cvm::to_str(axis)+".\n"); } } fixed_axis = true; } if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { cvm::log("Computing distance using absolute positions (not minimal-image)"); } if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) { cvm::log("Computing system force on group \"main\" only"); } }
colvar::distance_z::distance_z(std::string const &conf) : cvc(conf) { function_type = "distance_z"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); enable(f_cvc_com_based); x.type(colvarvalue::type_scalar); // TODO detect PBC from MD engine (in simple cases) // and then update period in real time if (period != 0.0) b_periodic = true; if ((wrap_center != 0.0) && (period == 0.0)) { cvm::error("Error: wrapAround was defined in a distanceZ component," " but its period has not been set.\n"); return; } main = parse_group(conf, "main"); ref1 = parse_group(conf, "ref"); // this group is optional ref2 = parse_group(conf, "ref2", true); if (ref2 && ref2->size()) { cvm::log("Using axis joining the centers of mass of groups \"ref\" and \"ref2\""); fixed_axis = false; if (key_lookup(conf, "axis")) cvm::log("Warning: explicit axis definition will be ignored!"); } else { if (get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0))) { if (axis.norm2() == 0.0) { cvm::error("Axis vector is zero!"); return; } if (axis.norm2() != 1.0) { axis = axis.unit(); cvm::log("The normalized axis is: "+cvm::to_str(axis)+".\n"); } } fixed_axis = true; } if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { cvm::log("Computing distance using absolute positions (not minimal-image)"); } init_total_force_params(conf); }
colvar::distance_inv::distance_inv(std::string const &conf) : cvc(conf) { function_type = "distance_inv"; group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); get_keyval(conf, "exponent", exponent, 6); if (exponent%2) { cvm::error("Error: odd exponent provided, can only use even ones.\n"); return; } if (exponent <= 0) { cvm::error("Error: negative or zero exponent provided.\n"); return; } for (cvm::atom_iter ai1 = group1->begin(); ai1 != group1->end(); ai1++) { for (cvm::atom_iter ai2 = group2->begin(); ai2 != group2->end(); ai2++) { if (ai1->id == ai2->id) { cvm::error("Error: group1 and group2 have some atoms in common: this is not allowed for distanceInv.\n"); return; } } } x.type(colvarvalue::type_scalar); }
colvar::inertia_z::inertia_z (std::string const &conf) : inertia (conf) { function_type = "inertia_z"; if (get_keyval (conf, "axis", axis, cvm::rvector (0.0, 0.0, 1.0))) { if (axis.norm2() == 0.0) cvm::fatal_error ("Axis vector is zero!"); axis = axis.unit(); } x.type (colvarvalue::type_scalar); }
colvar::distance::distance (std::string const &conf, bool twogroups) : cvc (conf) { function_type = "distance"; b_inverse_gradients = true; b_Jacobian_derivative = true; 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)) { cvm::log ("Computing system force on group 1 only"); } parse_group (conf, "group1", group1); atom_groups.push_back (&group1); if (twogroups) { parse_group (conf, "group2", group2); atom_groups.push_back (&group2); } x.type (colvarvalue::type_scalar); }
colvar::selfcoordnum::selfcoordnum(std::string const &conf) : distance(conf, false) { 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 b_inverse_gradients = false; get_keyval(conf, "cutoff", r0, cvm::real(4.0 * cvm::unit_angstrom())); get_keyval(conf, "expNumer", en, int(6) ); 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"); } }
colvar::coordnum::coordnum(std::string const &conf) : distance(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() if (group1.b_dummy) cvm::fatal_error("Error: only group2 is allowed to be a dummy atom\n"); // need to specify this explicitly because the distance() constructor // has set it to true b_inverse_gradients = false; 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; if (r0_vec.y < 0.0) r0_vec.y *= -1.0; if (r0_vec.z < 0.0) r0_vec.z *= -1.0; } get_keyval(conf, "expNumer", en, int(6) ); 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"); } get_keyval(conf, "group2CenterOnly", b_group2_center_only, group2.b_dummy); }
colvar::dipole_angle::dipole_angle(std::string const &conf) : cvc(conf) { function_type = "dipole_angle"; group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); group3 = parse_group(conf, "group3"); if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) { cvm::log("Computing system force on group 1 only"); } x.type(colvarvalue::type_scalar); }
// key_release_event: When a keyboard key is released // ----------------------------------------------- >> gboolean key_release_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { guint keyval = get_keyval(event); string key = gdk_keyval_name(keyval); //printf("\"%s\"\n", key.c_str()); binds.unset(key, (GdkModifierType)event->state, &released_keys); keys_edit(); released_keys.clear(); return false; }
colvar::tilt::tilt(std::string const &conf) : orientation(conf) { function_type = "tilt"; get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0)); if (axis.norm2() != 1.0) { axis /= axis.norm(); cvm::log("Normalizing rotation axis to "+cvm::to_str(axis)+".\n"); } x.type(colvarvalue::type_scalar); }
colvar::inertia_z::inertia_z (std::string const &conf) : inertia (conf) { function_type = "inertia_z"; if (get_keyval (conf, "axis", axis, cvm::rvector (0.0, 0.0, 1.0))) { if (axis.norm2() == 0.0) cvm::fatal_error ("Axis vector is zero!"); if (axis.norm2() != 1.0) { axis = axis.unit(); cvm::log ("The normalized axis is: "+cvm::to_str (axis)+".\n"); } } x.type (colvarvalue::type_scalar); }
colvar::distance_pairs::distance_pairs(std::string const &conf) : cvc(conf) { function_type = "distance_pairs"; if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { cvm::log("Computing distance using absolute positions (not minimal-image)"); } group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); x.type(colvarvalue::type_vector); x.vector1d_value.resize(group1->size() * group2->size()); }
// key_press_event: When a keyboard key is pressed // -------------------------------------------- >> gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { //printf("keyval: %d (%s)\nhardware: %d\n", event->keyval, gdk_keyval_name(event->keyval), event->hardware_keycode); down_pos.set(mouse); guint keyval = get_keyval(event); string key = gdk_keyval_name(keyval); //printf("\"%s\"\n", key.c_str()); binds.set(key, (GdkModifierType)event->state, &pressed_keys); keys_edit(); pressed_keys.clear(); return false; }
colvar::spin_angle::spin_angle(std::string const &conf) : orientation(conf) { function_type = "spin_angle"; get_keyval(conf, "axis", axis, cvm::rvector(0.0, 0.0, 1.0)); if (axis.norm2() != 1.0) { axis /= axis.norm(); cvm::log("Normalizing rotation axis to "+cvm::to_str(axis)+".\n"); } period = 360.0; b_periodic = true; x.type(colvarvalue::type_scalar); }
colvar::angle::angle(std::string const &conf) : cvc(conf) { function_type = "angle"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); provide(f_cvc_com_based); group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); group3 = parse_group(conf, "group3"); if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) { cvm::log("Computing system force on group 1 only"); } x.type(colvarvalue::type_scalar); }
colvar::angle::angle (std::string const &conf) : cvc (conf) { function_type = "angle"; b_inverse_gradients = true; b_Jacobian_derivative = true; parse_group (conf, "group1", group1); parse_group (conf, "group2", group2); parse_group (conf, "group3", group3); atom_groups.push_back (&group1); atom_groups.push_back (&group2); atom_groups.push_back (&group3); if (get_keyval (conf, "oneSiteSystemForce", b_1site_force, false)) { cvm::log ("Computing system force on group 1 only"); } x.type (colvarvalue::type_scalar); }
colvar::distance::distance(std::string const &conf) : cvc(conf) { function_type = "distance"; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); enable(f_cvc_com_based); group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { cvm::log("Computing distance using absolute positions (not minimal-image)"); } init_total_force_params(conf); x.type(colvarvalue::type_scalar); }
colvar::distance_pairs::distance_pairs(std::string const &conf) : cvc(conf) { function_type = "distance_pairs"; b_inverse_gradients = false; b_Jacobian_derivative = false; if (get_keyval(conf, "forceNoPBC", b_no_PBC, false)) { cvm::log("Computing distance using absolute positions (not minimal-image)"); } parse_group(conf, "group1", group1); atom_groups.push_back(&group1); parse_group(conf, "group2", group2); atom_groups.push_back(&group2); x.type(colvarvalue::type_vector); x.vector1d_value.resize(group1.size() * group2.size()); }
colvar::dihedral::dihedral(std::string const &conf) : cvc(conf) { function_type = "dihedral"; period = 360.0; b_periodic = true; provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); provide(f_cvc_com_based); if (get_keyval(conf, "oneSiteSystemForce", b_1site_force, false)) { cvm::log("Computing system force on group 1 only"); } group1 = parse_group(conf, "group1"); group2 = parse_group(conf, "group2"); group3 = parse_group(conf, "group3"); group4 = parse_group(conf, "group4"); x.type(colvarvalue::type_scalar); }
colvar::distance_inv::distance_inv (std::string const &conf) : distance (conf) { function_type = "distance_inv"; get_keyval (conf, "exponent", exponent, 6); if (exponent%2) { cvm::fatal_error ("Error: odd exponent provided, can only use even ones.\n"); } if (exponent <= 0) { cvm::fatal_error ("Error: negative or zero exponent provided.\n"); } for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++) { for (cvm::atom_iter ai2 = group2.begin(); ai2 != group2.end(); ai2++) { if (ai1->id == ai2->id) cvm::fatal_error ("Error: group1 and group1 have some atoms in common: this is not allowed for distanceInv.\n"); } } b_inverse_gradients = false; b_Jacobian_derivative = false; x.type (colvarvalue::type_scalar); }
colvar::cvc::cvc(std::string const &conf) : sup_coeff(1.0), sup_np(1), b_periodic(false), b_try_scalable(true) { if (cvm::debug()) cvm::log("Initializing cvc base object.\n"); init_cvc_requires(); if (get_keyval(conf, "name", this->name, std::string(""), parse_silent)) { // Temporary description until child object is initialized description = "cvc " + name; } else { description = "uninitialized cvc"; } get_keyval(conf, "componentCoeff", sup_coeff, 1.0); get_keyval(conf, "componentExp", sup_np, 1); get_keyval(conf, "period", period, 0.0); get_keyval(conf, "wrapAround", wrap_center, 0.0); // All cvcs implement this provide(f_cvc_debug_gradient); { bool b_debug_gradient; get_keyval(conf, "debugGradients", b_debug_gradient, false, parse_silent); if (b_debug_gradient) enable(f_cvc_debug_gradient); } // Attempt scalable calculations when in parallel? (By default yes, if available) get_keyval(conf, "scalable", b_try_scalable, true); if (cvm::debug()) cvm::log("Done initializing cvc base object.\n"); }
colvar::cvc::cvc (std::string const &conf) : sup_coeff (1.0), sup_np (1), b_periodic (false), b_debug_gradients (false), b_inverse_gradients (false), b_Jacobian_derivative (false) { if (cvm::debug()) cvm::log ("Initializing cvc base object.\n"); get_keyval (conf, "name", this->name, std::string (""), parse_silent); get_keyval (conf, "componentCoeff", sup_coeff, 1.0); get_keyval (conf, "componentExp", sup_np, 1); get_keyval (conf, "period", period, 0.0); get_keyval (conf, "wrapAround", wrap_center, 0.0); get_keyval (conf, "debugGradients", b_debug_gradients, false, parse_silent); if (cvm::debug()) cvm::log ("Done initializing cvc base object.\n"); }
colvar::eigenvector::eigenvector (std::string const &conf) : cvc (conf) { b_inverse_gradients = true; b_Jacobian_derivative = true; function_type = "eigenvector"; x.type (colvarvalue::type_scalar); parse_group (conf, "atoms", atoms); atom_groups.push_back (&atoms); if (atoms.b_rotate) { cvm::fatal_error ("Error: rotateReference should be disabled:" "eigenvector component will set it internally."); } if (get_keyval (conf, "refPositions", ref_pos, ref_pos)) { cvm::log ("Using reference positions from input file.\n"); if (ref_pos.size() != atoms.size()) { cvm::fatal_error ("Error: reference positions do not " "match the number of requested atoms.\n"); } } { std::string file_name; if (get_keyval (conf, "refPositionsFile", file_name)) { std::string file_col; double file_col_value; if (get_keyval (conf, "refPositionsCol", file_col, std::string (""))) { // use PDB flags if column is provided bool found = get_keyval (conf, "refPositionsColValue", file_col_value, 0.0); if (found && !file_col_value) cvm::fatal_error ("Error: refPositionsColValue, " "if provided, must be non-zero.\n"); } else { // if not, use atom indices atoms.create_sorted_ids(); } ref_pos.resize (atoms.size()); cvm::load_coords (file_name.c_str(), ref_pos, atoms.sorted_ids, file_col, file_col_value); } } // Set mobile frame of reference for atom group atoms.b_center = true; atoms.b_rotate = true; atoms.ref_pos = ref_pos; // now load the eigenvector if (get_keyval (conf, "vector", eigenvec, eigenvec)) { cvm::log ("Using vector components from input file.\n"); if (eigenvec.size() != atoms.size()) { cvm::fatal_error ("Error: vector components do not " "match the number of requested atoms.\n"); } } { std::string file_name; if (get_keyval (conf, "vectorFile", file_name)) { std::string file_col; if (!get_keyval (conf, "vectorCol", file_col, std::string (""))) { cvm::fatal_error ("Error: parameter vectorCol is required if vectorFile is set.\n"); } double file_col_value; bool found = get_keyval (conf, "vectorColValue", file_col_value, 0.0); if (found && !file_col_value) cvm::fatal_error ("Error: eigenvectorColValue, " "if provided, must be non-zero.\n"); eigenvec.resize (atoms.size()); cvm::load_coords (file_name.c_str(), eigenvec, atoms.sorted_ids, file_col, file_col_value); } } if (!ref_pos.size() || !eigenvec.size()) { cvm::fatal_error ("Error: both reference coordinates" "and eigenvector must be defined.\n"); } cvm::rvector center (0.0, 0.0, 0.0); eigenvec_invnorm2 = 0.0; for (size_t i = 0; i < atoms.size(); i++) { center += eigenvec[i]; } cvm::log ("Subtracting sum of eigenvector components: " + cvm::to_str (center) + "\n"); for (size_t i = 0; i < atoms.size(); i++) { eigenvec[i] = eigenvec[i] - center; eigenvec_invnorm2 += eigenvec[i].norm2(); } eigenvec_invnorm2 = 1.0 / eigenvec_invnorm2; // request derivatives of optimal rotation wrt 2nd group // for Jacobian atoms.rot.request_group1_gradients(atoms.size()); atoms.rot.request_group2_gradients(atoms.size()); }
int main(int argc, char **argv) { char *descriptor; char *curpos; /* current position in input string */ struct keyval *parser_id; /* the parser we are creating output for */ FILE *outputf; struct keyval *rkv; /* current read key:val */ struct keyval_list *curlist; bool do_token_check = true; /* if the check for valid tokens is done */ bool only_ident = true; /* if the only token type is ident */ bool is_generic = false; struct keyval_list base; struct keyval_list IDENT; struct keyval_list IDENT_LIST; struct keyval_list LENGTH_UNIT; struct keyval_list URI; struct keyval_list WRAP; struct keyval_list NUMBER; struct keyval_list COLOR; if (argc < 2) { fprintf(stderr,"Usage: %s [-o <filename>] <descriptor>\n", argv[0]); return 1; } if ((argv[1][0] == '-') && (argv[1][1] == 'o')) { if (argc != 4) { fprintf(stderr,"Usage: %s [-o <filename>] <descriptor>\n", argv[0]); return 1; } outputf = fopen(argv[2], "w"); if (outputf == NULL) { perror("unable to open file"); } descriptor = strdup(argv[3]); } else { outputf = stdout; descriptor = strdup(argv[1]); } curpos = descriptor; base.count = 0; IDENT.count = 0; URI.count = 0; WRAP.count = 0; NUMBER.count = 0; COLOR.count = 0; LENGTH_UNIT.count = 0; IDENT_LIST.count = 0; curlist = &base; while (*curpos != 0) { rkv = get_keyval(&curpos); if (rkv == NULL) { fprintf(stderr,"Token error at offset %ld\n", curpos - descriptor); fclose(outputf); return 2; } if (strcmp(rkv->key, "WRAP") == 0) { WRAP.item[WRAP.count++] = rkv; only_ident = false; } else if (strcmp(rkv->key, "NUMBER") == 0) { if (rkv->val[0] == '(') { curlist = &NUMBER; } else if (rkv->val[0] == ')') { curlist = &base; } else { NUMBER.item[NUMBER.count++] = rkv; } only_ident = false; } else if (strcmp(rkv->key, "IDENT") == 0) { if (rkv->val[0] == '(') { curlist = &IDENT; } else if (rkv->val[0] == ')') { curlist = &base; } else if (strcmp(rkv->val, str_INHERIT) == 0) { IDENT.item[IDENT.count++] = &ident_inherit; } } else if (strcmp(rkv->key, "IDENT_LIST") == 0) { if (rkv->val[0] == '(') { curlist = &IDENT_LIST; } else if (rkv->val[0] == ')') { curlist = &base; } } else if (strcmp(rkv->key, "LENGTH_UNIT") == 0) { if (rkv->val[0] == '(') { curlist = &LENGTH_UNIT; } else if (rkv->val[0] == ')') { curlist = &base; } only_ident = false; do_token_check = false; } else if (strcmp(rkv->key, "COLOR") == 0) { COLOR.item[COLOR.count++] = rkv; do_token_check = false; only_ident = false; } else if (strcmp(rkv->key, "URI") == 0) { URI.item[URI.count++] = rkv; only_ident = false; } else if (strcmp(rkv->key, "GENERIC") == 0) { is_generic = true; } else { /* just append to current list */ curlist->item[curlist->count++] = rkv; } } if (base.count != 1) { fprintf(stderr,"Incorrect base element count (got %d expected 1)\n", base.count); fclose(outputf); return 3; } /* header */ output_header(outputf, descriptor, base.item[0], is_generic); if (WRAP.count > 0) { output_wrap(outputf, base.item[0], &WRAP); } else { /* check token type is correct */ output_token_type_check(outputf, do_token_check, &IDENT, &URI, &NUMBER); if (IDENT.count > 0) output_ident(outputf, only_ident, base.item[0], &IDENT); if (URI.count > 0) output_uri(outputf, base.item[0], &URI); if (NUMBER.count > 0) output_number(outputf, base.item[0], &NUMBER); /* terminal blocks, these end the ladder ie no trailing else */ if (COLOR.count > 0) { output_color(outputf, base.item[0], &COLOR); } else if (LENGTH_UNIT.count > 0) { output_length_unit(outputf, base.item[0], &LENGTH_UNIT); } else if (IDENT_LIST.count > 0) { output_ident_list(outputf, base.item[0], &IDENT_LIST); } else { output_invalidcss(outputf); } output_footer(outputf); } fclose(outputf); return 0; }
int colvarbias_abf::init(std::string const &conf) { colvarbias::init(conf); enable(f_cvb_scalar_variables); enable(f_cvb_calc_pmf); // TODO relax this in case of VMD plugin if (cvm::temperature() == 0.0) cvm::log("WARNING: ABF should not be run without a thermostat or at 0 Kelvin!\n"); // ************* parsing general ABF options *********************** get_keyval_feature((colvarparse *)this, conf, "applyBias", f_cvb_apply_force, true); if (!is_enabled(f_cvb_apply_force)){ cvm::log("WARNING: ABF biases will *not* be applied!\n"); } get_keyval(conf, "updateBias", update_bias, true); if (update_bias) { enable(f_cvb_history_dependent); } else { cvm::log("WARNING: ABF biases will *not* be updated!\n"); } get_keyval(conf, "hideJacobian", hide_Jacobian, false); if (hide_Jacobian) { cvm::log("Jacobian (geometric) forces will be handled internally.\n"); } else { cvm::log("Jacobian (geometric) forces will be included in reported free energy gradients.\n"); } get_keyval(conf, "fullSamples", full_samples, 200); if ( full_samples <= 1 ) full_samples = 1; min_samples = full_samples / 2; // full_samples - min_samples >= 1 is guaranteed get_keyval(conf, "inputPrefix", input_prefix, std::vector<std::string>()); get_keyval(conf, "outputFreq", output_freq, cvm::restart_out_freq); get_keyval(conf, "historyFreq", history_freq, 0); b_history_files = (history_freq > 0); // shared ABF get_keyval(conf, "shared", shared_on, false); if (shared_on) { if (!cvm::replica_enabled() || cvm::replica_num() <= 1) { cvm::error("Error: shared ABF requires more than one replica."); return COLVARS_ERROR; } cvm::log("shared ABF will be applied among "+ cvm::to_str(cvm::replica_num()) + " replicas.\n"); if (cvm::proxy->smp_enabled() == COLVARS_OK) { cvm::error("Error: shared ABF is currently not available with SMP parallelism; " "please set \"SMP off\" at the top of the Colvars configuration file.\n", COLVARS_NOT_IMPLEMENTED); return COLVARS_NOT_IMPLEMENTED; } // If shared_freq is not set, we default to output_freq get_keyval(conf, "sharedFreq", shared_freq, output_freq); } // ************* checking the associated colvars ******************* if (num_variables() == 0) { cvm::error("Error: no collective variables specified for the ABF bias.\n"); return COLVARS_ERROR; } if (update_bias) { // Request calculation of total force if(enable(f_cvb_get_total_force)) return cvm::get_error(); } bool b_extended = false; size_t i; for (i = 0; i < num_variables(); i++) { if (colvars[i]->value().type() != colvarvalue::type_scalar) { cvm::error("Error: ABF bias can only use scalar-type variables.\n"); } colvars[i]->enable(f_cv_grid); if (hide_Jacobian) { colvars[i]->enable(f_cv_hide_Jacobian); } // If any colvar is extended-system, we need to collect the extended // system gradient if (colvars[i]->is_enabled(f_cv_extended_Lagrangian)) b_extended = true; // Cannot mix and match coarse time steps with ABF because it gives // wrong total force averages - total force needs to be averaged over // every time step if (colvars[i]->get_time_step_factor() != time_step_factor) { cvm::error("Error: " + colvars[i]->description + " has a value of timeStepFactor (" + cvm::to_str(colvars[i]->get_time_step_factor()) + ") different from that of " + description + " (" + cvm::to_str(time_step_factor) + ").\n"); return COLVARS_ERROR; } // Here we could check for orthogonality of the Cartesian coordinates // and make it just a warning if some parameter is set? } if (get_keyval(conf, "maxForce", max_force)) { if (max_force.size() != num_variables()) { cvm::error("Error: Number of parameters to maxForce does not match number of colvars."); } for (i = 0; i < num_variables(); i++) { if (max_force[i] < 0.0) { cvm::error("Error: maxForce should be non-negative."); } } cap_force = true; } else { cap_force = false; } bin.assign(num_variables(), 0); force_bin.assign(num_variables(), 0); system_force = new cvm::real [num_variables()]; // Construct empty grids based on the colvars if (cvm::debug()) { cvm::log("Allocating count and free energy gradient grids.\n"); } samples = new colvar_grid_count(colvars); gradients = new colvar_grid_gradient(colvars); gradients->samples = samples; samples->has_parent_data = true; // Data for eAB F z-based estimator if ( b_extended ) { get_keyval(conf, "CZARestimator", b_CZAR_estimator, true); // CZAR output files for stratified eABF get_keyval(conf, "writeCZARwindowFile", b_czar_window_file, false, colvarparse::parse_silent); z_bin.assign(num_variables(), 0); z_samples = new colvar_grid_count(colvars); z_samples->request_actual_value(); z_gradients = new colvar_grid_gradient(colvars); z_gradients->request_actual_value(); z_gradients->samples = z_samples; z_samples->has_parent_data = true; czar_gradients = new colvar_grid_gradient(colvars); } // For now, we integrate on-the-fly iff the grid is < 3D if ( num_variables() <= 3 ) { pmf = new integrate_potential(colvars, gradients); if ( b_CZAR_estimator ) { czar_pmf = new integrate_potential(colvars, czar_gradients); } get_keyval(conf, "integrate", b_integrate, true); // Integrate for output if ( num_variables() > 1 ) { // Projected ABF get_keyval(conf, "pABFintegrateFreq", pabf_freq, 0); // Parameters for integrating initial (and final) gradient data get_keyval(conf, "integrateInitSteps", integrate_initial_steps, 1e4); get_keyval(conf, "integrateInitTol", integrate_initial_tol, 1e-6); // for updating the integrated PMF on the fly get_keyval(conf, "integrateSteps", integrate_steps, 100); get_keyval(conf, "integrateTol", integrate_tol, 1e-4); } } else { b_integrate = false; } // For shared ABF, we store a second set of grids. // This used to be only if "shared" was defined, // but now we allow calling share externally (e.g. from Tcl). last_samples = new colvar_grid_count(colvars); last_gradients = new colvar_grid_gradient(colvars); last_gradients->samples = last_samples; last_samples->has_parent_data = true; shared_last_step = -1; // If custom grids are provided, read them if ( input_prefix.size() > 0 ) { read_gradients_samples(); // Update divergence to account for input data pmf->set_div(); } // if extendedLangrangian is on, then call UI estimator if (b_extended) { get_keyval(conf, "UIestimator", b_UI_estimator, false); if (b_UI_estimator) { std::vector<double> UI_lowerboundary; std::vector<double> UI_upperboundary; std::vector<double> UI_width; std::vector<double> UI_krestr; bool UI_restart = (input_prefix.size() > 0); for (i = 0; i < num_variables(); i++) { UI_lowerboundary.push_back(colvars[i]->lower_boundary); UI_upperboundary.push_back(colvars[i]->upper_boundary); UI_width.push_back(colvars[i]->width); UI_krestr.push_back(colvars[i]->force_constant()); } eabf_UI = UIestimator::UIestimator(UI_lowerboundary, UI_upperboundary, UI_width, UI_krestr, // force constant in eABF output_prefix, // the prefix of output files cvm::restart_out_freq, UI_restart, // whether restart from a .count and a .grad file input_prefix, // the prefixes of input files cvm::temperature()); } } cvm::log("Finished ABF setup.\n"); return COLVARS_OK; }
colvar::eigenvector::eigenvector(std::string const &conf) : cvc(conf) { provide(f_cvc_inv_gradient); provide(f_cvc_Jacobian); function_type = "eigenvector"; x.type(colvarvalue::type_scalar); atoms = parse_group(conf, "atoms"); { bool const b_inline = get_keyval(conf, "refPositions", ref_pos, ref_pos); if (b_inline) { cvm::log("Using reference positions from input file.\n"); if (ref_pos.size() != atoms->size()) { cvm::error("Error: reference positions do not " "match the number of requested atoms.\n"); return; } } std::string file_name; if (get_keyval(conf, "refPositionsFile", file_name)) { if (b_inline) { cvm::error("Error: refPositions and refPositionsFile cannot be specified at the same time.\n"); return; } std::string file_col; double file_col_value=0.0; if (get_keyval(conf, "refPositionsCol", file_col, std::string(""))) { // use PDB flags if column is provided bool found = get_keyval(conf, "refPositionsColValue", file_col_value, 0.0); if (found && file_col_value==0.0) { cvm::error("Error: refPositionsColValue, " "if provided, must be non-zero.\n"); return; } } else { // if not, use atom indices atoms->create_sorted_ids(); } ref_pos.resize(atoms->size()); cvm::load_coords(file_name.c_str(), ref_pos, atoms->sorted_ids, file_col, file_col_value); } } if (ref_pos.size() == 0) { cvm::error("Error: reference positions were not provided.\n", INPUT_ERROR); return; } if (ref_pos.size() != atoms->size()) { cvm::error("Error: reference positions do not " "match the number of requested atoms.\n", INPUT_ERROR); return; } // save for later the geometric center of the provided positions (may not be the origin) cvm::rvector ref_pos_center(0.0, 0.0, 0.0); for (size_t i = 0; i < atoms->size(); i++) { ref_pos_center += ref_pos[i]; } ref_pos_center *= 1.0 / atoms->size(); if (atoms->b_user_defined_fit) { cvm::log("WARNING: explicit fitting parameters were provided for atom group \"atoms\".\n"); } else { // default: fit everything cvm::log("Enabling \"centerReference\" and \"rotateReference\", to minimize RMSD before calculating the vector projection: " "if this is not the desired behavior, disable them explicitly within the \"atoms\" block.\n"); atoms->b_center = true; atoms->b_rotate = true; atoms->ref_pos = ref_pos; atoms->center_ref_pos(); atoms->disable(f_ag_fit_gradients); // cancel out if group is fitted on itself // and cvc is translationally invariant // request the calculation of the derivatives of the rotation defined by the atom group atoms->rot.request_group1_gradients(atoms->size()); // request derivatives of optimal rotation wrt reference coordinates for Jacobian: // this is only required for ABF, but we do both groups here for better caching atoms->rot.request_group2_gradients(atoms->size()); } { bool const b_inline = get_keyval(conf, "vector", eigenvec, eigenvec); // now load the eigenvector if (b_inline) { cvm::log("Using vector components from input file.\n"); if (eigenvec.size() != atoms->size()) { cvm::error("Error: vector components do not " "match the number of requested atoms->\n"); return; } } std::string file_name; if (get_keyval(conf, "vectorFile", file_name)) { if (b_inline) { cvm::error("Error: vector and vectorFile cannot be specified at the same time.\n"); return; } std::string file_col; double file_col_value=0.0; if (get_keyval(conf, "vectorCol", file_col, std::string(""))) { // use PDB flags if column is provided bool found = get_keyval(conf, "vectorColValue", file_col_value, 0.0); if (found && file_col_value==0.0) { cvm::error("Error: vectorColValue, if provided, must be non-zero.\n"); return; } } else { // if not, use atom indices atoms->create_sorted_ids(); } eigenvec.resize(atoms->size()); cvm::load_coords(file_name.c_str(), eigenvec, atoms->sorted_ids, file_col, file_col_value); } } if (!ref_pos.size() || !eigenvec.size()) { cvm::error("Error: both reference coordinates" "and eigenvector must be defined.\n"); return; } cvm::atom_pos eig_center(0.0, 0.0, 0.0); for (size_t eil = 0; eil < atoms->size(); eil++) { eig_center += eigenvec[eil]; } eig_center *= 1.0 / atoms->size(); cvm::log("Geometric center of the provided vector: "+cvm::to_str(eig_center)+"\n"); bool b_difference_vector = false; get_keyval(conf, "differenceVector", b_difference_vector, false); if (b_difference_vector) { if (atoms->b_center) { // both sets should be centered on the origin for fitting for (size_t i = 0; i < atoms->size(); i++) { eigenvec[i] -= eig_center; ref_pos[i] -= ref_pos_center; } } if (atoms->b_rotate) { atoms->rot.calc_optimal_rotation(eigenvec, ref_pos); for (size_t i = 0; i < atoms->size(); i++) { eigenvec[i] = atoms->rot.rotate(eigenvec[i]); } } cvm::log("\"differenceVector\" is on: subtracting the reference positions from the provided vector: v = v - x0.\n"); for (size_t i = 0; i < atoms->size(); i++) { eigenvec[i] -= ref_pos[i]; } if (atoms->b_center) { // bring back the ref positions to where they were for (size_t i = 0; i < atoms->size(); i++) { ref_pos[i] += ref_pos_center; } } } else { cvm::log("Centering the provided vector to zero.\n"); for (size_t i = 0; i < atoms->size(); i++) { eigenvec[i] -= eig_center; } } // cvm::log("The first three components(v1x, v1y, v1z) of the resulting vector are: "+cvm::to_str (eigenvec[0])+".\n"); // for inverse gradients eigenvec_invnorm2 = 0.0; for (size_t ein = 0; ein < atoms->size(); ein++) { eigenvec_invnorm2 += eigenvec[ein].norm2(); } eigenvec_invnorm2 = 1.0 / eigenvec_invnorm2; if (b_difference_vector) { cvm::log("\"differenceVector\" is on: normalizing the vector.\n"); for (size_t i = 0; i < atoms->size(); i++) { eigenvec[i] *= eigenvec_invnorm2; } } else { cvm::log("The norm of the vector is |v| = "+cvm::to_str(eigenvec_invnorm2)+".\n"); } }
colvar::rmsd::rmsd(std::string const &conf) : cvc(conf) { provide(f_cvc_inv_gradient); function_type = "rmsd"; x.type(colvarvalue::type_scalar); atoms = parse_group(conf, "atoms"); if (!atoms || atoms->size() == 0) { cvm::error("Error: \"atoms\" must contain at least 1 atom to compute RMSD."); return; } bool b_Jacobian_derivative = true; 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; } if (b_Jacobian_derivative) provide(f_cvc_Jacobian); // 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 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()) { cvm::error("Error: the number of reference positions provided ("+ cvm::to_str(ref_pos.size())+ ") does not match the number of atoms of group \"atoms\" ("+ cvm::to_str(atoms->size())+").\n"); return; } } { std::string ref_pos_file; if (get_keyval(conf, "refPositionsFile", ref_pos_file, std::string(""))) { if (ref_pos.size()) { cvm::error("Error: cannot specify \"refPositionsFile\" and " "\"refPositions\" at the same time.\n"); return; } std::string ref_pos_col; double ref_pos_col_value=0.0; if (get_keyval(conf, "refPositionsCol", ref_pos_col, std::string(""))) { // if provided, use PDB column to select coordinates bool found = get_keyval(conf, "refPositionsColValue", ref_pos_col_value, 0.0); if (found && ref_pos_col_value==0.0) { cvm::error("Error: refPositionsColValue, " "if provided, must be non-zero.\n"); return; } } else { // if not, rely on existing atom indices for the group atoms->create_sorted_ids(); ref_pos.resize(atoms->size()); } cvm::load_coords(ref_pos_file.c_str(), ref_pos, atoms->sorted_ids, ref_pos_col, ref_pos_col_value); } } if (ref_pos.size() != atoms->size()) { cvm::error("Error: found " + cvm::to_str(ref_pos.size()) + " reference positions; expected " + cvm::to_str(atoms->size())); return; } if (atoms->b_user_defined_fit) { cvm::log("WARNING: explicit fitting parameters were provided for atom group \"atoms\"."); } else { // Default: fit everything cvm::log("Enabling \"centerReference\" and \"rotateReference\", to minimize RMSD before calculating it as a variable: " "if this is not the desired behavior, disable them explicitly within the \"atoms\" block.\n"); atoms->b_center = true; atoms->b_rotate = true; // default case: reference positions for calculating the rmsd are also those used // for fitting atoms->ref_pos = ref_pos; atoms->center_ref_pos(); cvm::log("This is a standard minimum RMSD, derivatives of the optimal rotation " "will not be computed as they cancel out in the gradients."); atoms->disable(f_ag_fit_gradients); // request the calculation of the derivatives of the rotation defined by the atom group atoms->rot.request_group1_gradients(atoms->size()); // request derivatives of optimal rotation wrt reference coordinates for Jacobian: // this is only required for ABF, but we do both groups here for better caching atoms->rot.request_group2_gradients(atoms->size()); } }