Repository navigation
test: fix the atom mapping of XYZ frames in the stub interfaces #985
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
2118790
test: fix the atom mapping of XYZ frames in the stub interfaces
HanatoK 6bc7070
fix: measure debugGradients errors against the gradient scale of the CVC
HanatoK 103b48e
test: do not add all atoms in functional tests
jhenin 7c632e8
test: Update output for new force XYZ traj format
jhenin ab90278
refactor: move colvarproxy_stubs_gpu to own files
jhenin 399e496
test: harmonize CPU and GPU functional tests
jhenin 0faff29
build: fix the HIP build of the GPU stub test interface
HanatoK 9bda051
fix: compare the .xyz files in compare_test.sh
HanatoK d4d02f6
fix: check out-of-bound atom IDs when reading XYZ files in stubs
HanatoK File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,230 @@ | ||
| // -*- c++ -*- | ||
|
|
||
| // This file is part of the Collective Variables module (Colvars). | ||
| // The original version of Colvars and its updates are located at: | ||
| // https://github.com/Colvars/colvars | ||
| // Please update all Colvars source files before making any changes. | ||
| // If you wish to distribute your changes, please submit them to the | ||
| // Colvars repository at GitHub. | ||
|
|
||
|
|
||
| #include <iostream> | ||
| #include <fstream> | ||
| // #include <string> | ||
| #include <iomanip> | ||
|
|
||
| #include "colvar_gpu_support.h" | ||
| #include "colvarmodule.h" | ||
| #include "colvarscript.h" | ||
| #include "colvarproxy.h" | ||
| #include "colvarproxy_stub_gpu.h" | ||
|
|
||
| #define COLVARPROXY_VERSION COLVARS_VERSION | ||
|
|
||
| #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) | ||
|
|
||
| colvarproxy_stub_gpu::colvarproxy_stub_gpu(): | ||
| stream(0), d_mPositions(nullptr), d_mAppliedForces(nullptr), | ||
| d_mTotalForces(nullptr), mAtomsChanged(false) { | ||
| smp_mode = smp_mode_t::none; | ||
| support_gpu = true; | ||
| version_int = get_version_from_string(COLVARPROXY_VERSION); | ||
| b_simulation_running = false; | ||
|
|
||
| // both fields are taken from data structures already available | ||
| updated_masses_ = updated_charges_ = true; | ||
|
|
||
| checkGPUError(cudaStreamCreate(&stream)); | ||
| } | ||
|
|
||
| colvarproxy_stub_gpu::~colvarproxy_stub_gpu() { | ||
| checkGPUError(cudaStreamSynchronize(stream)); | ||
| checkGPUError(cudaStreamDestroy(stream)); | ||
| deallocateDeviceArrays(); | ||
| } | ||
|
|
||
| int colvarproxy_stub_gpu::setup() { | ||
| int error_code = colvarproxy::setup(); | ||
| // Set system boundaries as the default (non-periodic) | ||
| boundaries_.reset(); | ||
| if (cvmodule) { | ||
| cvmodule->it = cvmodule->it_restart = 0; | ||
| return cvmodule->update_engine_parameters(); | ||
| } | ||
| return error_code; | ||
| } | ||
|
|
||
| void colvarproxy_stub_gpu::request_total_force(bool yesno) | ||
| { | ||
| total_force_requested = yesno; | ||
| } | ||
|
|
||
| bool colvarproxy_stub_gpu::total_forces_enabled() const | ||
| { | ||
| return total_force_requested; | ||
| } | ||
|
|
||
| bool colvarproxy_stub_gpu::total_forces_same_step() const | ||
| { | ||
| return total_force_requested; | ||
| } | ||
|
|
||
|
|
||
| int colvarproxy_stub_gpu::set_unit_system(std::string const &units_in, | ||
| bool check_only) | ||
| { | ||
| // if check_only is specified, just test for compatibility | ||
| // colvarmodule sets this flag if new units are requested while colvars are already defined | ||
| if (check_only) { | ||
| if ((units != "" && units_in != units) || (units == "" && units_in != "real")) { | ||
| cvmodule->error("Specified unit system \"" + units_in + "\" is incompatible with previous setting \"" | ||
| + units + "\".\nReset the Colvars Module or delete all variables to change the unit.\n"); | ||
| return COLVARS_ERROR; | ||
| } else { | ||
| return COLVARS_OK; | ||
| } | ||
| } | ||
|
|
||
| if (units_in == "real") { | ||
| angstrom_value_ = 1.; | ||
| kcal_mol_value_ = 1.; | ||
| } else if (units_in == "metal") { | ||
| angstrom_value_ = 1.; | ||
| kcal_mol_value_ = 0.0433641017; // eV | ||
| // inverse of LAMMPS value is 1/23.060549 = .043364102 | ||
| } else if (units_in == "electron") { | ||
| angstrom_value_ = 1.88972612; // Bohr | ||
| kcal_mol_value_ = 0.00159360144; // Hartree | ||
| } else if (units_in == "gromacs") { | ||
| angstrom_value_ = 0.1; // nm | ||
| kcal_mol_value_ = 4.184; // kJ/mol | ||
| } else { | ||
| cvmodule->error("Unknown unit system specified: \"" + units_in + "\". Supported are real, metal, electron, and gromacs.\n"); | ||
| return COLVARS_ERROR; | ||
| } | ||
|
|
||
| units = units_in; | ||
| return COLVARS_OK; | ||
| } | ||
|
|
||
|
|
||
| void colvarproxy_stub_gpu::log(std::string const &message) | ||
| { | ||
| std::cout << "colvars: " << message; | ||
| } | ||
|
|
||
|
|
||
| void colvarproxy_stub_gpu::error(std::string const &message) | ||
| { | ||
| add_error_msg(message); | ||
| std::cerr << "colvars: " << message; | ||
| throw; | ||
| } | ||
|
|
||
|
|
||
| int colvarproxy_stub_gpu::check_atom_id(int atom_number) | ||
| { | ||
| return atom_number-1; | ||
| } | ||
|
|
||
|
|
||
| int colvarproxy_stub_gpu::init_atom(int atom_number) | ||
| { | ||
| // save time by checking first whether this atom has been requested before | ||
| // (this is more common than a non-valid atom number) | ||
| int aid = (atom_number-1); | ||
|
|
||
| for (size_t i = 0; i < atoms_ids.size(); i++) { | ||
| if (atoms_ids[i] == aid) { | ||
| // this atom id was already recorded | ||
| atoms_refcount[i] += 1; | ||
| return i; | ||
| } | ||
| } | ||
|
|
||
| aid = check_atom_id(atom_number); | ||
|
|
||
| if (aid < 0) { | ||
| return COLVARS_INPUT_ERROR; | ||
| } | ||
|
|
||
| int const index = add_atom_slot(aid); | ||
| mAtomsChanged = true; | ||
| return index; | ||
| } | ||
|
|
||
| void colvarproxy_stub_gpu::clear_atom(int index) { | ||
| colvarproxy::clear_atom(index); | ||
| mAtomsChanged = true; | ||
| } | ||
|
|
||
| int colvarproxy_stub_gpu::read_frame_xyz(const char *filename, const bool write_force_file) | ||
| { | ||
| // The XYZ file lists atoms by increasing ID, but atom slots follow the order in which the | ||
| // atoms were requested: read all positions first, then copy them into their slots | ||
| const size_t numAtoms = atoms_ids.size(); | ||
| // xyz_positions is empty on the first call, and resized to the total number of atoms on | ||
| // subsequent calls - this will read all positions in both cases | ||
| int error_code = cvmodule->load_coords_xyz(filename, &xyz_positions, nullptr, true); | ||
|
|
||
| if (mAtomsChanged) { | ||
| this->reallocate(); | ||
| error_code |= cvmodule->proxy_gpu_buffers_reallocated_done(); | ||
| } | ||
| // The XYZ file lists atoms by increasing ID, but atom slots follow the order | ||
| // in which the atoms were requested | ||
| m_positions_soa.resize(3 * numAtoms); | ||
| bool atom_id_invalid = false; | ||
| for (size_t i = 0; i < numAtoms; ++i) { | ||
| atom_id_invalid = atom_id_invalid || !(static_cast<size_t>(atoms_ids[i]) < xyz_positions.size()); | ||
| m_positions_soa[i] = !atom_id_invalid ? xyz_positions[atoms_ids[i]].x : 0; | ||
| m_positions_soa[i+numAtoms] = !atom_id_invalid ? xyz_positions[atoms_ids[i]].y : 0; | ||
| m_positions_soa[i+2*numAtoms] = !atom_id_invalid ? xyz_positions[atoms_ids[i]].z : 0; | ||
| } | ||
| if (atom_id_invalid) { | ||
| return cvmodule->error("Invalid atom ID.\n", COLVARS_INPUT_ERROR); | ||
| } | ||
| error_code |= copy_HtoD_async(m_positions_soa.data(), d_mPositions, 3 * numAtoms, stream); | ||
| error_code |= clear_device_array_async(d_mAppliedForces, 3 * numAtoms, stream); | ||
| error_code |= clear_device_array_async(d_mTotalForces, 3 * numAtoms, stream); | ||
| error_code |= checkGPUError(cudaEventRecord(get_event(colvarproxy_gpu::event_type::copy_atoms), stream)); | ||
| std::string force_filename; | ||
| if (write_force_file) { | ||
| force_filename = cvmodule->output_prefix() + ".forces.xyz"; | ||
| } | ||
| if ( !error_code ) { | ||
| error_code |= cvmodule->calc(); | ||
| cvmodule->it++; | ||
| m_applied_forces_soa.resize(3 * numAtoms); | ||
| error_code |= copy_DtoH_async(d_mAppliedForces, m_applied_forces_soa.data(), 3 * numAtoms, stream); | ||
| error_code |= checkGPUError(cudaStreamSynchronize(stream)); | ||
| if (write_force_file) { | ||
| // Write the forces in XYZ trajectory format | ||
| // forces_by_id is indexed by atom ID, so we need to cover all atoms | ||
| size_t const numAtoms_total = xyz_positions.size(); | ||
| forces_by_id.resize(numAtoms_total); | ||
| // Initialize all forces to zero, then fill in the relevant ones by atom ID | ||
| std::fill(forces_by_id.begin(), forces_by_id.end(), cvm::rvector{0, 0, 0}); | ||
| for (size_t i = 0; i < numAtoms; ++i) { | ||
| forces_by_id[atoms_ids[i]] = cvm::rvector(m_applied_forces_soa[i], | ||
| m_applied_forces_soa[i + numAtoms], | ||
| m_applied_forces_soa[i + 2 * numAtoms]); | ||
| } | ||
| // Create XYZ trajectory: overwrite on first frame, append on subsequent frames | ||
| std::ios::openmode mode = (cvmodule->it == 1) ? std::ios::out : std::ios::app; | ||
| std::ofstream ofs(force_filename, mode); | ||
| ofs << numAtoms_total << std::endl; | ||
| ofs << std::endl; | ||
| for (size_t i = 0; i < numAtoms_total; ++i) { | ||
| ofs << std::setw(7) << (i+1) << " " // Atom ID (1-based) | ||
| << std::scientific << std::setprecision(8) << std::setw(16) << forces_by_id[i].x << std::setw(0) << " " | ||
| << std::scientific << std::setprecision(8) << std::setw(16) << forces_by_id[i].y << std::setw(0) << " " | ||
| << std::scientific << std::setprecision(8) << std::setw(16) << forces_by_id[i].z << std::endl; | ||
| } | ||
| } | ||
| } | ||
| mAtomsChanged = false; | ||
| return error_code; | ||
| } | ||
| #endif | ||
|
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.