00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <tcl.h>
00011
00012 #include "VMDApp.h"
00013 #include "DrawMolecule.h"
00014 #include "MoleculeList.h"
00015 #include "Timestep.h"
00016 #include "Residue.h"
00017 #include "Inform.h"
00018 #include "utilities.h"
00019
00020 #include "colvarmodule.h"
00021 #include "colvarscript.h"
00022 #include "colvaratoms.h"
00023 #include "colvarscript.h"
00024 #include "colvarproxy.h"
00025 #include "colvarproxy_vmd.h"
00026
00027
00028 namespace {
00029
00030 VMDApp *colvars_vmd_ptr = NULL;
00031 colvarproxy_vmd *colvarproxy_vmd_ptr = NULL;
00032 }
00033
00034
00035
00036
00037
00038 #ifdef COLVARS_TCL
00039 extern "C" int tcl_run_colvarscript_command(ClientData clientData,
00040 Tcl_Interp *interp_in,
00041 int objc, Tcl_Obj *const objv[]);
00042 #endif
00043
00044
00045 int tcl_colvars(ClientData clientData, Tcl_Interp *interp,
00046 int objc, Tcl_Obj *const objv[])
00047 {
00048
00049 if (colvars_vmd_ptr == NULL) {
00050 colvars_vmd_ptr = (VMDApp *) clientData;
00051 }
00052 return tcl_run_colvarscript_command(clientData, interp, objc, objv);
00053 }
00054
00055
00056 int tcl_colvars_vmd_init(Tcl_Interp *interp, int molid_input)
00057 {
00058 VMDApp *const vmd = colvars_vmd_ptr;
00059 int molid = molid_input == -(1<<16) ? vmd->molecule_top() : molid_input;
00060 if (vmd->molecule_valid_id(molid)) {
00061 colvarproxy_vmd_ptr = new colvarproxy_vmd(interp, vmd, molid);
00062 return (cvm::get_error() == COLVARS_OK) ? TCL_OK : TCL_ERROR;
00063 } else {
00064 Tcl_SetResult(interp, (char *) "Error: molecule not found.",
00065 TCL_STATIC);
00066 return TCL_ERROR;
00067 }
00068 }
00069
00070
00071 colvarproxy_vmd::colvarproxy_vmd(Tcl_Interp *interp, VMDApp *v, int molid)
00072 : vmd(v),
00073 vmdmolid(molid),
00074 #if defined(VMDTKCON)
00075 msgColvars("colvars: ", VMDCON_INFO)
00076 #else
00077 msgColvars("colvars: ")
00078 #endif
00079 {
00080 version_int = get_version_from_string(COLVARPROXY_VERSION);
00081 b_simulation_running = false;
00082
00083
00084 updated_masses_ = updated_charges_ = true;
00085
00086
00087
00088
00089 #if defined(VMDTCL)
00090 have_scripts = true;
00091
00092 set_tcl_interp(interp);
00093 #else
00094 have_scripts = false;
00095 #endif
00096
00097 colvars = new colvarmodule(this);
00098 cvm::log("Using VMD interface, version "+
00099 cvm::to_str(COLVARPROXY_VERSION)+".\n");
00100
00101 colvars->cite_feature("VMD engine");
00102 colvars->cite_feature("Colvars-VMD interface (command line)");
00103
00104 colvars->cv_traj_freq = 0;
00105 colvars->restart_out_freq = 0;
00106 cvm::rotation::monitor_crossings = false;
00107
00108
00109
00110 angstrom_value_ = 1.;
00111 kcal_mol_value_ = 1.;
00112
00113 colvars->setup_input();
00114 colvars->setup_output();
00115
00116
00117 vmd_srandom(38572111);
00118
00119 colvarproxy_vmd::setup();
00120 }
00121
00122
00123 colvarproxy_vmd::~colvarproxy_vmd()
00124 {}
00125
00126
00127 int colvarproxy_vmd::request_deletion()
00128 {
00129 b_delete_requested = true;
00130 return COLVARS_OK;
00131 }
00132
00133
00134 int colvarproxy_vmd::setup()
00135 {
00136 int error_code = colvarproxy::setup();
00137 vmdmol = vmd->moleculeList->mol_from_id(vmdmolid);
00138 if (vmdmol) {
00139 set_frame(vmdmol->frame());
00140 } else {
00141 error("Error: requested molecule ("+cvm::to_str(vmdmolid)+") does not exist.\n");
00142 return COLVARS_ERROR;
00143 }
00144
00145 return colvars->update_engine_parameters();
00146 }
00147
00148
00149 cvm::real colvarproxy_vmd::rand_gaussian()
00150 {
00151 return vmd_random_gaussian();
00152 }
00153
00154
00155 int colvarproxy_vmd::set_unit_system(std::string const &units_in, bool check_only)
00156 {
00157
00158
00159 if (check_only) {
00160 if ((units != "" && units_in != units) || (units == "" && units_in != "real")) {
00161 cvm::error("Specified unit system \"" + units_in + "\" is incompatible with previous setting \""
00162 + units + "\".\nReset the Colvars Module or delete all variables to change the unit.\n");
00163 return COLVARS_ERROR;
00164 } else {
00165 return COLVARS_OK;
00166 }
00167 }
00168
00169 if (units_in == "real") {
00170 angstrom_value_ = 1.;
00171 kcal_mol_value_ = 1.;
00172 } else if (units_in == "metal") {
00173 angstrom_value_ = 1.;
00174 kcal_mol_value_ = 0.0433641017;
00175
00176 } else if (units_in == "electron") {
00177 angstrom_value_ = 1.88972612;
00178 kcal_mol_value_ = 0.00159360144;
00179 } else if (units_in == "gromacs") {
00180 angstrom_value_ = 0.1;
00181 kcal_mol_value_ = 4.184;
00182 } else {
00183 cvm::error("Unknown unit system specified: \"" + units_in + "\". Supported are real, metal, electron, and gromacs.\n");
00184 return COLVARS_ERROR;
00185 }
00186
00187 units = units_in;
00188 return COLVARS_OK;
00189 }
00190
00191
00192 int colvarproxy_vmd::update_input()
00193 {
00194 colvarproxy::update_input();
00195
00196 int error_code = COLVARS_OK;
00197
00198
00199 if (vmd->moleculeList->mol_from_id(vmdmolid) == NULL) {
00200 error("Error: requested molecule ("+cvm::to_str(vmdmolid)+") does not exist.\n");
00201 return COLVARS_ERROR;
00202 }
00203 error_code |= update_atomic_properties();
00204
00205 size_t i;
00206
00207
00208 for (i = 0; i < atoms_new_colvar_forces.size(); i++) {
00209 atoms_new_colvar_forces[i].reset();
00210 }
00211
00212
00213 if (error_code || vmdmol->get_frame(vmdmol_frame) == NULL) {
00214 error_code |= COLVARS_NO_SUCH_FRAME;
00215 return error_code;
00216 }
00217
00218
00219 float *vmdpos = (vmdmol->get_frame(vmdmol_frame))->pos;
00220 for (i = 0; i < atoms_positions.size(); i++) {
00221 atoms_positions[i] = cvm::atom_pos(angstrom_to_internal(vmdpos[atoms_ids[i]*3+0]),
00222 angstrom_to_internal(vmdpos[atoms_ids[i]*3+1]),
00223 angstrom_to_internal(vmdpos[atoms_ids[i]*3+2]));
00224 }
00225
00226
00227 Timestep const *ts = vmdmol->get_frame(vmdmol_frame);
00228 {
00229
00230 float A[3];
00231 float B[3];
00232 float C[3];
00233 ts->get_transform_vectors(A, B, C);
00234 unit_cell_x.set(angstrom_to_internal(A[0]), angstrom_to_internal(A[1]), angstrom_to_internal(A[2]));
00235 unit_cell_y.set(angstrom_to_internal(B[0]), angstrom_to_internal(B[1]), angstrom_to_internal(B[2]));
00236 unit_cell_z.set(angstrom_to_internal(C[0]), angstrom_to_internal(C[1]), angstrom_to_internal(C[2]));
00237 }
00238
00239 if (ts->a_length + ts->b_length + ts->c_length < 1.0e-6) {
00240 boundaries_type = boundaries_non_periodic;
00241 reset_pbc_lattice();
00242 } else if ((ts->a_length > 1.0e-6) &&
00243 (ts->b_length > 1.0e-6) &&
00244 (ts->c_length > 1.0e-6)) {
00245 if (((ts->alpha-90.0)*(ts->alpha-90.0)) +
00246 ((ts->beta-90.0)*(ts->beta-90.0)) +
00247 ((ts->gamma-90.0)*(ts->gamma-90.0)) < 1.0e-6) {
00248 boundaries_type = boundaries_pbc_ortho;
00249 } else {
00250 boundaries_type = boundaries_pbc_triclinic;
00251 }
00252 colvarproxy_system::update_pbc_lattice();
00253 } else {
00254 boundaries_type = boundaries_unsupported;
00255 }
00256
00257 return error_code;
00258 }
00259
00260
00261 void colvarproxy_vmd::add_energy(cvm::real energy)
00262 {
00263 }
00264
00265
00266 int colvarproxy_vmd::update_atomic_properties()
00267 {
00268 float const *masses = vmdmol->mass();
00269 float const *charges = vmdmol->charge();
00270
00271 int error_code = COLVARS_OK;
00272
00273 if (masses == NULL) {
00274 error("Error: masses are undefined for the molecule being used.\n");
00275 error_code |= COLVARS_BUG_ERROR;
00276 } else {
00277 for (size_t i = 0; i < atoms_ids.size(); i++) {
00278 atoms_masses[i] = masses[atoms_ids[i]];
00279 }
00280 }
00281
00282 if (charges == NULL) {
00283 error("Error: charges are undefined for the molecule being used.\n");
00284 error_code |= COLVARS_BUG_ERROR;
00285 } else {
00286 for (size_t i = 0; i < atoms_ids.size(); i++) {
00287 atoms_charges[i] = charges[atoms_ids[i]];
00288 }
00289 }
00290
00291 return error_code;
00292 }
00293
00294
00295 void colvarproxy_vmd::request_total_force(bool yesno)
00296 {
00297 if ((yesno == true) && (total_force_requested == false)) {
00298 cvm::log("Warning: a bias requested total forces, which are undefined in VMD. "
00299 "This is only meaningful when analyzing a simulation where these were used, "
00300 "provided that a state file is loaded.\n");
00301 }
00302 total_force_requested = yesno;
00303 }
00304
00305
00306 void colvarproxy_vmd::log(std::string const &message)
00307 {
00308 std::istringstream is(message);
00309 std::string line;
00310 while (std::getline(is, line)) {
00311 msgColvars << line.c_str() << sendmsg;
00312 }
00313 }
00314
00315
00316 void colvarproxy_vmd::error(std::string const &message)
00317 {
00318 add_error_msg(message);
00319 log(message);
00320 }
00321
00322
00323 int colvarproxy_vmd::get_molid(int &molid)
00324 {
00325 molid = vmdmolid;
00326 return COLVARS_OK;
00327 }
00328
00329
00330 int colvarproxy_vmd::get_frame(long int &f)
00331 {
00332 f = vmdmol_frame;
00333 return COLVARS_OK;
00334 }
00335
00336
00337 int colvarproxy_vmd::set_frame(long int f)
00338 {
00339 if (vmdmol->get_frame(f) != NULL) {
00340
00341 vmdmol_frame = f;
00342 colvars->it = f;
00343
00344 update_input();
00345
00346 return COLVARS_OK;
00347 } else {
00348 return COLVARS_NO_SUCH_FRAME;
00349 }
00350 }
00351
00352
00353 void colvarproxy_vmd::init_tcl_pointers()
00354 {
00355 #ifdef VMDTCL
00356
00357 #else
00358 colvarproxy::init_tcl_pointers();
00359 #endif
00360 }
00361
00362
00363
00364
00365 #ifdef VMDTCL
00366
00367 int colvarproxy_vmd::run_force_callback()
00368 {
00369 return colvarproxy::tcl_run_force_callback();
00370 }
00371
00372 int colvarproxy_vmd::run_colvar_callback(
00373 std::string const &name,
00374 std::vector<const colvarvalue *> const &cvc_values,
00375 colvarvalue &value)
00376 {
00377 return colvarproxy::tcl_run_colvar_callback(name, cvc_values, value);
00378 }
00379
00380 int colvarproxy_vmd::run_colvar_gradient_callback(
00381 std::string const &name,
00382 std::vector<const colvarvalue *> const &cvc_values,
00383 std::vector<cvm::matrix2d<cvm::real> > &gradient)
00384 {
00385 return colvarproxy::tcl_run_colvar_gradient_callback(name, cvc_values,
00386 gradient);
00387 }
00388 #endif
00389
00390
00391 enum e_pdb_field {
00392 e_pdb_none,
00393 e_pdb_occ,
00394 e_pdb_beta,
00395 e_pdb_x,
00396 e_pdb_y,
00397 e_pdb_z,
00398 e_pdb_ntot
00399 };
00400
00401 e_pdb_field pdb_field_str2enum(std::string const &pdb_field_str)
00402 {
00403 e_pdb_field pdb_field = e_pdb_none;
00404
00405 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
00406 colvarparse::to_lower_cppstr("O")) {
00407 pdb_field = e_pdb_occ;
00408 }
00409
00410 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
00411 colvarparse::to_lower_cppstr("B")) {
00412 pdb_field = e_pdb_beta;
00413 }
00414
00415 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
00416 colvarparse::to_lower_cppstr("X")) {
00417 pdb_field = e_pdb_x;
00418 }
00419
00420 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
00421 colvarparse::to_lower_cppstr("Y")) {
00422 pdb_field = e_pdb_y;
00423 }
00424
00425 if (colvarparse::to_lower_cppstr(pdb_field_str) ==
00426 colvarparse::to_lower_cppstr("Z")) {
00427 pdb_field = e_pdb_z;
00428 }
00429
00430 if (pdb_field == e_pdb_none) {
00431 cvm::error("Error: unsupported PDB field, \""+
00432 pdb_field_str+"\".\n");
00433 }
00434
00435 return pdb_field;
00436 }
00437
00438
00439 int colvarproxy_vmd::load_coords(char const *pdb_filename,
00440 std::vector<cvm::atom_pos> &pos,
00441 const std::vector<int> &indices,
00442 std::string const &pdb_field_str,
00443 double const pdb_field_value)
00444 {
00445 if (pdb_field_str.size() == 0 && indices.size() == 0) {
00446 cvm::error("Bug alert: either PDB field should be defined or list of "
00447 "atom IDs should be available when loading atom coordinates!\n",
00448 COLVARS_BUG_ERROR);
00449 return COLVARS_ERROR;
00450 }
00451
00452 e_pdb_field pdb_field_index = e_pdb_none;
00453 bool const use_pdb_field = (pdb_field_str.size() > 0);
00454 if (use_pdb_field) {
00455 pdb_field_index = pdb_field_str2enum(pdb_field_str);
00456 }
00457
00458
00459 std::vector<int>::const_iterator current_index = indices.begin();
00460
00461 FileSpec *tmpspec = new FileSpec();
00462 tmpspec->autobonds = 0;
00463 int tmpmolid = vmd->molecule_load(-1, pdb_filename, "pdb", tmpspec);
00464 delete tmpspec;
00465 if (tmpmolid < 0) {
00466 cvm::error("Error: VMD could not read file \""+std::string(pdb_filename)+"\".\n",
00467 COLVARS_FILE_ERROR);
00468 return COLVARS_ERROR;
00469 }
00470 DrawMolecule *tmpmol = vmd->moleculeList->mol_from_id(tmpmolid);
00471
00472 vmd->molecule_make_top(vmdmolid);
00473 size_t const pdb_natoms = tmpmol->nAtoms;
00474
00475 if (pos.size() != pdb_natoms) {
00476
00477 bool const pos_allocated = (pos.size() > 0);
00478
00479 size_t ipos = 0, ipdb = 0;
00480 for ( ; ipdb < pdb_natoms; ipdb++) {
00481
00482 if (use_pdb_field) {
00483
00484 double atom_pdb_field_value = 0.0;
00485
00486 switch (pdb_field_index) {
00487 case e_pdb_occ:
00488 atom_pdb_field_value = (tmpmol->occupancy())[ipdb];
00489 break;
00490 case e_pdb_beta:
00491 atom_pdb_field_value = (tmpmol->beta())[ipdb];
00492 break;
00493 case e_pdb_x:
00494 atom_pdb_field_value = (tmpmol->get_frame(0)->pos)[ipdb*3];
00495 break;
00496 case e_pdb_y:
00497 atom_pdb_field_value = (tmpmol->get_frame(0)->pos)[ipdb*3+1];
00498 break;
00499 case e_pdb_z:
00500 atom_pdb_field_value = (tmpmol->get_frame(0)->pos)[ipdb*3+2];
00501 break;
00502 default:
00503 break;
00504 }
00505
00506 if ( (pdb_field_value) &&
00507 (atom_pdb_field_value != pdb_field_value) ) {
00508 continue;
00509 } else if (atom_pdb_field_value == 0.0) {
00510 continue;
00511 }
00512
00513 } else {
00514
00515 if (((int)ipdb) != *current_index) {
00516
00517 continue;
00518 } else {
00519 current_index++;
00520 }
00521 }
00522
00523 if (!pos_allocated) {
00524 pos.push_back(cvm::atom_pos(0.0, 0.0, 0.0));
00525 } else if (ipos >= pos.size()) {
00526 cvm::error("Error: the PDB file \""+
00527 std::string(pdb_filename)+
00528 "\" contains coordinates for "
00529 "more atoms than needed.\n", COLVARS_INPUT_ERROR);
00530 return COLVARS_ERROR;
00531 }
00532
00533 pos[ipos] = cvm::atom_pos(angstrom_to_internal((tmpmol->get_frame(0)->pos)[ipdb*3]),
00534 angstrom_to_internal((tmpmol->get_frame(0)->pos)[ipdb*3+1]),
00535 angstrom_to_internal((tmpmol->get_frame(0)->pos)[ipdb*3+2]));
00536 ipos++;
00537 if (!use_pdb_field && current_index == indices.end())
00538 break;
00539 }
00540
00541 if (ipos < pos.size() || (!use_pdb_field && current_index != indices.end())) {
00542 size_t n_requested = use_pdb_field ? pos.size() : indices.size();
00543 cvm::error("Error: number of matching records in the PDB file \""+
00544 std::string(pdb_filename)+"\" ("+cvm::to_str(ipos)+
00545 ") does not match the number of requested coordinates ("+
00546 cvm::to_str(n_requested)+").\n", COLVARS_INPUT_ERROR);
00547 return COLVARS_ERROR;
00548 }
00549 } else {
00550
00551
00552
00553 for (size_t ia = 0; ia < pos.size(); ia++) {
00554 pos[ia] = cvm::atom_pos(angstrom_to_internal((tmpmol->get_frame(0)->pos)[ia*3]),
00555 angstrom_to_internal((tmpmol->get_frame(0)->pos)[ia*3+1]),
00556 angstrom_to_internal((tmpmol->get_frame(0)->pos)[ia*3+2]));
00557 }
00558 }
00559
00560 vmd->molecule_delete(tmpmolid);
00561 return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
00562 }
00563
00564
00565 int colvarproxy_vmd::load_atoms(char const *pdb_filename,
00566 cvm::atom_group &atoms,
00567 std::string const &pdb_field_str,
00568 double const pdb_field_value)
00569 {
00570 if (pdb_field_str.size() == 0) {
00571 cvm::log("Error: must define which PDB field to use "
00572 "in order to define atoms from a PDB file.\n");
00573 cvm::set_error_bits(COLVARS_INPUT_ERROR);
00574 return COLVARS_ERROR;
00575 }
00576
00577 FileSpec *tmpspec = new FileSpec();
00578 tmpspec->autobonds = 0;
00579 int tmpmolid = vmd->molecule_load(-1, pdb_filename, "pdb", tmpspec);
00580 delete tmpspec;
00581
00582 if (tmpmolid < 0) {
00583 cvm::error("Error: VMD could not read file \""+std::string(pdb_filename)+"\".\n",
00584 COLVARS_FILE_ERROR);
00585 return COLVARS_ERROR;
00586 }
00587 DrawMolecule *tmpmol = vmd->moleculeList->mol_from_id(tmpmolid);
00588
00589 vmd->molecule_make_top(vmdmolid);
00590 size_t const pdb_natoms = tmpmol->nAtoms;
00591
00592 e_pdb_field pdb_field_index = pdb_field_str2enum(pdb_field_str);
00593
00594 for (size_t ipdb = 0; ipdb < pdb_natoms; ipdb++) {
00595
00596 double atom_pdb_field_value = 0.0;
00597
00598 switch (pdb_field_index) {
00599 case e_pdb_occ:
00600 atom_pdb_field_value = (tmpmol->occupancy())[ipdb];
00601 break;
00602 case e_pdb_beta:
00603 atom_pdb_field_value = (tmpmol->beta())[ipdb];
00604 break;
00605 case e_pdb_x:
00606 atom_pdb_field_value = (tmpmol->get_frame(0)->pos)[ipdb*3];
00607 break;
00608 case e_pdb_y:
00609 atom_pdb_field_value = (tmpmol->get_frame(0)->pos)[ipdb*3+1];
00610 break;
00611 case e_pdb_z:
00612 atom_pdb_field_value = (tmpmol->get_frame(0)->pos)[ipdb*3+2];
00613 break;
00614 default:
00615 break;
00616 }
00617
00618 if ( (pdb_field_value) &&
00619 (atom_pdb_field_value != pdb_field_value) ) {
00620 continue;
00621 } else if (atom_pdb_field_value == 0.0) {
00622 continue;
00623 }
00624
00625 atoms.add_atom(cvm::atom(ipdb+1));
00626 }
00627
00628 vmd->molecule_delete(tmpmolid);
00629 return (cvm::get_error() ? COLVARS_ERROR : COLVARS_OK);
00630 }
00631
00632
00633
00634 int colvarproxy_vmd::check_atom_id(int atom_number)
00635 {
00636
00637 int const aid(atom_number-1);
00638
00639 if (cvm::debug())
00640 cvm::log("Adding atom "+cvm::to_str(aid+1)+
00641 " for collective variables calculation.\n");
00642
00643 if ( (aid < 0) || (aid >= vmdmol->nAtoms) ) {
00644 cvm::error("Error: invalid atom number specified, "+
00645 cvm::to_str(atom_number)+"\n");
00646 return COLVARS_INPUT_ERROR;
00647 }
00648
00649 return aid;
00650 }
00651
00652
00653 int colvarproxy_vmd::init_atom(int atom_number)
00654 {
00655
00656
00657 int aid = (atom_number-1);
00658
00659 for (size_t i = 0; i < atoms_ids.size(); i++) {
00660 if (atoms_ids[i] == aid) {
00661
00662 atoms_refcount[i] += 1;
00663 return i;
00664 }
00665 }
00666
00667 aid = check_atom_id(atom_number);
00668
00669 if (aid < 0) {
00670 return COLVARS_INPUT_ERROR;
00671 }
00672
00673 int const index = add_atom_slot(aid);
00674
00675 float const *masses = vmdmol->mass();
00676 float const *charges = vmdmol->charge();
00677 atoms_masses[index] = masses[aid];
00678 atoms_charges[index] = charges[aid];
00679
00680 return index;
00681 }
00682
00683
00684 int colvarproxy_vmd::check_atom_id(cvm::residue_id const &resid,
00685 std::string const &atom_name,
00686 std::string const &segment_id)
00687 {
00688 int aid = -1;
00689 for (int ir = 0; ir < vmdmol->nResidues; ir++) {
00690 Residue *vmdres = vmdmol->residue(ir);
00691 if (vmdres->resid == resid) {
00692 for (int ia = 0; ia < vmdres->atoms.num(); ia++) {
00693 int const resaid = vmdres->atoms[ia];
00694 std::string const sel_segname((vmdmol->segNames).name(vmdmol->atom(resaid)->segnameindex));
00695 std::string const sel_atom_name((vmdmol->atomNames).name(vmdmol->atom(resaid)->nameindex));
00696 if ( ((segment_id.size() == 0) || (segment_id == sel_segname)) &&
00697 (atom_name == sel_atom_name) ) {
00698 aid = resaid;
00699 break;
00700 }
00701 }
00702 }
00703 if (aid >= 0) break;
00704 }
00705
00706
00707 if (aid < 0) {
00708 cvm::error("Error: could not find atom \""+
00709 atom_name+"\" in residue "+
00710 cvm::to_str(resid)+
00711 ( (segment_id.size()) ?
00712 (", segment \""+segment_id+"\"") :
00713 ("") )+
00714 "\n", COLVARS_INPUT_ERROR);
00715 return COLVARS_INPUT_ERROR;
00716 }
00717
00718 return aid;
00719 }
00720
00721
00722 int colvarproxy_vmd::init_atom(cvm::residue_id const &resid,
00723 std::string const &atom_name,
00724 std::string const &segment_id)
00725 {
00726 int const aid = check_atom_id(resid, atom_name, segment_id);
00727
00728 for (size_t i = 0; i < atoms_ids.size(); i++) {
00729 if (atoms_ids[i] == aid) {
00730
00731 atoms_refcount[i] += 1;
00732 return i;
00733 }
00734 }
00735
00736 if (cvm::debug())
00737 cvm::log("Adding atom \""+
00738 atom_name+"\" in residue "+
00739 cvm::to_str(resid)+
00740 " (index "+cvm::to_str(aid)+
00741 ") for collective variables calculation.\n");
00742
00743 int const index = add_atom_slot(aid);
00744
00745 float const *masses = vmdmol->mass();
00746 float const *charges = vmdmol->charge();
00747 atoms_masses[index] = masses[aid];
00748 atoms_charges[index] = charges[aid];
00749
00750 return index;
00751 }
00752
00753
00754 int colvarproxy_vmd::init_volmap_by_id(int volmap_id)
00755 {
00756 for (size_t i = 0; i < volmaps_ids.size(); i++) {
00757 if (volmaps_ids[i] == volmap_id) {
00758
00759 volmaps_refcount[i] += 1;
00760 return i;
00761 }
00762 }
00763
00764 int index = -1;
00765
00766 int error_code = check_volmap_by_id(volmap_id);
00767 if (error_code == COLVARS_OK) {
00768 index = add_volmap_slot(volmap_id);
00769 }
00770
00771 return index;
00772 }
00773
00774
00775 int colvarproxy_vmd::check_volmap_by_id(int volmap_id)
00776 {
00777 if ((volmap_id < 0) || (volmap_id >= vmdmol->num_volume_data())) {
00778 return cvm::error("Error: invalid numeric ID ("+cvm::to_str(volmap_id)+
00779 ") for map.\n", COLVARS_INPUT_ERROR);
00780 }
00781 return COLVARS_OK;
00782 }
00783
00784
00785 void colvarproxy_vmd::clear_volmap(int index)
00786 {
00787 colvarproxy::clear_volmap(index);
00788 }
00789
00790
00791 template<int flags>
00792 void colvarproxy_vmd::compute_voldata(VolumetricData const *voldata,
00793 cvm::atom_iter atom_begin,
00794 cvm::atom_iter atom_end,
00795 cvm::real *value,
00796 cvm::real *atom_field)
00797 {
00798 int i = 0;
00799 float coord[3], voxcoord[3], grad[3];
00800 cvm::rvector dV(0.0);
00801 cvm::atom_iter ai = atom_begin;
00802 cvm::atom_pos const origin(0.0, 0.0, 0.0);
00803
00804 for ( ; ai != atom_end; ai++, i++) {
00805
00806
00807 cvm::rvector const wrapped_pos = position_distance(origin, ai->pos);
00808 coord[0] = internal_to_angstrom(wrapped_pos.x);
00809 coord[1] = internal_to_angstrom(wrapped_pos.y);
00810 coord[2] = internal_to_angstrom(wrapped_pos.z);
00811
00812
00813 voldata->voxel_coord_from_cartesian_coord(coord, voxcoord, 0);
00814 int const gx = static_cast<int>(voxcoord[0]);
00815 int const gy = static_cast<int>(voxcoord[1]);
00816 int const gz = static_cast<int>(voxcoord[2]);
00817 int valid_coord = 1;
00818 if ((gx < 0) || (gx >= voldata->xsize) ||
00819 (gy < 0) || (gy >= voldata->ysize) ||
00820 (gz < 0) || (gz >= voldata->zsize)) {
00821 valid_coord = 0;
00822 }
00823
00824 cvm::real const V = valid_coord ?
00825 static_cast<cvm::real>(voldata->voxel_value_interpolate(voxcoord[0],
00826 voxcoord[1],
00827 voxcoord[2])) :
00828 0.0;
00829
00830 if (flags & volmap_flag_gradients) {
00831 if (valid_coord) {
00832 voldata->voxel_gradient_interpolate(voxcoord, grad);
00833
00834 dV = cvm::rvector(-1.0*grad[0], -1.0*grad[1], -1.0*grad[2]);
00835 } else {
00836 dV = cvm::rvector(0.0);
00837 }
00838 }
00839
00840 if (flags & volmap_flag_use_atom_field) {
00841 *value += V * atom_field[i];
00842 if (flags & volmap_flag_gradients) {
00843 ai->grad += atom_field[i] * dV;
00844 }
00845 } else {
00846 *value += V;
00847 if (flags & volmap_flag_gradients) {
00848 ai->grad += dV;
00849 }
00850 }
00851 }
00852 }
00853
00854
00855 int colvarproxy_vmd::compute_volmap(int flags,
00856 int volmap_id,
00857 cvm::atom_iter atom_begin,
00858 cvm::atom_iter atom_end,
00859 cvm::real *value,
00860 cvm::real *atom_field)
00861 {
00862 int error_code = COLVARS_OK;
00863 VolumetricData const *voldata = vmdmol->get_volume_data(volmap_id);
00864 if (voldata != NULL) {
00865
00866 if (flags & volmap_flag_gradients) {
00867
00868 if (flags & volmap_flag_use_atom_field) {
00869 int const new_flags = volmap_flag_gradients |
00870 volmap_flag_use_atom_field;
00871 compute_voldata<new_flags>(voldata, atom_begin, atom_end,
00872 value, atom_field);
00873 } else {
00874 int const new_flags = volmap_flag_gradients;
00875 compute_voldata<new_flags>(voldata, atom_begin, atom_end,
00876 value, NULL);
00877 }
00878
00879 } else {
00880
00881 if (flags & volmap_flag_use_atom_field) {
00882 int const new_flags = volmap_flag_use_atom_field;
00883 compute_voldata<new_flags>(voldata, atom_begin, atom_end,
00884 value, atom_field);
00885 } else {
00886 int const new_flags = volmap_flag_null;
00887 compute_voldata<new_flags>(voldata, atom_begin, atom_end,
00888 value, NULL);
00889 }
00890 }
00891 } else {
00892
00893 error_code |=
00894 const_cast<colvarproxy_vmd *>(this)->check_volmap_by_id(volmap_id);
00895 }
00896 return error_code;
00897 }