int GlobalMasterFreeEnergy::getPosition(int atomid, Position &position) { AtomIDList::const_iterator a_i = getAtomIdBegin(); AtomIDList::const_iterator a_e = getAtomIdEnd(); PositionList::const_iterator p_i = getAtomPositionBegin(); for ( ; a_i != a_e; ++a_i, ++p_i ) { if ( *a_i == atomid ) { position = *p_i; return 0; // success } } return -1; // failure }
void colvarproxy_namd::calculate() { if (first_timestep) { this->setup(); colvars->setup(); colvars->setup_input(); colvars->setup_output(); first_timestep = false; } else { // Use the time step number inherited from GlobalMaster if ( step - previous_NAMD_step == 1 ) { colvars->it++; } // Other cases could mean: // - run 0 // - beginning of a new run statement // then the internal counter should not be incremented } previous_NAMD_step = step; { Vector const a = lattice->a(); Vector const b = lattice->b(); Vector const c = lattice->c(); unit_cell_x.set(a.x, a.y, a.z); unit_cell_y.set(b.x, b.y, c.z); unit_cell_z.set(c.x, c.y, c.z); } if (!lattice->a_p() && !lattice->b_p() && !lattice->c_p()) { boundaries_type = boundaries_non_periodic; reset_pbc_lattice(); } else if (lattice->a_p() && lattice->b_p() && lattice->c_p()) { if (lattice->orthogonal()) { boundaries_type = boundaries_pbc_ortho; } else { boundaries_type = boundaries_pbc_triclinic; } colvarproxy_system::update_pbc_lattice(); } else { boundaries_type = boundaries_unsupported; } if (cvm::debug()) { log(std::string(cvm::line_marker)+ "colvarproxy_namd, step no. "+cvm::to_str(colvars->it)+"\n"+ "Updating atomic data arrays.\n"); } // must delete the forces applied at the previous step: we can do // that because they have already been used and copied to other // memory locations modifyForcedAtoms().clear(); modifyAppliedForces().clear(); // prepare local arrays for (size_t i = 0; i < atoms_ids.size(); i++) { atoms_positions[i] = cvm::rvector(0.0, 0.0, 0.0); atoms_total_forces[i] = cvm::rvector(0.0, 0.0, 0.0); atoms_new_colvar_forces[i] = cvm::rvector(0.0, 0.0, 0.0); } for (size_t i = 0; i < atom_groups_ids.size(); i++) { atom_groups_total_forces[i] = cvm::rvector(0.0, 0.0, 0.0); atom_groups_new_colvar_forces[i] = cvm::rvector(0.0, 0.0, 0.0); } // create the atom map if needed size_t const n_all_atoms = Node::Object()->molecule->numAtoms; if (atoms_map.size() != n_all_atoms) { atoms_map.resize(n_all_atoms); atoms_map.assign(n_all_atoms, -1); update_atoms_map(getAtomIdBegin(), getAtomIdEnd()); } // if new atomic positions or forces have been communicated by other GlobalMasters, add them to the atom map if ((int(atoms_ids.size()) < (getAtomIdEnd() - getAtomIdBegin())) || (int(atoms_ids.size()) < (getForceIdEnd() - getForceIdBegin()))) { update_atoms_map(getAtomIdBegin(), getAtomIdEnd()); update_atoms_map(getForceIdBegin(), getForceIdEnd()); } { if (cvm::debug()) { log("Updating positions arrays.\n"); } size_t n_positions = 0; AtomIDList::const_iterator a_i = getAtomIdBegin(); AtomIDList::const_iterator a_e = getAtomIdEnd(); PositionList::const_iterator p_i = getAtomPositionBegin(); for ( ; a_i != a_e; ++a_i, ++p_i ) { atoms_positions[atoms_map[*a_i]] = cvm::rvector((*p_i).x, (*p_i).y, (*p_i).z); n_positions++; } // The following had to be relaxed because some atoms may be forced without their position being requested // if (n_positions < atoms_ids.size()) { // cvm::error("Error: did not receive the positions of all atoms.\n", BUG_ERROR); // } } if (total_force_requested && cvm::step_relative() > 0) { // sort the force arrays the previous step // (but only do so if there *is* a previous step!) { if (cvm::debug()) { log("Updating total forces arrays.\n"); } size_t n_total_forces = 0; AtomIDList::const_iterator a_i = getForceIdBegin(); AtomIDList::const_iterator a_e = getForceIdEnd(); ForceList::const_iterator f_i = getTotalForce(); for ( ; a_i != a_e; ++a_i, ++f_i ) { atoms_total_forces[atoms_map[*a_i]] = cvm::rvector((*f_i).x, (*f_i).y, (*f_i).z); n_total_forces++; } if (n_total_forces < atoms_ids.size()) { cvm::error("Error: total forces were requested, but total forces " "were not received for all atoms.\n" "The most probable cause is combination of energy " "minimization with a biasing method that requires MD (e.g. ABF).\n" "Always run minimization and ABF separately.", INPUT_ERROR); } } { if (cvm::debug()) { log("Updating group total forces arrays.\n"); } ForceList::const_iterator f_i = getGroupTotalForceBegin(); ForceList::const_iterator f_e = getGroupTotalForceEnd(); size_t i = 0; if ((f_e - f_i) != ((int) atom_groups_ids.size())) { cvm::error("Error: total forces were requested for scalable groups, " "but they are not in the same number from the number of groups.\n" "The most probable cause is combination of energy " "minimization with a biasing method that requires MD (e.g. ABF).\n" "Always run minimization and ABF separately.", INPUT_ERROR); } for ( ; f_i != f_e; f_i++, i++) { atom_groups_total_forces[i] = cvm::rvector((*f_i).x, (*f_i).y, (*f_i).z); } } } { if (cvm::debug()) { log("Updating group positions arrays.\n"); } // update group data (only coms available so far) size_t ig; // note: getGroupMassBegin() could be used here, but masses and charges // have already been calculated from the last call to setup() PositionList::const_iterator gp_i = getGroupPositionBegin(); for (ig = 0; gp_i != getGroupPositionEnd(); gp_i++, ig++) { atom_groups_coms[ig] = cvm::rvector(gp_i->x, gp_i->y, gp_i->z); } } if (cvm::debug()) { log("atoms_ids = "+cvm::to_str(atoms_ids)+"\n"); log("atoms_ncopies = "+cvm::to_str(atoms_ncopies)+"\n"); log("atoms_masses = "+cvm::to_str(atoms_masses)+"\n"); log("atoms_charges = "+cvm::to_str(atoms_charges)+"\n"); log("atoms_positions = "+cvm::to_str(atoms_positions)+"\n"); log("atoms_total_forces = "+cvm::to_str(atoms_total_forces)+"\n"); log(cvm::line_marker); log("atom_groups_ids = "+cvm::to_str(atom_groups_ids)+"\n"); log("atom_groups_ncopies = "+cvm::to_str(atom_groups_ncopies)+"\n"); log("atom_groups_masses = "+cvm::to_str(atom_groups_masses)+"\n"); log("atom_groups_charges = "+cvm::to_str(atom_groups_charges)+"\n"); log("atom_groups_coms = "+cvm::to_str(atom_groups_coms)+"\n"); log("atom_groups_total_forces = "+cvm::to_str(atom_groups_total_forces)+"\n"); log(cvm::line_marker); } // call the collective variable module if (colvars->calc() != COLVARS_OK) { cvm::error("Error in the collective variables module.\n", COLVARS_ERROR); } if (cvm::debug()) { log(cvm::line_marker); log("atoms_new_colvar_forces = "+cvm::to_str(atoms_new_colvar_forces)+"\n"); log(cvm::line_marker); log("atom_groups_new_colvar_forces = "+cvm::to_str(atom_groups_new_colvar_forces)+"\n"); log(cvm::line_marker); } // communicate all forces to the MD integrator for (size_t i = 0; i < atoms_ids.size(); i++) { cvm::rvector const &f = atoms_new_colvar_forces[i]; modifyForcedAtoms().add(atoms_ids[i]); modifyAppliedForces().add(Vector(f.x, f.y, f.z)); } { // zero out the applied forces on each group modifyGroupForces().resize(modifyRequestedGroups().size()); ForceList::iterator gf_i = modifyGroupForces().begin(); for (int ig = 0; gf_i != modifyGroupForces().end(); gf_i++, ig++) { cvm::rvector const &f = atom_groups_new_colvar_forces[ig]; *gf_i = Vector(f.x, f.y, f.z); } } // send MISC energy reduction->submit(); // NAMD does not destruct GlobalMaster objects, so we must remember // to write all output files at the end of a run if (step == simparams->N) { colvars->write_restart_file(cvm::output_prefix()+".colvars.state"); colvars->write_output_files(); } }