37 #include "colvarmodule.h" 39 #include "colvarbias.h" 40 #include "colvaratoms.h" 41 #include "colvarproxy.h" 43 #include "colvarscript.h" 48 engine_name_ =
"NAMD";
49 #if CMK_SMP && USE_CKLOOP 50 charm_lock_state = CmiCreateLock();
55 if ( 0 == CkMyPe() ) {
64 boltzmann_ = 0.001987191;
72 iout <<
"Info: initializing the colvars proxy object.\n" <<
endi;
79 colvarproxy_io::set_input_prefix(input_restart ? input_restart->
data :
"");
87 updated_masses_ = updated_charges_ =
true;
102 if ((!output_prefix_str.size()) && (!restart_output_prefix_str.size())) {
103 error(
"Error: neither the final output state file or " 104 "the output restart file could be defined, exiting.\n");
110 colvars =
new colvarmodule(
this);
112 cvm::log(
"Using NAMD interface, version "+
114 colvars->cite_feature(
"NAMD engine");
115 colvars->cite_feature(
"Colvars-NAMD interface");
118 for ( ; config; config = config->
next ) {
119 add_config(
"configfile", config->
data);
123 colvarproxy::parse_module_config();
125 colvars->update_engine_parameters();
126 colvars->setup_input();
127 colvars->setup_output();
135 have_scripts =
false;
142 #if !defined (NAMD_UNIFIED_REDUCTION) 146 #if defined(NODEGROUP_FORCE_REGISTER) && !defined(NAMD_UNIFIED_REDUCTION) 147 CProxy_PatchData cpdata(CkpvAccess(BOCclass_group).patchData);
148 PatchData *patchData = cpdata.ckLocalBranch();
153 iout <<
"Info: done initializing the colvars proxy object.\n" <<
endi;
159 #if CMK_SMP && USE_CKLOOP 160 CmiDestroyLock(charm_lock_state);
162 #if !defined (NAMD_UNIFIED_REDUCTION) 170 int error_code = COLVARS_OK;
184 error_code |= set_target_temperature(0.0);
209 for (
size_t i = 0; i < atoms_ids.size(); i++) {
210 if (atoms_ids[i] == *a_i) {
219 int const index = add_atom_slot(*a_i);
227 cvm::log(
"atoms_map = "+cvm::to_str(
atoms_map)+
".\n");
236 int error_code = colvarproxy::setup();
238 if (colvars->size() == 0) {
243 log(
"Updating NAMD interface:\n");
248 log(
"Warning: enabling wrapAll can lead to inconsistent results " 249 "for Colvars calculations: please disable wrapAll, " 250 "as is the default option in NAMD.\n");
253 log(
"updating atomic data ("+cvm::to_str(atoms_ids.size())+
" atoms).\n");
256 for (i = 0; i < atoms_ids.size(); i++) {
260 atoms_positions[i] = cvm::rvector(0.0, 0.0, 0.0);
261 atoms_total_forces[i] = cvm::rvector(0.0, 0.0, 0.0);
262 atoms_new_colvar_forces[i] = cvm::rvector(0.0, 0.0, 0.0);
265 size_t n_group_atoms = 0;
270 log(
"updating group data ("+cvm::to_str(atom_groups_ids.size())+
271 " scalable groups, "+
272 cvm::to_str(n_group_atoms)+
" atoms in total).\n");
280 atom_groups_coms[ig] = cvm::rvector(0.0, 0.0, 0.0);
281 atom_groups_total_forces[ig] = cvm::rvector(0.0, 0.0, 0.0);
282 atom_groups_new_colvar_forces[ig] = cvm::rvector(0.0, 0.0, 0.0);
285 #if NAMD_VERSION_NUMBER >= 34471681 286 log(
"updating grid object data ("+cvm::to_str(volmaps_ids.size())+
287 " grid objects in total).\n");
289 volmaps_new_colvar_forces[imap] = 0.0;
293 size_t const new_features_hash =
294 std::hash<std::string>{}(colvars->feature_report(0));
295 if (new_features_hash != features_hash) {
297 log(std::string(
"\n")+colvars->feature_report(0)+std::string(
"\n"));
298 features_hash = new_features_hash;
302 log(
"updating target temperature (T = "+
303 cvm::to_str(target_temperature())+
" K).\n");
316 cvm::log(
"colvarproxy_namd::reset()\n");
319 int error_code = COLVARS_OK;
329 #if NAMD_VERSION_NUMBER >= 34471681 339 error_code |= colvarproxy::reset();
354 colvars->update_engine_parameters();
355 colvars->setup_input();
356 colvars->setup_output();
367 b_simulation_continuing =
false;
375 b_simulation_continuing =
true;
381 colvars->setup_output();
393 unit_cell_x.
set(a.
x, a.
y, a.
z);
394 unit_cell_y.set(b.
x, b.
y, c.
z);
395 unit_cell_z.set(c.
x, c.
y, c.
z);
399 boundaries_type = boundaries_non_periodic;
403 boundaries_type = boundaries_pbc_ortho;
405 boundaries_type = boundaries_pbc_triclinic;
407 colvarproxy_system::update_pbc_lattice();
409 boundaries_type = boundaries_unsupported;
413 cvm::log(std::string(cvm::line_marker)+
414 "colvarproxy_namd, step no. "+cvm::to_str(colvars->it)+
"\n"+
415 "Updating atomic data arrays.\n");
427 if ( (
atoms_map.size() != n_all_atoms) ||
435 for (
size_t i = 0; i < atoms_ids.size(); i++) {
436 atoms_positions[i] = cvm::rvector(0.0, 0.0, 0.0);
437 atoms_total_forces[i] = cvm::rvector(0.0, 0.0, 0.0);
438 atoms_new_colvar_forces[i] = cvm::rvector(0.0, 0.0, 0.0);
441 for (
size_t i = 0; i < atom_groups_ids.size(); i++) {
442 atom_groups_total_forces[i] = cvm::rvector(0.0, 0.0, 0.0);
443 atom_groups_new_colvar_forces[i] = cvm::rvector(0.0, 0.0, 0.0);
446 #if NAMD_VERSION_NUMBER >= 34471681 447 for (
int imap = 0; imap < volmaps_ids.size(); imap++) {
448 volmaps_new_colvar_forces[imap] = 0.0;
454 cvm::log(
"Updating positions arrays.\n");
456 size_t n_positions = 0;
461 for ( ; a_i != a_e; ++a_i, ++p_i ) {
462 atoms_positions[
atoms_map[*a_i]] = cvm::rvector((*p_i).x, (*p_i).y, (*p_i).z);
472 if (total_force_requested && cvm::step_relative() > 0) {
479 cvm::log(
"Updating total forces arrays.\n");
481 size_t n_total_forces = 0;
486 for ( ; a_i != a_e; ++a_i, ++f_i ) {
487 atoms_total_forces[
atoms_map[*a_i]] = cvm::rvector((*f_i).x, (*f_i).y, (*f_i).z);
491 if ( (! b_simulation_continuing) &&
492 (n_total_forces < atoms_ids.size()) ) {
493 cvm::error(
"Error: total forces were requested, but total forces " 494 "were not received for all atoms.\n" 495 "The most probable cause is combination of energy " 496 "minimization with a biasing method that requires MD (e.g. ABF).\n" 497 "Always run minimization and ABF separately.", COLVARS_INPUT_ERROR);
503 cvm::log(
"Updating group total forces arrays.\n");
508 if ( (! b_simulation_continuing) &&
509 ((f_e - f_i) != ((
int) atom_groups_ids.size())) ) {
510 cvm::error(
"Error: total forces were requested for scalable groups, " 511 "but they are not in the same number from the number of groups.\n" 512 "The most probable cause is combination of energy " 513 "minimization with a biasing method that requires MD (e.g. ABF).\n" 514 "Always run minimization and ABF separately.", COLVARS_INPUT_ERROR);
516 for ( ; f_i != f_e; f_i++, i++) {
517 atom_groups_total_forces[i] = cvm::rvector((*f_i).x, (*f_i).y, (*f_i).z);
524 cvm::log(
"Updating group positions arrays.\n");
532 atom_groups_coms[ig] = cvm::rvector(gp_i->
x, gp_i->
y, gp_i->
z);
536 #if NAMD_VERSION_NUMBER >= 34471681 539 log(
"Updating grid objects.\n");
546 for (
size_t imap = 0; imap < volmaps_ids.size(); imap++) {
547 if (volmaps_ids[imap] == *goi_i) {
548 volmaps_values[imap] = *gov_i;
557 print_input_atomic_data();
561 if (colvars->calc() != COLVARS_OK) {
562 cvm::error(
"Error in the collective variables module.\n", COLVARS_ERROR);
566 print_output_atomic_data();
570 for (
size_t i = 0; i < atoms_ids.size(); i++) {
571 cvm::rvector
const &f = atoms_new_colvar_forces[i];
576 if (atom_groups_new_colvar_forces.size() > 0) {
580 cvm::rvector
const &f = atom_groups_new_colvar_forces[ig];
581 *gf_i =
Vector(f.x, f.y, f.z);
585 #if NAMD_VERSION_NUMBER >= 34471681 586 if (volmaps_new_colvar_forces.size() > 0) {
592 for (
size_t imap = 0; imap < volmaps_ids.size(); imap++) {
593 if (volmaps_ids[imap] == *goi_i) {
594 *gof_i = volmaps_new_colvar_forces[imap];
603 #if defined(NODEGROUP_FORCE_REGISTER) && !defined(NAMD_UNIFIED_REDUCTION) 608 #if !defined(NAMD_UNIFIED_REDUCTION) 636 colvarproxy::init_tcl_pointers();
642 return colvarproxy::tcl_run_force_callback();
646 std::string
const &name,
647 std::vector<const colvarvalue *>
const &cvc_values,
650 return colvarproxy::tcl_run_colvar_callback(name, cvc_values, value);
654 std::string
const &name,
655 std::vector<const colvarvalue *>
const &cvc_values,
656 std::vector<cvm::matrix2d<cvm::real> > &gradient)
658 return colvarproxy::tcl_run_colvar_gradient_callback(name, cvc_values,
665 #if defined(NODEGROUP_FORCE_REGISTER) && !defined(NAMD_UNIFIED_REDUCTION) 672 #if !defined(NAMD_UNIFIED_REDUCTION) 683 cvm::log(
"colvarproxy_namd::request_total_force()\n");
685 total_force_requested = yesno;
688 cvm::log(
"colvarproxy_namd::request_total_force() end\n");
695 std::istringstream is(message);
697 while (std::getline(is, line))
698 iout <<
"colvars: " << line <<
"\n";
706 switch (cvm::get_error()) {
707 case COLVARS_FILE_ERROR:
709 case COLVARS_NOT_IMPLEMENTED:
710 errno = ENOSYS;
break;
711 case COLVARS_MEMORY_ERROR:
712 errno = ENOMEM;
break;
714 char const *msg =
"Error in the collective variables module " 715 "(see above for details)";
727 int const aid = (atom_number-1);
730 cvm::log(
"Adding atom "+cvm::to_str(atom_number)+
731 " for collective variables calculation.\n");
734 cvm::error(
"Error: invalid atom number specified, "+
735 cvm::to_str(atom_number)+
"\n", COLVARS_INPUT_ERROR);
736 return COLVARS_INPUT_ERROR;
753 int aid = (atom_number-1);
755 for (
size_t i = 0; i < atoms_ids.size(); i++) {
756 if (atoms_ids[i] == aid) {
758 atoms_refcount[i] += 1;
766 return COLVARS_INPUT_ERROR;
769 int const index = add_atom_slot(aid);
778 std::string
const &atom_name,
779 std::string
const &segment_id)
792 cvm::error(
"Error: could not find atom \""+
793 atom_name+
"\" in residue "+
794 cvm::to_str(residue)+
795 ( (segment_id !=
"MAIN") ?
796 (
", segment \""+segment_id+
"\"") :
798 "\n", COLVARS_INPUT_ERROR);
799 return COLVARS_INPUT_ERROR;
811 std::string
const &atom_name,
812 std::string
const &segment_id)
814 int const aid =
check_atom_id(residue, atom_name, segment_id);
816 for (
size_t i = 0; i < atoms_ids.size(); i++) {
817 if (atoms_ids[i] == aid) {
819 atoms_refcount[i] += 1;
825 cvm::log(
"Adding atom \""+
826 atom_name+
"\" in residue "+
827 cvm::to_str(residue)+
828 " (index "+cvm::to_str(aid)+
829 ") for collective variables calculation.\n");
831 int const index = add_atom_slot(aid);
841 colvarproxy::clear_atom(index);
850 double const mass = mol->
atommass(atoms_ids[index]);
852 this->
log(
"Warning: near-zero mass for atom "+
853 cvm::to_str(atoms_ids[index]+1)+
854 "; expect unstable dynamics if you apply forces to it.\n");
856 atoms_masses[index] = mass;
858 atoms_charges[index] = mol->
atomcharge(atoms_ids[index]);
863 cvm::atom_pos
const &pos2)
866 Position const p1(pos1.x, pos1.y, pos1.z);
867 Position const p2(pos2.x, pos2.y, pos2.z);
870 return cvm::rvector(d.
x, d.
y, d.
z);
890 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
891 colvarparse::to_lower_cppstr(
"O")) {
895 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
896 colvarparse::to_lower_cppstr(
"B")) {
900 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
901 colvarparse::to_lower_cppstr(
"X")) {
905 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
906 colvarparse::to_lower_cppstr(
"Y")) {
910 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
911 colvarparse::to_lower_cppstr(
"Z")) {
916 cvm::error(
"Error: unsupported PDB field, \""+
917 pdb_field_str+
"\".\n", COLVARS_INPUT_ERROR);
925 std::vector<cvm::atom_pos> &pos,
926 const std::vector<int> &indices,
927 std::string
const &pdb_field_str,
928 double const pdb_field_value)
930 if (pdb_field_str.size() == 0 && indices.size() == 0) {
931 cvm::error(
"Bug alert: either PDB field should be defined or list of " 932 "atom IDs should be available when loading atom coordinates!\n", COLVARS_BUG_ERROR);
936 bool const use_pdb_field = (pdb_field_str.size() > 0);
942 std::vector<int>::const_iterator current_index = indices.begin();
944 PDB *pdb =
new PDB(pdb_filename);
945 size_t const pdb_natoms = pdb->
num_atoms();
947 if (pos.size() != pdb_natoms) {
949 bool const pos_allocated = (pos.size() > 0);
951 size_t ipos = 0, ipdb = 0;
952 for ( ; ipdb < pdb_natoms; ipdb++) {
956 double atom_pdb_field_value = 0.0;
958 switch (pdb_field_index) {
960 atom_pdb_field_value = (pdb->
atom(ipdb))->occupancy();
963 atom_pdb_field_value = (pdb->
atom(ipdb))->temperaturefactor();
966 atom_pdb_field_value = (pdb->
atom(ipdb))->xcoor();
969 atom_pdb_field_value = (pdb->
atom(ipdb))->ycoor();
972 atom_pdb_field_value = (pdb->
atom(ipdb))->zcoor();
978 if ( (pdb_field_value) &&
979 (atom_pdb_field_value != pdb_field_value) ) {
981 }
else if (atom_pdb_field_value == 0.0) {
987 if (((
int) ipdb) != *current_index) {
995 if (!pos_allocated) {
996 pos.push_back(cvm::atom_pos(0.0, 0.0, 0.0));
997 }
else if (ipos >= pos.size()) {
998 cvm::error(
"Error: the PDB file \""+
999 std::string(pdb_filename)+
1000 "\" contains coordinates for " 1001 "more atoms than needed.\n", COLVARS_BUG_ERROR);
1004 pos[ipos] = cvm::atom_pos((pdb->
atom(ipdb))->xcoor(),
1005 (pdb->
atom(ipdb))->ycoor(),
1006 (pdb->
atom(ipdb))->zcoor());
1008 if (!use_pdb_field && current_index == indices.end())
1012 if (ipos < pos.size() || (!use_pdb_field && current_index != indices.end())) {
1013 size_t n_requested = use_pdb_field ? pos.size() : indices.size();
1014 cvm::error(
"Error: number of matching records in the PDB file \""+
1015 std::string(pdb_filename)+
"\" ("+cvm::to_str(ipos)+
1016 ") does not match the number of requested coordinates ("+
1017 cvm::to_str(n_requested)+
").\n", COLVARS_INPUT_ERROR);
1018 return COLVARS_ERROR;
1024 for (
size_t ia = 0; ia < pos.size(); ia++) {
1025 pos[ia] = cvm::atom_pos((pdb->
atom(ia))->xcoor(),
1026 (pdb->
atom(ia))->ycoor(),
1027 (pdb->
atom(ia))->zcoor());
1037 cvm::atom_group &atoms,
1038 std::string
const &pdb_field_str,
1039 double const pdb_field_value)
1041 if (pdb_field_str.size() == 0)
1042 cvm::error(
"Error: must define which PDB field to use " 1043 "in order to define atoms from a PDB file.\n", COLVARS_INPUT_ERROR);
1045 PDB *pdb =
new PDB(pdb_filename);
1046 size_t const pdb_natoms = pdb->
num_atoms();
1050 for (
size_t ipdb = 0; ipdb < pdb_natoms; ipdb++) {
1052 double atom_pdb_field_value = 0.0;
1054 switch (pdb_field_index) {
1056 atom_pdb_field_value = (pdb->
atom(ipdb))->occupancy();
1059 atom_pdb_field_value = (pdb->
atom(ipdb))->temperaturefactor();
1062 atom_pdb_field_value = (pdb->
atom(ipdb))->xcoor();
1065 atom_pdb_field_value = (pdb->
atom(ipdb))->ycoor();
1068 atom_pdb_field_value = (pdb->
atom(ipdb))->zcoor();
1074 if ( (pdb_field_value) &&
1075 (atom_pdb_field_value != pdb_field_value) ) {
1077 }
else if (atom_pdb_field_value == 0.0) {
1081 if (atoms.is_enabled(colvardeps::f_ag_scalable)) {
1082 atoms.add_atom_id(ipdb);
1089 return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
1094 std::string
const description)
1097 cvm::log(
"Using colvarproxy_namd::output_stream()\n");
1100 if (!io_available()) {
1101 cvm::error(
"Error: trying to access an output file/channel " 1102 "from the wrong thread.\n", COLVARS_BUG_ERROR);
1103 return *output_stream_error_;
1106 if (output_streams_.count(output_name) > 0) {
1107 return *(output_streams_[output_name]);
1112 output_streams_[output_name] =
new ofstream_namd(output_name.c_str(), std::ios::binary);
1113 if (! output_streams_[output_name]->good()) {
1114 cvm::error(
"Error: cannot write to "+description+
" \""+output_name+
"\".\n",
1115 COLVARS_FILE_ERROR);
1118 return *(output_streams_[output_name]);
1124 if (!io_available()) {
1128 if (output_streams_.count(output_name) > 0) {
1129 (
reinterpret_cast<ofstream_namd *
>(output_streams_[output_name]))->flush();
1133 return cvm::error(
"Error: trying to flush an output file/channel " 1134 "that wasn't open.\n", COLVARS_BUG_ERROR);
1140 if (!io_available()) {
1144 for (std::map<std::string, std::ostream *>::iterator osi = output_streams_.begin();
1145 osi != output_streams_.end();
1156 if (!io_available()) {
1157 return cvm::error(
"Error: trying to access an output file/channel " 1158 "from the wrong thread.\n", COLVARS_BUG_ERROR);
1161 if (output_streams_.count(output_name) > 0) {
1162 (
reinterpret_cast<ofstream_namd *
>(output_streams_[output_name]))->close();
1163 delete output_streams_[output_name];
1164 output_streams_.erase(output_name);
1173 if (! io_available()) {
1177 for (std::map<std::string, std::ostream *>::iterator osi = output_streams_.begin();
1178 osi != output_streams_.end();
1182 output_streams_.clear();
1190 if (std::string(filename).rfind(std::string(
".colvars.state")) != std::string::npos) {
1202 cvm::log(
"Requesting from NAMD a group of size "+cvm::to_str(atoms_ids.size())+
1203 " for collective variables calculation.\n");
1205 colvars->cite_feature(
"Scalable center-of-mass computation (NAMD)");
1214 bool b_match =
true;
1216 if (namd_group.
size() != ((int) atoms_ids.size())) {
1220 for (ia = 0; ia < namd_group.
size(); ia++) {
1221 int const aid = atoms_ids[ia];
1222 if (namd_group[ia] != aid) {
1231 cvm::log(
"Group was already added.\n");
1233 atom_groups_refcount[ig] += 1;
1239 size_t const index = add_atom_group_slot(atom_groups_ids.size());
1244 namd_group.
resize(atoms_ids.size());
1246 for (
size_t ia = 0; ia < atoms_ids.size(); ia++) {
1247 int const aid = atoms_ids[ia];
1249 cvm::log(
"Adding atom "+cvm::to_str(aid+1)+
1250 " for collective variables calculation.\n");
1251 if ( (aid < 0) || (aid >= n_all_atoms) ) {
1252 cvm::error(
"Error: invalid atom number specified, "+
1253 cvm::to_str(aid+1)+
"\n", COLVARS_INPUT_ERROR);
1256 namd_group[ia] = aid;
1262 cvm::log(
"Group has index "+cvm::to_str(index)+
"\n");
1274 colvarproxy::clear_atom_group(index);
1282 cvm::log(
"Re-calculating total mass and charge for scalable group no. "+cvm::to_str(index+1)+
" ("+
1283 cvm::to_str(namd_group.
size())+
" atoms).\n");
1286 cvm::real total_mass = 0.0;
1287 cvm::real total_charge = 0.0;
1288 for (
int i = 0; i < namd_group.
size(); i++) {
1292 atom_groups_masses[index] = total_mass;
1293 atom_groups_charges[index] = total_charge;
1296 cvm::log(
"total mass = "+cvm::to_str(total_mass)+
1297 ", total charge = "+cvm::to_str(total_charge)+
"\n");
1307 if (units_in !=
"real") {
1308 cvm::error(
"Error: Specified unit system \"" + units_in +
"\" is unsupported in NAMD. Supported units are \"real\" (A, kcal/mol).\n");
1309 return COLVARS_ERROR;
1315 #if NAMD_VERSION_NUMBER >= 34471681 1326 for (
size_t i = 0; i < volmaps_ids.size(); i++) {
1327 if (volmaps_ids[i] == volmap_id) {
1329 volmaps_refcount[i] += 1;
1336 if (error_code == COLVARS_OK) {
1337 index = add_volmap_slot(volmap_id);
1341 return (error_code == COLVARS_OK) ? index : -1;
1347 if (volmap_name == NULL) {
1348 return cvm::error(
"Error: no grid object name provided.", COLVARS_INPUT_ERROR);
1351 int error_code = COLVARS_OK;
1356 if (error_code == COLVARS_OK) {
1364 if ((gfScale.
x != 0.0) || (gfScale.
y != 0.0) || (gfScale.
z != 0.0)) {
1365 error_code |= cvm::error(
"Error: GridForce map \""+
1366 std::string(volmap_name)+
1367 "\" has non-zero scale factors.\n",
1368 COLVARS_INPUT_ERROR);
1371 for (
size_t i = 0; i < volmaps_ids.size(); i++) {
1372 if (volmaps_ids[i] == volmap_id) {
1374 volmaps_refcount[i] += 1;
1379 index = add_volmap_slot(volmap_id);
1383 return (error_code == COLVARS_OK) ? index : -1;
1391 return cvm::error(
"Error: invalid numeric ID ("+cvm::to_str(volmap_id)+
1392 ") for map.\n", COLVARS_INPUT_ERROR);
1394 colvars->cite_feature(
"GridForces volumetric map implementation for NAMD");
1401 if (volmap_name == NULL) {
1402 return cvm::error(
"Error: no grid object name provided.", COLVARS_INPUT_ERROR);
1405 if (volmap_id < 0) {
1406 return cvm::error(
"Error: invalid map name \""+std::string(volmap_name)+
1407 "\".\n", COLVARS_INPUT_ERROR);
1409 colvars->cite_feature(
"GridForces volumetric map implementation for NAMD");
1417 colvarproxy::clear_volmap(index);
1423 int const volmap_id =
1425 if (volmap_id < 0) {
1433 template<
class T,
int flags>
1435 cvm::atom_iter atom_begin,
1436 cvm::atom_iter atom_end,
1438 cvm::real *atom_field)
1443 cvm::atom_iter ai = atom_begin;
1444 for ( ; ai != atom_end; ai++, i++) {
1445 if (g->compute_VdV(
Position(ai->pos.x, ai->pos.y, ai->pos.z), V, dV)) {
1450 if (flags & volmap_flag_use_atom_field) {
1451 *value += V * atom_field[i];
1452 if (flags & volmap_flag_gradients) {
1453 ai->grad += atom_field[i] * cvm::rvector(dV.
x, dV.
y, dV.
z);
1457 if (flags & volmap_flag_gradients) {
1458 ai->grad += cvm::rvector(dV.
x, dV.
y, dV.
z);
1469 cvm::atom_iter atom_begin,
1470 cvm::atom_iter atom_end,
1472 cvm::real *atom_field)
1474 if (flags & volmap_flag_use_atom_field) {
1475 int const new_flags = volmap_flag_use_atom_field | volmap_flag_gradients;
1476 GridForceGridLoop<T, new_flags>(g, atom_begin, atom_end,
1479 int const new_flags = volmap_flag_gradients;
1480 GridForceGridLoop<T, new_flags>(g, atom_begin, atom_end,
1488 cvm::atom_iter atom_begin,
1489 cvm::atom_iter atom_end,
1491 cvm::real *atom_field)
1498 getGridForceGridValue<GridforceFullMainGrid>(flags, g, atom_begin, atom_end,
1502 getGridForceGridValue<GridforceLiteGrid>(flags, g, atom_begin, atom_end,
1510 #if CMK_SMP && USE_CKLOOP // SMP only 1512 colvarproxy::smp_mode_t colvarproxy_namd::get_smp_mode()
const {
1516 int colvarproxy_namd::set_smp_mode(smp_mode_t mode) {
1522 int colvarproxy_namd::smp_loop(
int n_items, std::function<
int (
int)>
const &worker)
1524 auto cmkWorker = [&](
int start,
int end,
void * ) {
1525 #if CMK_TRACE_ENABLED 1526 double before = CmiWallTimer();
1528 for (
int i = start; i <= end; i++) {
1531 #if CMK_TRACE_ENABLED 1535 const int numChunks = smp_num_threads() > n_items ?
1538 cvm::increase_depth();
1539 CkLoop_Parallelize(numChunks, 0, n_items - 1, cmkWorker,
nullptr, CKLOOP_NONE,
nullptr);
1540 cvm::decrease_depth();
1542 return cvm::get_error();
1546 void calc_cv_biases_smp(
int first,
int last,
void *result,
int paramNum,
void *param)
1549 colvarmodule *cv = proxy->colvars;
1550 #if CMK_TRACE_ENABLED 1551 double before = CmiWallTimer();
1553 cvm::increase_depth();
1554 for (
int i = first; i <= last; i++) {
1555 colvarbias *b = (*(cv->biases_active()))[i];
1557 cvm::log(
"["+cvm::to_str(proxy->smp_thread_id())+
"/"+cvm::to_str(proxy->smp_num_threads())+
1558 "]: calc_cv_biases_smp(), first = "+cvm::to_str(first)+
1559 ", last = "+cvm::to_str(last)+
", bias = "+
1564 cvm::decrease_depth();
1565 #if CMK_TRACE_ENABLED 1571 int colvarproxy_namd::smp_biases_loop()
1573 colvarmodule *cv = this->colvars;
1574 const int numChunks = smp_num_threads() > cv->variables_active_smp()->size() ?
1575 cv->variables_active_smp()->size() :
1577 CkLoop_Parallelize(calc_cv_biases_smp, 1,
this,
1578 numChunks, 0, cv->biases_active()->size()-1);
1579 return cvm::get_error();
1583 void calc_cv_scripted_forces(
int paramNum,
void *param)
1586 colvarmodule *cv = proxy->colvars;
1587 #if CMK_TRACE_ENABLED 1588 double before = CmiWallTimer();
1591 cvm::log(
"["+cvm::to_str(proxy->smp_thread_id())+
"/"+cvm::to_str(proxy->smp_num_threads())+
1592 "]: calc_cv_scripted_forces()\n");
1594 cv->calc_scripted_forces();
1595 #if CMK_TRACE_ENABLED 1601 int colvarproxy_namd::smp_biases_script_loop()
1603 colvarmodule *cv = this->colvars;
1604 CkLoop_Parallelize(calc_cv_biases_smp, 1,
this,
1605 cv->biases_active()->size(), 0, cv->biases_active()->size()-1,
1606 1, NULL, CKLOOP_NONE,
1607 calc_cv_scripted_forces, 1,
this);
1608 return cvm::get_error();
1611 #endif // #if CMK_SMP && USE_CKLOOP 1615 #if CMK_HAS_PARTITION 1618 return COLVARS_NOT_IMPLEMENTED;
1624 return CmiMyPartition();
1629 return CmiNumPartitions();
1642 CmiAssert(recvMsg != NULL);
1643 int retval = recvMsg->
size;
1644 if (buf_len >= retval) {
1645 memcpy(msg_data,recvMsg->
data,retval);
1665 cvm::error(
"computeEnergies must be a divisor of lambda-dynamics period (" + cvm::to_str(freq) +
").\n");
1666 return COLVARS_INPUT_ERROR;
1669 cvm::error(
"alchOn must be enabled for lambda-dynamics.\n");
1670 return COLVARS_INPUT_ERROR;
1673 cvm::error(
"alchType must be set to TI for lambda-dynamics.\n");
1674 return COLVARS_INPUT_ERROR;
1690 cvm::error(
"Cannot set lambda from Colvars because alchLambdaFreq is enabled. " 1691 "Either remove biasing forces and extended Lagrangian dynamics on the alchemical coordinate, " 1692 "or disable alchLambdaFreq.\n");
1693 return COLVARS_INPUT_ERROR;
1704 if (cvm::step_relative() > 0) {
Real atomcharge(int anum) const
int check_volmaps_available() override
std::ostream & output_stream(std::string const &output_name, std::string const description) override
const Controller & getController() const
void clear_atom_group(int index) override
ForceList & modifyAppliedForces()
int get_volmap_id_from_name(char const *volmap_name) override
AtomIDList & modifyRequestedAtoms()
void clear_volmap(int index) override
GridforceGrid * get_gridfrc_grid(int gridnum) const
BigRealList & modifyGridObjForces()
void getGridForceGridValue(int flags, T const *grid, cvm::atom_iter atom_begin, cvm::atom_iter atom_end, cvm::real *value, cvm::real *atom_field)
Abstraction of the two types of NAMD volumetric maps.
SimParameters * simparams
Pointer to the NAMD simulation input object.
NAMD_HOST_DEVICE Vector c() const
Random random
NAMD-style PRNG object.
void NAMD_err(const char *err_msg)
BigReal getTIderivative(void) const
int init_atom_group(std::vector< int > const &atoms_ids) override
int compute_volmap(int flags, int volmap_id, cvm::atom_iter atom_begin, cvm::atom_iter atom_end, cvm::real *value, cvm::real *atom_field) override
NAMD_HOST_DEVICE int c_p() const
int set_unit_system(std::string const &units_in, bool check_only) override
#define GLOBAL_MASTER_CKLOOP_CALC_ITEM
void error(std::string const &message) override
void update_accelMD_info()
int replica_comm_send(char *msg_data, int msg_len, int dest_rep) override
int init_atom(int atom_number) override
AtomIDList::const_iterator getForceIdEnd()
AtomIDList::const_iterator getAtomIdBegin()
PositionList::const_iterator getGroupPositionEnd()
Communication between colvars and NAMD (implementation of colvarproxy)
Controller const * controller
Pointer to Controller object.
int init_volmap_by_id(int volmap_id) override
SimParameters * simParameters
int check_volmap_by_name(char const *volmap_name) override
void clear_atom(int index) override
cvm::real amd_weight_factor
e_pdb_field pdb_field_str2enum(std::string const &pdb_field_str)
void replica_send(const char *sndbuf, int sendcount, int destPart, int destPE)
int get_alch_lambda(cvm::real *lambda)
Get value of alchemical lambda parameter from back-end.
std::ostream & endi(std::ostream &s)
void GridForceGridLoop(T const *g, cvm::atom_iter atom_begin, cvm::atom_iter atom_end, cvm::real *value, cvm::real *atom_field)
Implementation of inner loop; allows for atom list computation and use.
ForceList::const_iterator getGroupTotalForceBegin()
cvm::step_number previous_NAMD_step
SubmitReduction * willSubmit(int setID, int size=-1)
int update_target_temperature()
Get the target temperature from the NAMD thermostats supported so far.
static ReductionMgr * Object(void)
NAMD_HOST_DEVICE int orthogonal() const
NodeReduction * reduction
int add(const Elem &elem)
PositionList::const_iterator getAtomPositionBegin()
Molecule stores the structural information for the system.
NAMD_HOST_DEVICE int b_p() const
const ResizeArray< AtomIDList > & requestedGroups()
void request_total_force(bool yesno) override
char outputFilename[NAMD_FILENAME_BUFFER_SIZE]
AtomIDList::const_iterator getForceIdBegin()
int init_volmap_by_name(const char *volmap_name) override
void setall(const Elem &elem)
int check_atom_id(int atom_number) override
#define COLVARPROXY_VERSION
int run_colvar_gradient_callback(std::string const &name, std::vector< const colvarvalue *> const &cvcs, std::vector< cvm::matrix2d< cvm::real > > &gradient) override
#define GLOBAL_MASTER_CKLOOP_CALC_SCRIPTED_BIASES
std::vector< int > atoms_map
Array of atom indices (relative to the colvarproxy arrays), usedfor faster copy of atomic data...
void replica_recv(DataMessage **precvMsg, int srcPart, int srcPE)
int check_atom_name_selections_available() override
int index_for_key(const char *key)
void log(std::string const &message) override
int request_alch_energy_freq(int const freq)
Request energy computation every freq steps.
IntList::const_iterator getGridObjIndexBegin()
int get_atom_from_name(const char *segid, int resid, const char *aname) const
bool accelMDOn
Used to submit restraint energy as MISC.
const AtomID * const_iterator
int backup_file(char const *filename) override
PDBAtom * atom(int place)
int load_atoms_pdb(char const *filename, cvm::atom_group &atoms, std::string const &pdb_field, double const pdb_field_value) override
void init_atoms_map()
Allocate an atoms map with the same size as the NAMD topology.
int flush_output_streams() override
IntList & modifyRequestedGridObjects()
#define GLOBAL_MASTER_CKLOOP_CALC_BIASES
void replica_comm_barrier() override
int send_alch_lambda(void)
Set value of alchemical lambda parameter in back-end.
int check_replicas_enabled() override
int close_output_stream(std::string const &output_name) override
int replica_index() override
NAMD_HOST_DEVICE int a_p() const
AtomIDList & modifyForcedAtoms()
ResizeArray< AtomIDList > & modifyRequestedGroups()
int update_group_properties(int index)
void NAMD_die(const char *err_msg)
int flush_output_stream(std::string const &output_name) override
ForceList & modifyGroupForces()
Real atommass(int anum) const
NAMD_HOST_DEVICE Vector b() const
MGridforceParamsList mgridforcelist
void init_tcl_pointers() override
void update_atom_properties(int index)
void NAMD_backup_file(const char *filename, const char *extension)
virtual Vector get_scale(void) const =0
char restartFilename[NAMD_FILENAME_BUFFER_SIZE]
BigRealList::const_iterator getGridObjValueBegin()
cvm::rvector position_distance(cvm::atom_pos const &pos1, cvm::atom_pos const &pos2) const
int check_volmap_by_id(int volmap_id) override
IntList::const_iterator getGridObjIndexEnd()
void add_energy(cvm::real energy) override
int get_dE_dlambda(cvm::real *dE_dlambda)
Get energy derivative with respect to lambda.
int close_output_streams() override
void requestTotalForce(bool yesno=true)
AtomIDList::const_iterator getAtomIdEnd()
BigReal getCurrentLambda(const int) const
int run_colvar_callback(std::string const &name, std::vector< const colvarvalue *> const &cvcs, colvarvalue &value) override
void addReductionEnergy(int reductionTag, BigReal energy)
GridforceGridType get_grid_type(void)
int num_replicas() override
const IntList & requestedGridObjs()
int run_force_callback() override
int replica_comm_recv(char *msg_data, int buf_len, int src_rep) override
StringList * find(const char *name) const
NAMD_HOST_DEVICE Vector a() const
int update_atoms_map(AtomIDList::const_iterator begin, AtomIDList::const_iterator end)
PositionList::const_iterator getGroupPositionBegin()
ForceList::const_iterator getTotalForce()
int load_coords_pdb(char const *filename, std::vector< cvm::atom_pos > &pos, const std::vector< int > &indices, std::string const &pdb_field, double const pdb_field_value) override
BigRealList::const_iterator getGridObjValueEnd()
NAMD_HOST_DEVICE Vector delta(const Position &pos1, const Position &pos2) const
ForceList::const_iterator getGroupTotalForceEnd()