00001 // -*- c++ -*- 00002 00003 // This file is part of the Collective Variables module (Colvars). 00004 // The original version of Colvars and its updates are located at: 00005 // https://github.com/Colvars/colvars 00006 // Please update all Colvars source files before making any changes. 00007 // If you wish to distribute your changes, please submit them to the 00008 // Colvars repository at GitHub. 00009 00010 #include "colvarmodule.h" 00011 #include "colvarvalue.h" 00012 #include "colvarparse.h" 00013 #include "colvar.h" 00014 #include "colvarcomp.h" 00015 00016 00017 00018 colvar::map_total::map_total() 00019 : cvc() 00020 { 00021 set_function_type("mapTotal"); 00022 volmap_id = -1; 00023 volmap_index = -1; 00024 atoms = NULL; 00025 x.type(colvarvalue::type_scalar); 00026 } 00027 00028 00029 colvar::map_total::map_total(std::string const &conf) 00030 : cvc() // init() will take care of this 00031 { 00032 set_function_type("mapTotal"); 00033 volmap_id = -1; 00034 volmap_index = -1; 00035 atoms = NULL; 00036 x.type(colvarvalue::type_scalar); 00037 map_total::init(conf); 00038 } 00039 00040 00041 int colvar::map_total::init(std::string const &conf) 00042 { 00043 int error_code = cvc::init(conf); 00044 colvarproxy *proxy = cvm::main()->proxy; 00045 get_keyval(conf, "mapName", volmap_name, volmap_name); 00046 get_keyval(conf, "mapID", volmap_id, volmap_id); 00047 register_param("mapID", reinterpret_cast<void *>(&volmap_id)); 00048 00049 cvm::main()->cite_feature("Volumetric map-based collective variables"); 00050 00051 if ((volmap_name.size() > 0) && (volmap_id >= 0)) { 00052 error_code |= 00053 cvm::error("Error: mapName and mapID are mutually exclusive.\n"); 00054 } 00055 00056 // Parse optional group 00057 atoms = parse_group(conf, "atoms", true); 00058 if (atoms != NULL) { 00059 00060 // Using internal selection 00061 if (volmap_name.size()) { 00062 error_code |= proxy->check_volmap_by_name(volmap_name); 00063 } 00064 if (volmap_id >= 0) { 00065 error_code |= proxy->check_volmap_by_id(volmap_id); 00066 } 00067 00068 } else { 00069 00070 // Using selection from the MD engine 00071 if (volmap_name.size()) { 00072 volmap_index = proxy->init_volmap_by_name(volmap_name); 00073 } 00074 if (volmap_id >= 0) { 00075 volmap_index = proxy->init_volmap_by_id(volmap_id); 00076 } 00077 error_code |= volmap_index > 0 ? COLVARS_OK : COLVARS_INPUT_ERROR; 00078 } 00079 00080 if (get_keyval(conf, "atomWeights", atom_weights, atom_weights)) { 00081 if (atoms == NULL) { 00082 error_code |= cvm::error("Error: weights can only be assigned when atoms " 00083 "are selected explicitly in Colvars.\n", 00084 COLVARS_INPUT_ERROR); 00085 } else { 00086 if (atoms->size() != atom_weights.size()) { 00087 error_code |= cvm::error("Error: if defined, the number of weights ("+ 00088 cvm::to_str(atom_weights.size())+ 00089 ") must equal the number of atoms ("+ 00090 cvm::to_str(atoms->size())+ 00091 ").\n", COLVARS_INPUT_ERROR); 00092 } 00093 } 00094 } 00095 00096 if (volmap_name.size() > 0) { 00097 volmap_id = proxy->get_volmap_id_from_name(volmap_name.c_str()); 00098 } 00099 00100 return error_code; 00101 } 00102 00103 00104 void colvar::map_total::calc_value() 00105 { 00106 colvarproxy *proxy = cvm::main()->proxy; 00107 int flags = is_enabled(f_cvc_gradient) ? colvarproxy::volmap_flag_gradients : 00108 colvarproxy::volmap_flag_null; 00109 00110 if (atoms != NULL) { 00111 // Compute the map inside Colvars 00112 x.real_value = 0.0; 00113 00114 cvm::real *w = NULL; 00115 if (atom_weights.size() > 0) { 00116 flags |= colvarproxy::volmap_flag_use_atom_field; 00117 w = &(atom_weights[0]); 00118 } 00119 proxy->compute_volmap(flags, volmap_id, atoms->begin(), atoms->end(), 00120 &(x.real_value), w); 00121 } else { 00122 // Get the externally computed value 00123 x.real_value = proxy->get_volmap_value(volmap_index); 00124 } 00125 } 00126 00127 00128 void colvar::map_total::calc_gradients() 00129 { 00130 // Computed in calc_value() or by the MD engine 00131 } 00132 00133 00134 void colvar::map_total::apply_force(colvarvalue const &force) 00135 { 00136 colvarproxy *proxy = cvm::main()->proxy; 00137 if (atoms) { 00138 if (!atoms->noforce) 00139 atoms->apply_colvar_force(force.real_value); 00140 } else { 00141 proxy->apply_volmap_force(volmap_index, force.real_value); 00142 } 00143 }