diff --git a/colvartools/poisson_integrator.cpp b/colvartools/poisson_integrator.cpp index 4ad4f3080..5d8066c5f 100644 --- a/colvartools/poisson_integrator.cpp +++ b/colvartools/poisson_integrator.cpp @@ -17,14 +17,14 @@ int main (int argc, char *argv[]) { proxy->cvmodule = new colvarmodule(proxy); // This could be omitted if we used the colvarproxy_stub class std::string gradfile (argv[1]); - std::shared_ptr grad_ptr = std::make_shared(gradfile); + std::shared_ptr grad_ptr = std::make_shared(proxy->cvmodule, gradfile); if (proxy->cvmodule->get_error()) { return -1; } int itmax = 10000; cvm::real err; cvm::real tol = 1e-8; - colvargrid_integrate fes(grad_ptr); + colvargrid_integrate fes(proxy->cvmodule, grad_ptr); fes.set_div(); fes.integrate(itmax, tol, err); fes.set_zero_minimum(); diff --git a/colvartools/poisson_integrator_conv.cpp b/colvartools/poisson_integrator_conv.cpp index e8a477ffc..a01610a15 100644 --- a/colvartools/poisson_integrator_conv.cpp +++ b/colvartools/poisson_integrator_conv.cpp @@ -17,17 +17,17 @@ int main (int argc, char *argv[]) { proxy->cvmodule = new colvarmodule(proxy); // This could be omitted if we used the colvarproxy_stub class std::string gradfile (argv[1]); - std::shared_ptr grad_ptr = std::make_shared(gradfile); + std::shared_ptr grad_ptr = std::make_shared(proxy->cvmodule, gradfile); if (proxy->cvmodule->get_error()) { return -1; } cvm::real err = 1.; cvm::real tol = 1e-10; - colvargrid_integrate fes(grad_ptr); + colvargrid_integrate fes(proxy->cvmodule, grad_ptr); fes.set_div(); // Load reference - colvar_grid_scalar ref(gradfile + ".ref"); + colvar_grid_scalar ref(proxy->cvmodule, gradfile + ".ref"); if (proxy->cvmodule->get_error()) { return -1; } if (ref.number_of_points() != fes.number_of_points()) { diff --git a/lammps/src/COLVARS/colvarproxy_lammps.cpp b/lammps/src/COLVARS/colvarproxy_lammps.cpp index 8cc40de7e..c74e58fb0 100644 --- a/lammps/src/COLVARS/colvarproxy_lammps.cpp +++ b/lammps/src/COLVARS/colvarproxy_lammps.cpp @@ -146,7 +146,7 @@ double colvarproxy_lammps::compute() (_lmp->domain->triclinic == 0)) { // Orthogonal unit cell boundaries_type = boundaries_pbc_ortho; - colvarproxy_system::update_pbc_lattice(); + colvarproxy::update_pbc_lattice(); // It is safer to let LAMMPS deal with high-tilt triclinic boxes } else { boundaries_type = boundaries_unsupported; diff --git a/misc_interfaces/C_fortran/C_test.c b/misc_interfaces/C_fortran/C_test.c index 0305cd01f..47269155d 100644 --- a/misc_interfaces/C_fortran/C_test.c +++ b/misc_interfaces/C_fortran/C_test.c @@ -11,8 +11,8 @@ int main() { // Cannot yet call colvarscript without language interface unsigned char cmd[][256] = {"", "version" }; - run_colvarscript_command(1, (unsigned char **)(cmd)); - const char *res = get_colvarscript_result(); + run_colvarscript_command(proxy, 1, (unsigned char **)(cmd)); + const char *res = get_colvarscript_result(proxy); printf("Colvarscript claims it runs version %s\n", res); return 0; } diff --git a/misc_interfaces/C_fortran/Makefile b/misc_interfaces/C_fortran/Makefile index cd5361a49..eac0e8b46 100644 --- a/misc_interfaces/C_fortran/Makefile +++ b/misc_interfaces/C_fortran/Makefile @@ -7,7 +7,7 @@ COLVARS_LIB = ../../src/libcolvars.a COLVARS_SRC_DIR = ../../src IF_OBJ = colvarproxy_C.o -CXXFLAGS := -std=c++11 -pedantic -g -O2 -fPIC +CXXFLAGS := -std=c++17 -pedantic -g -O2 -fPIC .PHONY: default $(COLVARS_LIB) diff --git a/misc_interfaces/C_fortran/colvarproxy_C.cpp b/misc_interfaces/C_fortran/colvarproxy_C.cpp index 6ccd68fcd..5337de084 100644 --- a/misc_interfaces/C_fortran/colvarproxy_C.cpp +++ b/misc_interfaces/C_fortran/colvarproxy_C.cpp @@ -10,7 +10,7 @@ static colvarproxy* unique_colvarproxy_object; colvarproxy_C::colvarproxy_C() { std::cerr << "This is the colvarproxy_C constructor at address " << this << std::endl; - colvars = new colvarmodule(this); + cvmodule = new colvarmodule(this); cvmodule->log("This is the Module speaking."); } diff --git a/misc_interfaces/C_fortran/colvarproxy_C_interface.h b/misc_interfaces/C_fortran/colvarproxy_C_interface.h index 583011d5b..6539d3ee0 100644 --- a/misc_interfaces/C_fortran/colvarproxy_C_interface.h +++ b/misc_interfaces/C_fortran/colvarproxy_C_interface.h @@ -15,8 +15,8 @@ void call_proxy_member(void *proxy); // Functions of this type should define a complete interface // This could be based on colvarscript -int run_colvarscript_command(int objc, unsigned char *const objv[]); -const char * get_colvarscript_result(); +int run_colvarscript_command(void *proxy_in, int objc, unsigned char *const objv[]); +const char * get_colvarscript_result(void *proxy_in); #ifdef __cplusplus } diff --git a/namd/cudaglobalmaster/colvarproxy_cudaglobalmaster.C b/namd/cudaglobalmaster/colvarproxy_cudaglobalmaster.C index ed1ea177e..cd0eadb2d 100644 --- a/namd/cudaglobalmaster/colvarproxy_cudaglobalmaster.C +++ b/namd/cudaglobalmaster/colvarproxy_cudaglobalmaster.C @@ -175,7 +175,7 @@ public: return smp_mode_t::none; } std::vector get_available_smp_modes() const override { - std::vector available_modes{ + std::vector available_modes{ smp_mode_t::none, smp_mode_t::gpu }; @@ -351,9 +351,9 @@ void colvarproxy_impl::initialize_from_cudagm( if (simParams->firstTimestep != 0) { cvmodule->set_initial_step(static_cast(simParams->firstTimestep)); } - colvarproxy_io::set_output_prefix(std::string(simParams->outputFilename)); - colvarproxy_io::set_restart_output_prefix(std::string(simParams->restartFilename)); - colvarproxy_io::set_default_restart_frequency(simParams->restartFrequency); + colvarproxy::set_output_prefix(std::string(simParams->outputFilename)); + colvarproxy::set_restart_output_prefix(std::string(simParams->restartFilename)); + colvarproxy::set_default_restart_frequency(simParams->restartFrequency); } // Copied from colvarproxy_namd.C @@ -814,9 +814,9 @@ void colvarproxy_impl::calculate() { // aware of this via the following flag b_simulation_continuing = true; // Update NAMD output and restart prefixes - colvarproxy_io::set_output_prefix(std::string(simParams->outputFilename)); - colvarproxy_io::set_restart_output_prefix(std::string(simParams->restartFilename)); - colvarproxy_io::set_default_restart_frequency(simParams->restartFrequency); + colvarproxy::set_output_prefix(std::string(simParams->outputFilename)); + colvarproxy::set_restart_output_prefix(std::string(simParams->restartFilename)); + colvarproxy::set_default_restart_frequency(simParams->restartFrequency); cvmodule->setup_output(); } } @@ -1018,7 +1018,7 @@ void colvarproxy_impl::set_lattice() { } else { boundaries_type = boundaries_pbc_triclinic; } - colvarproxy_system::update_pbc_lattice(); + colvarproxy::update_pbc_lattice(); } else { boundaries_type = boundaries_unsupported; } diff --git a/namd/src/colvarproxy_namd.C b/namd/src/colvarproxy_namd.C index cdda407ea..b51ba38e1 100644 --- a/namd/src/colvarproxy_namd.C +++ b/namd/src/colvarproxy_namd.C @@ -82,7 +82,7 @@ colvarproxy_namd::colvarproxy_namd(GlobalMasterColvars *gm) // find the input state file StringList *input_restart = Node::Object()->configList->find("colvarsInput"); - colvarproxy_io::set_input_prefix(input_restart ? input_restart->data : ""); + colvarproxy::set_input_prefix(input_restart ? input_restart->data : ""); update_target_temperature(); set_integration_timestep(simparams->dt); @@ -94,9 +94,9 @@ colvarproxy_namd::colvarproxy_namd(GlobalMasterColvars *gm) updated_masses_ = updated_charges_ = true; // Take the output prefixes from the NAMD input - colvarproxy_io::set_output_prefix(std::string(simparams->outputFilename)); - colvarproxy_io::set_restart_output_prefix(std::string(simparams->restartFilename)); - colvarproxy_io::set_default_restart_frequency(simparams->restartFrequency); + colvarproxy::set_output_prefix(std::string(simparams->outputFilename)); + colvarproxy::set_restart_output_prefix(std::string(simparams->restartFilename)); + colvarproxy::set_default_restart_frequency(simparams->restartFrequency); if (simparams->accelMDOn) { accelMDOn = true; @@ -376,9 +376,9 @@ void colvarproxy_namd::calculate() b_simulation_continuing = true; // Update NAMD output and restart prefixes - colvarproxy_io::set_output_prefix(std::string(simparams->outputFilename)); - colvarproxy_io::set_restart_output_prefix(std::string(simparams->restartFilename)); - colvarproxy_io::set_default_restart_frequency(simparams->restartFrequency); + colvarproxy::set_output_prefix(std::string(simparams->outputFilename)); + colvarproxy::set_restart_output_prefix(std::string(simparams->restartFilename)); + colvarproxy::set_default_restart_frequency(simparams->restartFrequency); cvmodule->setup_output(); } @@ -407,7 +407,7 @@ void colvarproxy_namd::calculate() } else { boundaries_type = boundaries_pbc_triclinic; } - colvarproxy_system::update_pbc_lattice(); + colvarproxy::update_pbc_lattice(); } else { boundaries_type = boundaries_unsupported; } diff --git a/namd/src/colvarproxy_namd.h b/namd/src/colvarproxy_namd.h index 655e33db7..3b61f9835 100644 --- a/namd/src/colvarproxy_namd.h +++ b/namd/src/colvarproxy_namd.h @@ -128,7 +128,7 @@ class colvarproxy_namd : public colvarproxy { return smp_mode_t::cvcs; } std::vector get_available_smp_modes() const override { - std::vector available_modes{ + std::vector available_modes{ smp_mode_t::cvcs, smp_mode_t::inner_loop, smp_mode_t::none diff --git a/src/Makefile b/src/Makefile index cd59fff35..5c191f468 100644 --- a/src/Makefile +++ b/src/Makefile @@ -17,7 +17,7 @@ ifeq ($(CXX),) CXX := g++ endif ifeq ($(CXXFLAGS),) -CXXFLAGS := -std=c++11 -pedantic -g -O2 -fPIC +CXXFLAGS := -std=c++17 -pedantic -g -O2 -fPIC ifneq ($(CXX),"CC") CXXFLAGS += -Wall endif diff --git a/src/colvar.cpp b/src/colvar.cpp index dea6f2d45..c96d9b653 100644 --- a/src/colvar.cpp +++ b/src/colvar.cpp @@ -23,8 +23,8 @@ #include "colvarcomp_torchann.h" #include "colvarcomp_coordnums.h" -std::map> colvar::global_cvc_map = - std::map>(); +std::map> colvar::global_cvc_map = + std::map>(); std::map colvar::global_cvc_desc_map = std::map(); @@ -822,8 +822,8 @@ template void colvar::add_component_type(char const *def_description, char const *def_config_key) { if (global_cvc_map.count(def_config_key) == 0) { - global_cvc_map[def_config_key] = []() { - return new def_class_name(); + global_cvc_map[def_config_key] = [](colvarmodule *cvmodule_in) { + return new def_class_name(cvmodule_in); }; global_cvc_desc_map[def_config_key] = std::string(def_description); } @@ -845,7 +845,7 @@ int colvar::init_components_type(const std::string& conf, const char* def_config "a new \""+std::string(def_config_key)+"\" component"+ (cvm::debug() ? ", with configuration:\n"+def_conf : ".\n")); - cvc *cvcp = global_cvc_map[def_config_key](); + cvc *cvcp = global_cvc_map[def_config_key](cvmodule); if (!cvcp) { return cvmodule->error("Error: in creating object of type \"" + std::string(def_config_key) + "\".\n", @@ -1991,7 +1991,7 @@ void colvar::update_extended_Lagrangian() // [O] leap to v_(i+1/2) (10c) if (is_enabled(f_cv_Langevin)) { colvarvalue rnd(x); - rnd.set_random(); + rnd.set_random(this->cvmodule); // ext_sigma has been computed at init time according to (10c) v_ext = cvm::exp(- 1.0 * dt * ext_gamma) * v_ext + ext_sigma * rnd / ext_mass; } diff --git a/src/colvar.h b/src/colvar.h index c8498a7ed..7283a58d1 100644 --- a/src/colvar.h +++ b/src/colvar.h @@ -652,7 +652,7 @@ class colvar : public colvardeps { class map_total; /// A global mapping of cvc names to the cvc constructors - static const std::map> &get_global_cvc_map() + static const std::map> &get_global_cvc_map() { return global_cvc_map; } @@ -705,7 +705,7 @@ class colvar : public colvardeps { #endif /// A global mapping of cvc names to the cvc constructors - static std::map> global_cvc_map; + static std::map> global_cvc_map; /// A global mapping of cvc names to the corresponding descriptions static std::map global_cvc_desc_map; diff --git a/src/colvar_gpu_calc.cpp b/src/colvar_gpu_calc.cpp index 376c7221a..e3a8bc2ec 100644 --- a/src/colvar_gpu_calc.cpp +++ b/src/colvar_gpu_calc.cpp @@ -21,7 +21,6 @@ int colvarmodule_gpu_calc::cv_update_flags(const std::vector& colvars) int colvarmodule_gpu_calc::cvc_calc_total_force( const std::vector& colvars, colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule, bool use_current_step) { int error_code = COLVARS_OK; const bool total_force_valid = cvmodule->proxy ? cvmodule->proxy->total_forces_valid() : false; @@ -133,8 +132,7 @@ int colvarmodule_gpu_calc::cvc_calc_total_force( int colvarmodule_gpu_calc::atom_group_read_data_gpu( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule) { + colvarmodule_gpu_calc::compute_gpu_graph_t& g) { colvarproxy* p = cvmodule->proxy; cudaStream_t stream = p->get_default_stream(); int error_code = COLVARS_OK; @@ -255,8 +253,7 @@ int colvarmodule_gpu_calc::atom_group_read_data_gpu( int colvarmodule_gpu_calc::cvc_calc_value( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule) { + colvarmodule_gpu_calc::compute_gpu_graph_t& g) { int error_code = COLVARS_OK; colvarproxy* p = cvmodule->proxy; cudaStream_t stream = p->get_default_stream(); @@ -342,8 +339,7 @@ int colvarmodule_gpu_calc::cvc_calc_value( int colvarmodule_gpu_calc::cvc_calc_gradients( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule) { + colvarmodule_gpu_calc::compute_gpu_graph_t& g) { int error_code = COLVARS_OK; colvarproxy* p = cvmodule->proxy; cudaStream_t stream = p->get_default_stream(); @@ -414,8 +410,7 @@ int colvarmodule_gpu_calc::cvc_calc_gradients( int colvarmodule_gpu_calc::atom_group_calc_fit_gradients( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule) { + colvarmodule_gpu_calc::compute_gpu_graph_t& g) { int error_code = COLVARS_OK; colvarproxy* p = cvmodule->proxy; cudaStream_t stream = p->get_default_stream(); @@ -510,7 +505,7 @@ int colvarmodule_gpu_calc::atom_group_calc_fit_gradients( return error_code; } -int colvarmodule_gpu_calc::cvc_debug_gradients(const std::vector& colvars, colvarmodule* cvmodule) { +int colvarmodule_gpu_calc::cvc_debug_gradients(const std::vector& colvars) { int error_code = COLVARS_OK; for (auto cvi = colvars.begin(); cvi != colvars.end(); cvi++) { const auto all_cvcs = (*cvi)->get_cvcs(); @@ -530,8 +525,7 @@ int colvarmodule_gpu_calc::cvc_debug_gradients(const std::vector& colva int colvarmodule_gpu_calc::cvc_calc_Jacobian_derivative( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule) { + colvarmodule_gpu_calc::compute_gpu_graph_t& g) { int error_code = COLVARS_OK; colvarproxy* p = cvmodule->proxy; cudaStream_t stream = p->get_default_stream(); @@ -615,7 +609,7 @@ int colvarmodule_gpu_calc::cvc_calc_Jacobian_derivative( return error_code; } -int colvarmodule_gpu_calc::cv_collect_cvc_data(const std::vector& colvars, colvarmodule* cvmodule) { +int colvarmodule_gpu_calc::cv_collect_cvc_data(const std::vector& colvars) { int error_code = COLVARS_OK; #if defined (COLVARS_NVTX_PROFILING) cv_collect_cvc_data_prof.start(); @@ -634,8 +628,8 @@ int colvarmodule_gpu_calc::cv_collect_cvc_data(const std::vector& colva return error_code; } -colvarmodule_gpu_calc::compute_gpu_graph_t::compute_gpu_graph_t(): -graph_exec_initialized(false), graph(NULL), graph_exec(NULL) { +colvarmodule_gpu_calc::compute_gpu_graph_t::compute_gpu_graph_t(colvarmodule* cvmodule_in): +graph_exec_initialized(false), graph(NULL), graph_exec(NULL), cvmodule(cvmodule_in) { } int colvarmodule_gpu_calc::compute_gpu_graph_t::init() { @@ -672,7 +666,15 @@ void colvarmodule_gpu_calc::compute_gpu_graph_t::dump_graph(const char* filename checkGPUError(cudaGraphDebugDotPrint(graph, filename, dotFlags)); } -colvarmodule_gpu_calc::colvarmodule_gpu_calc() { +colvarmodule_gpu_calc::colvarmodule_gpu_calc(colvarmodule* cvmodule_in): + read_data_compute(cvmodule_in), + calc_value_compute(cvmodule_in), + calc_gradients_compute(cvmodule_in), + calc_Jacobian_derivative_compute(cvmodule_in), + calc_total_force_compute(cvmodule_in), + calc_fit_gradients_compute(cvmodule_in), + apply_forces_compute(cvmodule_in), + cvmodule(cvmodule_in){ #if defined (COLVARS_NVTX_PROFILING) ag_read_data_prof.set_name_color("ag_read_data", 0xc36eff); cvc_calc_value_prof.set_name_color("cvc_calc_value", 0x99dfff); @@ -698,7 +700,7 @@ int colvarmodule_gpu_calc::init() { return error_code; } -int colvarmodule_gpu_calc::calc_cvs(const std::vector& colvars, colvarmodule* cvmodule) { +int colvarmodule_gpu_calc::calc_cvs(const std::vector& colvars) { int error_code = COLVARS_OK; #define checkColvarsError(stmt) do { \ error_code |= stmt; \ @@ -709,34 +711,32 @@ int colvarmodule_gpu_calc::calc_cvs(const std::vector& colvars, colvarm checkColvarsError(cv_update_flags(colvars)); // Calculate total force if (cvmodule->step_relative() > 0) { - checkColvarsError(cvc_calc_total_force(colvars, calc_total_force_compute, cvmodule, false)); + checkColvarsError(cvc_calc_total_force(colvars, calc_total_force_compute, false)); } // Read data to atom groups - checkColvarsError(atom_group_read_data_gpu( - colvars, read_data_compute, cvmodule)); + checkColvarsError(atom_group_read_data_gpu(colvars, read_data_compute)); // Wait for extra information (for example, lattice) from the MD engine // before the CPU loop checkColvarsError(p->wait_for_extra_info_ready()); // Calculate CVC values - checkColvarsError(cvc_calc_value(colvars, calc_value_compute, cvmodule)); + checkColvarsError(cvc_calc_value(colvars, calc_value_compute)); // Calculate CVC gradients - checkColvarsError(cvc_calc_gradients(colvars, calc_gradients_compute, cvmodule)); + checkColvarsError(cvc_calc_gradients(colvars, calc_gradients_compute)); // Calculate fit gradients for atom groups - checkColvarsError(atom_group_calc_fit_gradients( - colvars, calc_fit_gradients_compute, cvmodule)); + checkColvarsError(atom_group_calc_fit_gradients(colvars, calc_fit_gradients_compute)); // Debug gradients - checkColvarsError(cvc_debug_gradients(colvars, cvmodule)); + checkColvarsError(cvc_debug_gradients(colvars)); // Calculate the Jacobian terms - checkColvarsError(cvc_calc_Jacobian_derivative(colvars, calc_Jacobian_derivative_compute, cvmodule)); + checkColvarsError(cvc_calc_Jacobian_derivative(colvars, calc_Jacobian_derivative_compute)); // Calculate total force - checkColvarsError(cvc_calc_total_force(colvars, calc_total_force_compute, cvmodule, true)); + checkColvarsError(cvc_calc_total_force(colvars, calc_total_force_compute, true)); // Collect CVC data - checkColvarsError(cv_collect_cvc_data(colvars, cvmodule)); + checkColvarsError(cv_collect_cvc_data(colvars)); #undef checkColvarsError return error_code; } -int colvarmodule_gpu_calc::apply_forces(const std::vector& colvars, colvarmodule* cvmodule) { +int colvarmodule_gpu_calc::apply_forces(const std::vector& colvars) { int error_code = COLVARS_OK; #define checkColvarsError(stmt) do { \ error_code |= stmt; \ diff --git a/src/colvar_gpu_calc.h b/src/colvar_gpu_calc.h index a4b885adf..f6e17126b 100644 --- a/src/colvar_gpu_calc.h +++ b/src/colvar_gpu_calc.h @@ -54,7 +54,7 @@ class colvarmodule_gpu_calc { class compute_gpu_graph_t { public: /// \brief Constructor - compute_gpu_graph_t(); + compute_gpu_graph_t(colvarmodule* cvmodule_in); /// \brief (Re)initialize the CUDA graph int init(); /// \brief Destructor @@ -69,11 +69,13 @@ class colvarmodule_gpu_calc { cudaGraphExec_t graph_exec; /// \brief List of compute nodes std::vector nodes; + /// \brief colvarmodule object for logging and debugging + colvarmodule* cvmodule; }; /** * @brief Constructor */ - colvarmodule_gpu_calc(); + colvarmodule_gpu_calc(colvarmodule* cvmodule_in); /** * @brief Destructor */ @@ -104,10 +106,9 @@ class colvarmodule_gpu_calc { * launched for "atom_group_read_data_gpu" and "atom_group_calc_fit_gradients". * * @param[in] colvars A vector of all colvar objects - * @param[in] cvmodule The main colvarmodule object * @return COLVARS_OK if succeeded */ - int calc_cvs(const std::vector& colvars, colvarmodule* cvmodule); + int calc_cvs(const std::vector& colvars); /** * @brief Apply the forces to the atom groups from the CVCs * @@ -115,10 +116,9 @@ class colvarmodule_gpu_calc { * instantiated. On subsequent calls, the existing CUDA graph will be launched. * * @param[in] colvars A vector of all colvar objects - * @param[in] cvmodule The main colvarmodule object * @return COLVARS_OK if succeeded */ - int apply_forces(const std::vector& colvars, colvarmodule* cvmodule); + int apply_forces(const std::vector& colvars); private: /// \brief CUDA graph for reading data to GPU and calculating required properties compute_gpu_graph_t read_data_compute; @@ -162,35 +162,29 @@ class colvarmodule_gpu_calc { int cvc_calc_total_force( const std::vector& colvars, colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule, bool use_current_step = false); int atom_group_read_data_gpu( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule); + colvarmodule_gpu_calc::compute_gpu_graph_t& g); int cvc_calc_value( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule); + colvarmodule_gpu_calc::compute_gpu_graph_t& g); int cvc_calc_gradients( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule); + colvarmodule_gpu_calc::compute_gpu_graph_t& g); int atom_group_calc_fit_gradients( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule); + colvarmodule_gpu_calc::compute_gpu_graph_t& g); int cvc_debug_gradients( - const std::vector& colvars, - colvarmodule* cvmodule); + const std::vector& colvars); int cvc_calc_Jacobian_derivative( const std::vector& colvars, - colvarmodule_gpu_calc::compute_gpu_graph_t& g, - colvarmodule* cvmodule); + colvarmodule_gpu_calc::compute_gpu_graph_t& g); int cv_collect_cvc_data( - const std::vector& colvars, - colvarmodule* cvmodule); + const std::vector& colvars); /// @} + /// \brief colvarmodule object for logging and debugging + colvarmodule* cvmodule; }; } diff --git a/src/colvar_gpu_support.cpp b/src/colvar_gpu_support.cpp index 0fecaf699..3b8607dc5 100644 --- a/src/colvar_gpu_support.cpp +++ b/src/colvar_gpu_support.cpp @@ -13,7 +13,7 @@ namespace colvars_gpu { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) -int gpuAssert(cudaError_t code, const char *file, int line) +int gpuAssert(colvarmodule* cvmodule, cudaError_t code, const char *file, int line) { if (code != cudaSuccess) { std::string error = @@ -24,12 +24,13 @@ int gpuAssert(cudaError_t code, const char *file, int line) error += "\nBacktrace:\n" + std::to_string(std::stacktrace::current()) + "\n"; #endif #endif - return cvm::error_static(error, COLVARS_ERROR); + return cvm::error_static(cvmodule, error, COLVARS_ERROR); } return COLVARS_OK; } int add_clear_array_node_impl( + colvarmodule* cvmodule, void* dst, const size_t num_elements, const size_t sizeofT, cudaGraphNode_t& node_out, cudaGraph_t& graph, const std::vector& dependencies) { @@ -46,6 +47,7 @@ int add_clear_array_node_impl( memsetParams.height = 1; if (cvm::debug()) { cvm::log_static( + cvmodule, "Add a memset clear node: ptr = " + cvm::to_str(dst) + " width = " + cvm::to_str(width) + " elementSize = " + cvm::to_str(elementSize) + "\n"); @@ -56,11 +58,12 @@ int add_clear_array_node_impl( } int add_copy_node_impl( + colvarmodule* cvmodule, const void* src, void* dst, const size_t num_elements, const size_t sizeofT, cudaMemcpyKind kind, cudaGraphNode_t& node_out, cudaGraph_t& graph, const std::vector& dependencies) { if (cvm::debug()) { - cvm::log_static( + cvm::log_static(cvmodule, "Add a memcpy node: src = " + cvm::to_str(src) + " dst = " + cvm::to_str(dst) + " num_elements = " + cvm::to_str(num_elements) + "\n"); @@ -71,6 +74,7 @@ int add_copy_node_impl( } int prepare_dependencies( + colvarmodule* cvmodule, const std::vector>& node_names, std::vector& dependencies, const std::unordered_map& map, @@ -82,15 +86,15 @@ int prepare_dependencies( if (auto search = map.find(node_name); search != map.end()) { dependencies.push_back(search->second); if (cvm::debug()) { - cvm::log_static("Operation " + caller_operation_name + + cvm::log_static(cvmodule, "Operation " + caller_operation_name + " depends on node\" " + node_name + "\"\n"); } } else { if (!allow_not_found) { - error_code |= cvm::error_static("BUG: cannot find node " + node_name + "\n"); + error_code |= cvm::error_static(cvmodule, "BUG: cannot find node " + node_name + "\n"); } else { if (cvm::debug()) { - cvm::log_static("Operation " + caller_operation_name + + cvm::log_static(cvmodule, "Operation " + caller_operation_name + " cannot depend on node\" " + node_name + "\"\n"); } } diff --git a/src/colvar_gpu_support.h b/src/colvar_gpu_support.h index e8064e426..3c859d97a 100644 --- a/src/colvar_gpu_support.h +++ b/src/colvar_gpu_support.h @@ -170,6 +170,8 @@ #endif // defined(COLVARS_HIP) +class colvarmodule; + namespace colvars_gpu { #if defined(COLVARS_CUDA) || defined(COLVARS_HIP) @@ -243,7 +245,7 @@ class CudaHostAllocator { * @param line The line number in the source file * @return COLVARS_OK if no error, otherwise the COLVARS_ERROR */ -int gpuAssert(cudaError_t code, const char *file, int line); +int gpuAssert(colvarmodule* cvmodule, cudaError_t code, const char *file, int line); #endif } // namespace colvars_gpu @@ -251,7 +253,7 @@ int gpuAssert(cudaError_t code, const char *file, int line); #if defined(COLVARS_CUDA) || defined (COLVARS_HIP) /// \define checkGPUError(ans) { gpuAssert((ans), __FILE__, __LINE__); } /// \brief Macro to check for CUDA errors -#define checkGPUError(ans) colvars_gpu::gpuAssert((ans), __FILE__, __LINE__); +#define checkGPUError(ans) colvars_gpu::gpuAssert(cvmodule, (ans), __FILE__, __LINE__); #endif namespace colvars_gpu { @@ -261,6 +263,7 @@ namespace colvars_gpu { * @brief Add a CUDA graph node to clear an array to zero (used by add_clear_array_node) */ int add_clear_array_node_impl( + colvarmodule* cvmodule, void* dst, const size_t num_elements, const size_t sizeofT, cudaGraphNode_t& node_out, cudaGraph_t& graph, const std::vector& dependencies); @@ -269,6 +272,7 @@ int add_clear_array_node_impl( * @brief Add a CUDA graph node to copy an array (used by add_copy_node) */ int add_copy_node_impl( + colvarmodule* cvmodule, const void* src, void* dst, const size_t num_elements, const size_t sizeofT, cudaMemcpyKind kind, cudaGraphNode_t& node_out, cudaGraph_t& graph, const std::vector& dependencies); @@ -286,11 +290,12 @@ int add_copy_node_impl( */ template int add_clear_array_node( + colvarmodule* cvmodule, T* dst, const size_t num_elements, cudaGraphNode_t& node_out, cudaGraph_t& graph, const std::vector& dependencies) { return add_clear_array_node_impl( - dst, num_elements, sizeof(T), node_out, graph, dependencies); + cvmodule, dst, num_elements, sizeof(T), node_out, graph, dependencies); } /** @@ -308,10 +313,11 @@ int add_clear_array_node( */ template int add_copy_node( + colvarmodule* cvmodule, const T* src, T* dst, size_t num_elements, cudaMemcpyKind kind, cudaGraphNode_t& node_out, cudaGraph_t& graph, const std::vector& dependencies) { - return add_copy_node_impl(src, dst, num_elements, sizeof(T), + return add_copy_node_impl(cvmodule, src, dst, num_elements, sizeof(T), kind, node_out, graph, dependencies); } @@ -329,6 +335,7 @@ int add_copy_node( * @return COLVARS_OK if all required nodes are found, otherwise COLVARS_ERROR */ int prepare_dependencies( + colvarmodule* cvmodule, const std::vector>& node_names, std::vector& dependencies, const std::unordered_map& map, diff --git a/src/colvar_rotation_derivative.cpp b/src/colvar_rotation_derivative.cpp index 90d1107b3..a82cc8c64 100644 --- a/src/colvar_rotation_derivative.cpp +++ b/src/colvar_rotation_derivative.cpp @@ -52,7 +52,7 @@ int rotation_derivative_gpu::add_prepare_derivative_nodes( int error_code = COLVARS_OK; cudaGraphNode_t node; error_code |= colvars_gpu::prepare_derivative( - require_dl_dq, m_rot->d_S_eigval, + cvmodule, require_dl_dq, m_rot->d_S_eigval, m_rot->d_S_eigvec, tmp_Q0Q0, tmp_Q0Q0_L, node, graph, {}); nodes_map["prepare_rotation_derivative"] = node; diff --git a/src/colvaratoms.cpp b/src/colvaratoms.cpp index 56d750fed..96ff4eb24 100644 --- a/src/colvaratoms.cpp +++ b/src/colvaratoms.cpp @@ -93,9 +93,10 @@ cvm::atom_group::simple_atom cvm::atom_group::init_atom_from_proxy( /*.grad = */{0, 0, 0}}; } -cvm::atom_group::atom_group(): +cvm::atom_group::atom_group(colvarmodule* cvmodule_in): + colvardeps(cvmodule_in), b_dummy(false), - fitting_group(nullptr), + fitting_group(nullptr), rot(cvmodule_in), noforce(false), b_user_defined_fit(false), rot_deriv(nullptr), num_atoms(0), index(-1), num_ref_pos(0) @@ -108,7 +109,7 @@ cvm::atom_group::atom_group(): init(); } -cvm::atom_group::atom_group(char const *key_in): atom_group() { +cvm::atom_group::atom_group(char const *key_in, colvarmodule* cvmodule_in): atom_group(cvmodule_in) { key = std::string(key_in); init(); } @@ -837,7 +838,7 @@ int cvm::atom_group::parse_fitting_options(std::string const &group_conf) { return COLVARS_INPUT_ERROR; } cvmodule->log("Within atom group \""+key+"\":\n"); - fitting_group = new atom_group("fittingGroup"); + fitting_group = new atom_group("fittingGroup", cvmodule); if (fitting_group->parse(fitting_group_conf) == COLVARS_OK) { fitting_group->check_keywords(fitting_group_conf, "fittingGroup"); if (cvmodule->get_error()) { @@ -1002,7 +1003,7 @@ void cvm::atom_group::update_total_mass() { const double t_m = total_mass; std::transform(atoms_mass.begin(), atoms_mass.end(), atoms_weight.begin(), [t_m](cvm::real x){return x/t_m;}); - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined(COLVARS_CUDA) || defined(COLVARS_HIP) // thrust::device_ptr p_mass = thrust::device_pointer_cast(d_atoms_mass); // total_mass = thrust::reduce(p_mass, p_mass + num_atoms); @@ -1210,7 +1211,7 @@ void cvm::atom_group::center_ref_pos() } #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) colvarproxy* p = cvmodule->proxy; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { gpu_atom_group->setup_rotation(this); } #endif @@ -1254,7 +1255,7 @@ void cvm::atom_group::read_velocities() if (b_dummy) return; colvarproxy *p = cvmodule->proxy; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if 0 // This is never used. #endif @@ -1285,7 +1286,7 @@ void cvm::atom_group::read_total_forces() if (b_dummy) return; colvarproxy *p = cvmodule->proxy; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined(COLVARS_CUDA) || defined(COLVARS_HIP) // TODO: At this point, I don't know if read_total_forces // is called before or after getting the positions, so @@ -1657,7 +1658,7 @@ void cvm::atom_group::apply_colvar_force(cvm::real const &force) } colvarproxy* const p = cvmodule->proxy; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined(COLVARS_CUDA) || defined(COLVARS_HIP) gpu_atom_group->apply_colvar_force_from_cpu(force); // Just intercept the force and return @@ -1761,7 +1762,7 @@ void cvm::atom_group::set_ref_pos_from_aos(const std::vector& pos ref_pos = cvm::atom_group::pos_aos_to_soa(pos_aos); #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) colvarproxy* p = cvmodule->proxy; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { // p->reallocate_device(&gpu_buffers.d_ref_pos, ref_pos.size()); // p->copy_HtoD(ref_pos.data(), gpu_buffers.d_ref_pos, ref_pos.size()); gpu_atom_group->setup_rotation(this); @@ -1778,7 +1779,7 @@ m_ag(ag), m_group_for_fit(m_ag->fitting_group ? m_ag->fitting_group : m_ag), m_has_fitting_force(m_ag->is_enabled(f_ag_center) || m_ag->is_enabled(f_ag_rotate)) { // We need to store the CPU forces in case of the GPU-resident mode colvarproxy* const p = m_ag->cvmodule->proxy; - if (m_has_fitting_force || p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (m_has_fitting_force || p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { if (m_ag->group_forces.size() != 3 * m_ag->size()) { m_ag->group_forces.assign(3 * m_ag->size(), 0); } else { @@ -1790,7 +1791,7 @@ m_has_fitting_force(m_ag->is_enabled(f_ag_center) || m_ag->is_enabled(f_ag_rotat cvm::atom_group::group_force_object::~group_force_object() { colvarproxy* const p = m_ag->cvmodule->proxy; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) m_ag->gpu_atom_group->set_use_cpu_group_force(true); // CPU forces are already intercepted into group_forces @@ -1805,7 +1806,7 @@ cvm::atom_group::group_force_object::~group_force_object() { void cvm::atom_group::group_force_object::add_atom_force( size_t i, const cvm::rvector& force) { colvarproxy* const p = m_ag->cvmodule->proxy; - if (m_has_fitting_force || p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (m_has_fitting_force || p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { // m_ag->group_forces[i] += force; m_ag->group_forces_x(i) += force.x; m_ag->group_forces_y(i) += force.y; diff --git a/src/colvaratoms.h b/src/colvaratoms.h index 717d9a281..ab8d576e9 100644 --- a/src/colvaratoms.h +++ b/src/colvaratoms.h @@ -63,11 +63,11 @@ class cvm::atom_group: public colvardeps { * @attention Will call \p init_dependencies() to initialize the * dependency tree. */ - atom_group(); + atom_group(colvarmodule* cvmodule_in); /** * @brief Create a group object, assign a name to it */ - atom_group(char const *key_in); + atom_group(char const *key_in, colvarmodule* cvmodule_in); /** * @brief Destructor * diff --git a/src/colvaratoms_gpu.cpp b/src/colvaratoms_gpu.cpp index a041d7e07..03cdea1fa 100644 --- a/src/colvaratoms_gpu.cpp +++ b/src/colvaratoms_gpu.cpp @@ -10,7 +10,7 @@ namespace colvars_gpu { #if defined(COLVARS_CUDA) || defined(COLVARS_HIP) colvaratoms_gpu::colvaratoms_gpu(colvarmodule *cvmodule_in) - : cvmodule(cvmodule_in) { + : rot_gpu(cvmodule_in), cvmodule(cvmodule_in) { std::memset(&gpu_buffers, 0, sizeof(gpu_buffers)); std::memset(&debug_graphs, 0, sizeof(debug_graphs)); std::memset(&calc_fit_gradients_gpu_info, 0, sizeof(calc_fit_gradients_gpu_info)); @@ -181,7 +181,7 @@ int colvaratoms_gpu::add_reset_atoms_data_nodes( if (!cpu_atoms->is_enabled(colvardeps::f_ag_scalable)) { #define ADD_CLEAR_FIELD_NODE(fieldName, numAtoms) do {\ cudaGraphNode_t clear_ ## fieldName ## _node ;\ -error_code |= colvars_gpu::add_clear_array_node( \ +error_code |= colvars_gpu::add_clear_array_node(cvmodule, \ gpu_buffers.d_ ## fieldName, 3 * numAtoms, \ clear_ ## fieldName ## _node , graph, {});\ nodes_map[COLVARS_STRINGIFY(clear_ ## fieldName)] = clear_ ## fieldName ## _node;\ @@ -208,7 +208,7 @@ int colvaratoms_gpu::add_read_positions_nodes( cudaGraphNode_t read_positions_main; std::vector dependencies; error_code |= colvars_gpu::atoms_pos_from_proxy( - gpu_buffers.d_atoms_index, p->proxy_atoms_positions_gpu(), + cvmodule, gpu_buffers.d_atoms_index, p->proxy_atoms_positions_gpu(), gpu_buffers.d_atoms_pos, cpu_atoms->num_atoms, p->get_atom_ids()->size(), read_positions_main, graph, dependencies); @@ -217,7 +217,7 @@ int colvaratoms_gpu::add_read_positions_nodes( if (cpu_atoms->fitting_group) { cudaGraphNode_t read_positions_fitting; error_code |= colvars_gpu::atoms_pos_from_proxy( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_index, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_index, p->proxy_atoms_positions_gpu(), cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, cpu_atoms->fitting_group->num_atoms, @@ -246,10 +246,10 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( cudaGraphNode_t calc_com_cog_main; std::vector dependencies = extra_initial_dependencies; error_code |= colvars_gpu::prepare_dependencies( - {{"read_positions_main", true}}, + cvmodule, {{"read_positions_main", true}}, dependencies, nodes_map, "calc_cog_com_main"); error_code |= colvars_gpu::atoms_calc_cog_com( - gpu_buffers.d_atoms_pos, gpu_buffers.d_atoms_mass, cpu_atoms->num_atoms, + cvmodule, gpu_buffers.d_atoms_pos, gpu_buffers.d_atoms_mass, cpu_atoms->num_atoms, gpu_buffers.d_cog_tmp, gpu_buffers.d_cog, gpu_buffers.d_cog_orig, gpu_buffers.d_com_tmp, gpu_buffers.d_com, gpu_buffers.h_cog, gpu_buffers.h_com, cpu_atoms->total_mass, @@ -269,11 +269,11 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( // Add COG kernel node std::vector dependencies = extra_initial_dependencies; error_code |= colvars_gpu::prepare_dependencies( - {{"read_positions_fitting", true}}, + cvmodule, {{"read_positions_fitting", true}}, dependencies, nodes_map, "calc_cog_fitting"); cudaGraphNode_t calc_cog_fitting; error_code |= colvars_gpu::atoms_calc_cog( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, cpu_atoms->fitting_group->num_atoms, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_cog_tmp, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_cog, @@ -296,13 +296,13 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( std::vector dependencies; // d_rpg_cog could be the COG of the fitting group, so we need to wait for it error_code |= colvars_gpu::prepare_dependencies( - {{"calc_com_cog_main", false}, + cvmodule, {{"calc_com_cog_main", false}, {"read_positions_main", true}, {"calc_cog_fitting", true}}, dependencies, nodes_map, "apply_translation_main"); cudaGraphNode_t move_to_origin_main; error_code |= colvars_gpu::apply_translation( - gpu_buffers.d_atoms_pos, -1.0, d_rpg_cog, + cvmodule, gpu_buffers.d_atoms_pos, -1.0, d_rpg_cog, cpu_atoms->num_atoms, move_to_origin_main, graph, dependencies ); @@ -310,12 +310,12 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( if (cpu_atoms->fitting_group) { std::vector dependencies_fitting_group_translate; error_code |= colvars_gpu::prepare_dependencies( - {{"calc_cog_fitting", false}, + cvmodule, {{"calc_cog_fitting", false}, {"read_positions_fitting", true}}, dependencies_fitting_group_translate, nodes_map, "apply_translation_fitting"); cudaGraphNode_t move_to_origin_fitting; error_code |= colvars_gpu::apply_translation( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, -1.0, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, -1.0, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_cog, cpu_atoms->fitting_group->num_atoms, move_to_origin_fitting, @@ -329,11 +329,11 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( if (cpu_atoms->is_enabled(colvardeps::f_ag_fit_gradients) && !cpu_atoms->b_dummy) { std::vector dependencies; error_code |= colvars_gpu::prepare_dependencies( - {{"read_positions_main", true}, {"move_to_origin_main", true}}, + cvmodule, {{"read_positions_main", true}, {"move_to_origin_main", true}}, dependencies, nodes_map, "copy_unrotated_positions"); cudaGraphNode_t copy_unrotated_positions; error_code |= colvars_gpu::add_copy_node( - gpu_buffers.d_atoms_pos, gpu_buffers.d_atoms_pos_unrotated, + cvmodule, gpu_buffers.d_atoms_pos, gpu_buffers.d_atoms_pos_unrotated, 3 * cpu_atoms->num_atoms, cudaMemcpyDeviceToDevice, copy_unrotated_positions, graph, dependencies); @@ -354,27 +354,27 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( // The atom group may be moved to origin (but not always). // The rotation should also wait after the COG and COM done error_code |= colvars_gpu::prepare_dependencies( - {{"calc_optimal_rotation", false}, + cvmodule, {{"calc_optimal_rotation", false}, {"copy_unrotated_positions", true}, {"move_to_origin_main", true}, {"calc_com_cog_main", true}}, dependencies_rotate, nodes_map, "rotate_main"); cudaGraphNode_t rotate_main; error_code |= colvars_gpu::rotate_with_quaternion( - gpu_buffers.d_atoms_pos, rot_gpu.get_q(), cpu_atoms->num_atoms, + cvmodule, gpu_buffers.d_atoms_pos, rot_gpu.get_q(), cpu_atoms->num_atoms, rotate_main, graph, dependencies_rotate); nodes_map["rotate_main"] = rotate_main; if (cpu_atoms->fitting_group) { std::vector dependencies_rotate_fitting_group; error_code |= colvars_gpu::prepare_dependencies( - {{"calc_optimal_rotation", false}, + cvmodule, {{"calc_optimal_rotation", false}, {"move_to_origin_fitting", true}, {"calc_cog_fitting", true}}, dependencies_rotate_fitting_group, nodes_map, "rotate_fitting"); cudaGraphNode_t rotate_fitting; error_code |= colvars_gpu::rotate_with_quaternion( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, rot_gpu.get_q(), cpu_atoms->fitting_group->num_atoms, rotate_fitting, graph, @@ -389,28 +389,28 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( // It looks like that the moving to COG of ref_pos can depend on // any of the following operations, so I add them all. error_code |= colvars_gpu::prepare_dependencies( - {{"calc_com_cog_main", false}, + cvmodule, {{"calc_com_cog_main", false}, {"rotate_main", true}, {"copy_unrotated_positions", true}, {"move_to_origin_main", true}}, dependencies_move_to_ref_cog, nodes_map, "apply_translation_main_2"); cudaGraphNode_t move_to_ref_cog_main; error_code |= colvars_gpu::apply_translation( - gpu_buffers.d_atoms_pos, 1.0, gpu_buffers.d_ref_pos_cog, cpu_atoms->num_atoms, + cvmodule, gpu_buffers.d_atoms_pos, 1.0, gpu_buffers.d_ref_pos_cog, cpu_atoms->num_atoms, move_to_ref_cog_main, graph, dependencies_move_to_ref_cog); nodes_map["move_to_ref_cog_main"] = move_to_ref_cog_main; if (cpu_atoms->fitting_group) { std::vector dependencies_move_fitting_group_to_ref_cog; error_code |= colvars_gpu::prepare_dependencies( - {{"calc_cog_fitting", true}, + cvmodule, {{"calc_cog_fitting", true}, {"move_to_origin_fitting", true}, {"rotate_fitting", true}}, dependencies_move_fitting_group_to_ref_cog, nodes_map, "apply_translation_fitting_2"); cudaGraphNode_t move_to_ref_cog_fitting; error_code |= colvars_gpu::apply_translation( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, 1.0, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, 1.0, gpu_buffers.d_ref_pos_cog, cpu_atoms->fitting_group->num_atoms, move_to_ref_cog_fitting, graph, @@ -423,14 +423,14 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( // update COM and COG after fitting std::vector dependencies; error_code |= colvars_gpu::prepare_dependencies( - {{"calc_com_cog_main", false}, + cvmodule, {{"calc_com_cog_main", false}, {"move_to_origin_main", true}, {"rotate_main", true}, {"move_to_ref_cog_main", true}}, dependencies, nodes_map, "calc_cog_com_main_2"); cudaGraphNode_t calc_com_cog_main_2; error_code |= colvars_gpu::atoms_calc_cog_com( - gpu_buffers.d_atoms_pos, gpu_buffers.d_atoms_mass, cpu_atoms->num_atoms, + cvmodule, gpu_buffers.d_atoms_pos, gpu_buffers.d_atoms_mass, cpu_atoms->num_atoms, gpu_buffers.d_cog_tmp, gpu_buffers.d_cog, nullptr, gpu_buffers.d_com_tmp, gpu_buffers.d_com, gpu_buffers.h_cog, gpu_buffers.h_com, @@ -442,14 +442,14 @@ int colvaratoms_gpu::add_calc_required_properties_nodes( // The following operations may or may not exist, // but if any of them exist, we need to wait for them error_code |= colvars_gpu::prepare_dependencies( - {{"calc_cog_fitting", false}, + cvmodule, {{"calc_cog_fitting", false}, {"move_to_origin_fitting", true}, {"rotate_fitting", true}, {"move_to_ref_cog_fitting", true}}, dependencies, nodes_map, "calc_cog_fitting_2"); cudaGraphNode_t calc_cog_fitting_2; error_code |= colvars_gpu::atoms_calc_cog( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, cpu_atoms->fitting_group->num_atoms, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_cog_tmp, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_cog, @@ -472,28 +472,28 @@ int colvaratoms_gpu::add_update_cpu_buffers_nodes( if (!cpu_atoms->is_enabled(colvardeps::f_ag_scalable)) { std::vector dependencies; error_code |= colvars_gpu::prepare_dependencies( - {{"read_positions_main", true}, + cvmodule, {{"read_positions_main", true}, {"move_to_origin_main", true}, {"rotate_main", true}, {"move_to_ref_cog_main", true}}, dependencies, nodes_map, "copy_atoms_to_host"); cudaGraphNode_t copy_atoms_to_host_node; error_code |= colvars_gpu::add_copy_node( - gpu_buffers.d_atoms_pos, cpu_atoms->atoms_pos.data(), 3 * cpu_atoms->num_atoms, + cvmodule, gpu_buffers.d_atoms_pos, cpu_atoms->atoms_pos.data(), 3 * cpu_atoms->num_atoms, cudaMemcpyDeviceToHost, copy_atoms_to_host_node, graph, dependencies); nodes_map["copy_atoms_to_host"] = copy_atoms_to_host_node; if (cpu_atoms->fitting_group) { dependencies.clear(); error_code |= colvars_gpu::prepare_dependencies( - {{"read_positions_fitting", true}, + cvmodule, {{"read_positions_fitting", true}, {"move_to_origin_fitting", true}, {"rotate_fitting", true}, {"move_to_ref_cog_fitting", true}}, dependencies, nodes_map, "copy_fitting_group_atoms_to_host"); cudaGraphNode_t copy_fitting_group_atoms_to_host_node; error_code |= colvars_gpu::add_copy_node( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, cpu_atoms->fitting_group->atoms_pos.data(), 3 * cpu_atoms->fitting_group->num_atoms, cudaMemcpyDeviceToHost, @@ -508,11 +508,11 @@ int colvaratoms_gpu::add_update_cpu_buffers_nodes( } dependencies.clear(); error_code |= colvars_gpu::prepare_dependencies( - {{"copy_unrotated_positions", true}}, + cvmodule, {{"copy_unrotated_positions", true}}, dependencies, nodes_map, "copy_unrotated_positions_to_host"); cudaGraphNode_t copy_unrotated_positions_to_host_node; error_code |= colvars_gpu::add_copy_node( - gpu_buffers.d_atoms_pos_unrotated, + cvmodule, gpu_buffers.d_atoms_pos_unrotated, cpu_atoms->atoms_pos_unrotated.data(), 3 * cpu_atoms->num_atoms, cudaMemcpyDeviceToHost, copy_unrotated_positions_to_host_node, @@ -596,7 +596,7 @@ int colvaratoms_gpu::add_calc_fit_gradients_nodes( // cudaGraphNode_t clear_sum_dxdq_node; // cudaGraphNode_t clear_tbcount_node; error_code |= colvars_gpu::add_clear_array_node( - calc_fit_gradients_gpu_info.d_atom_grad, + cvmodule, calc_fit_gradients_gpu_info.d_atom_grad, 1, clear_atoms_grad_node, graph, {}); // error_code |= colvars_gpu::add_clear_array_node( // calc_fit_gradients_gpu_info.d_sum_dxdq, @@ -607,7 +607,7 @@ int colvaratoms_gpu::add_calc_fit_gradients_nodes( if (use_cpu_buffers) { cudaGraphNode_t copy_grad_HtoD_node; error_code |= colvars_gpu::add_copy_node( - cpu_atoms->atoms_grad.data(), gpu_buffers.d_atoms_grad, 3 * cpu_atoms->num_atoms, + cvmodule, cpu_atoms->atoms_grad.data(), gpu_buffers.d_atoms_grad, 3 * cpu_atoms->num_atoms, cudaMemcpyHostToDevice, copy_grad_HtoD_node, graph, {clear_atoms_grad_node}); nodes_map["copy_grad_HtoD"] = copy_grad_HtoD_node; @@ -621,13 +621,13 @@ int colvaratoms_gpu::add_calc_fit_gradients_nodes( if (cpu_atoms->is_enabled(colvardeps::f_ag_rotate) || cpu_atoms->is_enabled(colvardeps::f_ag_center)) { std::vector dependencies_main; error_code |= colvars_gpu::prepare_dependencies( - {{"clear_atoms_grad", false}, + cvmodule, {{"clear_atoms_grad", false}, {"prepare_rotation_derivative", true}, {"copy_grad_HtoD", true}}, dependencies_main, nodes_map, "calc_fit_gradients_loop1"); cudaGraphNode_t calc_fit_forces_loop1_node; error_code |= colvars_gpu::calc_fit_gradients_impl_loop1( - gpu_buffers.d_atoms_pos_unrotated, gpu_buffers.d_atoms_grad, + cvmodule, gpu_buffers.d_atoms_pos_unrotated, gpu_buffers.d_atoms_grad, rot_deriv_gpu, rot_gpu.get_q(), cpu_atoms->num_atoms, group_for_fit->size(), calc_fit_gradients_gpu_info.d_atom_grad, @@ -643,10 +643,10 @@ int colvaratoms_gpu::add_calc_fit_gradients_nodes( cudaGraphNode_t calc_fit_forces_loop2_node; std::vector dependencies_fit_gradients; error_code |= colvars_gpu::prepare_dependencies( - {{"calc_fit_gradients_loop1", false}}, + cvmodule, {{"calc_fit_gradients_loop1", false}}, dependencies_fit_gradients, nodes_map, "calc_fit_gradients_loop2"); error_code |= colvars_gpu::calc_fit_gradients_impl_loop2( - group_for_fit->gpu_atom_group->gpu_buffers.d_fit_gradients, rot_deriv_gpu, + cvmodule, group_for_fit->gpu_atom_group->gpu_buffers.d_fit_gradients, rot_deriv_gpu, calc_fit_gradients_gpu_info.d_atom_grad, calc_fit_gradients_gpu_info.d_dxdC, group_for_fit->size(), @@ -662,11 +662,11 @@ int colvaratoms_gpu::add_calc_fit_gradients_nodes( cudaGraphNode_t copy_fit_gradients_to_host; std::vector dependencies_copy_fit_gradients; error_code |= colvars_gpu::prepare_dependencies( - {{"calc_fit_gradients_loop2", false}}, + cvmodule, {{"calc_fit_gradients_loop2", false}}, dependencies_copy_fit_gradients, nodes_map, "copy_fit_gradients_to_host"); error_code |= colvars_gpu::add_copy_node( - group_for_fit->gpu_atom_group->gpu_buffers.d_fit_gradients, + cvmodule, group_for_fit->gpu_atom_group->gpu_buffers.d_fit_gradients, group_for_fit->fit_gradients.data(), 3 * group_for_fit->size(), cudaMemcpyDeviceToHost, copy_fit_gradients_to_host, graph, dependencies_copy_fit_gradients); @@ -711,7 +711,7 @@ int colvaratoms_gpu::add_apply_force_nodes( if (any_require_cpu_buffers) { cudaGraphNode_t copy_grad_to_device; error_code |= colvars_gpu::add_copy_node( - cpu_atoms->atoms_grad.data(), gpu_buffers.d_atoms_grad, 3 * cpu_atoms->num_atoms, + cvmodule, cpu_atoms->atoms_grad.data(), gpu_buffers.d_atoms_grad, 3 * cpu_atoms->num_atoms, cudaMemcpyHostToDevice, copy_grad_to_device, graph, {}); nodes_map["copy_grad_to_device"] = copy_grad_to_device; if (!all_require_cpu_buffers) { @@ -723,10 +723,10 @@ int colvaratoms_gpu::add_apply_force_nodes( cudaGraphNode_t apply_main_colvar_force_to_proxy_node; std::vector dependencies = extra_initial_dependencies; error_code |= colvars_gpu::prepare_dependencies( - {{"copy_grad_to_device", true}}, + cvmodule, {{"copy_grad_to_device", true}}, dependencies, nodes_map, "apply_main_colvar_force_to_proxy"); error_code |= colvars_gpu::apply_main_colvar_force_to_proxy( - gpu_buffers.d_atoms_index, + cvmodule, gpu_buffers.d_atoms_index, p->proxy_atoms_new_colvar_forces_gpu(), gpu_buffers.d_atoms_grad, h_sum_applied_colvar_force, @@ -741,7 +741,7 @@ int colvaratoms_gpu::add_apply_force_nodes( auto* group_for_fit = cpu_atoms->fitting_group ? cpu_atoms->fitting_group : cpu_atoms; dependencies = extra_initial_dependencies; error_code |= colvars_gpu::apply_fitting_colvar_force_to_proxy( - group_for_fit->gpu_atom_group->gpu_buffers.d_atoms_index, + cvmodule, group_for_fit->gpu_atom_group->gpu_buffers.d_atoms_index, p->proxy_atoms_new_colvar_forces_gpu(), group_for_fit->gpu_atom_group->gpu_buffers.d_fit_gradients, h_sum_applied_colvar_force, group_for_fit->size(), @@ -758,7 +758,7 @@ int colvaratoms_gpu::add_apply_force_nodes( // d_atoms_applied_force. cudaGraphNode_t copy_forces_to_device; error_code |= colvars_gpu::add_copy_node( - cpu_atoms->group_forces.data(), gpu_buffers.d_atoms_applied_force, 3 * cpu_atoms->num_atoms, + cvmodule, cpu_atoms->group_forces.data(), gpu_buffers.d_atoms_applied_force, 3 * cpu_atoms->num_atoms, cudaMemcpyHostToDevice, copy_forces_to_device, graph, dependencies); nodes_map["copy_forces_to_device"] = copy_forces_to_device; } else { @@ -767,19 +767,19 @@ int colvaratoms_gpu::add_apply_force_nodes( // need to add the CPU buffers to d_atoms_applied_force cudaGraphNode_t accumulate_cpu_force_node; error_code |= colvars_gpu::accumulate_cpu_force( - cpu_atoms->group_forces.data(), gpu_buffers.d_atoms_applied_force, cpu_atoms->num_atoms, + cvmodule, cpu_atoms->group_forces.data(), gpu_buffers.d_atoms_applied_force, cpu_atoms->num_atoms, accumulate_cpu_force_node, graph, dependencies); nodes_map["accumulate_cpu_force"] = accumulate_cpu_force_node; } } error_code |= colvars_gpu::prepare_dependencies( - {{"copy_forces_to_device", true}, {"accumulate_cpu_force", true}}, + cvmodule, {{"copy_forces_to_device", true}, {"accumulate_cpu_force", true}}, dependencies, nodes_map, "apply_force_main"); if (cpu_atoms->is_enabled(colvardeps::f_ag_rotate)) { // Rotate the forces back and add them to proxy cudaGraphNode_t apply_force_with_inverse_rotation_node; error_code |= colvars_gpu::apply_force_with_inverse_rotation( - cpu_atoms->group_forces.data(), rot_gpu.get_q(), gpu_buffers.d_atoms_index, + cvmodule, cpu_atoms->group_forces.data(), rot_gpu.get_q(), gpu_buffers.d_atoms_index, p->proxy_atoms_new_colvar_forces_gpu(), cpu_atoms->num_atoms, p->get_atom_ids()->size(), apply_force_with_inverse_rotation_node, @@ -795,7 +795,7 @@ int colvaratoms_gpu::add_apply_force_nodes( // Just add the forces to proxy cudaGraphNode_t apply_force_main_node; error_code |= colvars_gpu::apply_force( - cpu_atoms->group_forces.data(), gpu_buffers.d_atoms_index, + cvmodule, cpu_atoms->group_forces.data(), gpu_buffers.d_atoms_index, p->proxy_atoms_new_colvar_forces_gpu(), cpu_atoms->num_atoms, p->get_atom_ids()->size(), apply_force_main_node, graph, dependencies); @@ -807,16 +807,16 @@ int colvaratoms_gpu::add_apply_force_nodes( // Clear the temporary variables cudaGraphNode_t clear_atoms_grad_node; error_code |= colvars_gpu::add_clear_array_node( - calc_fit_forces_gpu_info.d_atom_grad, + cvmodule, calc_fit_forces_gpu_info.d_atom_grad, 1, clear_atoms_grad_node, graph, {}); nodes_map["clear_atoms_grad"] = clear_atoms_grad_node; error_code |= colvars_gpu::prepare_dependencies( - {{"clear_atoms_grad", false}, + cvmodule, {{"clear_atoms_grad", false}, {"prepare_rotation_derivative", true}}, dependencies, nodes_map, "calc_fit_forces_loop1"); cudaGraphNode_t calc_fit_forces_loop1_node; error_code |= colvars_gpu::calc_fit_forces_impl_loop1( - gpu_buffers.d_atoms_pos_unrotated, + cvmodule, gpu_buffers.d_atoms_pos_unrotated, gpu_buffers.d_atoms_applied_force, rot_deriv_gpu, rot_gpu.get_q(), cpu_atoms->num_atoms, group_for_fit->size(), @@ -832,7 +832,7 @@ int colvaratoms_gpu::add_apply_force_nodes( // Compute the forces on the fitting group and add them back to proxy cudaGraphNode_t calc_fit_forces_loop2_node; error_code |= colvars_gpu::calc_fit_forces_impl_loop2( - rot_deriv_gpu, + cvmodule, rot_deriv_gpu, calc_fit_forces_gpu_info.d_atom_grad, calc_fit_forces_gpu_info.d_dxdC, group_for_fit->gpu_atom_group->gpu_buffers.d_atoms_index, @@ -855,12 +855,12 @@ int colvaratoms_gpu::read_positions_gpu_debug( int error_code = COLVARS_OK; colvarproxy *p = cvmodule->proxy; error_code |= colvars_gpu::atoms_pos_from_proxy( - gpu_buffers.d_atoms_index, p->proxy_atoms_positions_gpu(), + cvmodule, gpu_buffers.d_atoms_index, p->proxy_atoms_positions_gpu(), gpu_buffers.d_atoms_pos, cpu_atoms->num_atoms, p->get_atom_ids()->size(), stream); if (cpu_atoms->fitting_group) { error_code |= colvars_gpu::atoms_pos_from_proxy( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_index, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_index, p->proxy_atoms_positions_gpu(), cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, cpu_atoms->fitting_group->num_atoms, p->get_atom_ids()->size(), @@ -868,12 +868,12 @@ int colvaratoms_gpu::read_positions_gpu_debug( } if (!change_fitting_group) { error_code |= colvars_gpu::change_one_coordinate( - gpu_buffers.d_atoms_pos, change_atom_i, xyz, + cvmodule, gpu_buffers.d_atoms_pos, change_atom_i, xyz, sign * cvmodule->debug_gradients_step_size, cpu_atoms->num_atoms, stream); } else { if (cpu_atoms->fitting_group) { error_code |= colvars_gpu::change_one_coordinate( - cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, change_atom_i, xyz, + cvmodule, cpu_atoms->fitting_group->gpu_atom_group->gpu_buffers.d_atoms_pos, change_atom_i, xyz, sign * cvmodule->debug_gradients_step_size, cpu_atoms->fitting_group->num_atoms, stream); } } @@ -977,7 +977,7 @@ int colvaratoms_gpu::read_total_forces(cvm::atom_group* cpu_atoms) { q_ptr = rot_gpu.get_q(); } error_code |= colvars_gpu::atoms_total_force_from_proxy( - gpu_buffers.d_atoms_index, p->proxy_atoms_total_forces_gpu(), + cvmodule, gpu_buffers.d_atoms_index, p->proxy_atoms_total_forces_gpu(), gpu_buffers.d_atoms_total_force, cpu_atoms->is_enabled(colvardeps::f_ag_rotate), q_ptr, cpu_atoms->num_atoms, p->get_atom_ids()->size(), p->get_default_stream()); // TODO: How can I check if the CVC has GPU implementation? diff --git a/src/colvarbias.cpp b/src/colvarbias.cpp index 065aec4d4..fa152a480 100644 --- a/src/colvarbias.cpp +++ b/src/colvarbias.cpp @@ -133,7 +133,7 @@ int colvarbias::init(std::string const &conf) std::string biasing_force_scaling_factors_in_filename; get_keyval(conf, "scaledBiasingForceFactorsGrid", biasing_force_scaling_factors_in_filename, std::string()); - biasing_force_scaling_factors = new colvar_grid_scalar(colvars); + biasing_force_scaling_factors = new colvar_grid_scalar(cvmodule, colvars); error_code |= biasing_force_scaling_factors->read_multicol(biasing_force_scaling_factors_in_filename, "grid file"); biasing_force_scaling_factors_bin.assign(num_variables(), 0); @@ -278,8 +278,8 @@ int colvarbias::reset() } -colvarbias::colvarbias() - : has_data(false) +colvarbias::colvarbias(colvarmodule* cvmodule_in) + : colvardeps(cvmodule_in), has_data(false) {} @@ -810,7 +810,7 @@ std::ostream & colvarbias::write_traj(std::ostream &os) } -colvarbias_ti::colvarbias_ti(char const *key) +colvarbias_ti::colvarbias_ti(colvarmodule* cvmodule_in, char const *key): colvardeps(cvmodule_in), colvarbias(cvmodule_in) { colvarproxy *proxy = cvmodule->proxy; provide(f_cvb_calc_ti_samples); @@ -891,8 +891,8 @@ int colvarbias_ti::init_grids() ti_system_forces[icv].is_derivative(); ti_system_forces[icv].reset(); } - ti_count.reset(new colvar_grid_count(colvars, grid_conf)); - ti_avg_forces.reset(new colvar_grid_gradient(colvars, ti_count)); + ti_count.reset(new colvar_grid_count(cvmodule, colvars, grid_conf)); + ti_avg_forces.reset(new colvar_grid_gradient(cvmodule, colvars, ti_count)); } } diff --git a/src/colvarbias.h b/src/colvarbias.h index bf05fc5be..adad93e49 100644 --- a/src/colvarbias.h +++ b/src/colvarbias.h @@ -124,7 +124,7 @@ class colvarbias protected: /// Default constructor - colvarbias(); + colvarbias(colvarmodule* cvmodule_in); /// Copy constructor colvarbias(colvarbias &); @@ -336,7 +336,7 @@ class colvar_grid_count; class colvarbias_ti : public virtual colvarbias { public: - colvarbias_ti(char const *key); + colvarbias_ti(colvarmodule* cvmodule_in, char const *key); virtual ~colvarbias_ti(); virtual int init(std::string const &conf); diff --git a/src/colvarbias_abf.cpp b/src/colvarbias_abf.cpp index f5278bb9f..ac5b793fd 100644 --- a/src/colvarbias_abf.cpp +++ b/src/colvarbias_abf.cpp @@ -15,7 +15,7 @@ #include "colvars_memstream.h" colvarbias_abf::colvarbias_abf(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), b_UI_estimator(false), b_CZAR_estimator(false), pabf_freq(0), @@ -181,16 +181,16 @@ int colvarbias_abf::init(std::string const &conf) std::string grid_conf; key_lookup(conf, "grid", &grid_conf); - samples.reset(new colvar_grid_count(colvars, grid_conf)); + samples.reset(new colvar_grid_count(cvmodule, colvars, grid_conf)); } - gradients.reset(new colvar_grid_gradient(colvars, samples)); // Also use samples as template for sizes + gradients.reset(new colvar_grid_gradient(cvmodule, colvars, samples)); // Also use samples as template for sizes gradients->full_samples = full_samples; gradients->min_samples = min_samples; if (shared_on) { - local_samples.reset(new colvar_grid_count(colvars, samples)); - local_gradients.reset(new colvar_grid_gradient(colvars, local_samples)); + local_samples.reset(new colvar_grid_count(cvmodule, colvars, samples)); + local_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, local_samples)); } // Data for eABF z-based estimator @@ -204,11 +204,11 @@ int colvarbias_abf::init(std::string const &conf) colvarparse::parse_silent); z_bin.assign(num_variables(), 0); - z_samples.reset(new colvar_grid_count(colvars, samples)); + z_samples.reset(new colvar_grid_count(cvmodule, colvars, samples)); z_samples->request_actual_value(); - z_gradients.reset(new colvar_grid_gradient(colvars, z_samples)); + z_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, z_samples)); z_gradients->request_actual_value(); - czar_gradients.reset(new colvar_grid_gradient(colvars, nullptr, samples)); + czar_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, nullptr, samples)); } get_keyval(conf, "integrate", b_integrate, num_variables() <= 3); // Integrate for output if d<=3 @@ -218,12 +218,12 @@ int colvarbias_abf::init(std::string const &conf) cvmodule->error("Error: cannot integrate free energy in dimension > 3.\n"); return COLVARS_ERROR; } - pmf.reset(new colvargrid_integrate(colvars, gradients)); + pmf.reset(new colvargrid_integrate(cvmodule, colvars, gradients)); if (b_CZAR_estimator) { - czar_pmf.reset(new colvargrid_integrate(colvars, czar_gradients)); + czar_pmf.reset(new colvargrid_integrate(cvmodule, colvars, czar_gradients)); } if (shared_on) { - local_pmf.reset(new colvargrid_integrate(colvars, local_gradients)); + local_pmf.reset(new colvargrid_integrate(cvmodule, colvars, local_gradients)); } // Parameters for integrating initial (and final) gradient data get_keyval(conf, "integrateMaxIterations", integrate_iterations, 10000, colvarparse::parse_silent); @@ -237,10 +237,10 @@ int colvarbias_abf::init(std::string const &conf) if (b_CZAR_estimator && shared_on && cvmodule->proxy->replica_index() == 0) { // The pointers below are used for outputting CZAR data // Allocate grids for collected global data, on replica 0 only - global_z_samples.reset(new colvar_grid_count(colvars, samples)); - global_z_gradients.reset(new colvar_grid_gradient(colvars, global_z_samples)); - global_czar_gradients.reset(new colvar_grid_gradient(colvars, nullptr, samples)); - global_czar_pmf.reset(new colvargrid_integrate(colvars, global_czar_gradients)); + global_z_samples.reset(new colvar_grid_count(cvmodule, colvars, samples)); + global_z_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, global_z_samples)); + global_czar_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, nullptr, samples)); + global_czar_pmf.reset(new colvargrid_integrate(cvmodule, colvars, global_czar_gradients)); } else { // otherwise they are just aliases for the local CZAR grids global_z_samples = z_samples; @@ -253,11 +253,11 @@ int colvarbias_abf::init(std::string const &conf) // This used to be only if "shared" was defined, // but now we allow calling share externally (e.g. from Tcl). if (b_CZAR_estimator) { - z_samples_in.reset(new colvar_grid_count(colvars, samples)); - z_gradients_in.reset(new colvar_grid_gradient(colvars, z_samples_in)); + z_samples_in.reset(new colvar_grid_count(cvmodule, colvars, samples)); + z_gradients_in.reset(new colvar_grid_gradient(cvmodule, colvars, z_samples_in)); } - last_samples.reset(new colvar_grid_count(colvars, samples)); - last_gradients.reset(new colvar_grid_gradient(colvars, last_samples)); + last_samples.reset(new colvar_grid_count(cvmodule, colvars, samples)); + last_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, last_samples)); // Any data collected after now is new for shared ABF purposes shared_last_step = cvmodule->step_absolute(); @@ -555,9 +555,9 @@ int colvarbias_abf::replica_share() { if (!local_samples) { // We arrive here if sharing has just been enabled by a script // in which case local arrays have not been initialized yet - local_samples.reset(new colvar_grid_count(colvars, samples)); - local_gradients.reset(new colvar_grid_gradient(colvars, local_samples)); - local_pmf.reset(new colvargrid_integrate(colvars, local_gradients)); + local_samples.reset(new colvar_grid_count(cvmodule, colvars, samples)); + local_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, local_samples)); + local_pmf.reset(new colvargrid_integrate(cvmodule, colvars, local_gradients)); } // Calculate the delta gradient and count for the local replica last_gradients->delta_grid(*gradients); @@ -675,10 +675,10 @@ int colvarbias_abf::replica_share_CZAR() { // We arrive here if sharing has just been enabled by a script // Allocate grids for collective data, on replica 0 only // overriding CZAR grids that are equal to local ones by default - global_z_samples.reset(new colvar_grid_count(colvars, samples)); - global_z_gradients.reset(new colvar_grid_gradient(colvars, global_z_samples)); - global_czar_gradients.reset(new colvar_grid_gradient(colvars, nullptr, samples)); - global_czar_pmf.reset(new colvargrid_integrate(colvars, global_czar_gradients)); + global_z_samples.reset(new colvar_grid_count(cvmodule, colvars, samples)); + global_z_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, global_z_samples)); + global_czar_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, nullptr, samples)); + global_czar_pmf.reset(new colvargrid_integrate(cvmodule, colvars, global_czar_gradients)); } // Start with data from replica 0 @@ -886,7 +886,7 @@ int colvarbias_abf::read_gradients_samples() // Therefore the czar_gradients grid is not linked to a sampling grid // Here we define a temporary czar_gradients grid linked to z_samples, // to correctly average input gradients if overlapping - czar_gradients_in.reset(new colvar_grid_gradient(colvars, z_samples)); + czar_gradients_in.reset(new colvar_grid_gradient(cvmodule, colvars, z_samples)); } for ( size_t i = 0; i < input_prefix.size(); i++ ) { diff --git a/src/colvarbias_abmd.cpp b/src/colvarbias_abmd.cpp index 65031e401..6930dfd0a 100644 --- a/src/colvarbias_abmd.cpp +++ b/src/colvarbias_abmd.cpp @@ -14,8 +14,8 @@ colvarbias_abmd::colvarbias_abmd(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), - colvarbias_ti(key) + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), + colvarbias_ti(cvmodule_in, key) { } diff --git a/src/colvarbias_alb.cpp b/src/colvarbias_alb.cpp index 1314b4876..f18cb662c 100644 --- a/src/colvarbias_alb.cpp +++ b/src/colvarbias_alb.cpp @@ -31,7 +31,7 @@ double fmin(double A, double B) { return ( A < B ? A : B ); } */ colvarbias_alb::colvarbias_alb(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), update_calls(0), b_equilibration(true) + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), update_calls(0), b_equilibration(true) { } diff --git a/src/colvarbias_histogram.cpp b/src/colvarbias_histogram.cpp index cd82afb5e..65a27092b 100644 --- a/src/colvarbias_histogram.cpp +++ b/src/colvarbias_histogram.cpp @@ -17,7 +17,7 @@ colvarbias_histogram::colvarbias_histogram(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), grid(NULL), out_name("") { provide(f_cvb_bypass_ext_lagrangian); // Allow histograms of actual cv for extended-Lagrangian @@ -90,7 +90,7 @@ int colvarbias_histogram::init(std::string const &conf) colvars[i]->enable(f_cv_grid); // Could be a child dependency of a f_cvb_use_grids feature } - grid = new colvar_grid_scalar(); + grid = new colvar_grid_scalar(cvmodule); grid->init_from_colvars(colvars); if (is_enabled(f_cvb_bypass_ext_lagrangian)) { diff --git a/src/colvarbias_histogram_reweight_amd.cpp b/src/colvarbias_histogram_reweight_amd.cpp index 2a1878310..29e06a0ca 100644 --- a/src/colvarbias_histogram_reweight_amd.cpp +++ b/src/colvarbias_histogram_reweight_amd.cpp @@ -12,7 +12,7 @@ #include "colvars_memstream.h" colvarbias_reweightaMD::colvarbias_reweightaMD(colvarmodule *cvmodule_in, char const *key) - : colvarbias_histogram(cvmodule_in, key) {} + : colvardeps(cvmodule_in), colvarbias_histogram(cvmodule_in, key) {} colvarbias_reweightaMD::~colvarbias_reweightaMD() {} @@ -31,21 +31,21 @@ int colvarbias_reweightaMD::init(std::string const &conf) { cvmodule->error("Error: historyFreq must be a multiple of outputFreq.\n", COLVARS_INPUT_ERROR); } b_history_files = (history_freq > 0); - grid_count.reset(new colvar_grid_scalar(colvars, nullptr, false, grid_conf)); + grid_count.reset(new colvar_grid_scalar(cvmodule, colvars, nullptr, false, grid_conf)); grid_count->request_actual_value(); grid->request_actual_value(); - pmf_grid_exp_avg.reset(new colvar_grid_scalar(colvars, grid_count)); + pmf_grid_exp_avg.reset(new colvar_grid_scalar(cvmodule, colvars, grid_count)); if (b_write_gradients) { - grad_grid_exp_avg.reset(new colvar_grid_gradient(colvars, nullptr, grid_count)); + grad_grid_exp_avg.reset(new colvar_grid_gradient(cvmodule, colvars, nullptr, grid_count)); } if (b_use_cumulant_expansion) { - grid_dV.reset(new colvar_grid_scalar(colvars, grid_count)); - grid_dV_square.reset(new colvar_grid_scalar(colvars, grid_count)); - pmf_grid_cumulant.reset(new colvar_grid_scalar(colvars, grid_count)); + grid_dV.reset(new colvar_grid_scalar(cvmodule, colvars, grid_count)); + grid_dV_square.reset(new colvar_grid_scalar(cvmodule, colvars, grid_count)); + pmf_grid_cumulant.reset(new colvar_grid_scalar(cvmodule, colvars, grid_count)); grid_dV->request_actual_value(); grid_dV_square->request_actual_value(); if (b_write_gradients) { - grad_grid_cumulant.reset(new colvar_grid_gradient(colvars, nullptr, grid_count)); + grad_grid_cumulant.reset(new colvar_grid_gradient(cvmodule, colvars, nullptr, grid_count)); } } previous_bin.assign(num_variables(), -1); diff --git a/src/colvarbias_meta.cpp b/src/colvarbias_meta.cpp index e06751788..f9cf9a410 100644 --- a/src/colvarbias_meta.cpp +++ b/src/colvarbias_meta.cpp @@ -20,7 +20,7 @@ colvarbias_meta::colvarbias_meta(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), colvarbias_ti(key) + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), colvarbias_ti(cvmodule_in, key) { new_hills_begin = hills.end(); @@ -157,8 +157,8 @@ int colvarbias_meta::init(std::string const &conf) get_keyval(conf, "keepFreeEnergyFiles", dump_fes_save, dump_fes_save); if (!hills_energy) { - hills_energy.reset(new colvar_grid_scalar(colvars, nullptr, false, grid_conf)); - hills_energy_gradients.reset(new colvar_grid_gradient(colvars, nullptr, hills_energy)); + hills_energy.reset(new colvar_grid_scalar(cvmodule, colvars, nullptr, false, grid_conf)); + hills_energy_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, nullptr, hills_energy)); } } else { @@ -285,7 +285,7 @@ int colvarbias_meta::init_ebmeta_params(std::string const &conf) "targetDistFile accordingly.\n", COLVARS_INPUT_ERROR); } - target_dist.reset(new colvar_grid_scalar()); + target_dist.reset(new colvar_grid_scalar(cvmodule)); error_code |= target_dist->init_from_colvars(colvars); std::string target_dist_file; get_keyval(conf, "targetDistFile", target_dist_file); @@ -1098,10 +1098,10 @@ int colvarbias_meta::update_replicas_registry() if (use_grids) { (replicas.back()) - ->hills_energy.reset(new colvar_grid_scalar(colvars, hills_energy)); + ->hills_energy.reset(new colvar_grid_scalar(cvmodule, colvars, hills_energy)); (replicas.back()) ->hills_energy_gradients.reset( - new colvar_grid_gradient(colvars, nullptr, hills_energy)); + new colvar_grid_gradient(cvmodule, colvars, nullptr, hills_energy)); } if (is_enabled(f_cvb_calc_ti_samples)) { @@ -1377,8 +1377,8 @@ template IST &colvarbias_meta::read_state_data_template_(IST &is) hills_energy_backup = std::move(hills_energy); hills_energy_gradients_backup = std::move(hills_energy_gradients); - hills_energy.reset(new colvar_grid_scalar(colvars, hills_energy)); - hills_energy_gradients.reset(new colvar_grid_gradient(colvars, nullptr, hills_energy)); + hills_energy.reset(new colvar_grid_scalar(cvmodule, colvars, hills_energy)); + hills_energy_gradients.reset(new colvar_grid_gradient(cvmodule, colvars, nullptr, hills_energy)); } read_grid_data_template_(is, "hills_energy", hills_energy.get(), @@ -1489,9 +1489,9 @@ void colvarbias_meta::rebin_grids_after_restart() // Create new grids based on the configuration parameters, because reading from the state // file automatically sets the old parameters std::shared_ptr new_hills_energy( - new colvar_grid_scalar(colvars, nullptr, false, grid_conf)); + new colvar_grid_scalar(cvmodule, colvars, nullptr, false, grid_conf)); std::shared_ptr new_hills_energy_gradients( - new colvar_grid_gradient(colvars, nullptr, new_hills_energy)); + new colvar_grid_gradient(cvmodule, colvars, nullptr, new_hills_energy)); if (cvm::debug()) { std::ostringstream tmp_os; diff --git a/src/colvarbias_opes.cpp b/src/colvarbias_opes.cpp index 7c44bba10..54edc27c7 100644 --- a/src/colvarbias_opes.cpp +++ b/src/colvarbias_opes.cpp @@ -44,7 +44,7 @@ colvarbias_opes::colvarbias_opes(colvarmodule *cvmodule_in, char const *key): - colvarbias(cvmodule_in, key), m_kbt(0), m_barrier(0), m_biasfactor(0), + colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), m_kbt(0), m_barrier(0), m_biasfactor(0), m_bias_prefactor(0), m_temperature(0), m_pace(0), m_adaptive_sigma_stride(0), m_adaptive_counter(0), m_counter(1), @@ -65,7 +65,7 @@ colvarbias_opes::colvarbias_opes(colvarmodule *cvmodule_in, char const *key): m_explore(false), m_inf_biasfactor(false) { #ifdef OPES_THREADING - provide(f_cvb_smp, cvmodule->proxy->get_smp_mode() == colvarproxy_smp::smp_mode_t::inner_loop); + provide(f_cvb_smp, cvmodule->proxy->get_smp_mode() == colvarproxy::smp_mode_t::inner_loop); if (is_available(f_cvb_smp)){ enable(f_cvb_smp); // Enabled by default } @@ -282,8 +282,8 @@ int colvarbias_opes::init(const std::string& conf) { } } key_lookup(conf, "grid", &grid_conf); - m_reweight_grid.reset(new colvar_grid_scalar(m_pmf_cvs, nullptr, false, grid_conf)); - m_pmf_grid.reset(new colvar_grid_scalar(m_pmf_cvs, m_reweight_grid)); + m_reweight_grid.reset(new colvar_grid_scalar(cvmodule, m_pmf_cvs, nullptr, false, grid_conf)); + m_pmf_grid.reset(new colvar_grid_scalar(cvmodule, m_pmf_cvs, m_reweight_grid)); get_keyval(conf, "pmfHistoryFrequency", m_pmf_hist_freq, output_freq); if ((m_pmf_hist_freq % output_freq) != 0) { error_code |= cvmodule->error("Error: pmfHistoryFrequency must be a multiple of outputFreq.\n", @@ -292,8 +292,8 @@ int colvarbias_opes::init(const std::string& conf) { if (comm == multiple_replicas) { get_keyval(conf, "pmfShared", m_pmf_shared, true); if (m_pmf_shared) { - m_global_reweight_grid.reset(new colvar_grid_scalar(m_pmf_cvs, m_reweight_grid)); - m_global_pmf_grid.reset(new colvar_grid_scalar(m_pmf_cvs, m_reweight_grid)); + m_global_reweight_grid.reset(new colvar_grid_scalar(cvmodule, m_pmf_cvs, m_reweight_grid)); + m_global_pmf_grid.reset(new colvar_grid_scalar(cvmodule, m_pmf_cvs, m_reweight_grid)); } } } diff --git a/src/colvarbias_restraint.cpp b/src/colvarbias_restraint.cpp index ba813c778..a307a9930 100644 --- a/src/colvarbias_restraint.cpp +++ b/src/colvarbias_restraint.cpp @@ -18,8 +18,8 @@ -colvarbias_restraint::colvarbias_restraint(char const *key) - : colvarbias_ti(key) +colvarbias_restraint::colvarbias_restraint(colvarmodule* cvmodule_in, char const *key) + : colvardeps(cvmodule_in), colvarbias_ti(cvmodule_in, key) // intermediate in virtual inheritance, no need to initialize base class colvarbias {} @@ -97,8 +97,8 @@ std::ostream & colvarbias_restraint::write_traj(std::ostream &os) -colvarbias_restraint_centers::colvarbias_restraint_centers(char const *key) - : colvarbias_ti(key) +colvarbias_restraint_centers::colvarbias_restraint_centers(colvarmodule* cvmodule_in, char const *key) + : colvardeps(cvmodule_in), colvarbias_ti(cvmodule_in, key) { } @@ -156,8 +156,8 @@ int colvarbias_restraint_centers::change_configuration(std::string const &conf) -colvarbias_restraint_k::colvarbias_restraint_k(char const *key) - : colvarbias_ti(key), colvarbias_restraint(key) +colvarbias_restraint_k::colvarbias_restraint_k(colvarmodule* cvmodule_in, char const *key) + : colvardeps(cvmodule_in), colvarbias_ti(cvmodule_in, key), colvarbias_restraint(cvmodule_in, key) { force_k = -1.0; check_positive_k = true; @@ -325,11 +325,11 @@ int colvarbias_restraint_moving::set_state_params(std::string const &conf) } -colvarbias_restraint_centers_moving::colvarbias_restraint_centers_moving(char const *key) - : colvarbias_ti(key), - colvarbias_restraint(key), - colvarbias_restraint_centers(key), - colvarbias_restraint_moving(key) +colvarbias_restraint_centers_moving::colvarbias_restraint_centers_moving(colvarmodule* cvmodule_in, char const *key) + : colvardeps(cvmodule_in), colvarbias_ti(cvmodule_in, key), + colvarbias_restraint(cvmodule_in, key), + colvarbias_restraint_centers(cvmodule_in, key), + colvarbias_restraint_moving(cvmodule_in, key) { b_chg_centers = false; b_output_centers = false; @@ -526,11 +526,11 @@ std::ostream & colvarbias_restraint_centers_moving::write_traj(std::ostream &os) -colvarbias_restraint_k_moving::colvarbias_restraint_k_moving(char const *key) - : colvarbias_ti(key), - colvarbias_restraint(key), - colvarbias_restraint_k(key), - colvarbias_restraint_moving(key) +colvarbias_restraint_k_moving::colvarbias_restraint_k_moving(colvarmodule* cvmodule_in, char const *key) + : colvardeps(cvmodule_in), colvarbias_ti(cvmodule_in, key), + colvarbias_restraint(cvmodule_in, key), + colvarbias_restraint_k(cvmodule_in, key), + colvarbias_restraint_moving(cvmodule_in, key) { b_chg_force_k = false; b_decoupling = false; @@ -694,14 +694,14 @@ std::ostream & colvarbias_restraint_k_moving::write_traj(std::ostream &os) colvarbias_restraint_harmonic::colvarbias_restraint_harmonic(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), - colvarbias_ti(key), - colvarbias_restraint(key), - colvarbias_restraint_centers(key), - colvarbias_restraint_moving(key), - colvarbias_restraint_k(key), - colvarbias_restraint_centers_moving(key), - colvarbias_restraint_k_moving(key) + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), + colvarbias_ti(cvmodule_in, key), + colvarbias_restraint(cvmodule_in, key), + colvarbias_restraint_centers(cvmodule_in, key), + colvarbias_restraint_moving(cvmodule_in, key), + colvarbias_restraint_k(cvmodule_in, key), + colvarbias_restraint_centers_moving(cvmodule_in, key), + colvarbias_restraint_k_moving(cvmodule_in, key) { } @@ -836,13 +836,13 @@ cvm::real colvarbias_restraint_harmonic::energy_difference(std::string const &co colvarbias_restraint_harmonic_walls::colvarbias_restraint_harmonic_walls(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), - colvarbias_ti(key), - colvarbias_restraint(key), - colvarbias_restraint_k(key), - colvarbias_restraint_moving(key), + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), + colvarbias_ti(cvmodule_in, key), + colvarbias_restraint(cvmodule_in, key), + colvarbias_restraint_k(cvmodule_in, key), + colvarbias_restraint_moving(cvmodule_in, key), // colvarbias_restraint_centers_moving(key) - colvarbias_restraint_k_moving(key) + colvarbias_restraint_k_moving(cvmodule_in, key) { lower_wall_k = -1.0; upper_wall_k = -1.0; @@ -1298,14 +1298,14 @@ std::ostream & colvarbias_restraint_harmonic_walls::write_traj(std::ostream &os) colvarbias_restraint_linear::colvarbias_restraint_linear(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key), - colvarbias_ti(key), - colvarbias_restraint(key), - colvarbias_restraint_centers(key), - colvarbias_restraint_moving(key), - colvarbias_restraint_k(key), - colvarbias_restraint_centers_moving(key), - colvarbias_restraint_k_moving(key) + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key), + colvarbias_ti(cvmodule_in, key), + colvarbias_restraint(cvmodule_in, key), + colvarbias_restraint_centers(cvmodule_in, key), + colvarbias_restraint_moving(cvmodule_in, key), + colvarbias_restraint_k(cvmodule_in, key), + colvarbias_restraint_centers_moving(cvmodule_in, key), + colvarbias_restraint_k_moving(cvmodule_in, key) { check_positive_k = false; } @@ -1444,7 +1444,7 @@ std::ostream & colvarbias_restraint_linear::write_traj(std::ostream &os) colvarbias_restraint_histogram::colvarbias_restraint_histogram(colvarmodule *cvmodule_in, char const *key) - : colvarbias(cvmodule_in, key) + : colvardeps(cvmodule_in), colvarbias(cvmodule_in, key) { lower_boundary = 0.0; upper_boundary = 0.0; diff --git a/src/colvarbias_restraint.h b/src/colvarbias_restraint.h index 402f35e12..8441d0bc9 100644 --- a/src/colvarbias_restraint.h +++ b/src/colvarbias_restraint.h @@ -42,7 +42,7 @@ class colvarbias_restraint virtual std::ostream & write_traj(std::ostream &os); /// \brief Constructor - colvarbias_restraint(char const *key); + colvarbias_restraint(colvarmodule* cvmodule_in, char const *key); virtual int init(std::string const &conf); virtual ~colvarbias_restraint(); @@ -67,7 +67,7 @@ class colvarbias_restraint_centers { public: - colvarbias_restraint_centers(char const *key); + colvarbias_restraint_centers(colvarmodule* cvmodule_in, char const *key); virtual int init(std::string const &conf); virtual int change_configuration(std::string const &conf); @@ -84,7 +84,7 @@ class colvarbias_restraint_k { public: - colvarbias_restraint_k(char const *key); + colvarbias_restraint_k(colvarmodule* cvmodule_in, char const *key); virtual int init(std::string const &conf); virtual int change_configuration(std::string const &conf); @@ -104,9 +104,9 @@ class colvarbias_restraint_moving public virtual colvardeps { public: - colvarbias_restraint_moving(char const *key) - : colvarbias_ti(key), - colvarbias_restraint(key) {} + colvarbias_restraint_moving(colvarmodule* cvmodule_in, char const *key) + : colvardeps(cvmodule_in), colvarbias_ti(cvmodule_in, key), + colvarbias_restraint(cvmodule_in, key) {} // Note: despite the diamond inheritance, most of this function gets only executed once virtual int init(std::string const &conf) override; virtual int update() override; @@ -192,7 +192,7 @@ class colvarbias_restraint_centers_moving { public: - colvarbias_restraint_centers_moving(char const *key); + colvarbias_restraint_centers_moving(colvarmodule* cvmodule_in, char const *key); virtual int init(std::string const &conf) override; virtual int change_configuration(std::string const & /* conf */) override { return COLVARS_NOT_IMPLEMENTED; } @@ -234,7 +234,7 @@ class colvarbias_restraint_k_moving public: // Do not initialize colvarbias here to avoid diamond inheritance issues // because this is an intermediate class - colvarbias_restraint_k_moving(char const *key); + colvarbias_restraint_k_moving(colvarmodule* cvmodule_in, char const *key); virtual int init(std::string const &conf) override; virtual int change_configuration(std::string const & /* conf */) override { return COLVARS_NOT_IMPLEMENTED; } diff --git a/src/colvarcomp.cpp b/src/colvarcomp.cpp index 620206444..e0b131014 100644 --- a/src/colvarcomp.cpp +++ b/src/colvarcomp.cpp @@ -18,15 +18,6 @@ #include "colvarcomp.h" -// This constructor depends on a static cvm pointer and is deprecated -colvar::cvc::cvc() - : colvardeps(cvm::main()) -{ - description = "uninitialized colvar component"; - cvc::init_dependencies(); -} - - colvar::cvc::cvc(colvarmodule *cvmodule_in) : colvardeps(cvmodule_in) { @@ -184,7 +175,7 @@ cvm::atom_group *colvar::cvc::parse_group(std::string const &conf, std::string group_conf; if (key_lookup(conf, group_key, &group_conf)) { - group = new cvm::atom_group(group_key); + group = new cvm::atom_group(group_key, cvmodule); if (b_try_scalable) { if (is_available(f_cvc_scalable_com) @@ -663,7 +654,7 @@ void colvar::cvc::debug_gradients() auto const this_atom = (*group)[ia]; for (size_t id = 0; id < 3; id++) { - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) group->get_gpu_atom_group()->read_positions_gpu_debug( group, false, ia, id, to_cpu, 1, stream); @@ -687,7 +678,7 @@ void colvar::cvc::debug_gradients() cvm::real x_1 = x.real_value; if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_1 = x[0]; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) group->get_gpu_atom_group()->read_positions_gpu_debug(group, false, ia, id, to_cpu, -1, stream); group->get_gpu_atom_group()->calc_required_properties_gpu_debug(group, to_cpu, stream); @@ -726,7 +717,7 @@ void colvar::cvc::debug_gradients() if ((group->is_enabled(f_ag_fit_gradients)) && (group->fitting_group != NULL)) { auto *ref_group = group->fitting_group; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) group->get_gpu_atom_group()->read_positions_gpu_debug( group, false, 0, -1, to_cpu, 1.0, stream); @@ -750,7 +741,7 @@ void colvar::cvc::debug_gradients() for (size_t id = 0; id < 3; id++) { // (re)read original positions - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) group->get_gpu_atom_group()->read_positions_gpu_debug( group, true, ia, id, to_cpu, 1.0, stream); @@ -774,7 +765,7 @@ void colvar::cvc::debug_gradients() cvm::real const x_1 = x.real_value; // (re)read original positions - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) group->get_gpu_atom_group()->read_positions_gpu_debug( group, true, ia, id, to_cpu, -1.0, stream); @@ -828,7 +819,7 @@ void colvar::cvc::debug_gradients() group->grad_z(ia) = 0; } // (re)read original positions - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) group->get_gpu_atom_group()->read_positions_gpu_debug( group, false, 0, -1, to_cpu, -1.0, stream); @@ -890,7 +881,7 @@ int colvar::cvc::debug_gradients_gpu( fit_gradients.data(), 3 * group_for_fit->size()); } if (group->is_enabled(f_ag_rotate)) { - cvm::rotation rot_cpu; + cvm::rotation rot_cpu(cvmodule); rot.to_cpu(rot_cpu); const auto rot_inv = rot_cpu.inverse().matrix(); auto grad_x = gradients[0].begin(); @@ -936,7 +927,7 @@ int colvar::cvc::debug_gradients_gpu( const auto& rot = group->get_gpu_atom_group()->get_rot_gpu(); auto& group_for_fit_gpu = group_for_fit->get_gpu_atom_group(); // Obtain the rotation matrix from GPU - cvm::rotation rot_cpu; + cvm::rotation rot_cpu(cvmodule); rot.to_cpu(rot_cpu); const auto rot_0 = rot_cpu.matrix(); // fit_gradients are in the simulation frame: we should print them in the rotated frame diff --git a/src/colvarcomp.h b/src/colvarcomp.h index 4634ed13a..b3e6b7322 100644 --- a/src/colvarcomp.h +++ b/src/colvarcomp.h @@ -95,7 +95,7 @@ class colvar::cvc cvm::real wrap_center = 0.0; /// Constructor - cvc(); + // cvc(); cvc(colvarmodule *cvmodule_in); @@ -385,7 +385,7 @@ class colvar::distance /// Vector distance, cached to be recycled cvm::rvector dist_v; public: - distance(); + distance(colvarmodule* cvmodule_in); virtual ~distance() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -394,8 +394,6 @@ class colvar::distance virtual void calc_Jacobian_derivative(); }; - - // \brief Colvar component: distance vector between centers of mass // of two groups (\link colvarvalue::type_3vector \endlink type, // range (-*:*)x(-*:*)x(-*:*)) @@ -403,7 +401,7 @@ class colvar::distance_vec : public colvar::distance { public: - distance_vec(); + distance_vec(colvarmodule* cvmodule_in); virtual ~distance_vec() {} virtual void calc_value(); virtual void calc_gradients(); @@ -426,7 +424,7 @@ class colvar::distance_dir : public colvar::distance { public: - distance_dir(); + distance_dir(colvarmodule* cvmodule_in); virtual ~distance_dir() {} virtual void calc_value(); virtual void calc_gradients(); @@ -464,7 +462,7 @@ class colvar::distance_z /// Flag: using a fixed axis vector? bool fixed_axis = true; public: - distance_z(); + distance_z(colvarmodule* cvmodule_in); virtual ~distance_z() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -486,7 +484,7 @@ class colvar::distance_xy /// Vector distances cvm::rvector v12, v13; public: - distance_xy(); + distance_xy(colvarmodule* cvmodule_in); virtual ~distance_xy() {} virtual void calc_value(); virtual void calc_gradients(); @@ -505,7 +503,7 @@ class colvar::polar_phi cvm::real r, theta, phi; public: - polar_phi(); + polar_phi(colvarmodule* cvmodule_in); virtual ~polar_phi() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -519,7 +517,7 @@ class colvar::polar_theta : public colvar::cvc { public: - polar_theta(); + polar_theta(colvarmodule* cvmodule_in); virtual ~polar_theta() {} virtual int init(std::string const &conf); protected: @@ -544,7 +542,7 @@ class colvar::distance_inv /// Components of the distance vector orthogonal to the axis int exponent = 6; public: - distance_inv(); + distance_inv(colvarmodule* cvmodule_in); virtual ~distance_inv() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -564,7 +562,7 @@ class colvar::distance_pairs /// Second atom group cvm::atom_group *group2 = nullptr; public: - distance_pairs(); + distance_pairs(colvarmodule* cvmodule_in); virtual ~distance_pairs() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -590,7 +588,7 @@ class colvar::dipole_magnitude cvm::atom_group *atoms = nullptr; cvm::atom_pos dipoleV; public: - dipole_magnitude(); + dipole_magnitude(colvarmodule* cvmodule_in); virtual ~dipole_magnitude() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -608,7 +606,7 @@ class colvar::gyration /// Atoms involved cvm::atom_group *atoms = nullptr; public: - gyration(); + gyration(colvarmodule* cvmodule_in); virtual ~gyration() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -625,7 +623,7 @@ class colvar::inertia : public colvar::gyration { public: - inertia(); + inertia(colvarmodule* cvmodule_in); virtual ~inertia() {} virtual void calc_value(); virtual void calc_gradients(); @@ -642,7 +640,7 @@ class colvar::inertia_z /// Vector on which the inertia tensor is projected cvm::rvector axis; public: - inertia_z(); + inertia_z(colvarmodule* cvmodule_in); virtual ~inertia_z() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -672,7 +670,7 @@ class colvar::eigenvector public: - eigenvector(); + eigenvector(colvarmodule* cvmodule_in); virtual ~eigenvector() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -708,11 +706,12 @@ class colvar::angle bool b_1site_force = false; public: - angle(); + angle(colvarmodule* cvmodule_in); /// \brief Initialize the three groups after three atoms angle(cvm::atom_group::simple_atom const &a1, cvm::atom_group::simple_atom const &a2, - cvm::atom_group::simple_atom const &a3); + cvm::atom_group::simple_atom const &a3, + colvarmodule* cvmodule_in); virtual ~angle() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -749,7 +748,7 @@ class colvar::dipole_angle bool b_1site_force = false; public: - dipole_angle(); + dipole_angle(colvarmodule* cvmodule_in); virtual ~dipole_angle() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -786,8 +785,9 @@ class colvar::dihedral dihedral(cvm::atom_group::simple_atom const &a1, cvm::atom_group::simple_atom const &a2, cvm::atom_group::simple_atom const &a3, - cvm::atom_group::simple_atom const &a4); - dihedral(); + cvm::atom_group::simple_atom const &a4, + colvarmodule* cvmodule_in); + dihedral(colvarmodule* cvmodule_in); virtual ~dihedral() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -832,7 +832,7 @@ class colvar::alpha_angles public: - alpha_angles(); + alpha_angles(colvarmodule* cvmodule_in); virtual ~alpha_angles(); virtual int init(std::string const &conf); void calc_value(); @@ -858,7 +858,7 @@ class colvar::dihedPC public: - dihedPC(); + dihedPC(colvarmodule* cvmodule_in); virtual ~dihedPC(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -904,7 +904,7 @@ class colvar::orientation public: - orientation(); + orientation(colvarmodule* cvmodule_in); virtual ~orientation(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -929,7 +929,7 @@ class colvar::orientation_angle { public: - orientation_angle(); + orientation_angle(colvarmodule* cvmodule_in); virtual ~orientation_angle() {} virtual void calc_value(); virtual void calc_gradients(); @@ -954,7 +954,7 @@ class colvar::orientation_proj { public: - orientation_proj(); + orientation_proj(colvarmodule* cvmodule_in); virtual ~orientation_proj() {} virtual void calc_value(); virtual void calc_gradients(); @@ -973,7 +973,7 @@ class colvar::tilt public: - tilt(); + tilt(colvarmodule* cvmodule_in); virtual ~tilt() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -989,7 +989,7 @@ class colvar::spin_angle { public: - spin_angle(); + spin_angle(colvarmodule* cvmodule_in); virtual ~spin_angle() {} virtual void calc_value(); virtual void calc_gradients(); @@ -1000,7 +1000,7 @@ class colvar::euler_phi : public colvar::orientation_angle { public: - euler_phi(); + euler_phi(colvarmodule* cvmodule_in); virtual ~euler_phi() {} virtual void calc_value(); virtual void calc_gradients(); @@ -1011,7 +1011,7 @@ class colvar::euler_psi : public colvar::orientation_angle { public: - euler_psi(); + euler_psi(colvarmodule* cvmodule_in); virtual ~euler_psi() {} virtual void calc_value(); virtual void calc_gradients(); @@ -1022,7 +1022,7 @@ class colvar::euler_theta : public colvar::orientation_angle { public: - euler_theta(); + euler_theta(colvarmodule* cvmodule_in); virtual ~euler_theta() {} virtual void calc_value(); virtual void calc_gradients(); @@ -1072,7 +1072,7 @@ class colvar::rmsd int init_permutation(std::vector& ref_pos, std::string const &conf); public: - rmsd(); + rmsd(colvarmodule* cvmodule_in); bool has_gpu_implementation() const override; #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) int add_calc_value_node( @@ -1112,7 +1112,7 @@ class colvar::cartesian /// Which Cartesian coordinates to include std::vector axes; public: - cartesian(); + cartesian(colvarmodule* cvmodule_in); virtual ~cartesian() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -1140,7 +1140,7 @@ class colvar::alch_lambda protected: // No atom groups needed public: - alch_lambda(); + alch_lambda(colvarmodule* cvmodule_in); int init_alchemy(int time_step_factor); virtual ~alch_lambda() {} virtual void calc_value(); @@ -1158,7 +1158,7 @@ class colvar::alch_Flambda protected: // No atom groups needed public: - alch_Flambda(); + alch_Flambda(colvarmodule* cvmodule_in); virtual ~alch_Flambda() {} virtual void calc_value(); virtual void calc_gradients(); @@ -1184,7 +1184,7 @@ class colvar::CartesianBasedPath /// Total number of reference frames size_t total_reference_frames = 0; public: - CartesianBasedPath(); + CartesianBasedPath(colvarmodule* cvmodule_in); virtual ~CartesianBasedPath(); virtual int init(std::string const &conf); virtual void calc_value() = 0; @@ -1205,7 +1205,7 @@ class colvar::gspath virtual void prepareVectors(); virtual void updateDistanceToReferenceFrames(); public: - gspath(); + gspath(colvarmodule* cvmodule_in); virtual ~gspath() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -1228,7 +1228,7 @@ class colvar::gzpath virtual void prepareVectors(); virtual void updateDistanceToReferenceFrames(); public: - gzpath(); + gzpath(colvarmodule* cvmodule_in); virtual ~gzpath() {} virtual int init(std::string const &conf); virtual void calc_value(); @@ -1248,7 +1248,7 @@ class colvar::linearCombination protected: cvm::real getPolynomialFactorOfCVGradient(size_t i_cv) const; public: - linearCombination(); + linearCombination(colvarmodule* cvmodule_in); virtual ~linearCombination(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1286,7 +1286,7 @@ class colvar::customColvar double dev_null = 0.0; #endif public: - customColvar(); + customColvar(colvarmodule* cvmodule_in); virtual ~customColvar(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1313,7 +1313,7 @@ class colvar::CVBasedPath virtual void computeDistanceBetweenReferenceFrames(std::vector& result) const; cvm::real getPolynomialFactorOfCVGradient(size_t i_cv) const; public: - CVBasedPath(); + CVBasedPath(colvarmodule* cvmodule_in); virtual ~CVBasedPath(); virtual int init(std::string const &conf); virtual void calc_value() = 0; @@ -1341,7 +1341,7 @@ class colvar::gspathCV virtual void updateDistanceToReferenceFrames(); virtual void prepareVectors(); public: - gspathCV(); + gspathCV(colvarmodule* cvmodule_in); virtual ~gspathCV(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1358,7 +1358,7 @@ class colvar::gzpathCV virtual void updateDistanceToReferenceFrames(); virtual void prepareVectors(); public: - gzpathCV(); + gzpathCV(colvarmodule* cvmodule_in); virtual ~gzpathCV(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1375,7 +1375,7 @@ class colvar::aspath std::unique_ptr impl_; friend struct ArithmeticPathImpl; public: - aspath(); + aspath(colvarmodule* cvmodule_in); virtual ~aspath(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1390,7 +1390,7 @@ class colvar::azpath std::unique_ptr impl_; friend struct ArithmeticPathImpl; public: - azpath(); + azpath(colvarmodule* cvmodule_in); virtual ~azpath(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1405,7 +1405,7 @@ class colvar::aspathCV std::unique_ptr impl_; friend struct ArithmeticPathImpl; public: - aspathCV(); + aspathCV(colvarmodule* cvmodule_in); virtual ~aspathCV(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1421,7 +1421,7 @@ class colvar::azpathCV std::unique_ptr impl_; friend struct ArithmeticPathImpl; public: - azpathCV(); + azpathCV(colvarmodule* cvmodule_in); virtual ~azpathCV(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1444,7 +1444,7 @@ class colvar::neuralNetwork /// the index of nn output components size_t m_output_index = 0; public: - neuralNetwork(); + neuralNetwork(colvarmodule* cvmodule_in); virtual ~neuralNetwork(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -1471,7 +1471,7 @@ class colvar::map_total { public: - map_total(); + map_total(colvarmodule* cvmodule_in); virtual ~map_total() {} virtual int init(std::string const &conf); virtual void calc_value(); diff --git a/src/colvarcomp_alchlambda.cpp b/src/colvarcomp_alchlambda.cpp index 7a780791b..2baa3551b 100644 --- a/src/colvarcomp_alchlambda.cpp +++ b/src/colvarcomp_alchlambda.cpp @@ -16,7 +16,7 @@ #include "colvarcomp.h" -colvar::alch_lambda::alch_lambda() +colvar::alch_lambda::alch_lambda(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("alchLambda"); @@ -85,7 +85,7 @@ void colvar::alch_lambda::apply_force(colvarvalue const & /* force */) } -colvar::alch_Flambda::alch_Flambda() +colvar::alch_Flambda::alch_Flambda(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("alch_Flambda"); diff --git a/src/colvarcomp_angles.cpp b/src/colvarcomp_angles.cpp index d6fc402c3..a8474a89e 100644 --- a/src/colvarcomp_angles.cpp +++ b/src/colvarcomp_angles.cpp @@ -12,7 +12,7 @@ #include "colvarcomp.h" -colvar::angle::angle() +colvar::angle::angle(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("angle"); init_as_angle(); @@ -38,11 +38,12 @@ int colvar::angle::init(std::string const &conf) colvar::angle::angle(cvm::atom_group::simple_atom const &a1, cvm::atom_group::simple_atom const &a2, - cvm::atom_group::simple_atom const &a3) : angle() + cvm::atom_group::simple_atom const &a3, + colvarmodule* cvmodule_in) : angle(cvmodule_in) { - group1 = new cvm::atom_group(); - group2 = new cvm::atom_group(); - group3 = new cvm::atom_group(); + group1 = new cvm::atom_group(cvmodule); + group2 = new cvm::atom_group(cvmodule); + group3 = new cvm::atom_group(cvmodule); { auto modify_group1 = group1->get_atom_modifier(); auto modify_group2 = group2->get_atom_modifier(); @@ -128,7 +129,7 @@ void colvar::angle::calc_Jacobian_derivative() -colvar::dipole_angle::dipole_angle() +colvar::dipole_angle::dipole_angle(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("dipoleAngle"); init_as_angle(); @@ -222,7 +223,7 @@ void colvar::dipole_angle::calc_gradients() -colvar::dihedral::dihedral() +colvar::dihedral::dihedral(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("dihedral"); init_as_periodic_angle(); @@ -248,15 +249,16 @@ int colvar::dihedral::init(std::string const &conf) colvar::dihedral::dihedral(cvm::atom_group::simple_atom const &a1, cvm::atom_group::simple_atom const &a2, cvm::atom_group::simple_atom const &a3, - cvm::atom_group::simple_atom const &a4) - : dihedral() + cvm::atom_group::simple_atom const &a4, + colvarmodule* cvmodule_in) + : dihedral(cvmodule_in) { b_1site_force = false; - group1 = new cvm::atom_group(); - group2 = new cvm::atom_group(); - group3 = new cvm::atom_group(); - group4 = new cvm::atom_group(); + group1 = new cvm::atom_group(cvmodule); + group2 = new cvm::atom_group(cvmodule); + group3 = new cvm::atom_group(cvmodule); + group4 = new cvm::atom_group(cvmodule); { auto modify_group1 = group1->get_atom_modifier(); auto modify_group2 = group2->get_atom_modifier(); @@ -363,7 +365,7 @@ void colvar::dihedral::calc_Jacobian_derivative() -colvar::polar_theta::polar_theta() +colvar::polar_theta::polar_theta(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { r = theta = phi = 0.0; set_function_type("polarTheta"); @@ -405,7 +407,7 @@ void colvar::polar_theta::calc_gradients() -colvar::polar_phi::polar_phi() +colvar::polar_phi::polar_phi(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { r = theta = phi = 0.0; set_function_type("polarPhi"); diff --git a/src/colvarcomp_apath.cpp b/src/colvarcomp_apath.cpp index c472708cd..a3c8e69bd 100644 --- a/src/colvarcomp_apath.cpp +++ b/src/colvarcomp_apath.cpp @@ -134,7 +134,7 @@ struct ArithmeticPathImpl: public ArithmeticPathCV::ArithmeticPathBase sub_cvc_confs; get_key_string_multi_value(conf, it_cv_map->first.c_str(), sub_cvc_confs); for (auto it_sub_cvc_conf = sub_cvc_confs.begin(); it_sub_cvc_conf != sub_cvc_confs.end(); ++it_sub_cvc_conf) { - cv.push_back((it_cv_map->second)()); + cv.push_back((it_cv_map->second)(cvmodule)); cv.back()->init(*(it_sub_cvc_conf)); if (cv.back()->has_gpu_implementation()) { // TODO: GPU support for nested CVs @@ -170,7 +170,7 @@ void colvar::linearCombination::wrap(colvarvalue & /* x_unwrapped */) const {} -colvar::customColvar::customColvar() +colvar::customColvar::customColvar(colvarmodule* cvmodule_in): colvar::linearCombination(cvmodule_in) { set_function_type("customColvar"); } diff --git a/src/colvarcomp_coordnums.cpp b/src/colvarcomp_coordnums.cpp index 16dd3b22f..6a38063fb 100644 --- a/src/colvarcomp_coordnums.cpp +++ b/src/colvarcomp_coordnums.cpp @@ -15,13 +15,13 @@ #include "colvarcomp_coordnums.h" -colvar::coordnum::coordnum() +colvar::coordnum::coordnum(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("coordNum"); x.type(colvarvalue::type_scalar); cvm::real const r0 = cvmodule->proxy->angstrom_to_internal(4.0); update_cutoffs({r0, r0, r0}); - b_use_internal_pbc = cvm::main()->proxy->use_internal_pbc(); + b_use_internal_pbc = cvmodule->proxy->use_internal_pbc(); // Boundaries will be set later, when the number of pairs is known } @@ -336,7 +336,7 @@ void colvar::coordnum::calc_gradients() // h_bond member functions -colvar::h_bond::h_bond() +colvar::h_bond::h_bond(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { cvm::real const r0 = cvmodule->proxy->angstrom_to_internal(3.3); r0_vec = {r0, r0, r0}; @@ -365,7 +365,7 @@ int colvar::h_bond::init(std::string const &conf) error_code |= cvmodule->error("Error: either acceptor or donor undefined.\n", COLVARS_INPUT_ERROR); } - register_atom_group(new cvm::atom_group); + register_atom_group(new cvm::atom_group(cvmodule)); { colvarproxy* const p = cvmodule->proxy; auto modify_atom = atom_groups[0]->get_atom_modifier(); @@ -398,13 +398,13 @@ int colvar::h_bond::init(std::string const &conf) colvar::h_bond::h_bond(cvm::atom_group::simple_atom const &acceptor, cvm::atom_group::simple_atom const &donor, - cvm::real r0_i, int en_i, int ed_i) - : h_bond() + cvm::real r0_i, int en_i, int ed_i, colvarmodule* cvmodule_in) + : h_bond(cvmodule_in) { r0_vec = {r0_i, r0_i, r0_i}; en = en_i; ed = ed_i; - register_atom_group(new cvm::atom_group); + register_atom_group(new cvm::atom_group(cvmodule)); auto modify_atom = atom_groups[0]->get_atom_modifier(); modify_atom.add_atom(acceptor); modify_atom.add_atom(donor); @@ -483,7 +483,12 @@ void colvar::h_bond::calc_gradients() } -colvar::selfcoordnum::selfcoordnum() +// <<<<<<< HEAD +// colvar::selfcoordnum::selfcoordnum() +// ======= + +colvar::selfcoordnum::selfcoordnum(colvarmodule* cvmodule_in): colvar::coordnum(cvmodule_in) +// >>>>>>> bdf8c50d (refactor: reduce the use of cvm::main()) { set_function_type("selfCoordNum"); } @@ -582,7 +587,7 @@ void colvar::selfcoordnum::calc_gradients() } -colvar::groupcoordnum::groupcoordnum() { set_function_type("groupCoord"); } +colvar::groupcoordnum::groupcoordnum(colvarmodule* cvmodule_in): colvar::coordnum(cvmodule_in) { set_function_type("groupCoord"); } void colvar::groupcoordnum::calc_value() diff --git a/src/colvarcomp_coordnums.h b/src/colvarcomp_coordnums.h index 650fa5b2d..aab38a999 100644 --- a/src/colvarcomp_coordnums.h +++ b/src/colvarcomp_coordnums.h @@ -23,7 +23,7 @@ class colvar::coordnum : public colvar::cvc { public: - coordnum(); + coordnum(colvarmodule* cvmodule_in); virtual ~coordnum(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -122,7 +122,7 @@ class colvar::coordnum : public colvar::cvc { class colvar::selfcoordnum : public colvar::coordnum { public: - selfcoordnum(); + selfcoordnum(colvarmodule* cvmodule_in); virtual void calc_value(); virtual void calc_gradients(); @@ -138,7 +138,7 @@ class colvar::selfcoordnum : public colvar::coordnum { /// (colvarvalue::type_scalar type, range [0:N1*N2]) class colvar::groupcoordnum : public colvar::coordnum { public: - groupcoordnum(); + groupcoordnum(colvarmodule* cvmodule_in); virtual ~groupcoordnum() {} virtual void calc_value(); virtual void calc_gradients(); @@ -152,8 +152,8 @@ class colvar::h_bond : public colvar::cvc { public: /// Constructor for atoms already allocated h_bond(cvm::atom_group::simple_atom const &acceptor, cvm::atom_group::simple_atom const &donor, - cvm::real r0, int en, int ed); - h_bond(); + cvm::real r0, int en, int ed, colvarmodule* cvmodule_in); + h_bond(colvarmodule* cvmodule_in); virtual ~h_bond() {} virtual int init(std::string const &conf); virtual void calc_value(); diff --git a/src/colvarcomp_distances.cpp b/src/colvarcomp_distances.cpp index f2ddd6863..05964f69c 100644 --- a/src/colvarcomp_distances.cpp +++ b/src/colvarcomp_distances.cpp @@ -21,7 +21,7 @@ #endif // defined (COLVARS_CUDA) || defined (COLVARS_HIP) -colvar::distance::distance() +colvar::distance::distance(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("distance"); init_as_distance(); @@ -88,7 +88,7 @@ void colvar::distance::calc_Jacobian_derivative() -colvar::distance_vec::distance_vec() +colvar::distance_vec::distance_vec(colvarmodule* cvmodule_in): colvar::distance(cvmodule_in) { set_function_type("distanceVec"); disable(f_cvc_explicit_gradient); @@ -151,7 +151,7 @@ colvarvalue colvar::distance_vec::dist2_rgrad(colvarvalue const &x1, colvarvalue void colvar::distance_vec::wrap(colvarvalue & /* x_unwrapped */) const {} -colvar::distance_z::distance_z() +colvar::distance_z::distance_z(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("distanceZ"); provide(f_cvc_inv_gradient); @@ -262,7 +262,7 @@ void colvar::distance_z::calc_Jacobian_derivative() -colvar::distance_xy::distance_xy() +colvar::distance_xy::distance_xy(colvarmodule* cvmodule_in): colvar::distance_z(cvmodule_in) { set_function_type("distanceXY"); provide(f_cvc_periodic, false); // Disable inherited distance_z flag @@ -343,7 +343,7 @@ void colvar::distance_xy::calc_Jacobian_derivative() -colvar::distance_dir::distance_dir() +colvar::distance_dir::distance_dir(colvarmodule* cvmodule_in): colvar::distance(cvmodule_in) { set_function_type("distanceDir"); enable(f_cvc_com_based); @@ -411,7 +411,7 @@ void colvar::distance_dir::wrap(colvarvalue & /* x_unwrapped */) const {} -colvar::distance_inv::distance_inv() +colvar::distance_inv::distance_inv(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("distanceInv"); init_as_distance(); @@ -514,7 +514,7 @@ void colvar::distance_inv::calc_gradients() -colvar::distance_pairs::distance_pairs() +colvar::distance_pairs::distance_pairs(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("distancePairs"); disable(f_cvc_explicit_gradient); @@ -635,7 +635,7 @@ void colvar::distance_pairs::wrap(colvarvalue & /* x_unwrapped */) const {} -colvar::dipole_magnitude::dipole_magnitude() +colvar::dipole_magnitude::dipole_magnitude(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("dipoleMagnitude"); x.type(colvarvalue::type_scalar); @@ -674,7 +674,7 @@ void colvar::dipole_magnitude::calc_gradients() -colvar::gyration::gyration() +colvar::gyration::gyration(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("gyration"); provide(f_cvc_inv_gradient); @@ -744,7 +744,7 @@ void colvar::gyration::calc_Jacobian_derivative() -colvar::inertia::inertia() +colvar::inertia::inertia(colvarmodule* cvmodule_in): colvar::gyration(cvmodule_in) { set_function_type("inertia"); } @@ -770,7 +770,7 @@ void colvar::inertia::calc_gradients() -colvar::inertia_z::inertia_z() +colvar::inertia_z::inertia_z(colvarmodule* cvmodule_in): colvar::inertia(cvmodule_in) { set_function_type("inertiaZ"); } @@ -821,7 +821,7 @@ void colvar::inertia_z::calc_gradients() -colvar::rmsd::rmsd() +colvar::rmsd::rmsd(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("rmsd"); init_as_distance(); @@ -863,7 +863,7 @@ colvar::rmsd::~rmsd() { bool colvar::rmsd::has_gpu_implementation() const { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) const colvarproxy* p = cvmodule->proxy; - if (p->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu){ + if (p->get_smp_mode() == colvarproxy::smp_mode_t::gpu){ return true; } else { return false; @@ -1182,7 +1182,7 @@ int colvar::rmsd::add_calc_value_node( std::vector calc_value_rmsd(n_permutations, nullptr); auto& gpu_buffers = atoms->get_gpu_atom_group()->get_gpu_buffers(); error_code |= colvars_gpu::calc_value_rmsd( - d_ref_pos_soa, gpu_buffers.d_atoms_pos, + cvmodule, d_ref_pos_soa, gpu_buffers.d_atoms_pos, d_permutation_msds, permutation_msds.data(), atoms->size(), n_permutations, num_ref_pos, d_tbcounts, calc_value_rmsd, graph, {}); @@ -1212,7 +1212,7 @@ int colvar::rmsd::add_calc_gradients_node( auto& gpu_buffers = atoms->get_gpu_atom_group()->get_gpu_buffers(); cudaGraphNode_t calc_gradients_rmsd; error_code |= colvars_gpu::calc_gradients_rmsd( - h_rmsd, h_best_perm_index, d_ref_pos_soa, + cvmodule, h_rmsd, h_best_perm_index, d_ref_pos_soa, gpu_buffers.d_atoms_pos, gpu_buffers.d_atoms_grad, atoms->size(), num_ref_pos, calc_gradients_rmsd, graph, {}); const std::string node_name = name + "_calc_gradients"; @@ -1234,7 +1234,7 @@ int colvar::rmsd::add_calc_force_invgrads_node( colvarproxy *p = cvmodule->proxy; const auto& rot = atoms->get_gpu_atom_group()->get_rot_gpu(); error_code |= colvars_gpu::calc_force_invgrads_rmsd( - atoms->is_enabled(f_ag_rotate), + cvmodule, atoms->is_enabled(f_ag_rotate), gpu_buffers.d_atoms_index, p->proxy_atoms_total_forces_gpu(), rot.get_q(), gpu_buffers.d_atoms_grad, d_ft, h_ft, @@ -1267,10 +1267,10 @@ int colvar::rmsd::add_calc_Jacobian_derivative_node( std::vector dependencies; if (atoms->is_enabled(f_ag_rotate)) { error_code |= colvars_gpu::prepare_dependencies( - {{"prepare_rotation_derivative", true}}, dependencies, nodes_map); + cvmodule, {{"prepare_rotation_derivative", true}}, dependencies, nodes_map); } error_code |= colvars_gpu::calc_Jacobian_derivative_rmsd( - atoms->is_enabled(f_ag_center), atoms->is_enabled(f_ag_rotate), + cvmodule, atoms->is_enabled(f_ag_center), atoms->is_enabled(f_ag_rotate), h_best_perm_index, d_ref_pos_soa, rot.get_q(), rot_deriv, h_rmsd, d_jd, h_jd, atoms->size(), num_ref_pos, d_tbcount_jd, calc_Jacobian_derivative, @@ -1285,7 +1285,7 @@ int colvar::rmsd::calc_Jacobian_derivative_after_gpu() { #endif // defined (COLVARS_CUDA) || defined (COLVARS_HIP) -colvar::eigenvector::eigenvector() +colvar::eigenvector::eigenvector(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("eigenvector"); provide(f_cvc_inv_gradient); @@ -1577,7 +1577,7 @@ void colvar::eigenvector::calc_Jacobian_derivative() -colvar::cartesian::cartesian() +colvar::cartesian::cartesian(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("cartesian"); x.type(colvarvalue::type_vector); diff --git a/src/colvarcomp_gpath.cpp b/src/colvarcomp_gpath.cpp index 32bcdbbd6..4b6ef9e9e 100644 --- a/src/colvarcomp_gpath.cpp +++ b/src/colvarcomp_gpath.cpp @@ -20,7 +20,7 @@ -colvar::CartesianBasedPath::CartesianBasedPath() +colvar::CartesianBasedPath::CartesianBasedPath(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { x.type(colvarvalue::type_scalar); // Don't use implicit gradient @@ -80,7 +80,7 @@ int colvar::CartesianBasedPath::init(std::string const &conf) } else { // parse a group of atoms for fitting std::string fitting_group_name = std::string("fittingAtoms") + cvm::to_str(i_frame); - cvm::atom_group* tmp_fitting_atoms = new cvm::atom_group(fitting_group_name.c_str()); + cvm::atom_group* tmp_fitting_atoms = new cvm::atom_group(fitting_group_name.c_str(), cvmodule); tmp_fitting_atoms->parse(fitting_conf); tmp_fitting_atoms->disable(f_ag_scalable); tmp_fitting_atoms->fit_gradients.assign(3 * tmp_fitting_atoms->size(), 0); @@ -156,7 +156,7 @@ void colvar::CartesianBasedPath::computeDistanceBetweenReferenceFrames(std::vect this_frame_atom_pos[i_atom] = reference_frames[this_index][i_atom] - reference_cog_this; next_frame_atom_pos[i_atom] = reference_frames[next_index][i_atom] - reference_cog_next; } - cvm::rotation rot_this_to_next; + cvm::rotation rot_this_to_next(cvmodule); // compute the optimal rotation rot_this_to_next.calc_optimal_rotation(this_frame_atom_pos, next_frame_atom_pos); // compute rmsd between reference frames @@ -178,7 +178,7 @@ void colvar::CartesianBasedPath::apply_force(colvarvalue const &force) -colvar::gspath::gspath() +colvar::gspath::gspath(colvarmodule* cvmodule_in): colvar::CartesianBasedPath(cvmodule_in), rot_v3(cvmodule_in) { set_function_type("gspath"); } @@ -342,7 +342,7 @@ void colvar::gspath::apply_force(colvarvalue const &force) { } -colvar::gzpath::gzpath() +colvar::gzpath::gzpath(colvarmodule* cvmodule_in): colvar::CartesianBasedPath(cvmodule_in), rot_v3(cvmodule_in), rot_v4(cvmodule_in) { set_function_type("gzpath"); } @@ -496,7 +496,7 @@ void colvar::gzpath::apply_force(colvarvalue const &force) { } -colvar::CVBasedPath::CVBasedPath() +colvar::CVBasedPath::CVBasedPath(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("gspathCV"); x.type(colvarvalue::type_scalar); @@ -514,7 +514,7 @@ int colvar::CVBasedPath::init(std::string const &conf) std::vector sub_cvc_confs; get_key_string_multi_value(conf, it_cv_map->first.c_str(), sub_cvc_confs); for (auto it_sub_cvc_conf = sub_cvc_confs.begin(); it_sub_cvc_conf != sub_cvc_confs.end(); ++it_sub_cvc_conf) { - cv.push_back((it_cv_map->second)()); + cv.push_back((it_cv_map->second)(cvmodule)); cv.back()->init(*(it_sub_cvc_conf)); if (cv.back()->has_gpu_implementation()) { // TODO: GPU support for nested CVs @@ -699,7 +699,7 @@ void colvar::CVBasedPath::wrap(colvarvalue & /* x_unwrapped */) const {} -colvar::gspathCV::gspathCV() +colvar::gspathCV::gspathCV(colvarmodule* cvmodule_in): colvar::CVBasedPath(cvmodule_in) { set_function_type("gspathCV"); x.type(colvarvalue::type_scalar); @@ -837,7 +837,7 @@ void colvar::gspathCV::apply_force(colvarvalue const &force) { } } -colvar::gzpathCV::gzpathCV() +colvar::gzpathCV::gzpathCV(colvarmodule* cvmodule_in): colvar::CVBasedPath(cvmodule_in) { set_function_type("gzpathCV"); } diff --git a/src/colvarcomp_neuralnetwork.cpp b/src/colvarcomp_neuralnetwork.cpp index f82719ea2..81f752ace 100644 --- a/src/colvarcomp_neuralnetwork.cpp +++ b/src/colvarcomp_neuralnetwork.cpp @@ -16,7 +16,7 @@ using namespace neuralnetworkCV; -colvar::neuralNetwork::neuralNetwork() +colvar::neuralNetwork::neuralNetwork(colvarmodule* cvmodule_in): colvar::linearCombination(cvmodule_in) { set_function_type("neuralNetwork"); } diff --git a/src/colvarcomp_protein.cpp b/src/colvarcomp_protein.cpp index c0a9e0cba..977131231 100644 --- a/src/colvarcomp_protein.cpp +++ b/src/colvarcomp_protein.cpp @@ -16,7 +16,7 @@ #include "colvarcomp_coordnums.h" -colvar::alpha_angles::alpha_angles() +colvar::alpha_angles::alpha_angles(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("alpha"); enable(f_cvc_explicit_gradient); @@ -35,7 +35,7 @@ int colvar::alpha_angles::init(std::string const &conf) std::vector residues; bool b_use_index_groups = false; - cvm::atom_group group_CA, group_N, group_O; + cvm::atom_group group_CA(cvmodule), group_N(cvmodule), group_O(cvmodule); std::string residues_conf = ""; std::string prefix; @@ -113,7 +113,7 @@ int colvar::alpha_angles::init(std::string const &conf) // Note: the angle constructor constructs copies of the atom objects theta.push_back(new colvar::angle(group_CA[i], group_CA[i+1], - group_CA[i+2])); + group_CA[i+2], cvmodule)); register_atom_group(theta.back()->atom_groups[0]); register_atom_group(theta.back()->atom_groups[1]); register_atom_group(theta.back()->atom_groups[2]); @@ -125,7 +125,8 @@ int colvar::alpha_angles::init(std::string const &conf) new colvar::angle( cvm::atom_group::init_atom_from_proxy(p, r[i ], "CA", sid), cvm::atom_group::init_atom_from_proxy(p, r[i+1], "CA", sid), - cvm::atom_group::init_atom_from_proxy(p, r[i+2], "CA", sid))); + cvm::atom_group::init_atom_from_proxy(p, r[i+2], "CA", sid), + cvmodule)); register_atom_group(theta.back()->atom_groups[0]); register_atom_group(theta.back()->atom_groups[1]); register_atom_group(theta.back()->atom_groups[2]); @@ -154,7 +155,7 @@ int colvar::alpha_angles::init(std::string const &conf) hb.push_back( new colvar::h_bond(cvm::atom_group::init_atom_from_proxy(p,group_O[i]), cvm::atom_group::init_atom_from_proxy(p,group_N[i+4]), - r0, en, ed)); + r0, en, ed, cvmodule)); register_atom_group(hb.back()->atom_groups[0]); } } else { @@ -162,7 +163,7 @@ int colvar::alpha_angles::init(std::string const &conf) hb.push_back( new colvar::h_bond(cvm::atom_group::init_atom_from_proxy(p,r[i ], "O", sid), cvm::atom_group::init_atom_from_proxy(p,r[i+4], "N", sid), - r0, en, ed)); + r0, en, ed, cvmodule)); register_atom_group(hb.back()->atom_groups[0]); } } @@ -339,7 +340,7 @@ void colvar::alpha_angles::apply_force(colvarvalue const &force) // dihedral principal component ////////////////////////////////////////////////////////////////////// -colvar::dihedPC::dihedPC() +colvar::dihedPC::dihedPC(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("dihedPC"); // Supported through references to atom groups of children cvcs @@ -361,7 +362,7 @@ int colvar::dihedPC::init(std::string const &conf) size_t n_residues; std::string residues_conf = ""; std::string prefix; - cvm::atom_group group_CA, group_N, group_C; + cvm::atom_group group_CA(cvmodule), group_N(cvmodule), group_C(cvmodule); // residueRange is mandatory for the topology-based case if (key_lookup(conf, "residueRange", &residues_conf)) { @@ -481,14 +482,14 @@ int colvar::dihedPC::init(std::string const &conf) theta.push_back(new colvar::dihedral( group_N[i], group_CA[i], group_C[i], - group_N[i+1])); + group_N[i+1], cvmodule)); } else { theta.push_back( new colvar::dihedral( cvm::atom_group::init_atom_from_proxy(p,r[i ], "N", sid), cvm::atom_group::init_atom_from_proxy(p,r[i ], "CA", sid), cvm::atom_group::init_atom_from_proxy(p,r[i ], "C", sid), - cvm::atom_group::init_atom_from_proxy(p,r[i+1], "N", sid))); + cvm::atom_group::init_atom_from_proxy(p,r[i+1], "N", sid), cvmodule)); } if (cvmodule->get_error()) { return cvmodule->get_error(); @@ -502,13 +503,13 @@ int colvar::dihedPC::init(std::string const &conf) theta.push_back(new colvar::dihedral(group_C[i], group_N[i+1], group_CA[i+1], - group_C[i+1])); + group_C[i+1], cvmodule)); } else { theta.push_back( new colvar::dihedral(cvm::atom_group::init_atom_from_proxy(p,r[i ], "C", sid), cvm::atom_group::init_atom_from_proxy(p,r[i+1], "N", sid), cvm::atom_group::init_atom_from_proxy(p,r[i+1], "CA", sid), - cvm::atom_group::init_atom_from_proxy(p,r[i+1], "C", sid))); + cvm::atom_group::init_atom_from_proxy(p,r[i+1], "C", sid), cvmodule)); } if (cvmodule->get_error()) { return cvmodule->get_error(); diff --git a/src/colvarcomp_rotations.cpp b/src/colvarcomp_rotations.cpp index 7c2b5b2b6..42a9725ae 100644 --- a/src/colvarcomp_rotations.cpp +++ b/src/colvarcomp_rotations.cpp @@ -25,7 +25,7 @@ struct colvar::orientation::rotation_derivative_impl_: public rotation_derivativ }; -colvar::orientation::orientation() +colvar::orientation::orientation(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in), rot(cvmodule_in) { set_function_type("orientation"); disable(f_cvc_explicit_gradient); @@ -179,7 +179,7 @@ void colvar::orientation::wrap(colvarvalue & /* x_unwrapped */) const {} -colvar::orientation_angle::orientation_angle() +colvar::orientation_angle::orientation_angle(colvarmodule* cvmodule_in): colvar::orientation(cvmodule_in) { set_function_type("orientationAngle"); init_as_angle(); @@ -250,7 +250,7 @@ void colvar::orientation_angle::wrap(colvarvalue & /* x_unwrapped */) const {} -colvar::orientation_proj::orientation_proj() +colvar::orientation_proj::orientation_proj(colvarmodule* cvmodule_in): colvar::orientation_angle(cvmodule_in) { set_function_type("orientationProj"); enable(f_cvc_explicit_gradient); @@ -283,7 +283,7 @@ void colvar::orientation_proj::calc_gradients() -colvar::tilt::tilt() +colvar::tilt::tilt(colvarmodule* cvmodule_in): colvar::orientation_proj(cvmodule_in) { set_function_type("tilt"); x.type(colvarvalue::type_scalar); @@ -333,7 +333,7 @@ void colvar::tilt::calc_gradients() -colvar::spin_angle::spin_angle() +colvar::spin_angle::spin_angle(colvarmodule* cvmodule_in): colvar::tilt(cvmodule_in) { set_function_type("spinAngle"); init_as_periodic_angle(); @@ -369,7 +369,7 @@ void colvar::spin_angle::calc_gradients() -colvar::euler_phi::euler_phi() +colvar::euler_phi::euler_phi(colvarmodule* cvmodule_in): colvar::orientation_angle(cvmodule_in) { set_function_type("eulerPhi"); init_as_periodic_angle(); @@ -416,7 +416,7 @@ void colvar::euler_phi::calc_gradients() -colvar::euler_psi::euler_psi() +colvar::euler_psi::euler_psi(colvarmodule* cvmodule_in): colvar::orientation_angle(cvmodule_in) { set_function_type("eulerPsi"); init_as_periodic_angle(); @@ -463,7 +463,7 @@ void colvar::euler_psi::calc_gradients() -colvar::euler_theta::euler_theta() +colvar::euler_theta::euler_theta(colvarmodule* cvmodule_in): colvar::orientation_angle(cvmodule_in) { set_function_type("eulerTheta"); init_as_angle(); diff --git a/src/colvarcomp_torchann.cpp b/src/colvarcomp_torchann.cpp index f4f580a0e..bc4491d70 100644 --- a/src/colvarcomp_torchann.cpp +++ b/src/colvarcomp_torchann.cpp @@ -18,7 +18,7 @@ #ifdef COLVARS_TORCH -colvar::torchANN::torchANN() +colvar::torchANN::torchANN(colvarmodule* cvmodule_in): colvar::linearCombination(cvmodule_in) { set_function_type("torchANN"); provide(f_cvc_periodic); @@ -213,7 +213,7 @@ void colvar::torchANN::apply_force(colvarvalue const &force) { #else -colvar::torchANN::torchANN() +colvar::torchANN::torchANN(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("torchANN"); } diff --git a/src/colvarcomp_torchann.h b/src/colvarcomp_torchann.h index ae241edbc..839ec93cd 100644 --- a/src/colvarcomp_torchann.h +++ b/src/colvarcomp_torchann.h @@ -39,7 +39,7 @@ class colvar::torchANN // record the initial index of of sub-cvcs in input_tensor std::vector cvc_indices; public: - torchANN(); + torchANN(colvarmodule* cvmodule_in); virtual ~torchANN(); virtual int init(std::string const &conf); virtual void calc_value(); @@ -53,7 +53,7 @@ class colvar::torchANN : public colvar::cvc { public: - torchANN(); + torchANN(colvarmodule* cvmodule_in); virtual ~torchANN(); virtual int init(std::string const &conf); virtual void calc_value(); diff --git a/src/colvarcomp_volmaps.cpp b/src/colvarcomp_volmaps.cpp index 66fa7fa1b..3f0bae61d 100644 --- a/src/colvarcomp_volmaps.cpp +++ b/src/colvarcomp_volmaps.cpp @@ -14,7 +14,7 @@ -colvar::map_total::map_total() +colvar::map_total::map_total(colvarmodule* cvmodule_in): colvar::cvc(cvmodule_in) { set_function_type("mapTotal"); x.type(colvarvalue::type_scalar); @@ -33,7 +33,7 @@ int colvar::map_total::init(std::string const &conf) if ((volmap_name.size() > 0) && (volmap_id >= 0)) { error_code |= - cvm::error_static("Error: mapName and mapID are mutually exclusive.\n", COLVARS_INPUT_ERROR); + cvm::error_static(cvmodule, "Error: mapName and mapID are mutually exclusive.\n", COLVARS_INPUT_ERROR); } // Parse optional group @@ -62,12 +62,12 @@ int colvar::map_total::init(std::string const &conf) if (get_keyval(conf, "atomWeights", atom_weights, atom_weights)) { if (!atoms) { - error_code |= cvm::error_static("Error: weights can only be assigned when atoms " + error_code |= cvm::error_static(cvmodule, "Error: weights can only be assigned when atoms " "are selected explicitly in Colvars.\n", COLVARS_INPUT_ERROR); } else { if (atoms->size() != atom_weights.size()) { - error_code |= cvm::error_static("Error: if defined, the number of weights ("+ + error_code |= cvm::error_static(cvmodule, "Error: if defined, the number of weights ("+ cvm::to_str(atom_weights.size())+ ") must equal the number of atoms ("+ cvm::to_str(atoms->size())+ diff --git a/src/colvardeps.cpp b/src/colvardeps.cpp index afdf561a9..650b67946 100644 --- a/src/colvardeps.cpp +++ b/src/colvardeps.cpp @@ -13,12 +13,6 @@ #include "colvardeps.h" -// This constructor depends on a static cvm pointer and is deprecated -colvardeps::colvardeps() - : colvarparse(cvm::main()) -{} - - colvardeps::colvardeps(colvarmodule *cvmodulein) : colvarparse(cvmodulein) {} diff --git a/src/colvardeps.h b/src/colvardeps.h index 113e97edb..45ea11c9d 100644 --- a/src/colvardeps.h +++ b/src/colvardeps.h @@ -34,7 +34,7 @@ class colvardeps : public colvarparse { public: - colvardeps (); + // colvardeps (); colvardeps(colvarmodule *cvmodule_in); virtual ~colvardeps(); diff --git a/src/colvargrid.cpp b/src/colvargrid.cpp index 00c573521..8c0c446c1 100644 --- a/src/colvargrid.cpp +++ b/src/colvargrid.cpp @@ -18,20 +18,22 @@ -colvar_grid_count::colvar_grid_count() - : colvar_grid() +colvar_grid_count::colvar_grid_count(colvarmodule* cvmodule_in) + : colvar_grid(cvmodule_in) { mult = 1; } -colvar_grid_count::colvar_grid_count(std::vector &colvars, +colvar_grid_count::colvar_grid_count(colvarmodule* cvmodule_in, + std::vector &colvars, std::string config) - : colvar_grid(colvars, 0, 1, false, nullptr, config) + : colvar_grid(cvmodule_in, colvars, 0, 1, false, nullptr, config) {} -colvar_grid_count::colvar_grid_count(std::vector &colvars, +colvar_grid_count::colvar_grid_count(colvarmodule* cvmodule_in, + std::vector &colvars, std::shared_ptr params) - : colvar_grid(colvars, 0, 1, false, params) + : colvar_grid(cvmodule_in, colvars, 0, 1, false, params) {} std::string colvar_grid_count::get_state_params() const @@ -122,25 +124,26 @@ int colvar_grid_count::write_opendx(std::string const &filename, -colvar_grid_scalar::colvar_grid_scalar() - : colvar_grid(), samples(NULL) +colvar_grid_scalar::colvar_grid_scalar(colvarmodule* cvmodule_in) + : colvar_grid(cvmodule_in), samples(NULL) {} -colvar_grid_scalar::colvar_grid_scalar(colvar_grid_scalar const &g) +colvar_grid_scalar::colvar_grid_scalar(colvarmodule* cvmodule_in, colvar_grid_scalar const &g) : colvar_grid(g), samples(NULL) { } -colvar_grid_scalar::colvar_grid_scalar(std::vector &colvars, +colvar_grid_scalar::colvar_grid_scalar(colvarmodule* cvmodule_in, + std::vector &colvars, std::shared_ptr params, bool add_extra_bin, std::string config) - : colvar_grid(colvars, 0.0, 1, add_extra_bin, params, config), samples(NULL) + : colvar_grid(cvmodule_in, colvars, 0.0, 1, add_extra_bin, params, config), samples(NULL) { } -colvar_grid_scalar::colvar_grid_scalar(std::string const &filename) - : colvar_grid(filename, 1), +colvar_grid_scalar::colvar_grid_scalar(colvarmodule* cvmodule_in, std::string const &filename) + : colvar_grid(cvmodule_in, filename, 1), samples(nullptr) { } @@ -305,7 +308,7 @@ cvm::real colvar_grid_scalar::entropy() const cvm::real colvar_grid_scalar::grid_rmsd(colvar_grid_scalar const &other_grid) const { if (other_grid.data.size() != this->data.size()) { - cvm::error_static("Error: trying to subtract two grids with " + cvm::error_static(cvmodule, "Error: trying to subtract two grids with " "different size.\n"); return -1.; } @@ -332,8 +335,8 @@ cvm::real colvar_grid_scalar::grid_rmsd(colvar_grid_scalar const &other_grid) co } -colvar_grid_gradient::colvar_grid_gradient() - : colvar_grid(), samples(NULL) +colvar_grid_gradient::colvar_grid_gradient(colvarmodule* cvmodule_in) + : colvar_grid(cvmodule_in), samples(NULL) {} @@ -349,19 +352,20 @@ colvar_grid_gradient::colvar_grid_gradient() // samples_in->has_parent_data = true; // } -colvar_grid_gradient::colvar_grid_gradient(std::vector &colvars, +colvar_grid_gradient::colvar_grid_gradient(colvarmodule* cvmodule_in, + std::vector &colvars, std::shared_ptr samples_in, std::shared_ptr params, std::string config) - : colvar_grid(colvars, 0.0, colvars.size(), false, params, config), samples(samples_in) + : colvar_grid(cvmodule_in, colvars, 0.0, colvars.size(), false, params, config), samples(samples_in) { if (samples_in) samples_in->has_parent_data = true; } -colvar_grid_gradient::colvar_grid_gradient(std::string const &filename) - : colvar_grid(filename, 0), +colvar_grid_gradient::colvar_grid_gradient(colvarmodule* cvmodule_in, std::string const &filename) + : colvar_grid(cvmodule_in, filename, 0), samples(nullptr) { } @@ -461,7 +465,7 @@ void colvar_grid_gradient::write_1D_integral(std::ostream &os) os << "# xi A(xi)\n"; if (cv.size() != 1) { - cvm::error_static("Cannot write integral for multi-dimensional gradient grids."); + cvm::error_static(cvmodule, "Cannot write integral for multi-dimensional gradient grids."); return; } @@ -513,13 +517,13 @@ void colvar_grid_gradient::write_1D_integral(std::ostream &os) cvm::real colvar_grid_gradient::grid_rmsd(colvar_grid_gradient const &other_grid) const { if (other_grid.multiplicity() != this->multiplicity()) { - cvm::error_static("Error: trying to subtract two grids with " + cvm::error_static(cvmodule, "Error: trying to subtract two grids with " "different multiplicity.\n"); return -1.; } if (other_grid.data.size() != this->data.size()) { - cvm::error_static("Error: trying to subtract two grids with " + cvm::error_static(cvmodule, "Error: trying to subtract two grids with " "different size.\n"); return -1.; } diff --git a/src/colvargrid.h b/src/colvargrid.h index 07e1a35db..936a57a59 100644 --- a/src/colvargrid.h +++ b/src/colvargrid.h @@ -178,7 +178,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp nt = mult; for (int i = nd-1; i >= 0; i--) { if (nx[i] <= 0) { - cvm::error_static("Error: providing an invalid number of grid points, "+ + cvm::error_static(cvmodule, "Error: providing an invalid number of grid points, "+ cvm::to_str(nx[i])+".\n", COLVARS_BUG_ERROR); return COLVARS_ERROR; } @@ -211,7 +211,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp /// Default constructor // This constructor depends on a static cvm pointer and is deprecated - colvar_grid() : colvarparse(cvm::main()), has_data(false) + colvar_grid(colvarmodule* cvmodule_in) : colvarparse(cvmodule_in), has_data(false) { nd = nt = 0; mult = 1; @@ -227,27 +227,29 @@ template class colvar_grid : public colvar_grid_params, public colvarp /// parameters from another grid, but doesn't reallocate stuff; /// setup() must be called after that; // This constructor depends on a static cvm pointer and is deprecated - colvar_grid(colvar_grid const &g) : colvar_grid_params(colvar_grid_params(g)), - colvarparse(cvm::main()), - mult(g.mult), - data(), - cv(g.cv), - use_actual_value(g.use_actual_value), - periodic(g.periodic), - hard_lower_boundaries(g.hard_lower_boundaries), - hard_upper_boundaries(g.hard_upper_boundaries), - has_parent_data(false), - has_data(false) + colvar_grid(colvarmodule* cvmodule_in, colvar_grid const &g) : + colvar_grid_params(colvar_grid_params(g)), + colvarparse(cvmodule_in), + mult(g.mult), + data(), + cv(g.cv), + use_actual_value(g.use_actual_value), + periodic(g.periodic), + hard_lower_boundaries(g.hard_lower_boundaries), + hard_upper_boundaries(g.hard_upper_boundaries), + has_parent_data(false), + has_data(false) {} /// \brief Constructor from explicit grid sizes \param nx_i Number /// of grid points along each dimension \param t Initial value for /// the function at each point (optional) \param mult_i Multiplicity /// of each value - colvar_grid(std::vector const &nx_i, + colvar_grid(colvarmodule* cvmodule_in, + std::vector const &nx_i, T const &t = T(), size_t mult_i = 1) - : colvarparse(cvm::main()), has_parent_data(false), has_data(false) + : colvarparse(cvmodule_in), has_parent_data(false), has_data(false) { this->setup(nx_i, t, mult_i); } @@ -255,13 +257,14 @@ template class colvar_grid : public colvar_grid_params, public colvarp /// \brief Constructor from a vector of colvars or an optional grid config string /// \param add_extra_bin requests that non-periodic dimensions are extended /// by 1 bin to accommodate the integral (PMF) of another gridded quantity (gradient) - colvar_grid(std::vector const &colvars, + colvar_grid(colvarmodule* cvmodule_in, + std::vector const &colvars, T const &t = T(), size_t mult_i = 1, bool add_extra_bin = false, std::shared_ptr params = nullptr, std::string config = std::string()) - : colvarparse(cvm::main()), has_parent_data(false), has_data(false) + : colvarparse(cvmodule_in), has_parent_data(false), has_data(false) { (void) t; this->init_from_colvars(colvars, mult_i, add_extra_bin, params, config); @@ -270,7 +273,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp /// \brief Constructor from a multicol file /// \param filename multicol file containing data to be read /// \param multi_i multiplicity of the data - if 0, assume gradient multiplicity (mult = nd) - colvar_grid(std::string const &filename, size_t mult_i = 1); + colvar_grid(colvarmodule* cvmodule_in, std::string const &filename, size_t mult_i = 1); int init_from_colvars(std::vector const &colvars, size_t mult_i = 1, @@ -295,7 +298,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp for (i = 0; i < nd; i++) { if (cv[i]->value().type() != colvarvalue::type_scalar) { - cvm::error_static("Colvar grids can only be automatically " + cvm::error_static(cvmodule, "Colvar grids can only be automatically " "constructed for scalar variables. " "ABF and histogram can not be used; metadynamics " "can be used with useGrids disabled.\n", COLVARS_INPUT_ERROR); @@ -303,7 +306,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp } if (cv[i]->width <= 0.0) { - cvm::error_static("Tried to initialize a grid on a " + cvm::error_static(cvmodule, "Tried to initialize a grid on a " "variable with negative or zero width.\n", COLVARS_INPUT_ERROR); return COLVARS_ERROR; } @@ -333,14 +336,14 @@ template class colvar_grid : public colvar_grid_params, public colvarp this->check_keywords(config, "grid"); if (params) { - cvm::error_static("Error: init_from_colvars was passed both a grid config and a template grid.", COLVARS_BUG_ERROR); + cvm::error_static(cvmodule, "Error: init_from_colvars was passed both a grid config and a template grid.", COLVARS_BUG_ERROR); return COLVARS_BUG_ERROR; } } else if (params) { // Match grid sizes with template if (params->nd != nd) { - cvm::error_static("Trying to initialize grid from template with wrong dimension (" + + cvm::error_static(cvmodule, "Trying to initialize grid from template with wrong dimension (" + cvm::to_str(params->nd) + " instead of " + cvm::to_str(this->nd) + ")."); return COLVARS_ERROR; @@ -424,7 +427,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp ix[i] = (ix[i] + nx[i]) % nx[i]; // Avoid modulo with negative operands (implementation-defined) } else { if (ix[i] < 0 || ix[i] >= nx[i]) { - cvm::error_static("Trying to wrap illegal index vector (non-PBC) for a grid point: " + cvm::error_static(cvmodule, "Trying to wrap illegal index vector (non-PBC) for a grid point: " + cvm::to_str(ix), COLVARS_BUG_ERROR); return; } @@ -588,13 +591,13 @@ template class colvar_grid : public colvar_grid_params, public colvarp { if (other_grid.multiplicity() != this->multiplicity()) { - cvm::error_static("Error: trying to subtract two grids with " + cvm::error_static(cvmodule, "Error: trying to subtract two grids with " "different multiplicity.\n"); return; } if (other_grid.data.size() != this->data.size()) { - cvm::error_static("Error: trying to subtract two grids with " + cvm::error_static(cvmodule, "Error: trying to subtract two grids with " "different size.\n"); return; } @@ -612,13 +615,13 @@ template class colvar_grid : public colvar_grid_params, public colvarp void copy_grid(colvar_grid const &other_grid) { if (other_grid.multiplicity() != this->multiplicity()) { - cvm::error_static("Error: trying to copy two grids with " + cvm::error_static(cvmodule, "Error: trying to copy two grids with " "different multiplicity.\n"); return; } if (other_grid.data.size() != this->data.size()) { - cvm::error_static("Error: trying to copy two grids with " + cvm::error_static(cvmodule, "Error: trying to copy two grids with " "different size.\n"); return; } @@ -761,7 +764,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp void map_grid(colvar_grid const &other_grid) { if (other_grid.multiplicity() != this->multiplicity()) { - cvm::error_static("Error: trying to merge two grids with values of " + cvm::error_static(cvmodule, "Error: trying to merge two grids with values of " "different multiplicity.\n"); return; } @@ -805,7 +808,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp cvm::real scale_factor = 1.0) { if (other_grid.multiplicity() != this->multiplicity()) { - cvm::error_static("Error: trying to sum togetehr two grids with values of " + cvm::error_static(cvmodule, "Error: trying to sum togetehr two grids with values of " "different multiplicity.\n"); return; } @@ -914,7 +917,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp upper_boundaries[i])) > 1.0E-10) || (cvm::sqrt(cv[i]->dist2(cv[i]->width, widths[i])) > 1.0E-10) ) { - cvm::error_static("Error: restart information for a grid is " + cvm::error_static(cvmodule, "Error: restart information for a grid is " "inconsistent with that of its colvars.\n"); return; } @@ -937,7 +940,7 @@ template class colvar_grid : public colvar_grid_params, public colvarp (cvm::fabs(other_grid.widths[i] - widths[i]) > 1.0E-10) || (data.size() != other_grid.data.size()) ) { - cvm::error_static("Error: inconsistency between " + cvm::error_static(cvmodule, "Error: inconsistency between " "two grids that are supposed to be equal, " "aside from the data stored.\n"); return; @@ -1015,17 +1018,19 @@ class colvar_grid_count : public colvar_grid public: /// Default constructor - colvar_grid_count(); + colvar_grid_count(colvarmodule* cvmodule_in); /// Destructor virtual ~colvar_grid_count() {} /// Constructor from a vector of colvars or a config string - colvar_grid_count(std::vector &colvars, + colvar_grid_count(colvarmodule* cvmodule_in, + std::vector &colvars, std::shared_ptr params = nullptr); - colvar_grid_count(std::vector &colvars, + colvar_grid_count(colvarmodule* cvmodule_in, + std::vector &colvars, std::string config); /// Increment the counter at given position @@ -1181,7 +1186,7 @@ class colvar_grid_count : public colvar_grid } break; default: - cvm::error_static("Error: local_sample_count is not implemented for grids of dimension > 3", COLVARS_NOT_IMPLEMENTED); + cvm::error_static(cvmodule, "Error: local_sample_count is not implemented for grids of dimension > 3", COLVARS_NOT_IMPLEMENTED); break; } @@ -1300,22 +1305,23 @@ class colvar_grid_scalar : public colvar_grid colvar_grid_count *samples; /// Default constructor - colvar_grid_scalar(); + colvar_grid_scalar(colvarmodule* cvmodule_in); /// Copy constructor (needed because of the grad pointer) - colvar_grid_scalar(colvar_grid_scalar const &g); + colvar_grid_scalar(colvarmodule* cvmodule_in, colvar_grid_scalar const &g); /// Destructor virtual ~colvar_grid_scalar(); /// Constructor from a vector of colvars - colvar_grid_scalar(std::vector &colvars, + colvar_grid_scalar(colvarmodule* cvmodule_in, + std::vector &colvars, std::shared_ptr params = nullptr, bool add_extra_bin = false, std::string config = std::string()); /// Constructor from a multicol file - colvar_grid_scalar(std::string const &filename); + colvar_grid_scalar(colvarmodule* cvmodule_in, std::string const &filename); /// Accumulate the value inline void acc_value(std::vector const &ix, @@ -1436,7 +1442,7 @@ class colvar_grid_scalar : public colvar_grid // 001 011 101 111 000 010 100 110 grad[2] = 0.25 * ((p[1] + p[3] + p[5] + p[7]) - (p[0] + p[2] + p[4] + p[6])) / widths[2]; } else { - cvm::error_static("Finite differences available in dimension 2 and 3 only."); + cvm::error_static(cvmodule, "Finite differences available in dimension 2 and 3 only."); } } @@ -1544,7 +1550,7 @@ class colvar_grid_scalar : public colvar_grid { int s; if (imult > 0) { - cvm::error_static("Error: trying to access a component " + cvm::error_static(cvmodule, "Error: trying to access a component " "larger than 1 in a scalar data grid.\n"); return 0.; } @@ -1564,7 +1570,7 @@ class colvar_grid_scalar : public colvar_grid bool add = false) override { if (imult > 0) { - cvm::error_static("Error: trying to access a component " + cvm::error_static(cvmodule, "Error: trying to access a component " "larger than 1 in a scalar data grid.\n"); return; } @@ -1615,7 +1621,7 @@ class colvar_grid_gradient : public colvar_grid std::shared_ptr samples; /// Default constructor - colvar_grid_gradient(); + colvar_grid_gradient(colvarmodule* cvmodule_in); /// Destructor virtual ~colvar_grid_gradient() @@ -1629,10 +1635,11 @@ class colvar_grid_gradient : public colvar_grid // std::string config = std::string()); /// Constructor from a multicol file - colvar_grid_gradient(std::string const &filename); + colvar_grid_gradient(colvarmodule* cvmodule_in, std::string const &filename); /// Constructor from a vector of colvars and a pointer to the count grid - colvar_grid_gradient(std::vector &colvars, + colvar_grid_gradient(colvarmodule* cvmodule_in, + std::vector &colvars, std::shared_ptr samples_in = nullptr, std::shared_ptr params = nullptr, std::string config = std::string()); diff --git a/src/colvargrid_def.h b/src/colvargrid_def.h index 24e025d94..caca3df92 100644 --- a/src/colvargrid_def.h +++ b/src/colvargrid_def.h @@ -23,35 +23,20 @@ template -colvar_grid::colvar_grid(std::string const &filename, size_t mult_i) - : colvarparse(cvm::main()) +colvar_grid::colvar_grid(colvarmodule* cvmodule_in, std::string const &filename, size_t mult_i) + : colvarparse(cvmodule_in) { -std::istream &is = cvm::main()->proxy->input_stream(filename, "multicol grid file"); -if (!is) { - return; -} - -// Data in the header: nColvars, then for each -// xiMin, dXi, nPoints, periodic flag - -std::string hash; -size_t i; - -if ( !(is >> hash) || (hash != "#") ) { - cvmodule->error("Error reading grid at position "+ - cvm::to_str(static_cast(is.tellg()))+ - " in stream(read \"" + hash + "\")\n"); - return; -} + std::istream &is = cvmodule_in->proxy->input_stream(filename, "multicol grid file"); + if (!is) { + return; + } -is >> nd; -mult = (mult_i == 0) ? nd : mult_i; + // Data in the header: nColvars, then for each + // xiMin, dXi, nPoints, periodic flag -std::vector lower_in(nd), widths_in(nd); -std::vector nx_in(nd); -std::vector periodic_in(nd); + std::string hash; + size_t i; -for (i = 0; i < nd; i++ ) { if ( !(is >> hash) || (hash != "#") ) { cvmodule->error("Error reading grid at position "+ cvm::to_str(static_cast(is.tellg()))+ @@ -59,23 +44,38 @@ for (i = 0; i < nd; i++ ) { return; } - is >> lower_in[i] >> widths_in[i] >> nx_in[i] >> periodic_in[i]; -} + is >> nd; + mult = (mult_i == 0) ? nd : mult_i; -this->setup(nx_in, 0., mult); + std::vector lower_in(nd), widths_in(nd); + std::vector nx_in(nd); + std::vector periodic_in(nd); -widths = widths_in; + for (i = 0; i < nd; i++ ) { + if ( !(is >> hash) || (hash != "#") ) { + cvmodule->error("Error reading grid at position "+ + cvm::to_str(static_cast(is.tellg()))+ + " in stream(read \"" + hash + "\")\n"); + return; + } -for (i = 0; i < nd; i++ ) { - lower_boundaries.push_back(colvarvalue(lower_in[i])); - periodic.push_back(static_cast(periodic_in[i])); -} + is >> lower_in[i] >> widths_in[i] >> nx_in[i] >> periodic_in[i]; + } -// Reset the istream for read_multicol, which expects the whole file -is.clear(); -is.seekg(0); -read_multicol(is); -cvm::main()->proxy->close_input_stream(filename); + this->setup(nx_in, 0., mult); + + widths = widths_in; + + for (i = 0; i < nd; i++ ) { + lower_boundaries.push_back(colvarvalue(lower_in[i])); + periodic.push_back(static_cast(periodic_in[i])); + } + + // Reset the istream for read_multicol, which expects the whole file + is.clear(); + is.seekg(0); + read_multicol(is); + cvmodule->proxy->close_input_stream(filename); } @@ -414,12 +414,12 @@ int colvar_grid::read_multicol(std::string const &filename, std::string description, bool add) { - std::istream &is = cvm::main()->proxy->input_stream(filename, description); + std::istream &is = cvmodule->proxy->input_stream(filename, description); if (!is) { return COLVARS_FILE_ERROR; } if (colvar_grid::read_multicol(is, add)) { - cvm::main()->proxy->close_input_stream(filename); + cvmodule->proxy->close_input_stream(filename); return COLVARS_OK; } return COLVARS_FILE_ERROR; @@ -479,13 +479,13 @@ int colvar_grid::write_multicol(std::string const &filename, std::string description) const { int error_code = COLVARS_OK; - std::ostream &os = cvm::main()->proxy->output_stream(filename, description); + std::ostream &os = cvmodule->proxy->output_stream(filename, description); if (!os) { return COLVARS_FILE_ERROR; } error_code |= colvar_grid::write_multicol(os) ? COLVARS_OK : COLVARS_FILE_ERROR; - cvm::main()->proxy->close_output_stream(filename); + cvmodule->proxy->close_output_stream(filename); return error_code; } @@ -537,13 +537,13 @@ int colvar_grid::write_opendx(std::string const &filename, std::string description) const { int error_code = COLVARS_OK; - std::ostream &os = cvm::main()->proxy->output_stream(filename, description); + std::ostream &os = cvmodule->proxy->output_stream(filename, description); if (!os) { return COLVARS_FILE_ERROR; } error_code |= colvar_grid::write_opendx(os) ? COLVARS_OK : COLVARS_FILE_ERROR; - cvm::main()->proxy->close_output_stream(filename); + cvmodule->proxy->close_output_stream(filename); return error_code; } diff --git a/src/colvargrid_integrate.cpp b/src/colvargrid_integrate.cpp index b85c8cbf8..ee1711d35 100644 --- a/src/colvargrid_integrate.cpp +++ b/src/colvargrid_integrate.cpp @@ -3,9 +3,9 @@ #include -colvargrid_integrate::colvargrid_integrate(std::vector &colvars, +colvargrid_integrate::colvargrid_integrate(colvarmodule* cvmodule_in, std::vector &colvars, std::shared_ptr gradients) - : colvar_grid_scalar(colvars, gradients, true), + : colvar_grid_scalar(cvmodule_in, colvars, gradients, true), b_smoothed(false), gradients(gradients) { @@ -35,8 +35,9 @@ colvargrid_integrate::colvargrid_integrate(std::vector &colvars, } -colvargrid_integrate::colvargrid_integrate(std::shared_ptr gradients) - : b_smoothed(false), +colvargrid_integrate::colvargrid_integrate(colvarmodule* cvmodule_in, std::shared_ptr gradients) + : colvar_grid_scalar(cvmodule_in), + b_smoothed(false), gradients(gradients) { nd = gradients->num_variables(); diff --git a/src/colvargrid_integrate.h b/src/colvargrid_integrate.h index 52b0001b6..a9a77a703 100644 --- a/src/colvargrid_integrate.h +++ b/src/colvargrid_integrate.h @@ -9,17 +9,19 @@ class colvargrid_integrate : public colvar_grid_scalar { public: - colvargrid_integrate(); + colvargrid_integrate(colvarmodule* cvmodule_in); virtual ~colvargrid_integrate() {} /// Constructor from a vector of colvars + gradient grid - colvargrid_integrate(std::vector &colvars, - std::shared_ptr gradients); + colvargrid_integrate(colvarmodule* cvmodule_in, + std::vector &colvars, + std::shared_ptr gradients); /// Constructor from a gradient grid (for processing grid files without a Colvars config) - colvargrid_integrate(std::shared_ptr gradients); + colvargrid_integrate(colvarmodule* cvmodule_in, + std::shared_ptr gradients); /// \brief Calculate potential from divergence (in 2D); return number of steps int integrate(const int itmax, const cvm::real & tol, cvm::real & err, bool verbose = true); diff --git a/src/colvarmodule.cpp b/src/colvarmodule.cpp index 31b0ad6fe..88f6502f2 100644 --- a/src/colvarmodule.cpp +++ b/src/colvarmodule.cpp @@ -122,7 +122,6 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) } proxy = proxy_in; // Pointer to the proxy object - proxy_static = proxy_in; // Temporary - assume single proxy & module objects parse = new colvarparse(this); // Parsing object for global options version_int = proxy->get_version_from_string(COLVARS_VERSION); @@ -202,11 +201,6 @@ colvarmodule::colvarmodule(colvarproxy *proxy_in) } -colvarmodule * colvarmodule::main() -{ - return proxy_static ? proxy_static->cvmodule : nullptr; -} - std::vector *colvarmodule::variables() { @@ -435,30 +429,30 @@ int colvarmodule::parse_global_params(std::string const &conf) std::string smp; if (parse->get_keyval(conf, "smp", smp)) { if (smp == "cvcs" || smp == "on" || smp == "yes") { - if (proxy->set_smp_mode(colvarproxy_smp::smp_mode_t::cvcs) != COLVARS_OK) { + if (proxy->set_smp_mode(colvarproxy::smp_mode_t::cvcs) != COLVARS_OK) { this->error("Colvars component-based parallelism is not implemented.\n"); return COLVARS_INPUT_ERROR; } } else if (smp == "inner_loop") { - if (proxy->set_smp_mode(colvarproxy_smp::smp_mode_t::inner_loop) != COLVARS_OK) { + if (proxy->set_smp_mode(colvarproxy::smp_mode_t::inner_loop) != COLVARS_OK) { this->error("SMP parallelism inside the calculation of Colvars components is not implemented.\n"); return COLVARS_INPUT_ERROR; } } else if (smp == "gpu") { - if (proxy->set_smp_mode(colvarproxy_smp::smp_mode_t::gpu) != COLVARS_OK) { + if (proxy->set_smp_mode(colvarproxy::smp_mode_t::gpu) != COLVARS_OK) { this->error("GPU parallelism is not implemented.\n"); return COLVARS_INPUT_ERROR; } else { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) gpu_calc = std::unique_ptr( - new colvars_gpu::colvarmodule_gpu_calc); + new colvars_gpu::colvarmodule_gpu_calc(this)); gpu_calc->init(); this->log("EXPERIMENTAL GPU parallelism will be applied inside:\n"); this->log(" - atom groups\n"); #endif } } else { - proxy->set_smp_mode(colvarproxy_smp::smp_mode_t::none); + proxy->set_smp_mode(colvarproxy::smp_mode_t::none); this->log("SMP parallelism has been disabled.\n"); } } else { @@ -467,19 +461,19 @@ int colvarmodule::parse_global_params(std::string const &conf) const auto available_smp_modes = proxy->get_available_smp_modes(); for (size_t i = 0; i < available_smp_modes.size(); ++i) { switch (available_smp_modes[i]) { - case colvarproxy_smp::smp_mode_t::cvcs: { + case colvarproxy::smp_mode_t::cvcs: { this->log(" - cvcs\n"); break; } - case colvarproxy_smp::smp_mode_t::inner_loop: { + case colvarproxy::smp_mode_t::inner_loop: { this->log(" - inner_loop\n"); break; } - case colvarproxy_smp::smp_mode_t::gpu: { + case colvarproxy::smp_mode_t::gpu: { this->log(" - gpu\n"); break; } - case colvarproxy_smp::smp_mode_t::none: { + case colvarproxy::smp_mode_t::none: { this->log(" - none\n"); break; } @@ -487,30 +481,30 @@ int colvarmodule::parse_global_params(std::string const &conf) } this->log("Set SMP parallelism to the preferred (default) mode to the proxy.\n"); // Find the proxy's preferred SMP mode if SMP is not defined - colvarproxy_smp::smp_mode_t preferred_smp_mode = proxy->get_preferred_smp_mode(); + colvarproxy::smp_mode_t preferred_smp_mode = proxy->get_preferred_smp_mode(); proxy->set_smp_mode(preferred_smp_mode); switch (preferred_smp_mode) { - case colvarproxy_smp::smp_mode_t::cvcs: { + case colvarproxy::smp_mode_t::cvcs: { this->log("SMP parallelism will be applied to Colvars components.\n"); this->log(" - SMP parallelism: enabled (num. threads = " + to_str(proxy->smp_num_threads()) + ")\n"); break; } - case colvarproxy_smp::smp_mode_t::inner_loop: { + case colvarproxy::smp_mode_t::inner_loop: { this->log("SMP parallelism will be applied inside the Colvars components.\n"); this->log(" - SMP parallelism: enabled (num. threads = " + to_str(proxy->smp_num_threads()) + ")\n"); break; } - case colvarproxy_smp::smp_mode_t::gpu: { + case colvarproxy::smp_mode_t::gpu: { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) gpu_calc = std::unique_ptr( - new colvars_gpu::colvarmodule_gpu_calc); + new colvars_gpu::colvarmodule_gpu_calc(this)); gpu_calc->init(); #endif this->log("EXPERIMENTAL GPU parallelism will be applied inside:\n"); this->log(" - atom groups\n"); break; } - case colvarproxy_smp::smp_mode_t::none: { + case colvarproxy::smp_mode_t::none: { this->log("SMP parallelism is disabled by default.\n"); break; } @@ -1051,7 +1045,7 @@ int colvarmodule::calc_colvars() } // if SMP support is available, split up the work - if (proxy->get_smp_mode() == colvarproxy_smp::smp_mode_t::cvcs) { + if (proxy->get_smp_mode() == colvarproxy::smp_mode_t::cvcs) { // first, calculate how much work (currently, how many active CVCs) each colvar has @@ -1088,10 +1082,10 @@ int colvarmodule::calc_colvars() } this->decrease_depth(); - } else if (proxy->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + } else if (proxy->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { this->increase_depth(); #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) - error_code |= gpu_calc->calc_cvs(*variables_active(), this); + error_code |= gpu_calc->calc_cvs(*variables_active()); #else return this->error("GPU calculation is not implemented.\n"); #endif @@ -1234,9 +1228,9 @@ int colvarmodule::update_colvar_forces() if (this->debug()) this->log("Communicating forces from the colvars to the atoms.\n"); this->increase_depth(); - if (proxy->get_smp_mode() == colvarproxy_smp::smp_mode_t::gpu) { + if (proxy->get_smp_mode() == colvarproxy::smp_mode_t::gpu) { #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) - error_code |= gpu_calc->apply_forces(*variables_active(), this); + error_code |= gpu_calc->apply_forces(*variables_active()); #endif } else { for (cvi = variables_active()->begin(); cvi != variables_active()->end(); cvi++) { @@ -2712,7 +2706,7 @@ int colvarmodule::usage::cite_feature(std::string const &feature) feature_count_[feature] += 1; return cite_paper(feature_paper_map_[feature]); } - cvmodule->log("Warning: cannot cite unknown feature \""+feature+"\"\n"); + cvm::log_static(cvmodule, "Warning: cannot cite unknown feature \""+feature+"\"\n"); return COLVARS_OK; } @@ -2722,7 +2716,7 @@ int colvarmodule::usage::cite_paper(std::string const &paper) paper_count_[paper] += 1; return COLVARS_OK; } - cvmodule->log("Warning: cannot cite unknown paper \""+paper+"\"\n"); + cvm::log_static(cvmodule, "Warning: cannot cite unknown paper \""+paper+"\"\n"); return COLVARS_OK; } @@ -2771,7 +2765,4 @@ std::string colvarmodule::usage::report(int flag) return result; } -// Static pointer to the proxy object -colvarproxy *colvarmodule::proxy_static = nullptr; - cvm::real colvarmodule::debug_gradients_step_size = 1.0e-07; diff --git a/src/colvarmodule.h b/src/colvarmodule.h index 16b0e0822..529459874 100644 --- a/src/colvarmodule.h +++ b/src/colvarmodule.h @@ -753,9 +753,9 @@ static inline real acos(real const &x) /// Print a message to stderr /// Used in lightweight objects that do not have access to cvmodule - static void log_static(std::string const &message) { - if (colvarmodule::main()) { - colvarmodule::main()->log(message); + static void log_static(colvarmodule* cvmodule, std::string const &message) { + if (cvmodule) { + cvmodule->log(message); } else { std::printf("colvars: %s\n", message.c_str()); } @@ -767,11 +767,11 @@ static inline real acos(real const &x) /// Print an error message to stderr /// Used in lightweight objects that do not have access to cvmodule /// Typically fatal errors that reflect bugs, so hopefully rare - static int error_static(std::string const &message, int code = -1) { - if (colvarmodule::main()) { - code = colvarmodule::main()->error(message, code); + static int error_static(colvarmodule* cvmodule, std::string const &message, int code = -1) { + if (cvmodule) { + code = cvmodule->error(message, code); } else { - std::cerr << "colvars: " << message << std::endl; + std::fprintf(stderr, "%s%s\n", "colvars: ", message.c_str()); exit(-1); } return code; @@ -955,11 +955,6 @@ static inline real acos(real const &x) /// \brief Pointer to the proxy object, used to retrieve atomic data /// from the hosting program colvarproxy *proxy = nullptr; - /// Temporary static pointer to unique proxy object - static colvarproxy *proxy_static; - - /// \brief Access the main instance of the Colvars module - static colvarmodule *main(); #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) template diff --git a/src/colvarparams.cpp b/src/colvarparams.cpp index bcb713355..6ed6bb2a6 100644 --- a/src/colvarparams.cpp +++ b/src/colvarparams.cpp @@ -17,7 +17,7 @@ -colvarparams::colvarparams() +colvarparams::colvarparams(colvarmodule* cvmodule_in): cvmodule(cvmodule_in) {} @@ -75,7 +75,7 @@ void const *colvarparams::get_param_ptr(std::string const ¶m_name) if (param_map.count(param_name) > 0) { return param_map[param_name]; } - cvm::error_static("Error: parameter \""+param_name+"\" not found.\n", COLVARS_INPUT_ERROR); + cvm::error_static(cvmodule, "Error: parameter \""+param_name+"\" not found.\n", COLVARS_INPUT_ERROR); return NULL; } @@ -85,7 +85,7 @@ void const *colvarparams::get_param_grad_ptr(std::string const ¶m_name) if (param_grad_map.count(param_name) > 0) { return param_grad_map[param_name]; } - cvm::error_static("Error: gradient of parameter \""+param_name+"\" not found.\n", + cvm::error_static(cvmodule, "Error: gradient of parameter \""+param_name+"\" not found.\n", COLVARS_INPUT_ERROR); return NULL; } @@ -103,9 +103,9 @@ int colvarparams::set_param(std::string const ¶m_name, void const * /* new_value */) { if (param_map.count(param_name) > 0) { - return cvm::error_static("Error: parameter \""+param_name+"\" cannot be " + return cvm::error_static(cvmodule, "Error: parameter \""+param_name+"\" cannot be " "modified.\n", COLVARS_NOT_IMPLEMENTED); } - return cvm::error_static("Error: parameter \""+param_name+"\" not found.\n", + return cvm::error_static(cvmodule, "Error: parameter \""+param_name+"\" not found.\n", COLVARS_INPUT_ERROR); } diff --git a/src/colvarparams.h b/src/colvarparams.h index 1d00300a8..53e824dcb 100644 --- a/src/colvarparams.h +++ b/src/colvarparams.h @@ -14,6 +14,7 @@ /// \file colvarparams.h Functions to handle scalar parameters used in objects +class colvarmodule; class colvarparams { @@ -40,10 +41,12 @@ class colvarparams { /// Set the named parameter to the given value virtual int set_param(std::string const ¶m_name, void const *new_value); - protected: +protected: + + colvarmodule *cvmodule = nullptr; /// Default constructor - colvarparams(); + colvarparams(colvarmodule *cvmodule_in); /// Default destructor virtual ~colvarparams(); diff --git a/src/colvarparse.cpp b/src/colvarparse.cpp index cd857a3b4..e744e568d 100644 --- a/src/colvarparse.cpp +++ b/src/colvarparse.cpp @@ -41,7 +41,7 @@ namespace { colvarparse::colvarparse(colvarmodule *cvmodule_in) - : cvmodule(cvmodule_in), + : colvarparams(cvmodule_in), keyword_delimiters_left("\n"+std::string(white_space)+"}"), keyword_delimiters_right("\n"+std::string(white_space)+"{") {} diff --git a/src/colvarparse.h b/src/colvarparse.h index b617b1a63..ffbda305a 100644 --- a/src/colvarparse.h +++ b/src/colvarparse.h @@ -26,10 +26,6 @@ /// need to parse input inherit from this class colvarparse : public colvarparams { -protected: - - colvarmodule *cvmodule = nullptr; - public: colvarmodule *get_cvmodule() { return cvmodule; } diff --git a/src/colvarproxy.cpp b/src/colvarproxy.cpp index a38f65f42..ad5addde6 100644 --- a/src/colvarproxy.cpp +++ b/src/colvarproxy.cpp @@ -20,22 +20,11 @@ #include -colvarproxy_atoms::colvarproxy_atoms() -{ - atoms_rms_applied_force_ = atoms_max_applied_force_ = 0.0; - atoms_max_applied_force_id_ = -1; - modified_atom_list_ = false; - updated_masses_ = updated_charges_ = false; -} - - -colvarproxy_atoms::~colvarproxy_atoms() -{ - reset(); -} - +#ifdef COLVARS_TCL +#include +#endif -int colvarproxy_atoms::reset() +int colvarproxy::reset_atoms() { atoms_ids.clear(); atoms_refcount.clear(); @@ -48,7 +37,7 @@ int colvarproxy_atoms::reset() } -int colvarproxy_atoms::add_atom_slot(int atom_id) +int colvarproxy::add_atom_slot(int atom_id) { atoms_ids.push_back(atom_id); atoms_refcount.push_back(1); @@ -62,47 +51,47 @@ int colvarproxy_atoms::add_atom_slot(int atom_id) } -int colvarproxy_atoms::init_atom(int /* atom_number */) +int colvarproxy::init_atom(int /* atom_number */) { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_atoms::check_atom_id(int /* atom_number */) +int colvarproxy::check_atom_id(int /* atom_number */) { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_atoms::check_atom_name_selections_available() +int colvarproxy::check_atom_name_selections_available() { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_atoms::init_atom(cvm::residue_id const & /* residue */, +int colvarproxy::init_atom(cvm::residue_id const & /* residue */, std::string const & /* atom_name */, std::string const & /* segment_id */) { - cvm::error_static("Error: initializing an atom by name and residue number is currently not supported.\n", + cvm::error_static(cvmodule, "Error: initializing an atom by name and residue number is currently not supported.\n", COLVARS_NOT_IMPLEMENTED); return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_atoms::check_atom_id(cvm::residue_id const &residue, +int colvarproxy::check_atom_id(cvm::residue_id const &residue, std::string const &atom_name, std::string const &segment_id) { - colvarproxy_atoms::init_atom(residue, atom_name, segment_id); + init_atom(residue, atom_name, segment_id); return COLVARS_NOT_IMPLEMENTED; } -void colvarproxy_atoms::clear_atom(int index) +void colvarproxy::clear_atom(int index) { if (((size_t) index) >= atoms_ids.size()) { - cvm::error_static("Error: trying to disable an atom that was not previously requested.\n", + cvm::error_static(cvmodule, "Error: trying to disable an atom that was not previously requested.\n", COLVARS_INPUT_ERROR); } if (atoms_refcount[index] > 0) { @@ -111,7 +100,7 @@ void colvarproxy_atoms::clear_atom(int index) } -size_t colvarproxy_atoms::get_num_active_atoms() const +size_t colvarproxy::get_num_active_atoms() const { size_t result = 0; for (size_t i = 0; i < atoms_refcount.size(); i++) { @@ -121,14 +110,14 @@ size_t colvarproxy_atoms::get_num_active_atoms() const } -void colvarproxy_atoms::compute_rms_atoms_applied_force() +void colvarproxy::compute_rms_atoms_applied_force() { atoms_rms_applied_force_ = compute_norm2_stats(atoms_new_colvar_forces); } -void colvarproxy_atoms::compute_max_atoms_applied_force() +void colvarproxy::compute_max_atoms_applied_force() { int minmax_index = -1; size_t const n_atoms_ids = atoms_ids.size(); @@ -149,20 +138,7 @@ void colvarproxy_atoms::compute_max_atoms_applied_force() } - -colvarproxy_atom_groups::colvarproxy_atom_groups() -{ - atom_groups_rms_applied_force_ = atom_groups_max_applied_force_ = 0.0; -} - - -colvarproxy_atom_groups::~colvarproxy_atom_groups() -{ - reset(); -} - - -int colvarproxy_atom_groups::reset() +int colvarproxy::reset_atom_groups() { atom_groups_ids.clear(); atom_groups_refcount.clear(); @@ -175,7 +151,7 @@ int colvarproxy_atom_groups::reset() } -int colvarproxy_atom_groups::add_atom_group_slot(int atom_group_id) +int colvarproxy::add_atom_group_slot(int atom_group_id) { atom_groups_ids.push_back(atom_group_id); atom_groups_refcount.push_back(1); @@ -188,25 +164,25 @@ int colvarproxy_atom_groups::add_atom_group_slot(int atom_group_id) } -int colvarproxy_atom_groups::scalable_group_coms() +int colvarproxy::scalable_group_coms() { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_atom_groups::init_atom_group(std::vector const & /* atoms_ids */) +int colvarproxy::init_atom_group(std::vector const & /* atoms_ids */) { - cvm::error_static("Error: initializing a group outside of the Colvars module " + cvm::error_static(cvmodule, "Error: initializing a group outside of the Colvars module " "is currently not supported.\n", COLVARS_NOT_IMPLEMENTED); return COLVARS_NOT_IMPLEMENTED; } -void colvarproxy_atom_groups::clear_atom_group(int index) +void colvarproxy::clear_atom_group(int index) { if (((size_t) index) >= atom_groups_ids.size()) { - cvm::error_static("Error: trying to disable an atom group " + cvm::error_static(cvmodule, "Error: trying to disable an atom group " "that was not previously requested.\n", COLVARS_INPUT_ERROR); } @@ -216,7 +192,7 @@ void colvarproxy_atom_groups::clear_atom_group(int index) } -size_t colvarproxy_atom_groups::get_num_active_atom_groups() const +size_t colvarproxy::get_num_active_atom_groups() const { size_t result = 0; for (size_t i = 0; i < atom_groups_refcount.size(); i++) { @@ -226,14 +202,14 @@ size_t colvarproxy_atom_groups::get_num_active_atom_groups() const } -void colvarproxy_atom_groups::compute_rms_atom_groups_applied_force() +void colvarproxy::compute_rms_atom_groups_applied_force() { atom_groups_rms_applied_force_ = compute_norm2_stats(atom_groups_new_colvar_forces); } -void colvarproxy_atom_groups::compute_max_atom_groups_applied_force() +void colvarproxy::compute_max_atom_groups_applied_force() { atom_groups_max_applied_force_ = compute_norm2_stats(atom_groups_new_colvar_forces); @@ -241,51 +217,26 @@ void colvarproxy_atom_groups::compute_max_atom_groups_applied_force() -colvarproxy_smp::colvarproxy_smp() -{ - smp_mode = smp_mode_t::none; // May be disabled by user option - omp_lock_state = NULL; -#if defined(_OPENMP) - smp_mode = smp_mode_t::cvcs; - if (omp_get_thread_num() == 0) { - omp_lock_state = new omp_lock_t; - omp_init_lock(omp_lock_state); - } -#endif -} - - -colvarproxy_smp::~colvarproxy_smp() -{ -#if defined(_OPENMP) - if (omp_get_thread_num() == 0) { - if (omp_lock_state) { - delete omp_lock_state; - } - } -#endif -} - -colvarproxy::smp_mode_t colvarproxy_smp::get_smp_mode() const { +colvarproxy::smp_mode_t colvarproxy::get_smp_mode() const { return smp_mode; } -std::vector colvarproxy_smp::get_available_smp_modes() const { - std::vector modes; +std::vector colvarproxy::get_available_smp_modes() const { + std::vector modes; #if defined(_OPENMP) - modes.push_back(colvarproxy_smp::smp_mode_t::cvcs); - modes.push_back(colvarproxy_smp::smp_mode_t::inner_loop); + modes.push_back(colvarproxy::smp_mode_t::cvcs); + modes.push_back(colvarproxy::smp_mode_t::inner_loop); #endif - modes.push_back(colvarproxy_smp::smp_mode_t::none); + modes.push_back(colvarproxy::smp_mode_t::none); return modes; } -colvarproxy_smp::smp_mode_t colvarproxy_smp::get_preferred_smp_mode() const { +colvarproxy::smp_mode_t colvarproxy::get_preferred_smp_mode() const { return get_available_smp_modes()[0]; } -int colvarproxy_smp::set_smp_mode(smp_mode_t mode) { - std::vector available_modes = get_available_smp_modes(); +int colvarproxy::set_smp_mode(smp_mode_t mode) { + std::vector available_modes = get_available_smp_modes(); auto it = std::find(available_modes.begin(), available_modes.end(), mode); if (it != available_modes.end()) { smp_mode = *it; @@ -296,18 +247,18 @@ int colvarproxy_smp::set_smp_mode(smp_mode_t mode) { } -int colvarproxy_smp::smp_loop(int n_items, std::function const &worker) +int colvarproxy::smp_loop(int n_items, std::function const &worker) { int error_code = COLVARS_OK; #if defined(_OPENMP) - cvm::main()->increase_depth(); + if (cvmodule) cvmodule->increase_depth(); #pragma omp parallel for for (int i = 0; i < n_items; i++) { int const retcode = worker(i); #pragma omp atomic error_code |= retcode; } - cvm::main()->decrease_depth(); + if (cvmodule) cvmodule->decrease_depth(); #else error_code |= COLVARS_NOT_IMPLEMENTED; #endif @@ -315,57 +266,56 @@ int colvarproxy_smp::smp_loop(int n_items, std::function const &worke } -int colvarproxy_smp::smp_biases_loop() +int colvarproxy::smp_biases_loop() { + if (!cvmodule) return COLVARS_BUG_ERROR; #if defined(_OPENMP) #pragma omp parallel { #pragma omp for - for (int i = 0; i < static_cast(cvm::main()->biases_active()->size()); i++) { - colvarbias *b = (*(cvm::main()->biases_active()))[i]; - if (cvm::main()->debug()) { - cvm::main()->log("Calculating bias \""+b->name+"\" on thread "+ + for (int i = 0; i < static_cast(cvmodule->biases_active()->size()); i++) { + colvarbias *b = (*(cvmodule->biases_active()))[i]; + if (cvmodule->debug()) { + cvmodule->log("Calculating bias \""+b->name+"\" on thread "+ cvm::to_str(smp_thread_id())+"\n"); } b->update(); } } - return cvm::main()->get_error(); + return cvmodule->get_error(); #else return COLVARS_NOT_IMPLEMENTED; #endif } -int colvarproxy_smp::smp_biases_script_loop() +int colvarproxy::smp_biases_script_loop() { #if defined(_OPENMP) + if (!cvmodule) return COLVARS_BUG_ERROR; #pragma omp parallel { #pragma omp single nowait { - cvm::main()->calc_scripted_forces(); + cvmodule->calc_scripted_forces(); } #pragma omp for - for (int i = 0; i < static_cast(cvm::main()->biases_active()->size()); i++) { - colvarbias *b = (*(cvm::main()->biases_active()))[i]; - if (cvm::main()->debug()) { - cvm::main()->log("Calculating bias \""+b->name+"\" on thread "+ + for (int i = 0; i < static_cast(cvmodule->biases_active()->size()); i++) { + colvarbias *b = (*(cvmodule->biases_active()))[i]; + if (cvmodule->debug()) { + cvmodule->log("Calculating bias \""+b->name+"\" on thread "+ cvm::to_str(smp_thread_id())+"\n"); } b->update(); } } - return cvm::main()->get_error(); + return cvmodule->get_error(); #else return COLVARS_NOT_IMPLEMENTED; #endif } - - - -int colvarproxy_smp::smp_thread_id() +int colvarproxy::smp_thread_id() { #if defined(_OPENMP) return omp_get_thread_num(); @@ -375,7 +325,7 @@ int colvarproxy_smp::smp_thread_id() } -int colvarproxy_smp::smp_num_threads() +int colvarproxy::smp_num_threads() { #if defined(_OPENMP) return omp_get_max_threads(); @@ -385,7 +335,7 @@ int colvarproxy_smp::smp_num_threads() } -int colvarproxy_smp::smp_lock() +int colvarproxy::smp_lock() { #if defined(_OPENMP) omp_set_lock(omp_lock_state); @@ -394,7 +344,7 @@ int colvarproxy_smp::smp_lock() } -int colvarproxy_smp::smp_trylock() +int colvarproxy::smp_trylock() { #if defined(_OPENMP) return omp_test_lock(omp_lock_state) ? COLVARS_OK : COLVARS_ERROR; @@ -404,7 +354,7 @@ int colvarproxy_smp::smp_trylock() } -int colvarproxy_smp::smp_unlock() +int colvarproxy::smp_unlock() { #if defined(_OPENMP) omp_unset_lock(omp_lock_state); @@ -414,25 +364,14 @@ int colvarproxy_smp::smp_unlock() -colvarproxy_script::colvarproxy_script() {} - - -colvarproxy_script::~colvarproxy_script() -{ - if (script) { - delete script; - script = nullptr; - } -} - -int colvarproxy_script::run_force_callback() +int colvarproxy::run_force_callback() { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_script::run_colvar_callback(std::string const & /* name */, +int colvarproxy::run_colvar_callback(std::string const & /* name */, std::vector const & /* cvcs */, colvarvalue & /* value */) { @@ -440,7 +379,7 @@ int colvarproxy_script::run_colvar_callback(std::string const & /* name */, } -int colvarproxy_script::run_colvar_gradient_callback(std::string const & /* name */, +int colvarproxy::run_colvar_gradient_callback(std::string const & /* name */, std::vector const & /* cvcs */, std::vector > & /* gradient */) { @@ -452,6 +391,51 @@ int colvarproxy_script::run_colvar_gradient_callback(std::string const & /* name colvarproxy::colvarproxy() { cvmodule = NULL; + // colvarproxy_system + angstrom_value_ = 0.0; + kcal_mol_value_ = 0.0; + timestep_ = 1.0; + target_temperature_ = 0.0; + boltzmann_ = 0.001987191; // Default: kcal/mol/K + boundaries_type = boundaries_unsupported; + total_force_requested = false; + indirect_lambda_biasing_force = 0.0; + cached_alch_lambda_changed = false; + cached_alch_lambda = -1.0; + reset_pbc_lattice(); + // colvarproxy_atoms + atoms_rms_applied_force_ = atoms_max_applied_force_ = 0.0; + atoms_max_applied_force_id_ = -1; + modified_atom_list_ = false; + updated_masses_ = updated_charges_ = false; + // colvarproxy_atom_groups + atom_groups_rms_applied_force_ = atom_groups_max_applied_force_ = 0.0; + // colvarproxy_volmaps + volmaps_rms_applied_force_ = volmaps_max_applied_force_ = 0.0; + // colvarproxy_smp + smp_mode = smp_mode_t::none; // May be disabled by user option + omp_lock_state = NULL; +#if defined(_OPENMP) + smp_mode = smp_mode_t::cvcs; + if (omp_get_thread_num() == 0) { + omp_lock_state = new omp_lock_t; + omp_init_lock(omp_lock_state); + } +#endif + // colvarproxy_replicas +#ifdef COLVARS_MPI + replicas_mpi_comm = MPI_COMM_NULL; +#endif + // colvarproxy_tcl + tcl_interp_ = nullptr; + // colvarproxy_io + restart_frequency_engine = 0; + input_stream_error_ = new std::istringstream(); + input_stream_error_->setstate(std::ios::badbit); + output_stream_error_ = new std::ostringstream(); + output_stream_error_->setstate(std::ios::badbit); + // colvarproxy_gpu + support_gpu = false; // By default, simulation engines allow to immediately request atoms engine_ready_ = true; b_simulation_running = true; @@ -465,12 +449,40 @@ colvarproxy::colvarproxy() colvarproxy::~colvarproxy() { - close_output_streams(); - if (cvmodule != NULL) { + // Destruct colvarproxy_script + if (script) { + delete script; + script = nullptr; + } + // The following dtor will be called by cvm::reset from the dtor of colvarmodule?? + // // Destruct colvarproxy_volmaps + // reset_volmaps(); + // // Destruct colvarproxy_atom_groups + // reset_atom_groups(); + // // Destruct colvarproxy_atoms + // reset_atoms(); + if (cvmodule) { delete cvmodule; - cvmodule = NULL; + cvmodule = nullptr; + } + // TODO: I guess that "delete cvmodule" will need to flush the streams, so close them after destructing cvmodule. + // Destruct colvarproxy_io + close_input_streams(); + close_output_streams(); + if (input_stream_error_) { + delete input_stream_error_; + } + if (output_stream_error_) { + delete output_stream_error_; } delete reinterpret_cast > *>(config_queue_); +#if defined(_OPENMP) + if (omp_get_thread_num() == 0) { + if (omp_lock_state) { + delete omp_lock_state; + } + } +#endif } @@ -488,9 +500,9 @@ int colvarproxy::reset() cvmodule->log("colvarproxy::reset()\n"); } int error_code = COLVARS_OK; - error_code |= colvarproxy_atoms::reset(); - error_code |= colvarproxy_atom_groups::reset(); - error_code |= colvarproxy_volmaps::reset(); + error_code |= reset_atoms(); + error_code |= reset_atom_groups(); + error_code |= reset_volmaps(); total_force_requested = false; return error_code; } diff --git a/src/colvarproxy.h b/src/colvarproxy.h index 53e700193..258a8e63e 100644 --- a/src/colvarproxy.h +++ b/src/colvarproxy.h @@ -11,15 +11,12 @@ #define COLVARPROXY_H #include +#include +#include #include "colvarmodule.h" #include "colvartypes.h" -#include "colvarproxy_io.h" -#include "colvarproxy_replicas.h" -#include "colvarproxy_system.h" -#include "colvarproxy_tcl.h" -#include "colvarproxy_volmaps.h" -#include "colvarproxy_gpu.h" +#include "colvar_gpu_support.h" /// \file colvarproxy.h /// \brief Colvars proxy classes @@ -39,12 +36,197 @@ // forward declarations class colvarscript; +#if defined(_OPENMP) +#include +#else +struct omp_lock_t; +#endif + +#ifdef COLVARS_MPI +#include +typedef MPI_Comm replicas_mpi_comm_t; +#else +typedef void * replicas_mpi_comm_t; +#endif + +#if defined(NAMD_TCL) || defined(VMDTCL) +#define COLVARS_TCL +#endif + +#ifdef COLVARS_TCL +#include +#else +// Allow for placeholders Tcl_Interp* variables +typedef void Tcl_Interp; +#endif + -/// \brief Container of atomic data for processing by Colvars -class colvarproxy_atoms { +/// Interface between Colvars and MD engine (GROMACS, LAMMPS, NAMD, VMD...) +/// +/// This is the base class: each engine is supported by a derived class. +class colvarproxy +{ public: + /// \brief Name of the unit system used internally by Colvars (by default, that of the back-end). + /// Supported depending on the back-end: real (A, kcal/mol), metal (A, eV), electron (Bohr, Hartree), gromacs (nm, kJ/mol) + /// Note: calls to back-end PBC functions assume back-end length unit + /// We use different unit from back-end in VMD bc using PBC functions from colvarproxy base class + /// Colvars internal units are user specified, because the module exchanges info in unknown + /// composite dimensions with user input, while it only exchanges quantities of known + /// dimension with the back-end (length and forces) + std::string units; + + /// \brief Request to set the units used internally by Colvars + virtual int set_unit_system(std::string const &units, bool check_only); + + /// \brief Convert a length from Angstrom to internal + inline cvm::real angstrom_to_internal(cvm::real l) const + { + return l * angstrom_value_; + } + + /// \brief Convert a length from internal to Angstrom + inline cvm::real internal_to_angstrom(cvm::real l) const + { + return l / angstrom_value_; + } + + /// Boltzmann constant, with unit the same as energy / K + inline cvm::real boltzmann() const + { + return boltzmann_; + } + + /// Current target temperature of the simulation (K units) + inline cvm::real target_temperature() const + { + return target_temperature_; + } + + /// Set the current target temperature of the simulation (K units) + virtual int set_target_temperature(cvm::real T); + + /// Time step of the simulation (fs units) + inline double dt() const + { + return timestep_; + } + + /// Set the current integration timestep of the simulation (fs units) + virtual int set_integration_timestep(cvm::real dt); + + /// Time step of the simulation (fs units) + inline int time_step_factor() const + { + return time_step_factor_; + } + + /// Set the current integration timestep of the simulation (fs units) + virtual int set_time_step_factor(int fact); + + /// \brief Pseudo-random number with Gaussian distribution + virtual cvm::real rand_gaussian(void); + + /// Pass restraint energy value for current timestep to MD engine + virtual void add_energy(cvm::real energy); + + /// Use the PBC functions from the Colvars library (as opposed to MD engine) + inline bool & use_internal_pbc() { return use_internal_pbc_; } + + /// \brief Get the PBC-aware distance vector between two positions + virtual cvm::rvector position_distance(cvm::atom_pos const &pos1, + cvm::atom_pos const &pos2) const; + + /// Inline version of position_distance() + cvm::rvector position_distance_internal(cvm::atom_pos const &pos1, + cvm::atom_pos const &pos2) const; + + /// Kernel used by position_distance_internal() + /// @param pos1 First position + /// @param pos2 Second position + /// @param a Unit cell vector + /// @param b Unit cell vector + /// @param c Unit cell vector + /// @param a_r Reciprocal cell vector + /// @param b_r Reciprocal cell vector + /// @param c_r Reciprocal cell vector + /// @param a_p Is this dimension periodic? + /// @param b_p Is this dimension periodic? + /// @param c_p Is this dimension periodic? + /// @return (pos2 - pos1) without periodicity, minimum-image difference otherwise + static cvm::rvector position_distance_kernel(cvm::atom_pos const &pos1, + cvm::atom_pos const &pos2, + cvm::rvector const &a, + cvm::rvector const &b, + cvm::rvector const &c, + cvm::rvector const &a_r, + cvm::rvector const &b_r, + cvm::rvector const &c_r, + bool a_p = false, + bool b_p = false, + bool c_p = false); + + + /// Recompute PBC reciprocal lattice (assumes XYZ periodicity) + void update_pbc_lattice(); + + /// Set the lattice vectors to zero + void reset_pbc_lattice(); + + /// \brief Tell the proxy whether total forces are needed (they may not + /// always be available) + virtual void request_total_force(bool yesno); + + /// Are total forces being used? + virtual bool total_forces_enabled() const; + + /// Are total forces from the current step available? + /// in which case they are really system forces + virtual bool total_forces_same_step() const; + + /// Get the molecule ID when called in VMD; raise error otherwise + /// \param molid Set this argument equal to the current VMD molid + virtual int get_molid(int &molid); + + /// Get value of alchemical lambda parameter from back-end (if available) + virtual int get_alch_lambda(cvm::real* lambda); + + /// Set value of alchemical lambda parameter to be sent to back-end at end of timestep + void set_alch_lambda(cvm::real lambda); + + /// Send cached value of alchemical lambda parameter to back-end (if available) + virtual int send_alch_lambda(); + + /// Request energy computation every freq steps (necessary for NAMD3, not all back-ends) + virtual int request_alch_energy_freq(int const /* freq */) { + return COLVARS_OK; + } + + /// Get energy derivative with respect to lambda (if available) + virtual int get_dE_dlambda(cvm::real* dE_dlambda); + + /// Apply a scalar force on dE_dlambda (back-end distributes it onto atoms) + virtual int apply_force_dE_dlambda(cvm::real* force); + + /// Get energy second derivative with respect to lambda (if available) + virtual int get_d2E_dlambda2(cvm::real* d2E_dlambda2); + + /// Force to be applied onto alch. lambda, propagated from biasing forces on dE_dlambda + cvm::real indirect_lambda_biasing_force; + + /// Get weight factor from accelMD + virtual cvm::real get_accelMD_factor() const { + cvm::error_static(cvmodule, "Error: accessing the reweighting factor of accelerated MD " + "is not yet implemented in the MD engine.\n", + COLVARS_NOT_IMPLEMENTED); + return 1.0; + } + virtual bool accelMD_enabled() const { + return false; + } + #if ( defined(COLVARS_CUDA) || defined(COLVARS_HIP) ) template using allocator_type = colvars_gpu::CudaHostAllocator; @@ -55,12 +237,6 @@ class colvarproxy_atoms { using atom_buffer_real_t = std::vector>; using atom_buffer_rvector_t = std::vector>; - /// Constructor - colvarproxy_atoms(); - - /// Destructor - virtual ~colvarproxy_atoms(); - /// Prepare this atom for collective variables calculation, selecting it by /// numeric index (1-based) virtual int init_atom(int atom_number); @@ -89,7 +265,7 @@ class colvarproxy_atoms { virtual void clear_atom(int index); /// Clear atomic data - int reset(); + int reset_atoms(); /// Get the numeric ID of the given atom /// \param index Internal index in the Colvars arrays @@ -144,7 +320,7 @@ class colvarproxy_atoms { /// Read the current velocity of the given atom inline cvm::rvector get_atom_velocity(int /* index */) { - cvm::error_static("Error: reading the current velocity of an atom " + cvm::error_static(cvmodule, "Error: reading the current velocity of an atom " "is not yet implemented.\n", COLVARS_NOT_IMPLEMENTED); return cvm::rvector(0.0); @@ -260,60 +436,8 @@ class colvarproxy_atoms { return updated_charges_; } -protected: - - /// \brief Array of 0-based integers used to uniquely associate atoms - /// within the host program - std::vector atoms_ids; - /// \brief Keep track of how many times each atom is used by a separate colvar object - std::vector atoms_refcount; - /// \brief Masses of the atoms (allow redefinition during a run, as done e.g. in LAMMPS) - std::vector> atoms_masses; - /// \brief Charges of the atoms (allow redefinition during a run, as done e.g. in LAMMPS) - std::vector> atoms_charges; - /// \brief Current three-dimensional positions of the atoms - std::vector> atoms_positions; - /// \brief Most recent total forces on each atom - std::vector> atoms_total_forces; - /// \brief Forces applied from colvars, to be communicated to the MD integrator - std::vector> atoms_new_colvar_forces; - - /// Root-mean-square of the applied forces - cvm::real atoms_rms_applied_force_; - - /// Maximum norm among all applied forces - cvm::real atoms_max_applied_force_; - - /// ID of the atom with the maximum norm among all applied forces - int atoms_max_applied_force_id_; - - /// Whether the atom list has been modified internally - bool modified_atom_list_; - - /// Whether the masses and charges have been updated from the host code - bool updated_masses_, updated_charges_; - - /// Used by all init_atom() functions: create a slot for an atom not - /// requested yet; returns the index in the arrays - int add_atom_slot(int atom_id); - -}; - - -/// \brief Container of atom group data (allow collection of aggregated atomic -/// data) -class colvarproxy_atom_groups { - -public: - - /// Constructor - colvarproxy_atom_groups(); - - /// Destructor - virtual ~colvarproxy_atom_groups(); - /// Clear atom group data - int reset(); + int reset_atom_groups(); /// \brief Whether this proxy implementation has capability for scalable groups virtual int scalable_group_coms(); @@ -363,7 +487,7 @@ class colvarproxy_atom_groups { /// Read the current velocity of the given atom group inline cvm::rvector get_atom_group_velocity(int /* index */) { - cvm::error_static("Error: reading the current velocity of an atom group is not yet implemented.\n", + cvm::error_static(cvmodule, "Error: reading the current velocity of an atom group is not yet implemented.\n", COLVARS_NOT_IMPLEMENTED); return cvm::rvector(0.0); } @@ -421,53 +545,92 @@ class colvarproxy_atom_groups { return atom_groups_max_applied_force_; } -protected: + /// Clear volumetric map data + int reset_volmaps(); - /// \brief Array of 0-based integers used to uniquely associate atom groups - /// within the host program - std::vector atom_groups_ids; - /// \brief Keep track of how many times each group is used by a separate cvc - std::vector atom_groups_refcount; - /// \brief Total masses of the atom groups - std::vector atom_groups_masses; - /// \brief Total charges of the atom groups (allow redefinition during a run, as done e.g. in LAMMPS) - std::vector atom_groups_charges; - /// \brief Current centers of mass of the atom groups - std::vector atom_groups_coms; - /// \brief Most recently updated total forces on the com of each group - std::vector atom_groups_total_forces; - /// \brief Forces applied from colvars, to be communicated to the MD integrator - std::vector atom_groups_new_colvar_forces; + /// Test whether this implementation can use volumetric maps as CVs + virtual int check_volmaps_available(); - /// Root-mean-square of the applied group forces - cvm::real atom_groups_rms_applied_force_; + /// Create a slot for a volumetric map not requested yet + int add_volmap_slot(int volmap_id); - /// Maximum norm among all applied group forces - cvm::real atom_groups_max_applied_force_; + /// Request and prepare this volumetric map for use by Colvars + /// \param volmap_id Numeric ID used by the MD engine + /// \returns Index of the map in the colvarproxy arrays + virtual int init_volmap_by_id(int volmap_id); - /// Used by all init_atom_group() functions: create a slot for an atom group not requested yet - int add_atom_group_slot(int atom_group_id); -}; + /// Request and prepare this volumetric map for use by Colvars + /// \param volmap_name Name used by the MD engine + /// \returns Index of the map in the colvarproxy arrays + virtual int init_volmap_by_name(char const *volmap_name); + /// Check that the given volmap ID is valid (return COLVARS_OK if it is) + /// \param volmap_id Numeric ID used by the MD engine + /// \returns Error code + virtual int check_volmap_by_id(int volmap_id); -#if defined(_OPENMP) -#include -#else -struct omp_lock_t; -#endif + /// Check that the given volmap name is valid (return COLVARS_OK if it is) + /// \param volmap_name Name used by the MD engine + /// \returns Error code + virtual int check_volmap_by_name(char const *volmap_name); -/// \brief Methods for SMP parallelization -class colvarproxy_smp { + /// Request and prepare this volumetric map for use by Colvars + int init_volmap_by_name(std::string const &volmap_name); -public: + /// Check that the given volmap name is valid (return COLVARS_OK if it is) + int check_volmap_by_name(std::string const &volmap_name); - enum class smp_mode_t {cvcs, inner_loop, gpu, none}; + /// \brief Used by the CVC destructors + virtual void clear_volmap(int index); - /// Constructor - colvarproxy_smp(); + /// Get the numeric ID of the given volumetric map (for the MD program) + virtual int get_volmap_id_from_name(char const *volmap_name); - /// Destructor - virtual ~colvarproxy_smp(); + /// Get the numeric ID of the given volumetric map (for the MD program) + inline int get_volmap_id(int index) const + { + return volmaps_ids[index]; + } + + /// Read the current value of the volumetric map + inline cvm::real get_volmap_value(int index) const + { + return volmaps_values[index]; + } + + /// Request that this force is applied to the given volumetric map + inline void apply_volmap_force(int index, cvm::real const &new_force) + { + volmaps_new_colvar_forces[index] += new_force; + } + + /// Re-weigh an atomic field (e.g. a colvar) by the value of a volumetric map + + /// \param flags Combination of flags + /// \param volmap_id Numeric index of the map (no need to request it) + /// \param ag Pointer to the SOA atom group + /// \param value Pointer to location of total to increment + /// \param atom_field Array of atomic field values (if NULL, ones are used) + virtual int compute_volmap(int flags, + int volmap_id, + cvm::atom_group* ag, + cvm::real *value, + cvm::real *atom_field); + + /// Flags controlling what computation is done on the map + enum { + volmap_flag_null = 0, + volmap_flag_gradients = 1, + volmap_flag_use_atom_field = (1<<8) + }; + + /// Compute the root-mean-square of the applied forces + void compute_rms_volmaps_applied_force(); + + /// Compute the maximum norm among all applied forces + void compute_max_volmaps_applied_force(); + + enum class smp_mode_t {cvcs, inner_loop, gpu, none}; /// Get the current SMP mode virtual smp_mode_t get_smp_mode() const; @@ -505,27 +668,26 @@ class colvarproxy_smp { /// Release the lock virtual int smp_unlock(); -protected: - - /// Lock state for OpenMP - omp_lock_t *omp_lock_state; + /// Set the multiple replicas communicator + virtual void set_replicas_mpi_communicator(replicas_mpi_comm_t comm); - /// Whether threaded parallelization should be used (TODO: make this a - /// cvmodule->deps feature) - smp_mode_t smp_mode; -}; + /// Indicate if multi-replica support is available and active + virtual int check_replicas_enabled(); + /// Index of this replica + virtual int replica_index(); -/// Methods for scripting language interface (Tcl or Python) -class colvarproxy_script { + /// Total number of replicas + virtual int num_replicas(); -public: + /// Synchronize replica with others + virtual void replica_comm_barrier(); - /// Constructor - colvarproxy_script(); + /// Receive data from other replica + virtual int replica_comm_recv(char* msg_data, int buf_len, int src_rep); - /// Destructor - virtual ~colvarproxy_script(); + /// Send data to other replica + virtual int replica_comm_send(char* msg_data, int msg_len, int dest_rep); /// Pointer to the scripting interface object /// (does not need to be allocated in a new interface) @@ -543,27 +705,446 @@ class colvarproxy_script { std::string const &name, std::vector const &cvcs, std::vector > &gradient); -}; + /// Is Tcl available? (trigger initialization if needed) + inline bool tcl_available() { +#if defined(COLVARS_TCL) + return true; +#else + return false; +#endif + } + /// Get a string representation of the Tcl object pointed to by obj + char const *tcl_get_str(void *obj); -/// Interface between Colvars and MD engine (GROMACS, LAMMPS, NAMD, VMD...) -/// -/// This is the base class: each engine is supported by a derived class. -class colvarproxy - : public colvarproxy_system, - public colvarproxy_atoms, - public colvarproxy_atom_groups, - public colvarproxy_volmaps, - public colvarproxy_smp, - public colvarproxy_replicas, - public colvarproxy_script, - public colvarproxy_tcl, - public colvarproxy_io, - public colvarproxy_gpu -{ + int tcl_run_script(std::string const &script); -public: + int tcl_run_file(std::string const &fileName); + + /// Tcl implementation of run_force_callback() + int tcl_run_force_callback(); + + /// Tcl implementation of run_colvar_callback() + int tcl_run_colvar_callback( + std::string const &name, + std::vector const &cvcs, + colvarvalue &value); + + /// Tcl implementation of run_colvar_gradient_callback() + int tcl_run_colvar_gradient_callback( + std::string const &name, + std::vector const &cvcs, + std::vector > &gradient); + + /// Get a pointer to the Tcl interpreter + inline Tcl_Interp *get_tcl_interp() + { + return tcl_interp_; + } + + /// Set the pointer to the Tcl interpreter + inline void set_tcl_interp(Tcl_Interp *interp) + { + tcl_interp_ = interp; + } + + /// Set Tcl pointers + virtual void init_tcl_pointers(); + + /// Ensure that we're on the main thread (derived class will do actual check) + virtual bool io_available(); + + /// \brief Save the current frame number in the argument given + // Returns error code + virtual int get_frame(long int &); + + /// \brief Set the current frame number (as well as cvmodule->it) + // Returns error code + virtual int set_frame(long int); + + /// Get the current working directory of this process + std::string get_current_work_dir() const; + + /// Join two paths using the operating system's path separation + std::string join_paths(std::string const &path1, std::string const &path2) const; + + /// \brief Rename the given file, before overwriting it + virtual int backup_file(char const *filename); + + /// \brief Rename the given file, before overwriting it + inline int backup_file(std::string const &filename) + { + return backup_file(filename.c_str()); + } + + /// Remove the given file (on Windows only, rename to filename.old) + virtual int remove_file(char const *filename); + + /// Remove the given file (on Windows only, rename to filename.old) + inline int remove_file(std::string const &filename) + { + return remove_file(filename.c_str()); + } + + /// Rename the given file + virtual int rename_file(char const *filename, char const *newfilename); + + /// Rename the given file + inline int rename_file(std::string const &filename, + std::string const &newfilename) + { + return rename_file(filename.c_str(), newfilename.c_str()); + } + + /// Prefix of the input state file to be read next + inline std::string const & input_prefix() const + { + return input_prefix_str; + } + + /// Initialize input_prefix (NOTE: it will be erased after state file is read) + virtual int set_input_prefix(std::string const &prefix); + + /// Default prefix to be used for all output files (final configuration) + inline std::string const & output_prefix() const + { + return output_prefix_str; + } + + /// Set default output prefix + virtual int set_output_prefix(std::string const &prefix); + + /// Prefix of the restart (checkpoint) file to be written next + inline std::string const & restart_output_prefix() const + { + return restart_output_prefix_str; + } + + /// Set default restart state file prefix + virtual int set_restart_output_prefix(std::string const &prefix); + + /// Default restart frequency (as set by the simulation engine) + inline int default_restart_frequency() const + { + return restart_frequency_engine; + } + + /// Communicate/set the restart frequency of the simulation engine + virtual int set_default_restart_frequency(int freq); + + // The input stream functions below are not virtual, because they currently + // rely on the fact that either std::ifstream or std::istringstream is used + + /// Returns a reference to given input stream, creating it if needed + /// \param input_name File name (later only a handle) + /// \param description Purpose of the file + /// \param error_on_fail Raise error when failing to open (allow testing) + std::istream & input_stream(std::string const &input_name, + std::string const description = "file/channel", + bool error_on_fail = true); + + /// Returns a reference to given input stream, creating it if needed + /// \param input_name Identifier of the input stream + /// \param content Set this string as the stream's buffer + /// \param description Purpose of the stream + std::istream & input_stream_from_string(std::string const &input_name, + std::string const &content, + std::string const description = "string"); + + /// Check if the file/channel is open (without opening it if not) + bool input_stream_exists(std::string const &input_name); + + /// Closes the given input stream + int close_input_stream(std::string const &input_name); + + /// Closes all input streams + int close_input_streams(); + + /// Same as close_input_stream(), but also removes the corresponding entry from memory + int delete_input_stream(std::string const &input_name); + + /// List all input streams that were opened at some point + std::list list_input_stream_names() const; + + /// Returns a reference to the named output file/channel (open it if needed) + /// \param output_name File name or identifier + /// \param description Purpose of the file + virtual std::ostream &output_stream(std::string const &output_name, + std::string const description); + + /// Check if the file/channel is open (without opening it if not) + virtual bool output_stream_exists(std::string const &output_name); + + /// Flushes the given output file/channel + virtual int flush_output_stream(std::string const &output_name); + + /// Flushes all output files/channels + virtual int flush_output_streams(); + + /// Closes the given output file/channel + virtual int close_output_stream(std::string const &output_name); + + /// Close all open files/channels to prevent data loss + virtual int close_output_streams(); + + /// \brief Whether the proxy supports GPU + bool has_gpu_support() const { + return support_gpu; + } +#if defined (COLVARS_CUDA) || defined (COLVARS_HIP) || defined (COLVARS_SYCL) + /// \brief Get the default CUDA stream from the proxy + virtual cudaStream_t get_default_stream() {return (cudaStream_t)0;} + /** + * @brief Template function to allocate host-pinned memory + * + * @tparam T The type of elements to allocate + * @param[out] pp Pointer to the pointer that will hold the allocated host-pinned memory + * @param[in] len Number of elements to allocate + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int allocate_host(T **pp, const size_t len) { + return allocate_host_T((void **)pp, len, sizeof(T)); + } + /** + * @brief Template function to deallocate host-pinned memory + * + * @tparam T The type of elements to deallocate + * @param[in,out] pp Pointer to the pointer that holds the allocated host-pinned memory + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int deallocate_host(T **pp) { + return deallocate_host_T((void **)pp); + } + /** + * @brief Template function to allocate device memory + * + * @tparam T The type of elements to allocate + * @param[out] pp Pointer to the pointer that will hold the allocated device memory + * @param[in] len Number of elements to allocate + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int allocate_device(T **pp, const size_t len) { + return allocate_device_T((void **)pp, len, sizeof(T)); + } + /** + * @brief Template function to reallocate device memory + * + * This function first deallocates any existing memory pointed to by `*pp`, + * then allocates new device memory for `len` elements of type `T`. + * + * @tparam T The type of elements to allocate + * @param[out] pp Pointer to the pointer that will hold the allocated device memory + * @param[in] len Number of elements to allocate + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int reallocate_device(T **pp, const size_t len) { + int error_code = COLVARS_OK; + error_code |= deallocate_device(pp); + error_code |= allocate_device_T((void **)pp, len, sizeof(T)); + return error_code; + } + /** + * @brief Template function to reallocate host-pinned memory + * + * This function first deallocates any existing memory pointed to by `*pp`, + * then allocates new host-pinned memory for `len` elements of type `T`. + * + * @tparam T The type of elements to allocate + * @param[out] pp Pointer to the pointer that will hold the allocated host-pinned memory + * @param[in] len Number of elements to allocate + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int reallocate_host(T **pp, const size_t len) { + int error_code = COLVARS_OK; + error_code |= deallocate_host(pp); + error_code |= allocate_host_T((void **)pp, len, sizeof(T)); + return error_code; + } + /** + * @brief Template function to allocate device memory asynchronously + * + * @tparam T The type of elements to allocate + * @param[out] pp Pointer to the pointer that will hold the allocated device memory + * @param[in] len Number of elements to allocate + * @param[in] stream The CUDA stream to use for the allocation + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int allocate_device_async(T **pp, const size_t len, cudaStream_t stream) { + return allocate_device_T_async((void **)pp, len, sizeof(T), stream); + } + /** + * @brief Template function to deallocate device memory + * + * @tparam T The type of elements to deallocate + * @param[in,out] pp Pointer to the pointer that holds the allocated device memory + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int deallocate_device(T **pp) { + return deallocate_device_T((void **)pp); + } + /** + * @brief Template function to deallocate device memory asynchronously + * + * @tparam T The type of elements to deallocate + * @param[in,out] pp Pointer to the pointer that holds the allocated device memory + * @param[in] stream The CUDA stream to use for the deallocation + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int deallocate_device_async(T **pp, cudaStream_t stream) { + return deallocate_device_T_async((void **)pp, stream); + } + /** + * @brief Template function to clear a device array to zero + * + * @tparam T The type of elements in the array + * @param[in] data Pointer to the device array to clear + * @param[in] ndata Number of elements in the array + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int clear_device_array(T *data, const size_t ndata) { + return clear_device_array_T(data, ndata, sizeof(T)); + } + /** + * @brief Template function to clear a device array to zero asynchronously + * + * @tparam T The type of elements in the array + * @param[in] data Pointer to the device array to clear + * @param[in] ndata Number of elements in the array + * @param[in] stream The CUDA stream to use for the operation + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int clear_device_array_async(T *data, const size_t ndata, cudaStream_t stream) { + return clear_device_array_T_async(data, ndata, sizeof(T), stream); + } + /** + * @brief Template function to copy data from host to device + * + * @tparam T The type of elements to copy + * @param[in] h_array Pointer to the host array + * @param[in] d_array Pointer to the device array + * @param[in] array_len Number of elements to copy + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int copy_HtoD(const T *h_array, T *d_array, size_t array_len) { + return copy_HtoD_T(h_array, d_array, array_len, sizeof(T)); + } + /** + * @brief Template function to copy data from host to device asynchronously + * + * @tparam T The type of elements to copy + * @param[in] h_array Pointer to the host array + * @param[out] d_array Pointer to the device array + * @param[in] array_len Number of elements to copy + * @param[in] stream The CUDA stream to use for the operation + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int copy_HtoD_async(const T *h_array, T *d_array, size_t array_len, cudaStream_t stream) { + return copy_HtoD_T_async(h_array, d_array, array_len, sizeof(T), stream); + } + /** + * @brief Template function to copy data from device to host + * + * @tparam T The type of elements to copy + * @param[in] d_array Pointer to the device array + * @param[out] h_array Pointer to the host array + * @param[in] array_len Number of elements to copy + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int copy_DtoH(const T *d_array, T *h_array, size_t array_len) { + return copy_DtoH_T(d_array, h_array, array_len, sizeof(T)); + } + /** + * @brief Template function to copy data from device to host asynchronously + * + * @tparam T The type of elements to copy + * @param[in] d_array Pointer to the device array + * @param[out] h_array Pointer to the host array + * @param[in] array_len Number of elements to copy + * @param[in] stream The CUDA stream to use for the operation + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int copy_DtoH_async(const T *d_array, T *h_array, size_t array_len, cudaStream_t stream) { + return copy_DtoH_T_async(d_array, h_array, array_len, sizeof(T), stream); + } + /** + * @brief Template function to copy data from device to device + * + * @tparam T The type of elements to copy + * @param[in] d_src Pointer to the source device array + * @param[out] d_dst Pointer to the destination device array + * @param[in] array_len Number of elements to copy + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int copy_DtoD(const T *d_src, T *d_dst, size_t array_len) { + return copy_DtoD_T(d_src, d_dst, array_len, sizeof(T)); + } + /** + * @brief Template function to copy data from device to device asynchronously + * + * @tparam T The type of elements to copy + * @param[in] d_src Pointer to the source device array + * @param[out] d_dst Pointer to the destination device array + * @param[in] array_len Number of elements to copy + * @param[in] stream The CUDA stream to use for the operation + * @return COLVARS_OK if successful, otherwise COLVARS_ERROR + */ + template + int copy_DtoD_async(const T *d_src, T *d_dst, size_t array_len, cudaStream_t stream) { + return copy_DtoD_T_async(d_src, d_dst, array_len, sizeof(T), stream); + } + /// @brief Memory management and data transfer implementations + /// @{ + virtual int allocate_host_T(void **pp, const size_t len, const size_t sizeofT); + virtual int deallocate_host_T(void **pp); + virtual int allocate_device_T(void **pp, const size_t len, const size_t sizeofT); + virtual int deallocate_device_T(void **pp); + virtual int clear_device_array_T(void *data, const size_t ndata, const size_t sizeofT); + virtual int allocate_device_T_async(void **pp, const size_t len, const size_t sizeofT, cudaStream_t stream); + virtual int deallocate_device_T_async(void **pp, cudaStream_t stream); + virtual int clear_device_array_T_async(void *data, const size_t ndata, const size_t sizeofT, cudaStream_t stream); + virtual int copy_HtoD_T(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT); + virtual int copy_HtoD_T_async(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT, cudaStream_t stream); + virtual int copy_DtoH_T(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT); + virtual int copy_DtoH_T_async(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT, cudaStream_t stream); + virtual int copy_DtoD_T(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT); + virtual int copy_DtoD_T_async(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT, cudaStream_t stream); + /// @} + /// @brief Functions to get device pointers for atom properties + /// This functions should be overridden in derived proxy classes that manage actual GPU memory + /// @{ + virtual float* proxy_atoms_masses_gpu_float() {return nullptr;} + virtual float* proxy_atoms_charges_gpu_float() {return nullptr;} + virtual cvm::real* proxy_atoms_masses_gpu() {return nullptr;} + virtual cvm::real* proxy_atoms_charges_gpu() {return nullptr;} + virtual cvm::real* proxy_atoms_positions_gpu() {return nullptr;} + virtual cvm::real* proxy_atoms_total_forces_gpu() {return nullptr;} + virtual cvm::real* proxy_atoms_new_colvar_forces_gpu() {return nullptr;} + /// @} + /** + * @brief This function will be called after atom groups are calculated on GPU. + * + * This function is useful when additional information is needed to transfer + * from the proxy. For example, the proxy can copy the lattice vectors in a + * separate stream, and this function can wait for that stream to complete. + */ + virtual int wait_for_extra_info_ready(); +#endif // defined (COLVARS_CUDA) || defined (COLVARS_HIP) /// Pointer to the associated colvarmodule object colvarmodule *cvmodule; @@ -572,14 +1153,14 @@ class colvarproxy colvarproxy(); /// Destructor - virtual ~colvarproxy() override; + virtual ~colvarproxy(); inline std::string const &engine_name() const { return engine_name_; } - bool io_available() override; + // bool io_available() override; /// Request deallocation of the module (currently only implemented by VMD) virtual int request_deletion(); @@ -701,6 +1282,186 @@ class colvarproxy protected: + /// Next value of lambda to be sent to back-end + cvm::real cached_alch_lambda; + + /// Whether lambda has been set and needs to be updated in backend + bool cached_alch_lambda_changed; + + /// Boltzmann constant in internal Colvars units + cvm::real boltzmann_; + + /// Most up to date target temperature (K units); default to 0.0 if undefined + cvm::real target_temperature_; + + /// Current integration timestep (engine units); default to 1.0 if undefined + double timestep_; + + /// Current timestep multiplier, if Colvars is only called once every n MD timesteps + int time_step_factor_ = 1; + + /// \brief Value of 1 Angstrom in the internal (front-end) Colvars unit for atomic coordinates + /// * defaults to 0 in the base class; derived proxy classes must set it + /// * in VMD proxy, can only be changed when no variables are defined + /// as user-defined values in composite units must be compatible with that system + cvm::real angstrom_value_; + + /// \brief Value of 1 kcal/mol in the internal Colvars unit for energy + cvm::real kcal_mol_value_; + + /// Whether the total forces have been requested + bool total_force_requested; + + /// Use the PBC functions from the Colvars library (as opposed to MD engine) + bool use_internal_pbc_ = false; + + /// \brief Type of boundary conditions + /// + /// Orthogonal and triclinic cells are made available to objects. + /// For any other conditions (mixed periodicity, triclinic cells in LAMMPS) + /// minimum-image distances are computed by the host engine regardless. + enum Boundaries_type { + boundaries_non_periodic, + boundaries_pbc_ortho, + boundaries_pbc_triclinic, + boundaries_unsupported + }; + + /// Type of boundary conditions + Boundaries_type boundaries_type; + + /// Bravais lattice vectors + cvm::rvector unit_cell_x, unit_cell_y, unit_cell_z; + + /// Reciprocal lattice vectors + cvm::rvector reciprocal_cell_x, reciprocal_cell_y, reciprocal_cell_z; + + /// \brief Array of 0-based integers used to uniquely associate atoms + /// within the host program + std::vector atoms_ids; + /// \brief Keep track of how many times each atom is used by a separate colvar object + std::vector atoms_refcount; + /// \brief Masses of the atoms (allow redefinition during a run, as done e.g. in LAMMPS) + std::vector> atoms_masses; + /// \brief Charges of the atoms (allow redefinition during a run, as done e.g. in LAMMPS) + std::vector> atoms_charges; + /// \brief Current three-dimensional positions of the atoms + std::vector> atoms_positions; + /// \brief Most recent total forces on each atom + std::vector> atoms_total_forces; + /// \brief Forces applied from colvars, to be communicated to the MD integrator + std::vector> atoms_new_colvar_forces; + + /// Root-mean-square of the applied forces + cvm::real atoms_rms_applied_force_; + + /// Maximum norm among all applied forces + cvm::real atoms_max_applied_force_; + + /// ID of the atom with the maximum norm among all applied forces + int atoms_max_applied_force_id_; + + /// Whether the atom list has been modified internally + bool modified_atom_list_; + + /// Whether the masses and charges have been updated from the host code + bool updated_masses_, updated_charges_; + + /// Used by all init_atom() functions: create a slot for an atom not + /// requested yet; returns the index in the arrays + int add_atom_slot(int atom_id); + + /// \brief Array of 0-based integers used to uniquely associate atom groups + /// within the host program + std::vector atom_groups_ids; + /// \brief Keep track of how many times each group is used by a separate cvc + std::vector atom_groups_refcount; + /// \brief Total masses of the atom groups + std::vector atom_groups_masses; + /// \brief Total charges of the atom groups (allow redefinition during a run, as done e.g. in LAMMPS) + std::vector atom_groups_charges; + /// \brief Current centers of mass of the atom groups + std::vector atom_groups_coms; + /// \brief Most recently updated total forces on the com of each group + std::vector atom_groups_total_forces; + /// \brief Forces applied from colvars, to be communicated to the MD integrator + std::vector atom_groups_new_colvar_forces; + + /// Root-mean-square of the applied group forces + cvm::real atom_groups_rms_applied_force_; + + /// Maximum norm among all applied group forces + cvm::real atom_groups_max_applied_force_; + + /// Used by all init_atom_group() functions: create a slot for an atom group not requested yet + int add_atom_group_slot(int atom_group_id); + + /// \brief Array of numeric IDs of volumetric maps + std::vector volmaps_ids; + + /// \brief Keep track of how many times each vol map is used by a + /// separate colvar object + std::vector volmaps_refcount; + + /// \brief Current values of the vol maps + std::vector volmaps_values; + + /// \brief Forces applied from colvars, to be communicated to the MD + /// integrator + std::vector volmaps_new_colvar_forces; + + /// Root-mean-square of the the applied forces + cvm::real volmaps_rms_applied_force_; + + /// Maximum norm among all applied forces + cvm::real volmaps_max_applied_force_; + + /// Lock state for OpenMP + omp_lock_t *omp_lock_state; + + /// Whether threaded parallelization should be used (TODO: make this a + /// cvmodule->deps feature) + smp_mode_t smp_mode; + + /// MPI communicator containint 1 root proc from each world + replicas_mpi_comm_t replicas_mpi_comm; + + /// Index (rank) of this replica in the MPI implementation + int replicas_mpi_rank = 0; + + /// Number of replicas in the MPI implementation + int replicas_mpi_num = 1; + + /// Pointer to Tcl interpreter object + Tcl_Interp *tcl_interp_; + + /// Prefix of the input state file to be read next + std::string input_prefix_str; + + /// Default prefix to be used for all output files (final configuration) + std::string output_prefix_str; + + /// Prefix of the restart (checkpoint) file to be written next + std::string restart_output_prefix_str; + + /// How often the simulation engine will write its own restart + int restart_frequency_engine; + + /// Container of input files/channels indexed by path name + std::map input_streams_; + + /// Object whose reference is returned when read errors occur + std::istream *input_stream_error_; + + /// Currently open output files/channels + std::map output_streams_; + + /// Object whose reference is returned when write errors occur + std::ostream *output_stream_error_; + + /// \brief Whether the proxy supports GPU + bool support_gpu; + /// Whether the engine allows to fully initialize Colvars immediately bool engine_ready_; @@ -727,8 +1488,6 @@ class colvarproxy /// Track which features have been acknowledged during the last run size_t features_hash; -protected: - /// Name of the simulation engine that the derived proxy object supports std::string engine_name_ = "standalone"; @@ -737,5 +1496,57 @@ class colvarproxy }; +inline cvm::rvector colvarproxy::position_distance_internal(cvm::atom_pos const &pos1, + cvm::atom_pos const &pos2) const +{ + if (boundaries_type == boundaries_unsupported) { + cvm::error_static(cvmodule, "Error: unsupported boundary conditions.\n", COLVARS_INPUT_ERROR); + return cvm::rvector({0.0, 0.0, 0.0}); + } + + if (boundaries_type == boundaries_non_periodic) { + return pos2 - pos1; + } + + // Periodicity flags are hard-coded, because this is the only case supported so far other than + // the two above + return position_distance_kernel(pos1, pos2, unit_cell_x, unit_cell_y, unit_cell_z, + reciprocal_cell_x, reciprocal_cell_y, reciprocal_cell_z, + true, true, true); +} + + +inline cvm::rvector colvarproxy::position_distance_kernel(cvm::atom_pos const &pos1, + cvm::atom_pos const &pos2, + cvm::rvector const &a, + cvm::rvector const &b, + cvm::rvector const &c, + cvm::rvector const &a_r, + cvm::rvector const &b_r, + cvm::rvector const &c_r, + bool a_p, + bool b_p, + bool c_p) +{ + cvm::rvector diff = (pos2 - pos1); + + cvm::real const x_shift = std::floor(a_r * diff + 0.5); + cvm::real const y_shift = std::floor(b_r * diff + 0.5); + cvm::real const z_shift = std::floor(c_r * diff + 0.5); + + if (a_p) { + diff.x -= x_shift * a.x + y_shift * b.x + z_shift * c.x; + } + + if (b_p) { + diff.y -= x_shift * a.y + y_shift * b.y + z_shift * c.y; + } + + if (c_p) { + diff.z -= x_shift * a.z + y_shift * b.z + z_shift * c.z; + } + + return diff; +} #endif diff --git a/src/colvarproxy_gpu.cpp b/src/colvarproxy_gpu.cpp index 14a429c6b..411394a29 100644 --- a/src/colvarproxy_gpu.cpp +++ b/src/colvarproxy_gpu.cpp @@ -1,16 +1,16 @@ -#include "colvarproxy_gpu.h" +#include "colvarproxy.h" #include "colvarmodule.h" using namespace colvars_gpu; #if defined (COLVARS_CUDA) || defined (COLVARS_HIP) || defined (COLVARS_SYCL) -int colvarproxy_gpu::allocate_host_T(void **pp, const size_t len, const size_t sizeofT) { +int colvarproxy::allocate_host_T(void **pp, const size_t len, const size_t sizeofT) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMallocHost(pp, sizeofT*len)); return error_code; } -int colvarproxy_gpu::deallocate_host_T(void **pp) { +int colvarproxy::deallocate_host_T(void **pp) { int error_code = COLVARS_OK; if (*pp != nullptr) { error_code |= checkGPUError(cudaFreeHost((void *)(*pp))); @@ -19,13 +19,13 @@ int colvarproxy_gpu::deallocate_host_T(void **pp) { return error_code; } -int colvarproxy_gpu::allocate_device_T(void **pp, const size_t len, const size_t sizeofT) { +int colvarproxy::allocate_device_T(void **pp, const size_t len, const size_t sizeofT) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMalloc(pp, sizeofT*len)); return error_code; } -int colvarproxy_gpu::deallocate_device_T(void **pp) { +int colvarproxy::deallocate_device_T(void **pp) { int error_code = COLVARS_OK; if (*pp != nullptr) { error_code |= checkGPUError(cudaFree((void *)(*pp))); @@ -34,13 +34,13 @@ int colvarproxy_gpu::deallocate_device_T(void **pp) { return error_code; } -int colvarproxy_gpu::allocate_device_T_async(void **pp, const size_t len, const size_t sizeofT, cudaStream_t stream) { +int colvarproxy::allocate_device_T_async(void **pp, const size_t len, const size_t sizeofT, cudaStream_t stream) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMallocAsync(pp, sizeofT*len, stream)); return error_code; } -int colvarproxy_gpu::deallocate_device_T_async(void **pp, cudaStream_t stream) { +int colvarproxy::deallocate_device_T_async(void **pp, cudaStream_t stream) { int error_code = COLVARS_OK; if (*pp != nullptr) { error_code |= checkGPUError(cudaFreeAsync((void *)(*pp), stream)); @@ -49,59 +49,56 @@ int colvarproxy_gpu::deallocate_device_T_async(void **pp, cudaStream_t stream) { return error_code; } -int colvarproxy_gpu::clear_device_array_T(void *data, const size_t ndata, const size_t sizeofT) { +int colvarproxy::clear_device_array_T(void *data, const size_t ndata, const size_t sizeofT) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemset(data, 0, sizeofT*ndata)); return error_code; } -int colvarproxy_gpu::clear_device_array_T_async(void *data, const size_t ndata, const size_t sizeofT, cudaStream_t stream) { +int colvarproxy::clear_device_array_T_async(void *data, const size_t ndata, const size_t sizeofT, cudaStream_t stream) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemsetAsync(data, 0, sizeofT*ndata, stream)); return error_code; } -int colvarproxy_gpu::copy_HtoD_T(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT) { +int colvarproxy::copy_HtoD_T(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemcpy(d_array, h_array, sizeofT*array_len, cudaMemcpyHostToDevice)); return error_code; } -int colvarproxy_gpu::copy_HtoD_T_async(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT, cudaStream_t stream) { +int colvarproxy::copy_HtoD_T_async(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT, cudaStream_t stream) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemcpyAsync(d_array, h_array, sizeofT*array_len, cudaMemcpyHostToDevice, stream)); return error_code; } -int colvarproxy_gpu::copy_DtoH_T(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT) { +int colvarproxy::copy_DtoH_T(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemcpy(h_array, d_array, sizeofT*array_len, cudaMemcpyDeviceToHost)); return error_code; } -int colvarproxy_gpu::copy_DtoH_T_async(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT, cudaStream_t stream) { +int colvarproxy::copy_DtoH_T_async(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT, cudaStream_t stream) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemcpyAsync(h_array, d_array, sizeofT*array_len, cudaMemcpyDeviceToHost, stream)); return error_code; } -int colvarproxy_gpu::copy_DtoD_T(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT) { +int colvarproxy::copy_DtoD_T(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemcpy(d_dst, d_src, sizeofT*array_len, cudaMemcpyDeviceToDevice)); return error_code; } -int colvarproxy_gpu::copy_DtoD_T_async(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT, cudaStream_t stream) { +int colvarproxy::copy_DtoD_T_async(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT, cudaStream_t stream) { int error_code = COLVARS_OK; error_code |= checkGPUError(cudaMemcpyAsync(d_dst, d_src, sizeofT*array_len, cudaMemcpyDeviceToDevice, stream)); return error_code; } -int colvarproxy_gpu::wait_for_extra_info_ready() { +int colvarproxy::wait_for_extra_info_ready() { return COLVARS_OK; } #endif // defined (COLVARS_CUDA) || defined (COLVARS_HIP) - -colvarproxy_gpu::~colvarproxy_gpu() { -} diff --git a/src/colvarproxy_gpu.h b/src/colvarproxy_gpu.h index e9bfac43b..65494ba24 100644 --- a/src/colvarproxy_gpu.h +++ b/src/colvarproxy_gpu.h @@ -1,283 +1,5 @@ #ifndef COLVARPROXY_GPU_H #define COLVARPROXY_GPU_H -#include "colvar_gpu_support.h" -#include "colvarmodule.h" - -/** - * @file colvarproxy_gpu.h - * @brief Declaration of the class for GPU memory management - */ - -/** - * @brief Class for managing GPU memory allocation and data transfer - */ -class colvarproxy_gpu { -public: - /// \brief Constructor - colvarproxy_gpu(): support_gpu(false) {} - /// \brief Whether the proxy supports GPU - bool has_gpu_support() const { - return support_gpu; - } -#if defined (COLVARS_CUDA) || defined (COLVARS_HIP) || defined (COLVARS_SYCL) - /// \brief Get the default CUDA stream from the proxy - virtual cudaStream_t get_default_stream() {return (cudaStream_t)0;} - /** - * @brief Template function to allocate host-pinned memory - * - * @tparam T The type of elements to allocate - * @param[out] pp Pointer to the pointer that will hold the allocated host-pinned memory - * @param[in] len Number of elements to allocate - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int allocate_host(T **pp, const size_t len) { - return allocate_host_T((void **)pp, len, sizeof(T)); - } - /** - * @brief Template function to deallocate host-pinned memory - * - * @tparam T The type of elements to deallocate - * @param[in,out] pp Pointer to the pointer that holds the allocated host-pinned memory - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int deallocate_host(T **pp) { - return deallocate_host_T((void **)pp); - } - /** - * @brief Template function to allocate device memory - * - * @tparam T The type of elements to allocate - * @param[out] pp Pointer to the pointer that will hold the allocated device memory - * @param[in] len Number of elements to allocate - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int allocate_device(T **pp, const size_t len) { - return allocate_device_T((void **)pp, len, sizeof(T)); - } - /** - * @brief Template function to reallocate device memory - * - * This function first deallocates any existing memory pointed to by `*pp`, - * then allocates new device memory for `len` elements of type `T`. - * - * @tparam T The type of elements to allocate - * @param[out] pp Pointer to the pointer that will hold the allocated device memory - * @param[in] len Number of elements to allocate - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int reallocate_device(T **pp, const size_t len) { - int error_code = COLVARS_OK; - error_code |= deallocate_device(pp); - error_code |= allocate_device_T((void **)pp, len, sizeof(T)); - return error_code; - } - /** - * @brief Template function to reallocate host-pinned memory - * - * This function first deallocates any existing memory pointed to by `*pp`, - * then allocates new host-pinned memory for `len` elements of type `T`. - * - * @tparam T The type of elements to allocate - * @param[out] pp Pointer to the pointer that will hold the allocated host-pinned memory - * @param[in] len Number of elements to allocate - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int reallocate_host(T **pp, const size_t len) { - int error_code = COLVARS_OK; - error_code |= deallocate_host(pp); - error_code |= allocate_host_T((void **)pp, len, sizeof(T)); - return error_code; - } - /** - * @brief Template function to allocate device memory asynchronously - * - * @tparam T The type of elements to allocate - * @param[out] pp Pointer to the pointer that will hold the allocated device memory - * @param[in] len Number of elements to allocate - * @param[in] stream The CUDA stream to use for the allocation - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int allocate_device_async(T **pp, const size_t len, cudaStream_t stream) { - return allocate_device_T_async((void **)pp, len, sizeof(T), stream); - } - /** - * @brief Template function to deallocate device memory - * - * @tparam T The type of elements to deallocate - * @param[in,out] pp Pointer to the pointer that holds the allocated device memory - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int deallocate_device(T **pp) { - return deallocate_device_T((void **)pp); - } - /** - * @brief Template function to deallocate device memory asynchronously - * - * @tparam T The type of elements to deallocate - * @param[in,out] pp Pointer to the pointer that holds the allocated device memory - * @param[in] stream The CUDA stream to use for the deallocation - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int deallocate_device_async(T **pp, cudaStream_t stream) { - return deallocate_device_T_async((void **)pp, stream); - } - /** - * @brief Template function to clear a device array to zero - * - * @tparam T The type of elements in the array - * @param[in] data Pointer to the device array to clear - * @param[in] ndata Number of elements in the array - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int clear_device_array(T *data, const size_t ndata) { - return clear_device_array_T(data, ndata, sizeof(T)); - } - /** - * @brief Template function to clear a device array to zero asynchronously - * - * @tparam T The type of elements in the array - * @param[in] data Pointer to the device array to clear - * @param[in] ndata Number of elements in the array - * @param[in] stream The CUDA stream to use for the operation - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int clear_device_array_async(T *data, const size_t ndata, cudaStream_t stream) { - return clear_device_array_T_async(data, ndata, sizeof(T), stream); - } - /** - * @brief Template function to copy data from host to device - * - * @tparam T The type of elements to copy - * @param[in] h_array Pointer to the host array - * @param[in] d_array Pointer to the device array - * @param[in] array_len Number of elements to copy - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int copy_HtoD(const T *h_array, T *d_array, size_t array_len) { - return copy_HtoD_T(h_array, d_array, array_len, sizeof(T)); - } - /** - * @brief Template function to copy data from host to device asynchronously - * - * @tparam T The type of elements to copy - * @param[in] h_array Pointer to the host array - * @param[out] d_array Pointer to the device array - * @param[in] array_len Number of elements to copy - * @param[in] stream The CUDA stream to use for the operation - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int copy_HtoD_async(const T *h_array, T *d_array, size_t array_len, cudaStream_t stream) { - return copy_HtoD_T_async(h_array, d_array, array_len, sizeof(T), stream); - } - /** - * @brief Template function to copy data from device to host - * - * @tparam T The type of elements to copy - * @param[in] d_array Pointer to the device array - * @param[out] h_array Pointer to the host array - * @param[in] array_len Number of elements to copy - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int copy_DtoH(const T *d_array, T *h_array, size_t array_len) { - return copy_DtoH_T(d_array, h_array, array_len, sizeof(T)); - } - /** - * @brief Template function to copy data from device to host asynchronously - * - * @tparam T The type of elements to copy - * @param[in] d_array Pointer to the device array - * @param[out] h_array Pointer to the host array - * @param[in] array_len Number of elements to copy - * @param[in] stream The CUDA stream to use for the operation - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int copy_DtoH_async(const T *d_array, T *h_array, size_t array_len, cudaStream_t stream) { - return copy_DtoH_T_async(d_array, h_array, array_len, sizeof(T), stream); - } - /** - * @brief Template function to copy data from device to device - * - * @tparam T The type of elements to copy - * @param[in] d_src Pointer to the source device array - * @param[out] d_dst Pointer to the destination device array - * @param[in] array_len Number of elements to copy - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int copy_DtoD(const T *d_src, T *d_dst, size_t array_len) { - return copy_DtoD_T(d_src, d_dst, array_len, sizeof(T)); - } - /** - * @brief Template function to copy data from device to device asynchronously - * - * @tparam T The type of elements to copy - * @param[in] d_src Pointer to the source device array - * @param[out] d_dst Pointer to the destination device array - * @param[in] array_len Number of elements to copy - * @param[in] stream The CUDA stream to use for the operation - * @return COLVARS_OK if successful, otherwise COLVARS_ERROR - */ - template - int copy_DtoD_async(const T *d_src, T *d_dst, size_t array_len, cudaStream_t stream) { - return copy_DtoD_T_async(d_src, d_dst, array_len, sizeof(T), stream); - } - /// @brief Memory management and data transfer implementations - /// @{ - virtual int allocate_host_T(void **pp, const size_t len, const size_t sizeofT); - virtual int deallocate_host_T(void **pp); - virtual int allocate_device_T(void **pp, const size_t len, const size_t sizeofT); - virtual int deallocate_device_T(void **pp); - virtual int clear_device_array_T(void *data, const size_t ndata, const size_t sizeofT); - virtual int allocate_device_T_async(void **pp, const size_t len, const size_t sizeofT, cudaStream_t stream); - virtual int deallocate_device_T_async(void **pp, cudaStream_t stream); - virtual int clear_device_array_T_async(void *data, const size_t ndata, const size_t sizeofT, cudaStream_t stream); - virtual int copy_HtoD_T(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT); - virtual int copy_HtoD_T_async(const void *h_array, void *d_array, size_t array_len, const size_t sizeofT, cudaStream_t stream); - virtual int copy_DtoH_T(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT); - virtual int copy_DtoH_T_async(const void *d_array, void *h_array, size_t array_len, const size_t sizeofT, cudaStream_t stream); - virtual int copy_DtoD_T(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT); - virtual int copy_DtoD_T_async(const void *d_src, void *d_dst, size_t array_len, const size_t sizeofT, cudaStream_t stream); - /// @} - /// @brief Functions to get device pointers for atom properties - /// This functions should be overridden in derived proxy classes that manage actual GPU memory - /// @{ - virtual float* proxy_atoms_masses_gpu_float() {return nullptr;} - virtual float* proxy_atoms_charges_gpu_float() {return nullptr;} - virtual cvm::real* proxy_atoms_masses_gpu() {return nullptr;} - virtual cvm::real* proxy_atoms_charges_gpu() {return nullptr;} - virtual cvm::real* proxy_atoms_positions_gpu() {return nullptr;} - virtual cvm::real* proxy_atoms_total_forces_gpu() {return nullptr;} - virtual cvm::real* proxy_atoms_new_colvar_forces_gpu() {return nullptr;} - /// @} - /** - * @brief This function will be called after atom groups are calculated on GPU. - * - * This function is useful when additional information is needed to transfer - * from the proxy. For example, the proxy can copy the lattice vectors in a - * separate stream, and this function can wait for that stream to complete. - */ - virtual int wait_for_extra_info_ready(); -#endif // defined (COLVARS_CUDA) || defined (COLVARS_HIP) - /// \brief Destructor - virtual ~colvarproxy_gpu(); -protected: - /// \brief Whether the proxy supports GPU - bool support_gpu; -}; #endif // COLVARPROXY_GPU_H diff --git a/src/colvarproxy_io.cpp b/src/colvarproxy_io.cpp index 015a7699e..b61b24313 100644 --- a/src/colvarproxy_io.cpp +++ b/src/colvarproxy_io.cpp @@ -7,6 +7,19 @@ // If you wish to distribute your changes, please submit them to the // Colvars repository at GitHub. + + +#include +#include + +#include +#include +#include +#include + +#include "colvarmodule.h" +#include "colvarproxy.h" + #if defined(__cplusplus) && __cplusplus >= 202002L #include #endif @@ -32,56 +45,19 @@ #include #endif -#include -#include - -#include -#include -#include -#include - -#include "colvarmodule.h" -#include "colvarproxy_io.h" - - -colvarproxy_io::colvarproxy_io() -{ - restart_frequency_engine = 0; - input_stream_error_ = new std::istringstream(); - input_stream_error_->setstate(std::ios::badbit); - output_stream_error_ = new std::ostringstream(); - output_stream_error_->setstate(std::ios::badbit); -} - - -colvarproxy_io::~colvarproxy_io() -{ - delete input_stream_error_; - close_input_streams(); - delete output_stream_error_; - close_output_streams(); -} - - -bool colvarproxy_io::io_available() -{ - return false; -} - - -int colvarproxy_io::get_frame(long int&) +int colvarproxy::get_frame(long int&) { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_io::set_frame(long int) +int colvarproxy::set_frame(long int) { return COLVARS_NOT_IMPLEMENTED; } -std::string colvarproxy_io::get_current_work_dir() const +std::string colvarproxy::get_current_work_dir() const { #ifdef __cpp_lib_filesystem @@ -109,7 +85,7 @@ std::string colvarproxy_io::get_current_work_dir() const } -std::string colvarproxy_io::join_paths(std::string const &path1, std::string const &path2) const +std::string colvarproxy::join_paths(std::string const &path1, std::string const &path2) const { #ifdef __cpp_lib_filesystem @@ -128,7 +104,7 @@ std::string colvarproxy_io::join_paths(std::string const &path1, std::string con } -int colvarproxy_io::backup_file(char const *filename) +int colvarproxy::backup_file(char const *filename) { // Simplified version of NAMD_file_exists() int exit_code; @@ -145,7 +121,7 @@ int colvarproxy_io::backup_file(char const *filename) // File does not exist return COLVARS_OK; } else { - return cvm::error_static("Unknown error while checking if file \""+ + return cvm::error_static(cvmodule, "Unknown error while checking if file \""+ std::string(filename)+"\" exists.\n", COLVARS_ERROR); } } @@ -160,7 +136,7 @@ int colvarproxy_io::backup_file(char const *filename) } -int colvarproxy_io::remove_file(char const *filename) +int colvarproxy::remove_file(char const *filename) { int error_code = COLVARS_OK; #if defined(_WIN32) && !defined(__CYGWIN__) @@ -185,7 +161,7 @@ int colvarproxy_io::remove_file(char const *filename) } #endif if (error_code != COLVARS_OK) { - return cvm::error_static("Error: in removing file \""+std::string(filename)+ + return cvm::error_static(cvmodule, "Error: in removing file \""+std::string(filename)+ "\".\n.", error_code); } @@ -193,7 +169,7 @@ int colvarproxy_io::remove_file(char const *filename) } -int colvarproxy_io::rename_file(char const *filename, char const *newfilename) +int colvarproxy::rename_file(char const *filename, char const *newfilename) { int error_code = COLVARS_OK; #if defined(_WIN32) && !defined(__CYGWIN__) @@ -202,11 +178,12 @@ int colvarproxy_io::rename_file(char const *filename, char const *newfilename) error_code |= remove_file(newfilename); } #endif + if (!cvmodule) return COLVARS_BUG_ERROR; int rename_exit_code = 0; while ((rename_exit_code = std::rename(filename, newfilename)) != 0) { if (errno == EINTR) continue; // Call log() instead of error to allow the next try - cvm::main()->log("Error: in renaming file \""+std::string(filename)+"\" to \""+ + cvmodule->log("Error: in renaming file \""+std::string(filename)+"\" to \""+ std::string(newfilename)+"\".\n."); error_code |= COLVARS_FILE_ERROR; if (errno == EXDEV) continue; @@ -216,7 +193,7 @@ int colvarproxy_io::rename_file(char const *filename, char const *newfilename) } -int colvarproxy_io::set_input_prefix(std::string const &prefix) +int colvarproxy::set_input_prefix(std::string const &prefix) { // set input restart name and strip the extension, if present input_prefix_str = prefix; @@ -228,7 +205,7 @@ int colvarproxy_io::set_input_prefix(std::string const &prefix) } -int colvarproxy_io::set_output_prefix(std::string const &prefix) +int colvarproxy::set_output_prefix(std::string const &prefix) { // set input restart name and strip the extension, if present output_prefix_str = prefix; @@ -240,7 +217,7 @@ int colvarproxy_io::set_output_prefix(std::string const &prefix) } -int colvarproxy_io::set_restart_output_prefix(std::string const &prefix) +int colvarproxy::set_restart_output_prefix(std::string const &prefix) { // set input restart name and strip the extension, if present restart_output_prefix_str = prefix; @@ -252,7 +229,7 @@ int colvarproxy_io::set_restart_output_prefix(std::string const &prefix) } -int colvarproxy_io::set_default_restart_frequency(int freq) +int colvarproxy::set_default_restart_frequency(int freq) { // TODO check for compatibility with colvarsRestartFrequency restart_frequency_engine = freq; @@ -261,17 +238,17 @@ int colvarproxy_io::set_default_restart_frequency(int freq) -std::istream &colvarproxy_io::input_stream(std::string const &input_name, +std::istream &colvarproxy::input_stream(std::string const &input_name, std::string const description, bool error_on_fail) { if (!io_available()) { - cvm::error_static("Error: trying to access an input file/channel " + cvm::error_static(cvmodule, "Error: trying to access an input file/channel " "from the wrong thread.\n", COLVARS_BUG_ERROR); return *input_stream_error_; } - if (colvarproxy_io::input_stream_exists(input_name)) { + if (colvarproxy::input_stream_exists(input_name)) { std::ifstream *ifs = dynamic_cast(input_streams_[input_name]); if (ifs && !ifs->is_open()) { @@ -286,7 +263,7 @@ std::istream &colvarproxy_io::input_stream(std::string const &input_name, } if (input_streams_[input_name]->fail() && error_on_fail) { - cvm::error_static("Error: cannot open "+description+" \""+input_name+"\".\n", + cvm::error_static(cvmodule, "Error: cannot open "+description+" \""+input_name+"\".\n", COLVARS_FILE_ERROR); } @@ -295,17 +272,17 @@ std::istream &colvarproxy_io::input_stream(std::string const &input_name, std::istream & -colvarproxy_io::input_stream_from_string(std::string const &input_name, +colvarproxy::input_stream_from_string(std::string const &input_name, std::string const &content, std::string const description) { if (!io_available()) { - cvm::error_static("Error: trying to access an input file/channel " + cvm::error_static(cvmodule, "Error: trying to access an input file/channel " "from the wrong thread.\n", COLVARS_BUG_ERROR); return *input_stream_error_; } - if (colvarproxy_io::input_stream_exists(input_name)) { + if (colvarproxy::input_stream_exists(input_name)) { std::istringstream *iss = dynamic_cast(input_streams_[input_name]); @@ -329,15 +306,15 @@ colvarproxy_io::input_stream_from_string(std::string const &input_name, } -bool colvarproxy_io::input_stream_exists(std::string const &input_name) +bool colvarproxy::input_stream_exists(std::string const &input_name) { return (input_streams_.count(input_name) > 0); } -int colvarproxy_io::close_input_stream(std::string const &input_name) +int colvarproxy::close_input_stream(std::string const &input_name) { - if (colvarproxy_io::input_stream_exists(input_name)) { + if (colvarproxy::input_stream_exists(input_name)) { std::ifstream *ifs = dynamic_cast(input_streams_[input_name]); if (ifs) { if (ifs->is_open()) { @@ -353,14 +330,14 @@ int colvarproxy_io::close_input_stream(std::string const &input_name) } return COLVARS_OK; } - return cvm::error_static("Error: input file/channel \""+input_name+ + return cvm::error_static(cvmodule, "Error: input file/channel \""+input_name+ "\" does not exist.\n", COLVARS_FILE_ERROR); } -int colvarproxy_io::delete_input_stream(std::string const &input_name) +int colvarproxy::delete_input_stream(std::string const &input_name) { - if (colvarproxy_io::close_input_stream(input_name) == COLVARS_OK) { + if (colvarproxy::close_input_stream(input_name) == COLVARS_OK) { std::ifstream *ifs = dynamic_cast(input_streams_[input_name]); if (ifs) { delete ifs; @@ -373,12 +350,12 @@ int colvarproxy_io::delete_input_stream(std::string const &input_name) input_streams_.erase(input_name); return COLVARS_OK; } - return cvm::error_static("Error: input file/channel \""+input_name+ + return cvm::error_static(cvmodule, "Error: input file/channel \""+input_name+ "\" does not exist.\n", COLVARS_FILE_ERROR); } -int colvarproxy_io::close_input_streams() +int colvarproxy::close_input_streams() { for (std::map::iterator ii = input_streams_.begin(); @@ -391,7 +368,7 @@ int colvarproxy_io::close_input_streams() } -std::list colvarproxy_io::list_input_stream_names() const +std::list colvarproxy::list_input_stream_names() const { std::list result; for (std::map colvarproxy_io::list_input_stream_names() const } -std::ostream & colvarproxy_io::output_stream(std::string const &output_name, +std::ostream & colvarproxy::output_stream(std::string const &output_name, std::string const description) { if (cvm::debug()) { - cvm::main()->log("Using colvarproxy_io::output_stream()\n"); + cvm::log_static(cvmodule, "Using colvarproxy_io::output_stream()\n"); } if (!io_available()) { - cvm::error_static("Error: trying to access an output file/channel " + cvm::error_static(cvmodule, "Error: trying to access an output file/channel " "from the wrong thread.\n", COLVARS_BUG_ERROR); return *output_stream_error_; } - if (colvarproxy_io::output_stream_exists(output_name)) { + if (colvarproxy::output_stream_exists(output_name)) { return *(output_streams_[output_name]); } @@ -425,7 +402,7 @@ std::ostream & colvarproxy_io::output_stream(std::string const &output_name, output_streams_[output_name] = new std::ofstream(output_name.c_str(), std::ios::binary); if (!*(output_streams_[output_name])) { - cvm::error_static("Error: cannot write to "+description+" \""+output_name+"\".\n", + cvm::error_static(cvmodule, "Error: cannot write to "+description+" \""+output_name+"\".\n", COLVARS_FILE_ERROR); } @@ -433,20 +410,20 @@ std::ostream & colvarproxy_io::output_stream(std::string const &output_name, } -bool colvarproxy_io::output_stream_exists(std::string const &output_name) +bool colvarproxy::output_stream_exists(std::string const &output_name) { return (output_streams_.count(output_name) > 0); } -int colvarproxy_io::flush_output_stream(std::string const &output_name) +int colvarproxy::flush_output_stream(std::string const &output_name) { if (!io_available()) { // No-op return COLVARS_OK; } - if (colvarproxy_io::output_stream_exists(output_name)) { + if (colvarproxy::output_stream_exists(output_name)) { (dynamic_cast(output_streams_[output_name]))->flush(); return COLVARS_OK; } @@ -455,7 +432,7 @@ int colvarproxy_io::flush_output_stream(std::string const &output_name) } -int colvarproxy_io::flush_output_streams() +int colvarproxy::flush_output_streams() { if (!io_available()) { return COLVARS_OK; @@ -471,14 +448,14 @@ int colvarproxy_io::flush_output_streams() } -int colvarproxy_io::close_output_stream(std::string const &output_name) +int colvarproxy::close_output_stream(std::string const &output_name) { if (!io_available()) { - return cvm::error_static("Error: trying to access an output file/channel " + return cvm::error_static(cvmodule, "Error: trying to access an output file/channel " "from the wrong thread.\n", COLVARS_BUG_ERROR); } - if (colvarproxy_io::output_stream_exists(output_name)) { + if (colvarproxy::output_stream_exists(output_name)) { (dynamic_cast(output_streams_[output_name]))->close(); delete output_streams_[output_name]; output_streams_.erase(output_name); @@ -488,7 +465,7 @@ int colvarproxy_io::close_output_stream(std::string const &output_name) } -int colvarproxy_io::close_output_streams() +int colvarproxy::close_output_streams() { if (! io_available()) { return COLVARS_OK; diff --git a/src/colvarproxy_io.h b/src/colvarproxy_io.h index 2d2492a0c..7707b3545 100644 --- a/src/colvarproxy_io.h +++ b/src/colvarproxy_io.h @@ -10,185 +10,5 @@ #ifndef COLVARPROXY_IO_H #define COLVARPROXY_IO_H -#include -#include -#include -#include - - -/// Methods for data input/output -class colvarproxy_io { - -public: - - /// Constructor - colvarproxy_io(); - - /// Destructor - virtual ~colvarproxy_io(); - - /// Ensure that we're on the main thread (derived class will do actual check) - virtual bool io_available(); - - /// \brief Save the current frame number in the argument given - // Returns error code - virtual int get_frame(long int &); - - /// \brief Set the current frame number (as well as cvmodule->it) - // Returns error code - virtual int set_frame(long int); - - /// Get the current working directory of this process - std::string get_current_work_dir() const; - - /// Join two paths using the operating system's path separation - std::string join_paths(std::string const &path1, std::string const &path2) const; - - /// \brief Rename the given file, before overwriting it - virtual int backup_file(char const *filename); - - /// \brief Rename the given file, before overwriting it - inline int backup_file(std::string const &filename) - { - return backup_file(filename.c_str()); - } - - /// Remove the given file (on Windows only, rename to filename.old) - virtual int remove_file(char const *filename); - - /// Remove the given file (on Windows only, rename to filename.old) - inline int remove_file(std::string const &filename) - { - return remove_file(filename.c_str()); - } - - /// Rename the given file - virtual int rename_file(char const *filename, char const *newfilename); - - /// Rename the given file - inline int rename_file(std::string const &filename, - std::string const &newfilename) - { - return rename_file(filename.c_str(), newfilename.c_str()); - } - - /// Prefix of the input state file to be read next - inline std::string const & input_prefix() const - { - return input_prefix_str; - } - - /// Initialize input_prefix (NOTE: it will be erased after state file is read) - virtual int set_input_prefix(std::string const &prefix); - - /// Default prefix to be used for all output files (final configuration) - inline std::string const & output_prefix() const - { - return output_prefix_str; - } - - /// Set default output prefix - virtual int set_output_prefix(std::string const &prefix); - - /// Prefix of the restart (checkpoint) file to be written next - inline std::string const & restart_output_prefix() const - { - return restart_output_prefix_str; - } - - /// Set default restart state file prefix - virtual int set_restart_output_prefix(std::string const &prefix); - - /// Default restart frequency (as set by the simulation engine) - inline int default_restart_frequency() const - { - return restart_frequency_engine; - } - - /// Communicate/set the restart frequency of the simulation engine - virtual int set_default_restart_frequency(int freq); - - // The input stream functions below are not virtual, because they currently - // rely on the fact that either std::ifstream or std::istringstream is used - - /// Returns a reference to given input stream, creating it if needed - /// \param input_name File name (later only a handle) - /// \param description Purpose of the file - /// \param error_on_fail Raise error when failing to open (allow testing) - std::istream & input_stream(std::string const &input_name, - std::string const description = "file/channel", - bool error_on_fail = true); - - /// Returns a reference to given input stream, creating it if needed - /// \param input_name Identifier of the input stream - /// \param content Set this string as the stream's buffer - /// \param description Purpose of the stream - std::istream & input_stream_from_string(std::string const &input_name, - std::string const &content, - std::string const description = "string"); - - /// Check if the file/channel is open (without opening it if not) - bool input_stream_exists(std::string const &input_name); - - /// Closes the given input stream - int close_input_stream(std::string const &input_name); - - /// Closes all input streams - int close_input_streams(); - - /// Same as close_input_stream(), but also removes the corresponding entry from memory - int delete_input_stream(std::string const &input_name); - - /// List all input streams that were opened at some point - std::list list_input_stream_names() const; - - /// Returns a reference to the named output file/channel (open it if needed) - /// \param output_name File name or identifier - /// \param description Purpose of the file - virtual std::ostream &output_stream(std::string const &output_name, - std::string const description); - - /// Check if the file/channel is open (without opening it if not) - virtual bool output_stream_exists(std::string const &output_name); - - /// Flushes the given output file/channel - virtual int flush_output_stream(std::string const &output_name); - - /// Flushes all output files/channels - virtual int flush_output_streams(); - - /// Closes the given output file/channel - virtual int close_output_stream(std::string const &output_name); - - /// Close all open files/channels to prevent data loss - virtual int close_output_streams(); - -protected: - - /// Prefix of the input state file to be read next - std::string input_prefix_str; - - /// Default prefix to be used for all output files (final configuration) - std::string output_prefix_str; - - /// Prefix of the restart (checkpoint) file to be written next - std::string restart_output_prefix_str; - - /// How often the simulation engine will write its own restart - int restart_frequency_engine; - - /// Container of input files/channels indexed by path name - std::map input_streams_; - - /// Object whose reference is returned when read errors occur - std::istream *input_stream_error_; - - /// Currently open output files/channels - std::map output_streams_; - - /// Object whose reference is returned when write errors occur - std::ostream *output_stream_error_; -}; - #endif diff --git a/src/colvarproxy_replicas.cpp b/src/colvarproxy_replicas.cpp index 342ad3752..e957b9f2a 100644 --- a/src/colvarproxy_replicas.cpp +++ b/src/colvarproxy_replicas.cpp @@ -9,35 +9,24 @@ #include "colvarmodule.h" -#include "colvarproxy_replicas.h" +#include "colvarproxy.h" -colvarproxy_replicas::colvarproxy_replicas() -{ -#ifdef COLVARS_MPI - replicas_mpi_comm = MPI_COMM_NULL; -#endif -} - - -colvarproxy_replicas::~colvarproxy_replicas() {} - - -void colvarproxy_replicas::set_replicas_mpi_communicator(replicas_mpi_comm_t comm) +void colvarproxy::set_replicas_mpi_communicator(replicas_mpi_comm_t comm) { replicas_mpi_comm = comm; #ifdef COLVARS_MPI if (comm != MPI_COMM_NULL) { MPI_Comm_rank(comm, &replicas_mpi_rank); MPI_Comm_size(comm, &replicas_mpi_num); - cvm::log_static("Enabling multiple replicas: this is replica number " + + cvm::log_static(cvmodule, "Enabling multiple replicas: this is replica number " + cvm::to_str(replica_index() + 1) + " of " + cvm::to_str(num_replicas()) + ".\n"); } #endif } -int colvarproxy_replicas::check_replicas_enabled() +int colvarproxy::check_replicas_enabled() { #ifdef COLVARS_MPI if (replicas_mpi_comm != MPI_COMM_NULL) { @@ -50,19 +39,19 @@ int colvarproxy_replicas::check_replicas_enabled() } -int colvarproxy_replicas::replica_index() +int colvarproxy::replica_index() { return replicas_mpi_rank; } -int colvarproxy_replicas::num_replicas() +int colvarproxy::num_replicas() { return replicas_mpi_num; } -void colvarproxy_replicas::replica_comm_barrier() +void colvarproxy::replica_comm_barrier() { #ifdef COLVARS_MPI MPI_Barrier(replicas_mpi_comm); @@ -70,7 +59,7 @@ void colvarproxy_replicas::replica_comm_barrier() } -int colvarproxy_replicas::replica_comm_recv(char *buffer, int buffer_length, int source_rank) +int colvarproxy::replica_comm_recv(char *buffer, int buffer_length, int source_rank) { #ifdef COLVARS_MPI MPI_Status status; @@ -90,7 +79,7 @@ int colvarproxy_replicas::replica_comm_recv(char *buffer, int buffer_length, int } -int colvarproxy_replicas::replica_comm_send(char *buffer, int buffer_length, int destination_rank) +int colvarproxy::replica_comm_send(char *buffer, int buffer_length, int destination_rank) { #ifdef COLVARS_MPI int retval = MPI_Send(buffer, buffer_length, MPI_CHAR, destination_rank, 0, replicas_mpi_comm); diff --git a/src/colvarproxy_replicas.h b/src/colvarproxy_replicas.h index b58c80bf5..880b23b27 100644 --- a/src/colvarproxy_replicas.h +++ b/src/colvarproxy_replicas.h @@ -11,56 +11,4 @@ #define COLVARPROXY_REPLICAS_H -#ifdef COLVARS_MPI -#include -typedef MPI_Comm replicas_mpi_comm_t; -#else -typedef void * replicas_mpi_comm_t; -#endif - - -/// \brief Methods for multiple-replica communication -class colvarproxy_replicas { - -public: - - /// Constructor - colvarproxy_replicas(); - - /// Destructor - virtual ~colvarproxy_replicas(); - - /// Set the multiple replicas communicator - virtual void set_replicas_mpi_communicator(replicas_mpi_comm_t comm); - - /// Indicate if multi-replica support is available and active - virtual int check_replicas_enabled(); - - /// Index of this replica - virtual int replica_index(); - - /// Total number of replicas - virtual int num_replicas(); - - /// Synchronize replica with others - virtual void replica_comm_barrier(); - - /// Receive data from other replica - virtual int replica_comm_recv(char* msg_data, int buf_len, int src_rep); - - /// Send data to other replica - virtual int replica_comm_send(char* msg_data, int msg_len, int dest_rep); - -protected: - - /// MPI communicator containint 1 root proc from each world - replicas_mpi_comm_t replicas_mpi_comm; - - /// Index (rank) of this replica in the MPI implementation - int replicas_mpi_rank = 0; - - /// Number of replicas in the MPI implementation - int replicas_mpi_num = 1; -}; - #endif diff --git a/src/colvarproxy_system.cpp b/src/colvarproxy_system.cpp index 1daf31750..132c5b7f9 100644 --- a/src/colvarproxy_system.cpp +++ b/src/colvarproxy_system.cpp @@ -11,92 +11,78 @@ #include "colvarmodule.h" #include "colvartypes.h" -#include "colvarproxy_system.h" +#include "colvarproxy.h" - -colvarproxy_system::colvarproxy_system() -{ - angstrom_value_ = 0.0; - kcal_mol_value_ = 0.0; - timestep_ = 1.0; - target_temperature_ = 0.0; - boltzmann_ = 0.001987191; // Default: kcal/mol/K - boundaries_type = boundaries_unsupported; - total_force_requested = false; - indirect_lambda_biasing_force = 0.0; - cached_alch_lambda_changed = false; - cached_alch_lambda = -1.0; - reset_pbc_lattice(); -} - - -colvarproxy_system::~colvarproxy_system() {} - - -int colvarproxy_system::set_unit_system(std::string const & /* units */, +int colvarproxy::set_unit_system(std::string const & /* units */, bool /* check_only */) { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_system::set_target_temperature(cvm::real T) +int colvarproxy::set_target_temperature(cvm::real T) { target_temperature_ = T; return COLVARS_OK; } -int colvarproxy_system::set_integration_timestep(cvm::real dt) +int colvarproxy::set_integration_timestep(cvm::real dt) { timestep_ = dt; return COLVARS_OK; } -int colvarproxy_system::set_time_step_factor(int fact) +int colvarproxy::set_time_step_factor(int fact) { time_step_factor_ = fact; return COLVARS_OK; } -cvm::real colvarproxy_system::rand_gaussian() +cvm::real colvarproxy::rand_gaussian() { // TODO define, document and implement a user method to set the value of this return 0.0; } -void colvarproxy_system::add_energy(cvm::real /* energy */) {} +void colvarproxy::add_energy(cvm::real /* energy */) {} -void colvarproxy_system::request_total_force(bool yesno) +void colvarproxy::request_total_force(bool yesno) { if (yesno == true) - cvm::error_static("Error: total forces are currently not implemented.\n", + cvm::error_static(cvmodule, "Error: total forces are currently not implemented.\n", COLVARS_NOT_IMPLEMENTED); } -bool colvarproxy_system::total_forces_enabled() const +bool colvarproxy::total_forces_enabled() const { return false; } -bool colvarproxy_system::total_forces_same_step() const +bool colvarproxy::total_forces_same_step() const { return false; } -void colvarproxy_system::update_pbc_lattice() +inline int round_to_integer(cvm::real x) +{ + return int(cvm::floor(x+0.5)); +} + + +void colvarproxy::update_pbc_lattice() { // Periodicity is assumed in all directions if (boundaries_type == boundaries_unsupported || boundaries_type == boundaries_non_periodic) { - cvm::error_static("Error: setting PBC lattice with unsupported boundaries.\n", + cvm::error_static(cvmodule, "Error: setting PBC lattice with unsupported boundaries.\n", COLVARS_BUG_ERROR); return; } @@ -116,7 +102,7 @@ void colvarproxy_system::update_pbc_lattice() } -void colvarproxy_system::reset_pbc_lattice() +void colvarproxy::reset_pbc_lattice() { unit_cell_x.reset(); unit_cell_y.reset(); @@ -127,58 +113,58 @@ void colvarproxy_system::reset_pbc_lattice() } -cvm::rvector colvarproxy_system::position_distance(cvm::atom_pos const &pos1, +cvm::rvector colvarproxy::position_distance(cvm::atom_pos const &pos1, cvm::atom_pos const &pos2) const { return position_distance_internal(pos1, pos2); } -int colvarproxy_system::get_molid(int &) +int colvarproxy::get_molid(int &) { - cvm::error_static("Error: only VMD allows the use of multiple \"molecules\", " + cvm::error_static(cvmodule, "Error: only VMD allows the use of multiple \"molecules\", " "i.e. multiple molecular systems.", COLVARS_NOT_IMPLEMENTED); return -1; } -int colvarproxy_system::get_alch_lambda(cvm::real * /* lambda */) +int colvarproxy::get_alch_lambda(cvm::real * /* lambda */) { - return cvm::error_static("Error in get_alch_lambda: alchemical lambda dynamics is not supported by this build.", + return cvm::error_static(cvmodule, "Error in get_alch_lambda: alchemical lambda dynamics is not supported by this build.", COLVARS_NOT_IMPLEMENTED); } -void colvarproxy_system::set_alch_lambda(cvm::real lambda) +void colvarproxy::set_alch_lambda(cvm::real lambda) { cached_alch_lambda = lambda; cached_alch_lambda_changed = true; } -int colvarproxy_system::send_alch_lambda() +int colvarproxy::send_alch_lambda() { - return cvm::error_static("Error in set_alch_lambda: alchemical lambda dynamics is not supported by this build.", + return cvm::error_static(cvmodule, "Error in set_alch_lambda: alchemical lambda dynamics is not supported by this build.", COLVARS_NOT_IMPLEMENTED); } -int colvarproxy_system::get_dE_dlambda(cvm::real * /* force */) +int colvarproxy::get_dE_dlambda(cvm::real * /* force */) { - return cvm::error_static("Error in get_dE_dlambda: alchemical lambda dynamics is not supported by this build.", + return cvm::error_static(cvmodule, "Error in get_dE_dlambda: alchemical lambda dynamics is not supported by this build.", COLVARS_NOT_IMPLEMENTED); } -int colvarproxy_system::apply_force_dE_dlambda(cvm::real* /* force */) +int colvarproxy::apply_force_dE_dlambda(cvm::real* /* force */) { - return cvm::error_static("Error in apply_force_dE_dlambda: function is not implemented by this build.", + return cvm::error_static(cvmodule, "Error in apply_force_dE_dlambda: function is not implemented by this build.", COLVARS_NOT_IMPLEMENTED); } -int colvarproxy_system::get_d2E_dlambda2(cvm::real*) +int colvarproxy::get_d2E_dlambda2(cvm::real*) { - return cvm::error_static("Error in get_d2E_dlambda2: function is not implemented by this build.", + return cvm::error_static(cvmodule, "Error in get_d2E_dlambda2: function is not implemented by this build.", COLVARS_NOT_IMPLEMENTED); } diff --git a/src/colvarproxy_system.h b/src/colvarproxy_system.h index 3746a5b66..7c8e70f46 100644 --- a/src/colvarproxy_system.h +++ b/src/colvarproxy_system.h @@ -11,284 +11,4 @@ #define COLVARPROXY_SYSTEM_H -/// Methods for accessing the simulation system (PBCs, integrator, etc) -class colvarproxy_system { - -public: - - /// Constructor - colvarproxy_system(); - - /// Destructor - virtual ~colvarproxy_system(); - - /// \brief Name of the unit system used internally by Colvars (by default, that of the back-end). - /// Supported depending on the back-end: real (A, kcal/mol), metal (A, eV), electron (Bohr, Hartree), gromacs (nm, kJ/mol) - /// Note: calls to back-end PBC functions assume back-end length unit - /// We use different unit from back-end in VMD bc using PBC functions from colvarproxy base class - /// Colvars internal units are user specified, because the module exchanges info in unknown - /// composite dimensions with user input, while it only exchanges quantities of known - /// dimension with the back-end (length and forces) - std::string units; - - /// \brief Request to set the units used internally by Colvars - virtual int set_unit_system(std::string const &units, bool check_only); - - /// \brief Convert a length from Angstrom to internal - inline cvm::real angstrom_to_internal(cvm::real l) const - { - return l * angstrom_value_; - } - - /// \brief Convert a length from internal to Angstrom - inline cvm::real internal_to_angstrom(cvm::real l) const - { - return l / angstrom_value_; - } - - /// Boltzmann constant, with unit the same as energy / K - inline cvm::real boltzmann() const - { - return boltzmann_; - } - - /// Current target temperature of the simulation (K units) - inline cvm::real target_temperature() const - { - return target_temperature_; - } - - /// Set the current target temperature of the simulation (K units) - virtual int set_target_temperature(cvm::real T); - - /// Time step of the simulation (fs units) - inline double dt() const - { - return timestep_; - } - - /// Set the current integration timestep of the simulation (fs units) - virtual int set_integration_timestep(cvm::real dt); - - /// Time step of the simulation (fs units) - inline int time_step_factor() const - { - return time_step_factor_; - } - - /// Set the current integration timestep of the simulation (fs units) - virtual int set_time_step_factor(int fact); - - /// \brief Pseudo-random number with Gaussian distribution - virtual cvm::real rand_gaussian(void); - - /// Pass restraint energy value for current timestep to MD engine - virtual void add_energy(cvm::real energy); - - /// Use the PBC functions from the Colvars library (as opposed to MD engine) - inline bool & use_internal_pbc() { return use_internal_pbc_; } - - /// Get the PBC-aware distance vector between two positions (using the MD engine's convention) - virtual cvm::rvector position_distance(cvm::atom_pos const &pos1, - cvm::atom_pos const &pos2) const; - - /// Inline version of position_distance() - cvm::rvector position_distance_internal(cvm::atom_pos const &pos1, - cvm::atom_pos const &pos2) const; - - /// Kernel used by position_distance_internal() - /// @param pos1 First position - /// @param pos2 Second position - /// @param a Unit cell vector - /// @param b Unit cell vector - /// @param c Unit cell vector - /// @param a_r Reciprocal cell vector - /// @param b_r Reciprocal cell vector - /// @param c_r Reciprocal cell vector - /// @param a_p Is this dimension periodic? - /// @param b_p Is this dimension periodic? - /// @param c_p Is this dimension periodic? - /// @return (pos2 - pos1) without periodicity, minimum-image difference otherwise - static cvm::rvector position_distance_kernel(cvm::atom_pos const &pos1, - cvm::atom_pos const &pos2, - cvm::rvector const &a, - cvm::rvector const &b, - cvm::rvector const &c, - cvm::rvector const &a_r, - cvm::rvector const &b_r, - cvm::rvector const &c_r, - bool a_p = false, - bool b_p = false, - bool c_p = false); - - /// Recompute PBC reciprocal lattice (assumes XYZ periodicity) - void update_pbc_lattice(); - - /// Set the lattice vectors to zero - void reset_pbc_lattice(); - - /// \brief Tell the proxy whether total forces are needed (they may not - /// always be available) - virtual void request_total_force(bool yesno); - - /// Are total forces being used? - virtual bool total_forces_enabled() const; - - /// Are total forces from the current step available? - /// in which case they are really system forces - virtual bool total_forces_same_step() const; - - /// Get the molecule ID when called in VMD; raise error otherwise - /// \param molid Set this argument equal to the current VMD molid - virtual int get_molid(int &molid); - - /// Get value of alchemical lambda parameter from back-end (if available) - virtual int get_alch_lambda(cvm::real* lambda); - - /// Set value of alchemical lambda parameter to be sent to back-end at end of timestep - void set_alch_lambda(cvm::real lambda); - - /// Send cached value of alchemical lambda parameter to back-end (if available) - virtual int send_alch_lambda(); - - /// Request energy computation every freq steps (necessary for NAMD3, not all back-ends) - virtual int request_alch_energy_freq(int const /* freq */) { - return COLVARS_OK; - } - - /// Get energy derivative with respect to lambda (if available) - virtual int get_dE_dlambda(cvm::real* dE_dlambda); - - /// Apply a scalar force on dE_dlambda (back-end distributes it onto atoms) - virtual int apply_force_dE_dlambda(cvm::real* force); - - /// Get energy second derivative with respect to lambda (if available) - virtual int get_d2E_dlambda2(cvm::real* d2E_dlambda2); - - /// Force to be applied onto alch. lambda, propagated from biasing forces on dE_dlambda - cvm::real indirect_lambda_biasing_force; - - /// Get weight factor from accelMD - virtual cvm::real get_accelMD_factor() const { - cvm::error_static("Error: accessing the reweighting factor of accelerated MD " - "is not yet implemented in the MD engine.\n", - COLVARS_NOT_IMPLEMENTED); - return 1.0; - } - virtual bool accelMD_enabled() const { - return false; - } - -protected: - - /// Next value of lambda to be sent to back-end - cvm::real cached_alch_lambda; - - /// Whether lambda has been set and needs to be updated in backend - bool cached_alch_lambda_changed; - - /// Boltzmann constant in internal Colvars units - cvm::real boltzmann_; - - /// Most up to date target temperature (K units); default to 0.0 if undefined - cvm::real target_temperature_; - - /// Current integration timestep (engine units); default to 1.0 if undefined - double timestep_; - - /// Current timestep multiplier, if Colvars is only called once every n MD timesteps - int time_step_factor_ = 1; - - /// \brief Value of 1 Angstrom in the internal (front-end) Colvars unit for atomic coordinates - /// * defaults to 0 in the base class; derived proxy classes must set it - /// * in VMD proxy, can only be changed when no variables are defined - /// as user-defined values in composite units must be compatible with that system - cvm::real angstrom_value_; - - /// \brief Value of 1 kcal/mol in the internal Colvars unit for energy - cvm::real kcal_mol_value_; - - /// Whether the total forces have been requested - bool total_force_requested; - - /// Use the PBC functions from the Colvars library (as opposed to MD engine) - bool use_internal_pbc_ = false; - - /// Type of boundary conditions defined for the current computation - /// - /// Orthogonal and triclinic cells are made available to objects. - /// For any other conditions (mixed periodicity, triclinic cells in LAMMPS) - /// minimum-image distances are computed by the host engine by default - enum Boundaries_type { - boundaries_non_periodic, - boundaries_pbc_ortho, - boundaries_pbc_triclinic, - boundaries_unsupported - }; - - /// Type of boundary conditions - Boundaries_type boundaries_type; - - /// Bravais lattice vectors - cvm::rvector unit_cell_x, unit_cell_y, unit_cell_z; - - /// Reciprocal lattice vectors - cvm::rvector reciprocal_cell_x, reciprocal_cell_y, reciprocal_cell_z; -}; - - -inline cvm::rvector colvarproxy_system::position_distance_internal(cvm::atom_pos const &pos1, - cvm::atom_pos const &pos2) const -{ - if (boundaries_type == boundaries_unsupported) { - cvm::error_static("Error: unsupported boundary conditions.\n", COLVARS_INPUT_ERROR); - return cvm::rvector({0.0, 0.0, 0.0}); - } - - if (boundaries_type == boundaries_non_periodic) { - return pos2 - pos1; - } - - // Periodicity flags are hard-coded, because this is the only case supported so far other than - // the two above - return position_distance_kernel(pos1, pos2, unit_cell_x, unit_cell_y, unit_cell_z, - reciprocal_cell_x, reciprocal_cell_y, reciprocal_cell_z, - true, true, true); -} - - -inline cvm::rvector colvarproxy_system::position_distance_kernel(cvm::atom_pos const &pos1, - cvm::atom_pos const &pos2, - cvm::rvector const &a, - cvm::rvector const &b, - cvm::rvector const &c, - cvm::rvector const &a_r, - cvm::rvector const &b_r, - cvm::rvector const &c_r, - bool a_p, - bool b_p, - bool c_p) -{ - cvm::rvector diff = (pos2 - pos1); - - cvm::real const x_shift = std::floor(a_r * diff + 0.5); - cvm::real const y_shift = std::floor(b_r * diff + 0.5); - cvm::real const z_shift = std::floor(c_r * diff + 0.5); - - if (a_p) { - diff.x -= x_shift * a.x + y_shift * b.x + z_shift * c.x; - } - - if (b_p) { - diff.y -= x_shift * a.y + y_shift * b.y + z_shift * c.y; - } - - if (c_p) { - diff.z -= x_shift * a.z + y_shift * b.z + z_shift * c.z; - } - - return diff; -} - - #endif diff --git a/src/colvarproxy_tcl.cpp b/src/colvarproxy_tcl.cpp index 390c4f3bf..189c751c6 100644 --- a/src/colvarproxy_tcl.cpp +++ b/src/colvarproxy_tcl.cpp @@ -12,45 +12,28 @@ #include "colvarmodule.h" #include "colvarproxy.h" -#include "colvarproxy_tcl.h" #include "colvaratoms.h" -#ifdef COLVARS_TCL -#include -#endif - - - -colvarproxy_tcl::colvarproxy_tcl() -{ - tcl_interp_ = nullptr; -} - -colvarproxy_tcl::~colvarproxy_tcl() -{ -} - - -void colvarproxy_tcl::init_tcl_pointers() +void colvarproxy::init_tcl_pointers() { // This is overloaded by NAMD and VMD proxies to use the local interpreters #if defined(COLVARS_TCL) if (tcl_interp_ == nullptr) { // Allocate a dedicated Tcl interpreter for Colvars // We may not have an allocated module yet - cvm::log_static("Allocating Tcl interpreter.\n"); + cvm::log_static(cvmodule, "Allocating Tcl interpreter.\n"); set_tcl_interp(Tcl_CreateInterp()); } else { - cvm::error_static("Error: init_tcl_pointers called with non-NULL tcl_interp_\n"); + cvm::error_static(cvmodule, "Error: init_tcl_pointers called with non-NULL tcl_interp_\n"); } #else - cvm::error_static("Error: Tcl support is not available in this build.\n"); + cvm::error_static(cvmodule, "Error: Tcl support is not available in this build.\n"); #endif } -char const *colvarproxy_tcl::tcl_get_str(void *obj) +char const *colvarproxy::tcl_get_str(void *obj) { #if defined(COLVARS_TCL) return Tcl_GetString(reinterpret_cast(obj)); @@ -61,77 +44,80 @@ char const *colvarproxy_tcl::tcl_get_str(void *obj) } -int colvarproxy_tcl::tcl_run_script(std::string const &script) +int colvarproxy::tcl_run_script(std::string const &script) { #if defined(COLVARS_TCL) + if (!cvmodule) return COLVARS_BUG_ERROR; Tcl_Interp *const interp = get_tcl_interp(); int err = Tcl_Eval(interp, script.c_str()); if (err != TCL_OK) { - cvm::main()->log("Error while executing Tcl script:\n"); - cvm::error_static(Tcl_GetStringResult(interp)); + cvmodule->log("Error while executing Tcl script:\n"); + cvm::error_static(cvmodule, Tcl_GetStringResult(interp)); return COLVARS_ERROR; } - return cvm::main()->get_error(); + return cvmodule->get_error(); #else return COLVARS_NOT_IMPLEMENTED; #endif } -int colvarproxy_tcl::tcl_run_file(std::string const &fileName) +int colvarproxy::tcl_run_file(std::string const &fileName) { #if defined(COLVARS_TCL) + if (!cvmodule) return COLVARS_BUG_ERROR; Tcl_Interp *const interp = get_tcl_interp(); int err = Tcl_EvalFile(interp, fileName.c_str()); if (err != TCL_OK) { - cvm::main()->log("Error while executing Tcl script file \"" + fileName + "\":\n"); - cvm::error_static(Tcl_GetStringResult(interp)); + cvmodule->log("Error while executing Tcl script file \"" + fileName + "\":\n"); + cvm::error_static(cvmodule, Tcl_GetStringResult(interp)); return COLVARS_ERROR; } - return cvm::main()->get_error(); + return cvmodule->get_error(); #else return COLVARS_NOT_IMPLEMENTED; #endif } -int colvarproxy_tcl::tcl_run_force_callback() +int colvarproxy::tcl_run_force_callback() { #if defined(COLVARS_TCL) + if (!cvmodule) return COLVARS_BUG_ERROR; Tcl_Interp *const interp = get_tcl_interp(); if (Tcl_FindCommand(interp, "calc_colvar_forces", NULL, 0) == NULL) { - cvm::error_static("Error: Colvars force procedure calc_colvar_forces is not defined.\n"); + cvm::error_static(cvmodule, "Error: Colvars force procedure calc_colvar_forces is not defined.\n"); return COLVARS_ERROR; } std::string cmd = std::string("calc_colvar_forces ") - + cvm::to_str(cvm::main()->step_absolute()); + + cvm::to_str(cvmodule->step_absolute()); int err = Tcl_Eval(interp, cmd.c_str()); if (err != TCL_OK) { - cvm::main()->log("Error while executing calc_colvar_forces:\n"); - cvm::error_static(Tcl_GetStringResult(interp)); + cvmodule->log("Error while executing calc_colvar_forces:\n"); + cvm::error_static(cvmodule, Tcl_GetStringResult(interp)); return COLVARS_ERROR; } - return cvm::main()->get_error(); + return cvmodule->get_error(); #else return COLVARS_NOT_IMPLEMENTED; #endif } -int colvarproxy_tcl::tcl_run_colvar_callback( +int colvarproxy::tcl_run_colvar_callback( std::string const &name, std::vector const &cvc_values, colvarvalue &value) { #if defined(COLVARS_TCL) - + if (!cvmodule) return COLVARS_BUG_ERROR; Tcl_Interp *const interp = get_tcl_interp(); size_t i; std::string cmd = std::string("calc_") + name; if (Tcl_FindCommand(interp, cmd.c_str(), NULL, 0) == NULL) { - cvm::error_static("Error: scripted colvar procedure \"" + cmd + "\" is not defined.\n"); + cvm::error_static(cvmodule, "Error: scripted colvar procedure \"" + cmd + "\" is not defined.\n"); return COLVARS_ERROR; } @@ -142,18 +128,18 @@ int colvarproxy_tcl::tcl_run_colvar_callback( int err = Tcl_Eval(interp, cmd.c_str()); const char *result = Tcl_GetStringResult(interp); if (err != TCL_OK) { - return cvm::error_static(std::string("Error while executing ") + return cvm::error_static(cvmodule, std::string("Error while executing ") + cmd + std::string(":\n") + std::string(Tcl_GetStringResult(interp)), COLVARS_ERROR); } std::istringstream is(result); if (value.from_simple_string(is.str()) != COLVARS_OK) { - cvm::main()->log("Error parsing colvar value from script:"); - cvm::error_static(result); + cvmodule->log("Error parsing colvar value from script:"); + cvm::error_static(cvmodule, result); return COLVARS_ERROR; } - return cvm::main()->get_error(); + return cvmodule->get_error(); #else @@ -166,19 +152,19 @@ int colvarproxy_tcl::tcl_run_colvar_callback( } -int colvarproxy_tcl::tcl_run_colvar_gradient_callback( +int colvarproxy::tcl_run_colvar_gradient_callback( std::string const &name, std::vector const &cvc_values, std::vector > &gradient) { #if defined(COLVARS_TCL) - + if (!cvmodule) return COLVARS_BUG_ERROR; Tcl_Interp *const interp = get_tcl_interp(); size_t i; std::string cmd = std::string("calc_") + name + "_gradient"; if (Tcl_FindCommand(interp, cmd.c_str(), NULL, 0) == NULL) { - cvm::error_static("Error: scripted colvar gradient procedure \"" + cmd + "\" is not defined.\n"); + cvm::error_static(cvmodule, "Error: scripted colvar gradient procedure \"" + cmd + "\" is not defined.\n"); return COLVARS_ERROR; } @@ -188,7 +174,7 @@ int colvarproxy_tcl::tcl_run_colvar_gradient_callback( } int err = Tcl_Eval(interp, cmd.c_str()); if (err != TCL_OK) { - return cvm::error_static(std::string("Error while executing ") + return cvm::error_static(cvmodule, std::string("Error while executing ") + cmd + std::string(":\n") + std::string(Tcl_GetStringResult(interp)), COLVARS_ERROR); @@ -198,7 +184,7 @@ int colvarproxy_tcl::tcl_run_colvar_gradient_callback( Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &n, &list); if (n != int(gradient.size())) { - cvm::error_static("Error parsing list of gradient values from script: found " + cvm::error_static(cvmodule, "Error parsing list of gradient values from script: found " + cvm::to_str(n) + " values instead of " + cvm::to_str(gradient.size())); return COLVARS_ERROR; @@ -206,14 +192,14 @@ int colvarproxy_tcl::tcl_run_colvar_gradient_callback( for (i = 0; i < gradient.size(); i++) { std::istringstream is(Tcl_GetString(list[i])); if (gradient[i].from_simple_string(is.str()) != COLVARS_OK) { - cvm::main()->log("Gradient matrix size: " + cvm::to_str(gradient[i].size())); - cvm::main()->log("Gradient string: " + cvm::to_str(Tcl_GetString(list[i]))); - cvm::error_static("Error parsing gradient value from script", COLVARS_ERROR); + cvmodule->log("Gradient matrix size: " + cvm::to_str(gradient[i].size())); + cvmodule->log("Gradient string: " + cvm::to_str(Tcl_GetString(list[i]))); + cvm::error_static(cvmodule, "Error parsing gradient value from script", COLVARS_ERROR); return COLVARS_ERROR; } } - return cvm::main()->get_error(); + return cvmodule->get_error(); #else diff --git a/src/colvarproxy_tcl.h b/src/colvarproxy_tcl.h index ceebd4c76..e369b82d4 100644 --- a/src/colvarproxy_tcl.h +++ b/src/colvarproxy_tcl.h @@ -10,80 +10,26 @@ #ifndef COLVARPROXY_TCL_H #define COLVARPROXY_TCL_H -#if defined(NAMD_TCL) || defined(VMDTCL) -#define COLVARS_TCL -#endif -#ifdef COLVARS_TCL -#include -#else -// Allow for placeholders Tcl_Interp* variables -typedef void Tcl_Interp; -#endif #include /// Methods for using Tcl within Colvars -class colvarproxy_tcl { - -public: - - /// Constructor - colvarproxy_tcl(); - - /// Destructor - virtual ~colvarproxy_tcl(); - - /// Is Tcl available? (trigger initialization if needed) - inline bool tcl_available() { -#if defined(COLVARS_TCL) - return true; -#else - return false; -#endif - } - - /// Get a string representation of the Tcl object pointed to by obj - char const *tcl_get_str(void *obj); - - int tcl_run_script(std::string const &script); - - int tcl_run_file(std::string const &fileName); - - /// Tcl implementation of run_force_callback() - int tcl_run_force_callback(); - - /// Tcl implementation of run_colvar_callback() - int tcl_run_colvar_callback( - std::string const &name, - std::vector const &cvcs, - colvarvalue &value); - - /// Tcl implementation of run_colvar_gradient_callback() - int tcl_run_colvar_gradient_callback( - std::string const &name, - std::vector const &cvcs, - std::vector > &gradient); - - /// Get a pointer to the Tcl interpreter - inline Tcl_Interp *get_tcl_interp() - { - return tcl_interp_; - } - - /// Set the pointer to the Tcl interpreter - inline void set_tcl_interp(Tcl_Interp *interp) - { - tcl_interp_ = interp; - } - - /// Set Tcl pointers - virtual void init_tcl_pointers(); - -protected: - /// Pointer to Tcl interpreter object - Tcl_Interp *tcl_interp_; -}; +// class colvarproxy_tcl { +// +// public: +// +// /// Constructor +// colvarproxy_tcl(); +// +// /// Destructor +// virtual ~colvarproxy_tcl(); +// +// +// +// protected: +// +// }; #endif diff --git a/src/colvarproxy_volmaps.cpp b/src/colvarproxy_volmaps.cpp index a96d8e825..90ae957af 100644 --- a/src/colvarproxy_volmaps.cpp +++ b/src/colvarproxy_volmaps.cpp @@ -8,26 +8,17 @@ // Colvars repository at GitHub. #include "colvarmodule.h" -#include "colvarproxy_volmaps.h" +#include "colvarproxy.h" #include "colvarmodule_utils.h" -colvarproxy_volmaps::colvarproxy_volmaps() -{ - volmaps_rms_applied_force_ = volmaps_max_applied_force_ = 0.0; -} - - -colvarproxy_volmaps::~colvarproxy_volmaps() {} - - -int colvarproxy_volmaps::check_volmaps_available() +int colvarproxy::check_volmaps_available() { return COLVARS_NOT_IMPLEMENTED; } -int colvarproxy_volmaps::reset() +int colvarproxy::reset_volmaps() { for (size_t i = 0; i < volmaps_ids.size(); i++) { clear_volmap(i); @@ -40,7 +31,7 @@ int colvarproxy_volmaps::reset() } -int colvarproxy_volmaps::add_volmap_slot(int volmap_id) +int colvarproxy::add_volmap_slot(int volmap_id) { volmaps_ids.push_back(volmap_id); volmaps_refcount.push_back(1); @@ -50,48 +41,48 @@ int colvarproxy_volmaps::add_volmap_slot(int volmap_id) } -int colvarproxy_volmaps::check_volmap_by_id(int /* volmap_id */) +int colvarproxy::check_volmap_by_id(int /* volmap_id */) { - return cvm::error_static("Error: selecting volumetric maps is not available.\n", + return cvm::error_static(cvmodule, "Error: selecting volumetric maps is not available.\n", COLVARS_NOT_IMPLEMENTED); } -int colvarproxy_volmaps::check_volmap_by_name(const char * /* volmap_name */) +int colvarproxy::check_volmap_by_name(const char * /* volmap_name */) { - return cvm::error_static("Error: selecting volumetric maps by name is not " + return cvm::error_static(cvmodule, "Error: selecting volumetric maps by name is not " "available.\n", COLVARS_NOT_IMPLEMENTED); } -int colvarproxy_volmaps::init_volmap_by_name(char const * /* volmap_name */) +int colvarproxy::init_volmap_by_name(char const * /* volmap_name */) { return -1; } -int colvarproxy_volmaps::init_volmap_by_id(int /* volmap_id */) +int colvarproxy::init_volmap_by_id(int /* volmap_id */) { return -1; } -int colvarproxy_volmaps::init_volmap_by_name(std::string const &volmap_name) +int colvarproxy::init_volmap_by_name(std::string const &volmap_name) { return init_volmap_by_name(volmap_name.c_str()); } -int colvarproxy_volmaps::check_volmap_by_name(std::string const &volmap_name) +int colvarproxy::check_volmap_by_name(std::string const &volmap_name) { return check_volmap_by_name(volmap_name.c_str()); } -void colvarproxy_volmaps::clear_volmap(int index) +void colvarproxy::clear_volmap(int index) { if (((size_t) index) >= volmaps_ids.size()) { - cvm::error_static("Error: trying to unrequest a volumetric map that was not " + cvm::error_static(cvmodule, "Error: trying to unrequest a volumetric map that was not " "previously requested.\n", COLVARS_INPUT_ERROR); } @@ -101,14 +92,14 @@ void colvarproxy_volmaps::clear_volmap(int index) } -int colvarproxy_volmaps::get_volmap_id_from_name(char const *volmap_name) +int colvarproxy::get_volmap_id_from_name(char const *volmap_name) { // Raise error - colvarproxy_volmaps::check_volmap_by_name(volmap_name); + check_volmap_by_name(volmap_name); return -1; } -int colvarproxy_volmaps::compute_volmap(int /* flags */, +int colvarproxy::compute_volmap(int /* flags */, int /* volmap_id */, cvm::atom_group* ag, cvm::real * /* value */, @@ -118,14 +109,14 @@ int colvarproxy_volmaps::compute_volmap(int /* flags */, } -void colvarproxy_volmaps::compute_rms_volmaps_applied_force() +void colvarproxy::compute_rms_volmaps_applied_force() { volmaps_rms_applied_force_ = compute_norm2_stats(volmaps_new_colvar_forces); } -void colvarproxy_volmaps::compute_max_volmaps_applied_force() +void colvarproxy::compute_max_volmaps_applied_force() { volmaps_max_applied_force_ = compute_norm2_stats(volmaps_new_colvar_forces); diff --git a/src/colvarproxy_volmaps.h b/src/colvarproxy_volmaps.h index 18ef9fb5b..8cff88af3 100644 --- a/src/colvarproxy_volmaps.h +++ b/src/colvarproxy_volmaps.h @@ -6,124 +6,4 @@ #include "colvarmodule.h" -/// \brief Container of grid-based objects -class colvarproxy_volmaps { - -public: - - /// Contructor - colvarproxy_volmaps(); - - /// Destructor - virtual ~colvarproxy_volmaps(); - - /// Clear volumetric map data - int reset(); - - /// Test whether this implementation can use volumetric maps as CVs - virtual int check_volmaps_available(); - - /// Create a slot for a volumetric map not requested yet - int add_volmap_slot(int volmap_id); - - /// Request and prepare this volumetric map for use by Colvars - /// \param volmap_id Numeric ID used by the MD engine - /// \returns Index of the map in the colvarproxy arrays - virtual int init_volmap_by_id(int volmap_id); - - /// Request and prepare this volumetric map for use by Colvars - /// \param volmap_name Name used by the MD engine - /// \returns Index of the map in the colvarproxy arrays - virtual int init_volmap_by_name(char const *volmap_name); - - /// Check that the given volmap ID is valid (return COLVARS_OK if it is) - /// \param volmap_id Numeric ID used by the MD engine - /// \returns Error code - virtual int check_volmap_by_id(int volmap_id); - - /// Check that the given volmap name is valid (return COLVARS_OK if it is) - /// \param volmap_name Name used by the MD engine - /// \returns Error code - virtual int check_volmap_by_name(char const *volmap_name); - - /// Request and prepare this volumetric map for use by Colvars - int init_volmap_by_name(std::string const &volmap_name); - - /// Check that the given volmap name is valid (return COLVARS_OK if it is) - int check_volmap_by_name(std::string const &volmap_name); - - /// \brief Used by the CVC destructors - virtual void clear_volmap(int index); - - /// Get the numeric ID of the given volumetric map (for the MD program) - virtual int get_volmap_id_from_name(char const *volmap_name); - - /// Get the numeric ID of the given volumetric map (for the MD program) - inline int get_volmap_id(int index) const - { - return volmaps_ids[index]; - } - - /// Read the current value of the volumetric map - inline cvm::real get_volmap_value(int index) const - { - return volmaps_values[index]; - } - - /// Request that this force is applied to the given volumetric map - inline void apply_volmap_force(int index, cvm::real const &new_force) - { - volmaps_new_colvar_forces[index] += new_force; - } - - /// Re-weigh an atomic field (e.g. a colvar) by the value of a volumetric map - - /// \param flags Combination of flags - /// \param volmap_id Numeric index of the map (no need to request it) - /// \param ag Pointer to the SOA atom group - /// \param value Pointer to location of total to increment - /// \param atom_field Array of atomic field values (if NULL, ones are used) - virtual int compute_volmap(int flags, - int volmap_id, - cvm::atom_group* ag, - cvm::real *value, - cvm::real *atom_field); - - /// Flags controlling what computation is done on the map - enum { - volmap_flag_null = 0, - volmap_flag_gradients = 1, - volmap_flag_use_atom_field = (1<<8) - }; - - /// Compute the root-mean-square of the applied forces - void compute_rms_volmaps_applied_force(); - - /// Compute the maximum norm among all applied forces - void compute_max_volmaps_applied_force(); - -protected: - - /// \brief Array of numeric IDs of volumetric maps - std::vector volmaps_ids; - - /// \brief Keep track of how many times each vol map is used by a - /// separate colvar object - std::vector volmaps_refcount; - - /// \brief Current values of the vol maps - std::vector volmaps_values; - - /// \brief Forces applied from colvars, to be communicated to the MD - /// integrator - std::vector volmaps_new_colvar_forces; - - /// Root-mean-square of the the applied forces - cvm::real volmaps_rms_applied_force_; - - /// Maximum norm among all applied forces - cvm::real volmaps_max_applied_force_; -}; - - #endif diff --git a/src/colvarscript.cpp b/src/colvarscript.cpp index ae5155cd8..e65b0e183 100644 --- a/src/colvarscript.cpp +++ b/src/colvarscript.cpp @@ -42,7 +42,7 @@ colvarscript::colvarscript(colvarproxy *p, colvarmodule *m) // TODO put this in backend functions so we don't have to delete Tcl_Interp *const interp = proxy()->get_tcl_interp(); if (interp == NULL) { - cvm::error_static("Error: trying to construct colvarscript without a Tcl interpreter.\n"); + cvm::error_static(cvmodule, "Error: trying to construct colvarscript without a Tcl interpreter.\n"); return; } bool deleted = (Tcl_DeleteCommand(interp, "cv") == TCL_OK); @@ -133,7 +133,7 @@ int colvarscript::init_command(colvarscript::command const &comm, std::string line; for (int iarg = 0; iarg < n_args_max; iarg++) { if (! std::getline(is, line)) { - return cvm::error_static("Error: could not initialize help string for scripting " + return cvm::error_static(cvmodule, "Error: could not initialize help string for scripting " "command \""+std::string(name)+"\".\n", COLVARS_BUG_ERROR); } cmd_arghelp[comm].push_back(line); @@ -178,7 +178,7 @@ std::string colvarscript::get_cmd_prefix(colvarscript::Object_type t) case use_bias: return std::string("bias_"); break; default: - cvm::error_static("Error: undefined colvarscript object type.", COLVARS_BUG_ERROR); + cvm::error_static(cvmodule, "Error: undefined colvarscript object type.", COLVARS_BUG_ERROR); return std::string(""); } } @@ -191,7 +191,7 @@ char const *colvarscript::get_command_help(char const *cmd) colvarscript::command const c = cmd_str_map[std::string(cmd)]; return cmd_help[c].c_str(); } - cvm::error_static("Error: command "+std::string(cmd)+ + cvm::error_static(cvmodule, "Error: command "+std::string(cmd)+ " is not implemented.\n", COLVARS_INPUT_ERROR); return NULL; } @@ -203,7 +203,7 @@ char const *colvarscript::get_command_rethelp(char const *cmd) colvarscript::command const c = cmd_str_map[std::string(cmd)]; return cmd_rethelp[c].c_str(); } - cvm::error_static("Error: command "+std::string(cmd)+ + cvm::error_static(cvmodule, "Error: command "+std::string(cmd)+ " is not implemented.\n", COLVARS_INPUT_ERROR); return NULL; } @@ -215,7 +215,7 @@ char const *colvarscript::get_command_arghelp(char const *cmd, int i) colvarscript::command const c = cmd_str_map[std::string(cmd)]; return cmd_arghelp[c][i].c_str(); } - cvm::error_static("Error: command "+std::string(cmd)+ + cvm::error_static(cvmodule, "Error: command "+std::string(cmd)+ " is not implemented.\n", COLVARS_INPUT_ERROR); return NULL; } @@ -227,7 +227,7 @@ int colvarscript::get_command_n_args_min(char const *cmd) colvarscript::command const c = cmd_str_map[std::string(cmd)]; return cmd_n_args_min[c]; } - cvm::error_static("Error: command "+std::string(cmd)+ + cvm::error_static(cvmodule, "Error: command "+std::string(cmd)+ " is not implemented.\n", COLVARS_INPUT_ERROR); return -1; } @@ -239,7 +239,7 @@ int colvarscript::get_command_n_args_max(char const *cmd) colvarscript::command const c = cmd_str_map[std::string(cmd)]; return cmd_n_args_max[c]; } - cvm::error_static("Error: command "+std::string(cmd)+ + cvm::error_static(cvmodule, "Error: command "+std::string(cmd)+ " is not implemented.\n", COLVARS_INPUT_ERROR); return -1; } @@ -251,7 +251,7 @@ char const *colvarscript::get_command_full_help(char const *cmd) colvarscript::command const c = cmd_str_map[std::string(cmd)]; return cmd_full_help[c].c_str(); } - cvm::error_static("Error: command "+std::string(cmd)+ + cvm::error_static(cvmodule, "Error: command "+std::string(cmd)+ " is not implemented.\n", COLVARS_INPUT_ERROR); return NULL; } @@ -482,7 +482,7 @@ std::vector colvarscript::obj_to_str_vector(unsigned char *obj) if (c == '\"') { i++; if (i >= str.length()) { - cvm::error_static("Error: could not split the following string:\n"+ + cvm::error_static(cvmodule, "Error: could not split the following string:\n"+ str+"\n", COLVARS_INPUT_ERROR); break; } @@ -490,7 +490,7 @@ std::vector colvarscript::obj_to_str_vector(unsigned char *obj) while (str[i] != '\"') { new_result.back().append(1, str[i]); if (i >= str.length()) { - cvm::error_static("Error: could not split the following string:\n"+ + cvm::error_static(cvmodule, "Error: could not split the following string:\n"+ str+"\n", COLVARS_INPUT_ERROR); break; } else { @@ -581,7 +581,7 @@ int colvarscript::proc_features(colvardeps *obj, int colvarscript::unsupported_op() { - return cvm::error_static("Error: unsupported script operation.\n", + return cvm::error_static(cvmodule, "Error: unsupported script operation.\n", COLVARS_NOT_IMPLEMENTED); } @@ -616,10 +616,12 @@ int colvarscript::clear_str_result() extern "C" -int run_colvarscript_command(colvarscript *script, int objc, unsigned char *const objv[]) +int run_colvarscript_command(void* proxy_in, int objc, unsigned char *const objv[]) { + colvarproxy* proxy = (colvarproxy*)proxy_in; + colvarscript* script = proxy->script; if (!script) { - cvm::error_static("Called run_colvarscript_command without a script object.\n", + cvm::error_static(proxy->cvmodule, "Called run_colvarscript_command without a script object.\n", COLVARS_BUG_ERROR); return -1; } @@ -629,11 +631,12 @@ int run_colvarscript_command(colvarscript *script, int objc, unsigned char *cons extern "C" -const char * get_colvarscript_result() +const char * get_colvarscript_result(void* proxy_in) { - colvarscript *script = colvarscript_obj(); + colvarproxy* proxy = (colvarproxy*)proxy_in; + colvarscript* script = proxy->script; if (!script) { - cvm::error_static("Called get_colvarscript_result without a script object.\n"); + cvm::error_static(proxy->cvmodule, "Called get_colvarscript_result without a script object.\n"); return NULL; } return script->str_result().c_str(); diff --git a/src/colvarscript.h b/src/colvarscript.h index 80b24520c..456c50bc2 100644 --- a/src/colvarscript.h +++ b/src/colvarscript.h @@ -343,11 +343,6 @@ inline static colvarscript *colvarscript_obj(void *pobj) return reinterpret_cast(pobj); } -/// Get a pointer to the main colvarscript object -inline static colvarscript *colvarscript_obj() -{ - return cvm::main()->proxy->script; -} /// Get a pointer to the colvar object pointed to by pobj inline static colvar *colvar_obj(void *pobj) @@ -466,10 +461,10 @@ extern "C" { /// Generic wrapper for string-based scripting // New: requires pointer to colvarscript object - TODO - pass it in ctypes Python example - int run_colvarscript_command(colvarscript *script, int objc, unsigned char *const objv[]); + int run_colvarscript_command(void *proxy_in, int objc, unsigned char *const objv[]); /// Get the string result of a script call - const char * get_colvarscript_result(); + const char * get_colvarscript_result(void *proxy_in); } diff --git a/src/colvarscript_commands.cpp b/src/colvarscript_commands.cpp index 10900561c..2adecebea 100644 --- a/src/colvarscript_commands.cpp +++ b/src/colvarscript_commands.cpp @@ -26,58 +26,93 @@ int cvscript_n_commands() extern "C" -char const **cvscript_command_names() +char const **cvscript_command_names(void *proxy_in) { - colvarscript *script = colvarscript_obj(); - return script->get_command_names(); + colvarproxy* proxy = (colvarproxy*)proxy_in; + if (proxy) { + if (proxy->script) { + return proxy->script->get_command_names(); + } + } + return nullptr; } extern "C" -char const *cvscript_command_help(char const *c) +char const *cvscript_command_help(void *proxy_in, char const *c) { - colvarscript *script = colvarscript_obj(); - return script->get_command_help(c); + colvarproxy* proxy = (colvarproxy*)proxy_in; + if (proxy) { + if (proxy->script) { + return proxy->script->get_command_help(c); + } + } + return nullptr; } extern "C" -char const *cvscript_command_rethelp(char const *c) +char const *cvscript_command_rethelp(void *proxy_in, char const *c) { - colvarscript *script = colvarscript_obj(); - return script->get_command_rethelp(c); + colvarproxy* proxy = (colvarproxy*)proxy_in; + if (proxy) { + if (proxy->script) { + return proxy->script->get_command_rethelp(c); + } + } + return nullptr; } extern "C" -char const *cvscript_command_arghelp(char const *c, int i) +char const *cvscript_command_arghelp(void *proxy_in, char const *c, int i) { - colvarscript *script = colvarscript_obj(); - return script->get_command_arghelp(c, i); + colvarproxy* proxy = (colvarproxy*)proxy_in; + if (proxy) { + if (proxy->script) { + return proxy->script->get_command_arghelp(c, i); + } + } + return nullptr; } extern "C" -char const *cvscript_command_full_help(char const *c) +char const *cvscript_command_full_help(void *proxy_in, char const *c) { - colvarscript *script = colvarscript_obj(); - return script->get_command_full_help(c); + colvarproxy* proxy = (colvarproxy*)proxy_in; + if (proxy) { + if (proxy->script) { + return proxy->script->get_command_full_help(c); + } + } + return nullptr; } extern "C" -int cvscript_command_n_args_min(char const *c) +int cvscript_command_n_args_min(void *proxy_in, char const *c) { - colvarscript *script = colvarscript_obj(); - return script->get_command_n_args_min(c); + colvarproxy* proxy = (colvarproxy*)proxy_in; + if (proxy) { + if (proxy->script) { + return proxy->script->get_command_n_args_min(c); + } + } + return -1; } extern "C" -int cvscript_command_n_args_max(char const *c) +int cvscript_command_n_args_max(void *proxy_in, char const *c) { - colvarscript *script = colvarscript_obj(); - return script->get_command_n_args_max(c); + colvarproxy* proxy = (colvarproxy*)proxy_in; + if (proxy) { + if (proxy->script) { + return proxy->script->get_command_n_args_max(c); + } + } + return -1; } diff --git a/src/colvarscript_commands.h b/src/colvarscript_commands.h index 9db6c903b..f6f39946e 100644 --- a/src/colvarscript_commands.h +++ b/src/colvarscript_commands.h @@ -63,34 +63,34 @@ extern "C" { int cvscript_n_commands(); /// Get the names of all commands (array of strings) - char const ** cvscript_command_names(); + char const ** cvscript_command_names(void *proxy_in); /// Get the help summary of the given command /// \param cmd Name of the command's function (e.g. "cv_units") - char const *cvscript_command_help(char const *cmd); + char const *cvscript_command_help(void *proxy_in, char const *cmd); /// Get description of the return value of a command /// \param cmd Name of the command's function (e.g. "cv_units") - char const *cvscript_command_rethelp(char const *cmd); + char const *cvscript_command_rethelp(void *proxy_in, char const *cmd); /// Get description of the arguments of a command (excluding prefix) /// \param cmd Name of the command's function (e.g. "cv_units") /// \param i Index of the argument; 0 is the first argument after the /// prefix, e.g. "value" has an index of 0 in the array of arguments: /// { "cv", "colvar", "xi", "value" } - char const *cvscript_command_arghelp(char const *cmd, int i); + char const *cvscript_command_arghelp(void *proxy_in, char const *cmd, int i); /// Get the full help string of a command /// \param cmd Name of the command's function (e.g. "cv_units") - char const *cvscript_command_full_help(char const *cmd); + char const *cvscript_command_full_help(void *proxy_in, char const *cmd); /// Get number of required arguments (excluding prefix) /// \param cmd Name of the command's function (e.g. "cv_units") - int cvscript_command_n_args_min(char const *cmd); + int cvscript_command_n_args_min(void *proxy_in, char const *cmd); /// Get number of total arguments (excluding prefix) /// \param cmd Name of the command's function (e.g. "cv_units") - int cvscript_command_n_args_max(char const *cmd); + int cvscript_command_n_args_max(void *proxy_in, char const *cmd); } @@ -439,7 +439,7 @@ CVSCRIPT(cv_listcommands, 0, 0, "", int const n_commands = cvscript_n_commands(); - char const **command_names = cvscript_command_names(); + char const **command_names = cvscript_command_names(cvmodule->proxy); std::string result; for (int i = 0; i < n_commands; i++) { if (i > 0) result.append(1, ' '); diff --git a/src/colvartypes.cpp b/src/colvartypes.cpp index da7c66bcd..d7b5c7c4d 100644 --- a/src/colvartypes.cpp +++ b/src/colvartypes.cpp @@ -31,7 +31,7 @@ std::string cvm::rvector::to_simple_string() const { std::ostringstream os; os.setf(std::ios::scientific, std::ios::floatfield); - os.precision(cvm::main()->cv_prec); + os.precision(cvm::cv_prec); os << x << " " << y << " " << z; return os.str(); } @@ -86,7 +86,7 @@ std::string cvm::quaternion::to_simple_string() const { std::ostringstream os; os.setf(std::ios::scientific, std::ios::floatfield); - os.precision(cvm::main()->cv_prec); + os.precision(cvm::cv_prec); os << q0 << " " << q1 << " " << q2 << " " << q3; return os.str(); } @@ -154,12 +154,14 @@ int colvarmodule::rotation::init() { b_debug_gradients = false; // lambda = 0.0; - cvm::main()->cite_feature("Optimal rotation via flexible fitting"); + if (cvmodule) { + cvmodule->cite_feature("Optimal rotation via flexible fitting"); + } return COLVARS_OK; } -colvarmodule::rotation::rotation() +colvarmodule::rotation::rotation(colvarmodule* cvmodule_in): cvmodule(cvmodule_in) { init(); #ifdef COLVARS_LAMMPS @@ -170,8 +172,8 @@ colvarmodule::rotation::rotation() } -colvarmodule::rotation::rotation(cvm::quaternion const &qi) - : q(qi) +colvarmodule::rotation::rotation(colvarmodule* cvmodule_in, cvm::quaternion const &qi) + : cvmodule(cvmodule_in), q(qi) { init(); #ifdef COLVARS_LAMMPS @@ -182,7 +184,7 @@ colvarmodule::rotation::rotation(cvm::quaternion const &qi) } -colvarmodule::rotation::rotation(cvm::real angle, cvm::rvector const &axis) +colvarmodule::rotation::rotation(colvarmodule* cvmodule_in, cvm::real angle, cvm::rvector const &axis): cvmodule(cvmodule_in) { init(); cvm::rvector const axis_n = axis.unit(); @@ -306,21 +308,21 @@ void colvarmodule::rotation::debug_gradients( cvm::quaternion const Q2(rot.S_eigvec[2]); cvm::quaternion const Q3(rot.S_eigvec[3]); - cvm::log_static("L0 = "+cvm::to_str(L0, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q0 = "+cvm::to_str(Q0, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q0*Q0 = "+cvm::to_str(Q0.inner(Q0), cvm::main()->cv_width, cvm::main()->cv_prec)+ + cvm::log_static(cvmodule, "L0 = "+cvm::to_str(L0, cvm::cv_width, cvm::cv_prec)+ + ", Q0 = "+cvm::to_str(Q0, cvm::cv_width, cvm::cv_prec)+ + ", Q0*Q0 = "+cvm::to_str(Q0.inner(Q0), cvm::cv_width, cvm::cv_prec)+ "\n"); - cvm::log_static("L1 = "+cvm::to_str(L1, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q1 = "+cvm::to_str(Q1, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q0*Q1 = "+cvm::to_str(Q0.inner(Q1), cvm::main()->cv_width, cvm::main()->cv_prec)+ + cvm::log_static(cvmodule, "L1 = "+cvm::to_str(L1, cvm::cv_width, cvm::cv_prec)+ + ", Q1 = "+cvm::to_str(Q1, cvm::cv_width, cvm::cv_prec)+ + ", Q0*Q1 = "+cvm::to_str(Q0.inner(Q1), cvm::cv_width, cvm::cv_prec)+ "\n"); - cvm::log_static("L2 = "+cvm::to_str(L2, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q2 = "+cvm::to_str(Q2, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q0*Q2 = "+cvm::to_str(Q0.inner(Q2), cvm::main()->cv_width, cvm::main()->cv_prec)+ + cvm::log_static(cvmodule, "L2 = "+cvm::to_str(L2, cvm::cv_width, cvm::cv_prec)+ + ", Q2 = "+cvm::to_str(Q2, cvm::cv_width, cvm::cv_prec)+ + ", Q0*Q2 = "+cvm::to_str(Q0.inner(Q2), cvm::cv_width, cvm::cv_prec)+ "\n"); - cvm::log_static("L3 = "+cvm::to_str(L3, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q3 = "+cvm::to_str(Q3, cvm::main()->cv_width, cvm::main()->cv_prec)+ - ", Q0*Q3 = "+cvm::to_str(Q0.inner(Q3), cvm::main()->cv_width, cvm::main()->cv_prec)+ + cvm::log_static(cvmodule, "L3 = "+cvm::to_str(L3, cvm::cv_width, cvm::cv_prec)+ + ", Q3 = "+cvm::to_str(Q3, cvm::cv_width, cvm::cv_prec)+ + ", Q0*Q3 = "+cvm::to_str(Q0.inner(Q3), cvm::cv_width, cvm::cv_prec)+ "\n"); rotation_derivative deriv(rot, pos1, pos2, num_atoms_pos1, num_atoms_pos2); cvm::rvector dl0_2; @@ -367,10 +369,10 @@ void colvarmodule::rotation::debug_gradients( dq0_2[2][comp] * colvarmodule::debug_gradients_step_size, dq0_2[3][comp] * colvarmodule::debug_gradients_step_size); - cvm::log_static( "|(l_0+dl_0) - l_0^new|/l_0 = "+ - cvm::to_str(cvm::fabs(L0+DL0 - L0_new)/L0, cvm::main()->cv_width, cvm::main()->cv_prec)+ + cvm::log_static(cvmodule, "|(l_0+dl_0) - l_0^new|/l_0 = "+ + cvm::to_str(cvm::fabs(L0+DL0 - L0_new)/L0, cvm::cv_width, cvm::cv_prec)+ ", |(q_0+dq_0) - q_0^new| = "+ - cvm::to_str((Q0+DQ0 - Q0_new).norm(), cvm::main()->cv_width, cvm::main()->cv_prec)+ + cvm::to_str((Q0+DQ0 - Q0_new).norm(), cvm::cv_width, cvm::cv_prec)+ "\n"); } } @@ -441,7 +443,7 @@ void colvarmodule::rotation::calc_optimal_rotation_impl() { S_backup_out[i][j] = S_backup[i][j]; } } - cvm::log_static("S = "+cvm::to_str(S_backup_out, cvm::main()->cv_width, cvm::main()->cv_prec)+"\n"); + cvm::log_static(cvmodule, "S = "+cvm::to_str(S_backup_out, cvm::cv_width, cvm::cv_prec)+"\n"); } @@ -458,18 +460,18 @@ void colvarmodule::rotation::calc_optimal_rotation_impl() { int ierror = NR::diagonalize_matrix(S, S_eigval, S_eigvec); #endif if (ierror) { - cvm::log_static("Failed to diagonalize the following overlapping matrix:\n"); + cvm::log_static(cvmodule, "Failed to diagonalize the following overlapping matrix:\n"); for (size_t i = 0; i < 4; ++i) { for (size_t j = 0; j < 4; ++j) { - cvm::log_static(cvm::to_str(S[i][j]) + " "); + cvm::log_static(cvmodule, cvm::to_str(S[i][j]) + " "); } - cvm::log_static("\n"); + cvm::log_static(cvmodule, "\n"); } - cvm::log_static("The corresponding correlation matrix is:\n"); - cvm::log_static(" " + cvm::to_str(C.xx) + " " + cvm::to_str(C.xy) + " " + cvm::to_str(C.xz)); - cvm::log_static(" " + cvm::to_str(C.yx) + " " + cvm::to_str(C.yy) + " " + cvm::to_str(C.yz)); - cvm::log_static(" " + cvm::to_str(C.zx) + " " + cvm::to_str(C.zy) + " " + cvm::to_str(C.zz) + "\n"); - cvm::error_static("Too many iterations in jacobi diagonalization.\n" + cvm::log_static(cvmodule, "The corresponding correlation matrix is:\n"); + cvm::log_static(cvmodule, " " + cvm::to_str(C.xx) + " " + cvm::to_str(C.xy) + " " + cvm::to_str(C.xz)); + cvm::log_static(cvmodule, " " + cvm::to_str(C.yx) + " " + cvm::to_str(C.yy) + " " + cvm::to_str(C.yz)); + cvm::log_static(cvmodule, " " + cvm::to_str(C.zx) + " " + cvm::to_str(C.zy) + " " + cvm::to_str(C.zz) + "\n"); + cvm::error_static(cvmodule, "Too many iterations in jacobi diagonalization.\n" "This is usually the result of an ill-defined set of atoms for " "rotational alignment (RMSD, rotateReference, etc).\n"); } @@ -479,7 +481,7 @@ void colvarmodule::rotation::calc_optimal_rotation_impl() { if (q_old.norm2() > 0.0) { q.match(q_old); if (q_old.inner(q) < (1.0 - crossing_threshold)) { - cvm::log_static("Warning: one molecular orientation has changed by more than "+ + cvm::log_static(cvmodule, "Warning: one molecular orientation has changed by more than "+ cvm::to_str(crossing_threshold)+": discontinuous rotation ?\n"); } } @@ -490,37 +492,42 @@ void colvarmodule::rotation::calc_optimal_rotation_impl() { #if defined(COLVARS_CUDA) || defined(COLVARS_HIP) namespace colvars_gpu { -rotation_gpu::rotation_gpu(): +rotation_gpu::rotation_gpu(colvarmodule* cvmodule_in): d_S(nullptr), d_S_eigval(nullptr), d_S_eigvec(nullptr), tbcount(nullptr), d_q(nullptr), d_q_old(nullptr), discontinuous_rotation(nullptr), max_iteration_reached(nullptr), b_initialized(false), h_C(nullptr), h_S(nullptr), h_S_eigval(nullptr), - h_S_eigvec(nullptr) + h_S_eigvec(nullptr), cvmodule(cvmodule_in) {} rotation_gpu::~rotation_gpu() { - colvarproxy* p = cvm::main()->proxy; - p->deallocate_device(&d_S); - p->deallocate_device(&d_S_eigval); - p->deallocate_device(&d_S_eigvec); - p->deallocate_device(&tbcount); - p->deallocate_device(&d_q); - p->deallocate_device(&d_q_old); - p->deallocate_host(&discontinuous_rotation); - p->deallocate_host(&max_iteration_reached); - p->deallocate_host(&h_C); - p->deallocate_host(&h_S); - p->deallocate_host(&h_S_eigval); - p->deallocate_host(&h_S_eigvec); - b_initialized = false; + if (cvmodule) { + colvarproxy* p = cvmodule->proxy; + p->deallocate_device(&d_S); + p->deallocate_device(&d_S_eigval); + p->deallocate_device(&d_S_eigvec); + p->deallocate_device(&tbcount); + p->deallocate_device(&d_q); + p->deallocate_device(&d_q_old); + p->deallocate_host(&discontinuous_rotation); + p->deallocate_host(&max_iteration_reached); + p->deallocate_host(&h_C); + p->deallocate_host(&h_S); + p->deallocate_host(&h_S_eigval); + p->deallocate_host(&h_S_eigvec); + b_initialized = false; + } } int rotation_gpu::init(/*const cudaStream_t& stream_in*/) { int error_code = COLVARS_OK; // stream = stream_in; - colvarproxy* p = cvm::main()->proxy; + if (cvmodule == nullptr) { + return cvm::error_static(cvmodule, "cvmodule is NULL.\n", COLVARS_ERROR); + } + colvarproxy* p = cvmodule->proxy; if (!b_initialized) { error_code |= p->allocate_device(&d_S, 4 * 4); error_code |= p->allocate_device(&d_S_eigval, 4); @@ -540,7 +547,7 @@ int rotation_gpu::init(/*const cudaStream_t& stream_in*/) { if (colvarmodule::rotation::monitor_crossings) { error_code |= p->clear_device_array(&d_q_old, 1); } - cvm::main()->cite_feature("Optimal rotation via flexible fitting"); + cvmodule->cite_feature("Optimal rotation via flexible fitting"); b_initialized = true; } return error_code; @@ -558,7 +565,7 @@ int rotation_gpu::add_optimal_rotation_nodes( // Add memset nodes cudaGraphNode_t d_SSetNode; error_code |= colvars_gpu::add_clear_array_node( - d_S, 4*4, d_SSetNode, graph, {}); + cvmodule, d_S, 4*4, d_SSetNode, graph, {}); nodes_map["rotation_gpu_S_set"] = d_SSetNode; const cvm::real* d_pos1_x = d_pos1; const cvm::real* d_pos1_y = d_pos1_x + num_atoms_pos1; @@ -571,14 +578,14 @@ int rotation_gpu::add_optimal_rotation_nodes( std::vector dependencies; // The coordinates are not always moved to origin, so these dependencies are conditional colvars_gpu::prepare_dependencies( - {{"read_positions_main", true}, + cvmodule, {{"read_positions_main", true}, {"read_positions_fitting", true}, {"move_to_origin_main", true}, {"move_to_origin_fitting", true}}, dependencies, nodes_map, "build_overlapping_matrix"); dependencies.push_back(d_SSetNode); error_code |= colvars_gpu::build_overlapping_matrix( - d_pos1_x, d_pos1_y, d_pos1_z, + cvmodule, d_pos1_x, d_pos1_y, d_pos1_z, d_pos2_x, d_pos2_y, d_pos2_z, d_S, d_S_eigvec, h_C, tbcount, num_atoms_pos1, build_S_node, graph, dependencies); @@ -586,13 +593,13 @@ int rotation_gpu::add_optimal_rotation_nodes( // Copy the overlapping matrix to host for CPU buffers cudaGraphNode_t copy_DtoH_S_node; error_code |= colvars_gpu::add_copy_node( - d_S, h_S, 4*4, cudaMemcpyDeviceToHost, copy_DtoH_S_node, + cvmodule, d_S, h_S, 4*4, cudaMemcpyDeviceToHost, copy_DtoH_S_node, graph, {build_S_node}); nodes_map["copy_DtoH_S"] = copy_DtoH_S_node; // Kernel node for eigensystem cudaGraphNode_t Jacobi4x4Node; error_code |= colvars_gpu::jacobi_4x4( - d_S_eigvec, d_S_eigval, + cvmodule, d_S_eigvec, d_S_eigval, max_iteration_reached, d_q, colvarmodule::rotation::monitor_crossings, colvarmodule::rotation::crossing_threshold, @@ -601,13 +608,13 @@ int rotation_gpu::add_optimal_rotation_nodes( nodes_map["calc_optimal_rotation"] = Jacobi4x4Node; cudaGraphNode_t copy_DtoH_S_eigvec_node; error_code |= colvars_gpu::add_copy_node( - d_S_eigvec, h_S_eigvec, 4*4, + cvmodule, d_S_eigvec, h_S_eigvec, 4*4, cudaMemcpyDeviceToHost, copy_DtoH_S_eigvec_node, graph, {Jacobi4x4Node}); nodes_map["copy_DtoH_S_eigvec"] = copy_DtoH_S_eigvec_node; cudaGraphNode_t copy_DtoH_S_eigval_node; error_code |= colvars_gpu::add_copy_node( - d_S_eigval, h_S_eigval, 4, + cvmodule, d_S_eigval, h_S_eigval, 4, cudaMemcpyDeviceToHost, copy_DtoH_S_eigval_node, graph, {Jacobi4x4Node}); nodes_map["copy_DtoH_S_eigval"] = copy_DtoH_S_eigval_node; @@ -616,14 +623,14 @@ int rotation_gpu::add_optimal_rotation_nodes( void rotation_gpu::after_sync_check() const { if (max_iteration_reached[0]) { - cvm::error_static("Too many iterations in jacobi diagonalization.\n" + cvmodule->error("Too many iterations in jacobi diagonalization.\n" "This is usually the result of an ill-defined set of atoms for " "rotational alignment (RMSD, rotateReference, etc).\n"); max_iteration_reached[0] = 0; } if (colvarmodule::rotation::monitor_crossings) { if (discontinuous_rotation[0]) { - cvm::main()->log("Warning: one molecular orientation has changed by more than "+ + cvmodule->log("Warning: one molecular orientation has changed by more than "+ cvm::to_str(colvarmodule::rotation::crossing_threshold)+ ": discontinuous rotation ?\n"); } diff --git a/src/colvartypes.h b/src/colvartypes.h index def572d89..dce7c0a46 100644 --- a/src/colvartypes.h +++ b/src/colvartypes.h @@ -122,10 +122,12 @@ template class colvarmodule::vector1d inline static void check_sizes(vector1d const &v1, vector1d const &v2) { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if (v1.size() != v2.size()) { - cvm::error_static("Error: trying to perform an operation between vectors of different sizes, "+ + cvm::error_static(nullptr, "Error: trying to perform an operation between vectors of different sizes, "+ cvm::to_str(v1.size())+" and "+cvm::to_str(v2.size())+".\n"); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } inline void operator += (vector1d const &v) @@ -252,9 +254,11 @@ template class colvarmodule::vector1d /// Slicing inline vector1d const slice(size_t const i1, size_t const i2) const { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if ((i2 < i1) || (i2 >= this->size())) { - cvm::error_static("Error: trying to slice a vector using incorrect boundaries.\n"); + cvm::error_static(nullptr, "Error: trying to slice a vector using incorrect boundaries.\n"); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK vector1d result(i2 - i1); size_t i; for (i = 0; i < (i2 - i1); i++) { @@ -267,9 +271,11 @@ template class colvarmodule::vector1d inline void sliceassign(size_t const i1, size_t const i2, vector1d const &v) { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if ((i2 < i1) || (i2 >= this->size())) { - cvm::error_static("Error: trying to slice a vector using incorrect boundaries.\n"); + cvm::error_static(nullptr, "Error: trying to slice a vector using incorrect boundaries.\n"); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK size_t i; for (i = 0; i < (i2 - i1); i++) { (*this)[i1+i] = v[i]; @@ -401,10 +407,12 @@ template class colvarmodule::matrix2d } inline int set(cvm::vector1d const &v) const { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if (v.size() != length) { - return cvm::error_static("Error: setting a matrix row from a vector of " + return cvm::error_static(nullptr, "Error: setting a matrix row from a vector of " "incompatible size.\n", COLVARS_BUG_ERROR); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK for (size_t i = 0; i < length; i++) data[i] = v[i]; return COLVARS_OK; } @@ -550,15 +558,17 @@ template class colvarmodule::matrix2d inline static void check_sizes(matrix2d const &m1, matrix2d const &m2) { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if ((m1.outer_length != m2.outer_length) || (m1.inner_length != m2.inner_length)) { - cvm::error_static("Error: trying to perform an operation between " + cvm::error_static(nullptr, "Error: trying to perform an operation between " "matrices of different sizes, "+ cvm::to_str(m1.outer_length)+"x"+ cvm::to_str(m1.inner_length)+" and "+ cvm::to_str(m2.outer_length)+"x"+ cvm::to_str(m2.inner_length)+".\n"); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } inline void operator += (matrix2d const &m) @@ -650,11 +660,13 @@ template class colvarmodule::matrix2d { vector1d result(m.inner_length); if (m.outer_length != v.size()) { - cvm::error_static("Error: trying to multiply a vector and a matrix " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to multiply a vector and a matrix " "of incompatible sizes, "+ cvm::to_str(v.size()) + " and " + cvm::to_str(m.outer_length)+"x"+cvm::to_str(m.inner_length) + ".\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } else { size_t i, k; for (i = 0; i < m.inner_length; i++) { @@ -1039,7 +1051,9 @@ class colvarmodule::quaternion { return this->q3; default: #if !(defined(__NVCC__) || defined(__HIPCC__)) - cvm::error_static("Error: incorrect quaternion component.\n"); +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: incorrect quaternion component.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK #endif return q0; } @@ -1058,8 +1072,10 @@ class colvarmodule::quaternion { return this->q3; default: #if !(defined(__NVCC__) || defined(__HIPCC__)) - cvm::error_static("Error: trying to access a quaternion " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to access a quaternion " "component which is not between 0 and 3.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK #endif return 0.0; } @@ -1382,6 +1398,9 @@ class colvarmodule::rotation /// Used for debugging gradients cvm::real S_backup[4][4]; + /// For logging + colvarmodule* cvmodule; + public: /// \brief Perform gradient tests bool b_debug_gradients; @@ -1434,13 +1453,13 @@ class colvarmodule::rotation int init(); /// Default constructor - rotation(); + rotation(colvarmodule* cvmodule_in); /// Constructor after a quaternion - rotation(cvm::quaternion const &qi); + rotation(colvarmodule* cvmodule_in, cvm::quaternion const &qi); /// Constructor after an axis of rotation and an angle (in radians) - rotation(cvm::real angle, cvm::rvector const &axis); + rotation(colvarmodule* cvmodule_in, cvm::real angle, cvm::rvector const &axis); /// Destructor ~rotation(); @@ -1454,7 +1473,7 @@ class colvarmodule::rotation /// Return the inverse of this rotation inline cvm::rotation inverse() const { - return cvm::rotation(this->q.conjugate()); + return cvm::rotation(cvmodule, this->q.conjugate()); } /// Return the associated 3x3 matrix @@ -1613,9 +1632,11 @@ class rotation_gpu { cvm::real* h_S; cvm::real* h_S_eigval; cvm::real* h_S_eigvec; + /// \brief Colvar module object for debugging and logging + colvarmodule* cvmodule; public: /// Constructor - rotation_gpu(); + rotation_gpu(colvarmodule* cvmodule_in); /// Destructor ~rotation_gpu(); /// Check if the object is initialized diff --git a/src/colvarvalue.cpp b/src/colvarvalue.cpp index 3801859da..f961bbb88 100644 --- a/src/colvarvalue.cpp +++ b/src/colvarvalue.cpp @@ -74,9 +74,11 @@ colvarvalue::colvarvalue(cvm::vector1d const &v, : real_value(0.0) { if ((vti != type_vector) && (v.size() != num_dimensions(vti))) { - cvm::error_static("Error: trying to initialize a variable of type \""+type_desc(vti)+ +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to initialize a variable of type \""+type_desc(vti)+ "\" using a vector of size "+cvm::to_str(v.size())+ ".\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK value_type = type_notset; } else { value_type = vti; @@ -291,7 +293,9 @@ void colvarvalue::is_derivative() void colvarvalue::add_elem(colvarvalue const &x) { if (this->value_type != type_vector) { - cvm::error_static("Error: trying to set an element for a variable that is not set to be a vector.\n"); +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to set an element for a variable that is not set to be a vector.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return; } size_t const n = vector1d_value.size(); @@ -310,7 +314,9 @@ colvarvalue const colvarvalue::get_elem(int const i_begin, int const i_end, Type cvm::vector1d const v(vector1d_value.slice(i_begin, i_end)); return colvarvalue(v, vt); } else { - cvm::error_static("Error: trying to get an element from a variable that is not a vector.\n"); +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to get an element from a variable that is not a vector.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return colvarvalue(type_notset); } } @@ -321,7 +327,9 @@ void colvarvalue::set_elem(int const i_begin, int const i_end, colvarvalue const if (vector1d_value.size() > 0) { vector1d_value.sliceassign(i_begin, i_end, x.as_vector()); } else { - cvm::error_static("Error: trying to set an element for a variable that is not a vector.\n"); +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to set an element for a variable that is not a vector.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } } @@ -332,7 +340,9 @@ colvarvalue const colvarvalue::get_elem(int const icv) const return get_elem(elem_indices[icv], elem_indices[icv] + elem_sizes[icv], elem_types[icv]); } else { - cvm::error_static("Error: trying to get a colvarvalue element from a vector colvarvalue that was initialized as a plain array.\n"); +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to get a colvarvalue element from a vector colvarvalue that was initialized as a plain array.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return colvarvalue(type_notset); } } @@ -344,35 +354,37 @@ void colvarvalue::set_elem(int const icv, colvarvalue const &x) check_types_assign(elem_types[icv], x.value_type); set_elem(elem_indices[icv], elem_indices[icv] + elem_sizes[icv], x); } else { - cvm::error_static("Error: trying to set a colvarvalue element for a colvarvalue that was initialized as a plain array.\n"); +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to set a colvarvalue element for a colvarvalue that was initialized as a plain array.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } } -void colvarvalue::set_random() +void colvarvalue::set_random(colvarmodule* cvmodule) { size_t ic; switch (this->type()) { case colvarvalue::type_scalar: - this->real_value = cvm::main()->rand_gaussian(); + this->real_value = cvmodule->rand_gaussian(); break; case colvarvalue::type_3vector: case colvarvalue::type_unit3vector: case colvarvalue::type_unit3vectorderiv: - this->rvector_value.x = cvm::main()->rand_gaussian(); - this->rvector_value.y = cvm::main()->rand_gaussian(); - this->rvector_value.z = cvm::main()->rand_gaussian(); + this->rvector_value.x = cvmodule->rand_gaussian(); + this->rvector_value.y = cvmodule->rand_gaussian(); + this->rvector_value.z = cvmodule->rand_gaussian(); break; case colvarvalue::type_quaternion: case colvarvalue::type_quaternionderiv: - this->quaternion_value.q0 = cvm::main()->rand_gaussian(); - this->quaternion_value.q1 = cvm::main()->rand_gaussian(); - this->quaternion_value.q2 = cvm::main()->rand_gaussian(); - this->quaternion_value.q3 = cvm::main()->rand_gaussian(); + this->quaternion_value.q0 = cvmodule->rand_gaussian(); + this->quaternion_value.q1 = cvmodule->rand_gaussian(); + this->quaternion_value.q2 = cvmodule->rand_gaussian(); + this->quaternion_value.q3 = cvmodule->rand_gaussian(); break; case colvarvalue::type_vector: for (ic = 0; ic < this->vector1d_value.size(); ic++) { - this->vector1d_value[ic] = cvm::main()->rand_gaussian(); + this->vector1d_value[ic] = cvmodule->rand_gaussian(); } break; case colvarvalue::type_notset: @@ -419,8 +431,10 @@ void colvarvalue::set_ones(cvm::real assigned_value) void colvarvalue::undef_op() const { - cvm::error_static("Error: Undefined operation on a colvar of type \""+ +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: Undefined operation on a colvar of type \""+ type_desc(this->type())+"\".\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } @@ -646,9 +660,11 @@ cvm::real colvarvalue::dist2(colvarvalue const &x2) const return (this->vector1d_value - x2.vector1d_value).norm2(); case colvarvalue::type_unit3vectorderiv: case colvarvalue::type_quaternionderiv: - cvm::error_static("Error: computing a squared-distance between two variables of type \"" + +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: computing a squared-distance between two variables of type \"" + type_desc(this->type()) + "\", for which it is not defined.\n", COLVARS_BUG_ERROR); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK case colvarvalue::type_notset: default: this->undef_op(); @@ -684,9 +700,11 @@ colvarvalue colvarvalue::dist2_grad(colvarvalue const &x2) const break; case colvarvalue::type_unit3vectorderiv: case colvarvalue::type_quaternionderiv: - cvm::error_static("Error: computing a squared-distance gradient between two variables of type \"" + +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: computing a squared-distance gradient between two variables of type \"" + type_desc(this->type()) + "\", for which it is not defined.\n", COLVARS_BUG_ERROR); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK case colvarvalue::type_notset: default: this->undef_op(); @@ -706,8 +724,10 @@ colvarvalue const colvarvalue::interpolate(colvarvalue const &x1, colvarvalue::check_types(x1, x2); if ((lambda < 0.0) || (lambda > 1.0)) { - cvm::error_static("Error: trying to interpolate between two colvarvalues with a " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to interpolate between two colvarvalues with a " "lamdba outside [0:1].\n", COLVARS_BUG_ERROR); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } colvarvalue interp = ((1.0-lambda)*x1 + lambda*x2); @@ -724,10 +744,12 @@ colvarvalue const colvarvalue::interpolate(colvarvalue const &x1, case colvarvalue::type_unit3vector: case colvarvalue::type_quaternion: if (interp.norm()/cvm::sqrt(d2) < 1.0e-6) { - cvm::error_static("Error: interpolation between "+cvm::to_str(x1)+" and "+ +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: interpolation between "+cvm::to_str(x1)+" and "+ cvm::to_str(x2)+" with lambda = "+cvm::to_str(lambda)+ " is undefined: result = "+cvm::to_str(interp)+"\n", COLVARS_INPUT_ERROR); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } interp.apply_constraints(); return interp; @@ -745,7 +767,7 @@ std::string colvarvalue::to_simple_string() const { switch (type()) { case colvarvalue::type_scalar: - return cvm::to_str(real_value, 0, cvm::main()->cv_prec); + return cvm::to_str(real_value, 0, cvm::cv_prec); break; case colvarvalue::type_3vector: case colvarvalue::type_unit3vector: @@ -849,8 +871,10 @@ std::ostream & operator << (std::ostream &os, std::vector const &v) template void colvarvalue::read_from_stream_template_(IST &is) { if (type() == colvarvalue::type_notset) { - cvm::error_static("Trying to read from a stream a colvarvalue, " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Trying to read from a stream a colvarvalue, " "which has not yet been assigned a data type.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK } switch (type()) { @@ -1012,8 +1036,10 @@ void colvarvalue::p2leg_opt(colvarvalue const &x, switch (x.value_type) { case colvarvalue::type_scalar: - cvm::error_static("Error: cannot calculate Legendre polynomials " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: cannot calculate Legendre polynomials " "for scalar variables.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return; break; case colvarvalue::type_3vector: @@ -1067,8 +1093,10 @@ void colvarvalue::p2leg_opt(colvarvalue const &x, switch (x.value_type) { case colvarvalue::type_scalar: - cvm::error_static("Error: cannot calculate Legendre polynomials " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: cannot calculate Legendre polynomials " "for scalar variables.\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK break; case colvarvalue::type_3vector: while (xvi != xv_end) { diff --git a/src/colvarvalue.h b/src/colvarvalue.h index bea7199a8..67e674908 100644 --- a/src/colvarvalue.h +++ b/src/colvarvalue.h @@ -214,36 +214,42 @@ class colvarvalue { // Cast to scalar inline operator cvm::real() const { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if (value_type != type_scalar) { - cvm::error_static("Error: trying to use a variable of type \""+ + cvm::error_static(nullptr, "Error: trying to use a variable of type \""+ type_desc(value_type)+"\" as one of type \""+ type_desc(type_scalar)+"\".\n"); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return real_value; } // Cast to 3-vector inline operator cvm::rvector() const { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if ((value_type != type_3vector) && (value_type != type_unit3vector) && (value_type != type_unit3vectorderiv)) { - cvm::error_static("Error: trying to use a variable of type \""+ + cvm::error_static(nullptr, "Error: trying to use a variable of type \""+ type_desc(value_type)+"\" as one of type \""+ type_desc(type_3vector)+"\".\n"); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return rvector_value; } // Cast to quaternion inline operator cvm::quaternion() const { +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) if ((value_type != type_quaternion) && (value_type != type_quaternionderiv)) { - cvm::error_static("Error: trying to use a variable of type \""+ + cvm::error_static(nullptr, "Error: trying to use a variable of type \""+ type_desc(value_type)+"\" as one of type \""+ type_desc(type_quaternion)+"\".\n"); } +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return quaternion_value; } @@ -277,7 +283,7 @@ class colvarvalue { void set_elem(int const i_begin, int const i_end, colvarvalue const &x); /// Make each element a random number in N(0,1) - void set_random(); + void set_random(colvarmodule* cvmodule); /// Make each element equal to the given argument void set_ones(cvm::real assigned_value = 1.0); @@ -396,8 +402,10 @@ inline cvm::real colvarvalue::operator [] (int const i) const switch (value_type) { case colvarvalue::type_notset: default: - cvm::error_static("Error: trying to access a colvar value " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to access a colvar value " "that is not initialized.\n", COLVARS_BUG_ERROR); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return 0.0; break; case colvarvalue::type_scalar: return real_value; break; @@ -419,8 +427,10 @@ inline cvm::real & colvarvalue::operator [] (int const i) switch (value_type) { case colvarvalue::type_notset: default: - cvm::error_static("Error: trying to access a colvar value " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Error: trying to access a colvar value " "that is not initialized.\n", COLVARS_BUG_ERROR); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return real_value; break; case colvarvalue::type_scalar: return real_value; break; @@ -455,24 +465,28 @@ inline int colvarvalue::check_types(colvarvalue const &x1, (x1.type() == type_quaternionderiv))) { return COLVARS_OK; } else { - cvm::error_static("Trying to perform an operation between two colvar " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Trying to perform an operation between two colvar " "values with different types, \""+ colvarvalue::type_desc(x1.type())+ "\" and \""+ colvarvalue::type_desc(x2.type())+ "\".\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return COLVARS_ERROR; } } if (x1.type() == type_vector) { if (x1.vector1d_value.size() != x2.vector1d_value.size()) { - cvm::error_static("Trying to perform an operation between two vector colvar " +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Trying to perform an operation between two vector colvar " "values with different sizes, "+ cvm::to_str(x1.vector1d_value.size())+ " and "+ cvm::to_str(x2.vector1d_value.size())+ ".\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return COLVARS_ERROR; } } @@ -499,9 +513,11 @@ inline int colvarvalue::check_types_assign(colvarvalue::Type const &vt1, return COLVARS_OK; } else { if (vt1 != vt2) { - cvm::error_static("Trying to assign a colvar value with type \""+ +#if defined(COLVARS_DEBUG_SIZE_BOUNDARY_CHECK) + cvm::error_static(nullptr, "Trying to assign a colvar value with type \""+ type_desc(vt2)+"\" to one with type \""+ type_desc(vt1)+"\".\n"); +#endif // COLVARS_DEBUG_SIZE_BOUNDARY_CHECK return COLVARS_ERROR; } } diff --git a/src/cuda/colvar_rotation_derivative_kernel.cu b/src/cuda/colvar_rotation_derivative_kernel.cu index 7d275a52b..294351f50 100644 --- a/src/cuda/colvar_rotation_derivative_kernel.cu +++ b/src/cuda/colvar_rotation_derivative_kernel.cu @@ -68,6 +68,7 @@ __global__ void prepare_derivative_kernel( } int prepare_derivative( + colvarmodule* cvmodule, rotation_derivative_dldq dldq, const cvm::real* S_eigval, const cvm::real* S_eigvec, @@ -92,7 +93,7 @@ int prepare_derivative( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), diff --git a/src/cuda/colvar_rotation_derivative_kernel.h b/src/cuda/colvar_rotation_derivative_kernel.h index 755c3d0a8..f0400735f 100644 --- a/src/cuda/colvar_rotation_derivative_kernel.h +++ b/src/cuda/colvar_rotation_derivative_kernel.h @@ -10,6 +10,7 @@ namespace colvars_gpu { int prepare_derivative( + colvarmodule* cvmodule, rotation_derivative_dldq dldq, const cvm::real* S_eigval, const cvm::real* S_eigvec, diff --git a/src/cuda/colvaratoms_kernel.cu b/src/cuda/colvaratoms_kernel.cu index 89ee4a5f6..12d1d3036 100644 --- a/src/cuda/colvaratoms_kernel.cu +++ b/src/cuda/colvaratoms_kernel.cu @@ -30,6 +30,7 @@ __global__ void atoms_pos_from_proxy_kernel( } int atoms_pos_from_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, const cvm::real* atoms_pos_proxy, cvm::real* atoms_pos_ag, @@ -63,7 +64,7 @@ int atoms_pos_from_proxy( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add atoms_pos_from_proxy node.\n"); + cvmodule->log("Add atoms_pos_from_proxy node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -71,6 +72,7 @@ int atoms_pos_from_proxy( } int atoms_pos_from_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, const cvm::real* atoms_pos_proxy, cvm::real* atoms_pos_ag, @@ -95,7 +97,7 @@ int atoms_pos_from_proxy( &atoms_pos_z_ag, &num_atoms}; if (cvm::debug()) { - cvm::log_static("Run atoms_pos_from_proxy.\n"); + cvmodule->log("Run atoms_pos_from_proxy.\n"); } return checkGPUError(cudaLaunchKernel((void*)atoms_pos_from_proxy_kernel, num_blocks, block_size, args, 0, stream)); @@ -111,6 +113,7 @@ __global__ void change_one_coordinate_kernel( } int change_one_coordinate( + colvarmodule* cvmodule, cvm::real* atoms_pos_ag, size_t atom_id_in_group, int xyz, cvm::real step_size, unsigned int num_atoms, cudaStream_t stream) { int error_code = COLVARS_OK; @@ -118,7 +121,7 @@ int change_one_coordinate( size_t array_id = num_atoms * xyz + atom_id_in_group; void* args[] = {&atoms_pos_ag, &array_id, &step_size}; if (cvm::debug()) { - cvm::log_static("Run change_one_coordinate.\n"); + cvmodule->log("Run change_one_coordinate.\n"); } error_code |= checkGPUError(cudaLaunchKernel( (void*)change_one_coordinate_kernel, @@ -239,6 +242,7 @@ __global__ void atoms_calc_cog_com_kernel( } int atoms_calc_cog_com( + colvarmodule* cvmodule, const cvm::real* atoms_pos_ag, const cvm::real* atoms_mass, unsigned int num_atoms, @@ -289,7 +293,7 @@ int atoms_calc_cog_com( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -297,6 +301,7 @@ int atoms_calc_cog_com( } int atoms_calc_cog( + colvarmodule* cvmodule, const cvm::real* atoms_pos_ag, unsigned int num_atoms, cvm::rvector* d_cog_tmp, @@ -345,7 +350,7 @@ int atoms_calc_cog( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -386,6 +391,7 @@ __global__ void atoms_total_force_from_proxy_kernel( } int atoms_total_force_from_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, const cvm::real* atoms_total_force_proxy, cvm::real* atoms_total_force_ag, @@ -414,7 +420,7 @@ int atoms_total_force_from_proxy( &q, &num_atoms}; if (cvm::debug()) { - cvm::log_static("Run " + cvm::to_str(__func__) + " kernel.\n"); + cvmodule->log("Run " + cvm::to_str(__func__) + " kernel.\n"); } if (rotate) { return checkGPUError(cudaLaunchKernel( @@ -467,6 +473,7 @@ __global__ void apply_colvar_force_to_proxy_kernel( } int apply_main_colvar_force_to_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, cvm::real* atoms_applied_force_proxy, const cvm::real* atoms_grad_ag, @@ -505,7 +512,7 @@ int apply_main_colvar_force_to_proxy( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } if (rotate) { kernelNodeParams.func = (void*)apply_colvar_force_to_proxy_kernel; @@ -518,6 +525,7 @@ int apply_main_colvar_force_to_proxy( } int apply_fitting_colvar_force_to_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, cvm::real* atoms_applied_force_proxy, const cvm::real* atoms_grad_ag, @@ -554,7 +562,7 @@ int apply_fitting_colvar_force_to_proxy( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } kernelNodeParams.func = (void*)apply_colvar_force_to_proxy_kernel; return checkGPUError(cudaGraphAddKernelNode( @@ -718,6 +726,7 @@ __global__ void calc_fit_forces_impl_loop1_kernel( } int calc_fit_gradients_impl_loop1( + colvarmodule* cvmodule, const cvm::real* pos_unrotated, cvm::real* main_grad, const colvars_gpu::rotation_derivative_gpu* rot_deriv, @@ -769,7 +778,7 @@ int calc_fit_gradients_impl_loop1( return COLVARS_OK; } if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -821,6 +830,7 @@ __global__ void calc_fit_forces_impl_loop2_kernel( } int calc_fit_gradients_impl_loop2( + colvarmodule* cvmodule, cvm::real* fit_grad, const colvars_gpu::rotation_derivative_gpu* rot_deriv, const double3* atom_grad, @@ -869,7 +879,7 @@ int calc_fit_gradients_impl_loop2( return COLVARS_OK; } if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -892,6 +902,7 @@ __global__ void apply_translation_kernel( } int apply_translation( + colvarmodule* cvmodule, cvm::real* atoms_pos_ag, cvm::real translation_vector_factor, const cvm::rvector* translation_vector, @@ -919,13 +930,13 @@ int apply_translation( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); - cvm::log_static("x_ptr = " + cvm::to_str((void*)atoms_pos_x_ag) + "\n"); - cvm::log_static("y_ptr = " + cvm::to_str((void*)atoms_pos_y_ag) + "\n"); - cvm::log_static("z_ptr = " + cvm::to_str((void*)atoms_pos_z_ag) + "\n"); - cvm::log_static("pos = " + cvm::to_str((void*)translation_vector) + "\n"); - cvm::log_static("factor = " + cvm::to_str(translation_vector_factor) + "\n"); - cvm::log_static("num_atoms = " + cvm::to_str((int)num_atoms) + "\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); + // cvmodule->log("x_ptr = " + cvm::to_str((void*)atoms_pos_x_ag) + "\n"); + // cvmodule->log("y_ptr = " + cvm::to_str((void*)atoms_pos_y_ag) + "\n"); + // cvmodule->log("z_ptr = " + cvm::to_str((void*)atoms_pos_z_ag) + "\n"); + // cvmodule->log("pos = " + cvm::to_str((void*)translation_vector) + "\n"); + // cvmodule->log("factor = " + cvm::to_str(translation_vector_factor) + "\n"); + // cvmodule->log("num_atoms = " + cvm::to_str((int)num_atoms) + "\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -959,6 +970,7 @@ __global__ void rotate_with_quaternion_kernel( } int rotate_with_quaternion( + colvarmodule* cvmodule, cvm::real* atoms_pos_ag, const cvm::quaternion* q, unsigned int num_atoms, @@ -983,7 +995,7 @@ int rotate_with_quaternion( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -1009,6 +1021,7 @@ __global__ void accumulate_cpu_force_kernel( } int accumulate_cpu_force( + colvarmodule* cvmodule, const cvm::real* h_atoms_force, cvm::real* d_atoms_force, unsigned int num_atoms, @@ -1039,7 +1052,7 @@ int accumulate_cpu_force( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -1078,6 +1091,7 @@ __global__ void apply_force_with_inverse_rotation_kernel( } int apply_force_with_inverse_rotation( + colvarmodule* cvmodule, const cvm::real* atoms_force, const cvm::quaternion* q, const int* atoms_proxy_index, @@ -1113,7 +1127,7 @@ int apply_force_with_inverse_rotation( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -1139,6 +1153,7 @@ __global__ void apply_force_kernel( } int apply_force( + colvarmodule* cvmodule, const cvm::real* atoms_force, const int* atoms_proxy_index, cvm::real* proxy_new_force, @@ -1172,7 +1187,7 @@ int apply_force( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -1180,6 +1195,7 @@ int apply_force( } int calc_fit_forces_impl_loop1( + colvarmodule* cvmodule, const cvm::real* pos_unrotated, cvm::real* main_force, const colvars_gpu::rotation_derivative_gpu* rot_deriv, @@ -1195,15 +1211,16 @@ int calc_fit_forces_impl_loop1( cudaGraph_t& graph, const std::vector& dependencies) { if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return calc_fit_gradients_impl_loop1( - pos_unrotated, main_force, rot_deriv, q, num_atoms_main, + cvmodule, pos_unrotated, main_force, rot_deriv, q, num_atoms_main, num_atoms_fitting, atom_grad, sum_dxdq, dxdC, tbcount, ag_center, ag_rotate, node, graph, dependencies); } int calc_fit_forces_impl_loop2( + colvarmodule* cvmodule, const colvars_gpu::rotation_derivative_gpu* rot_deriv, const double3* atom_grad, const cvm::rmatrix* dxdC, @@ -1253,9 +1270,9 @@ int calc_fit_forces_impl_loop2( return COLVARS_OK; } // cvmodule pointer not available here - // if (cvmodule->debug()) { - // cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); - // } + if (cvm::debug()) { + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); + } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), dependencies.size(), &kernelNodeParams)); diff --git a/src/cuda/colvaratoms_kernel.h b/src/cuda/colvaratoms_kernel.h index d387bcb20..da842dc8d 100644 --- a/src/cuda/colvaratoms_kernel.h +++ b/src/cuda/colvaratoms_kernel.h @@ -11,6 +11,7 @@ namespace colvars_gpu { int atoms_pos_from_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, const cvm::real* atoms_pos_proxy, cvm::real* atoms_pos_ag, @@ -22,6 +23,7 @@ int atoms_pos_from_proxy( // For debug gradients int atoms_pos_from_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, const cvm::real* atoms_pos_proxy, cvm::real* atoms_pos_ag, @@ -30,6 +32,7 @@ int atoms_pos_from_proxy( cudaStream_t stream); int change_one_coordinate( + colvarmodule* cvmodule, cvm::real* atoms_pos_ag, size_t atom_id_in_group, int xyz, cvm::real step_size, @@ -37,6 +40,7 @@ int change_one_coordinate( cudaStream_t stream); int atoms_calc_cog_com( + colvarmodule* cvmodule, const cvm::real* atoms_pos_ag, const cvm::real* atoms_mass, unsigned int num_atoms, @@ -54,6 +58,7 @@ int atoms_calc_cog_com( const std::vector& dependencies); int atoms_calc_cog( + colvarmodule* cvmodule, const cvm::real* atoms_pos_ag, unsigned int num_atoms, cvm::rvector* d_cog_tmp, @@ -66,6 +71,7 @@ int atoms_calc_cog( const std::vector& dependencies); int atoms_total_force_from_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, const cvm::real* atoms_total_force_proxy, cvm::real* atoms_total_force_ag, @@ -76,6 +82,7 @@ int atoms_total_force_from_proxy( cudaStream_t stream); int apply_main_colvar_force_to_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, cvm::real* atoms_applied_force_proxy, const cvm::real* atoms_grad_ag, @@ -89,6 +96,7 @@ int apply_main_colvar_force_to_proxy( const std::vector& dependencies); int apply_fitting_colvar_force_to_proxy( + colvarmodule* cvmodule, const int* atoms_proxy_index, cvm::real* atoms_applied_force_proxy, const cvm::real* atoms_grad_ag, @@ -100,6 +108,7 @@ int apply_fitting_colvar_force_to_proxy( const std::vector& dependencies); int accumulate_cpu_force( + colvarmodule* cvmodule, const cvm::real* h_atoms_force, cvm::real* d_atoms_force, unsigned int num_atoms, @@ -108,6 +117,7 @@ int accumulate_cpu_force( const std::vector& dependencies); int calc_fit_gradients_impl_loop1( + colvarmodule* cvmodule, const cvm::real* pos_unrotated, cvm::real* main_grad, const colvars_gpu::rotation_derivative_gpu* rot_deriv, @@ -124,6 +134,7 @@ int calc_fit_gradients_impl_loop1( const std::vector& dependencies); int calc_fit_gradients_impl_loop2( + colvarmodule* cvmodule, cvm::real* fit_grad, const colvars_gpu::rotation_derivative_gpu* rot_deriv, const double3* atom_grad, @@ -135,6 +146,7 @@ int calc_fit_gradients_impl_loop2( const std::vector& dependencies); int apply_translation( + colvarmodule* cvmodule, cvm::real* atoms_pos_ag, cvm::real translation_vector_factor, const cvm::rvector* translation_vector, @@ -144,6 +156,7 @@ int apply_translation( const std::vector& dependencies); int rotate_with_quaternion( + colvarmodule* cvmodule, cvm::real* atoms_pos_ag, const cvm::quaternion* q, unsigned int num_atoms, @@ -152,6 +165,7 @@ int rotate_with_quaternion( const std::vector& dependencies); int apply_force_with_inverse_rotation( + colvarmodule* cvmodule, const cvm::real* atoms_force, const cvm::quaternion* q, const int* atoms_proxy_index, @@ -163,6 +177,7 @@ int apply_force_with_inverse_rotation( const std::vector& dependencies); int apply_force( + colvarmodule* cvmodule, const cvm::real* atoms_force, const int* atoms_proxy_index, cvm::real* proxy_new_force, @@ -173,6 +188,7 @@ int apply_force( const std::vector& dependencies); int calc_fit_forces_impl_loop1( + colvarmodule* cvmodule, const cvm::real* pos_unrotated, cvm::real* main_force, const colvars_gpu::rotation_derivative_gpu* rot_deriv, @@ -189,6 +205,7 @@ int calc_fit_forces_impl_loop1( const std::vector& dependencies); int calc_fit_forces_impl_loop2( + colvarmodule* cvmodule, const colvars_gpu::rotation_derivative_gpu* rot_deriv, const double3* atom_grad, const cvm::rmatrix* dxdC, diff --git a/src/cuda/colvarcomp_distance_kernel.cu b/src/cuda/colvarcomp_distance_kernel.cu index 0cd26c209..5ec5d2314 100644 --- a/src/cuda/colvarcomp_distance_kernel.cu +++ b/src/cuda/colvarcomp_distance_kernel.cu @@ -58,6 +58,7 @@ __global__ void calc_value_rmsd_kernel( } int calc_value_rmsd( + colvarmodule* cvmodule, const cvm::real* ref_pos, const cvm::real* ag_pos, cvm::real* d_permutation_msds, @@ -138,6 +139,7 @@ __global__ void calc_gradients_rmsd_kernel( } int calc_gradients_rmsd( + colvarmodule* cvmodule, const cvm::real* h_rmsd, const size_t* h_best_perm_index, const cvm::real* ref_pos, @@ -249,6 +251,7 @@ __global__ void calc_force_invgrads_rmsd_kernel( } int calc_force_invgrads_rmsd( + colvarmodule* cvmodule, const bool rotate, const int* atoms_proxy_index, const cvm::real* atoms_total_force_proxy, @@ -399,6 +402,7 @@ __global__ void calc_Jacobian_derivative_rmsd_kernel( } int calc_Jacobian_derivative_rmsd( + colvarmodule* cvmodule, const bool center, const bool rotate, const size_t* h_best_perm_index, diff --git a/src/cuda/colvarcomp_distance_kernel.h b/src/cuda/colvarcomp_distance_kernel.h index eeeafec21..3a9cebd55 100644 --- a/src/cuda/colvarcomp_distance_kernel.h +++ b/src/cuda/colvarcomp_distance_kernel.h @@ -9,6 +9,7 @@ namespace colvars_gpu { int calc_value_rmsd( + colvarmodule* cvmodule, const cvm::real* ref_pos, const cvm::real* ag_pos, cvm::real* d_permutation_msds, @@ -22,6 +23,7 @@ int calc_value_rmsd( const std::vector& dependencies); int calc_gradients_rmsd( + colvarmodule* cvmodule, const cvm::real* h_rmsd, const size_t* h_best_perm_index, const cvm::real* ref_pos, @@ -34,6 +36,7 @@ int calc_gradients_rmsd( const std::vector& dependencies); int calc_force_invgrads_rmsd( + colvarmodule* cvmodule, const bool rotate, const int* atoms_proxy_index, const cvm::real* atoms_total_force_proxy, @@ -51,6 +54,7 @@ int calc_force_invgrads_rmsd( class rotation_derivative_gpu; int calc_Jacobian_derivative_rmsd( + colvarmodule* cvmodule, const bool center, const bool rotate, const size_t* h_best_perm_index, diff --git a/src/cuda/colvartypes_kernel.cu b/src/cuda/colvartypes_kernel.cu index d1a03cb39..080ea9f59 100644 --- a/src/cuda/colvartypes_kernel.cu +++ b/src/cuda/colvartypes_kernel.cu @@ -126,6 +126,7 @@ __global__ void build_overlapping_matrix_kernel( } int build_overlapping_matrix( + colvarmodule* cvmodule, const cvm::real* pos1_x, const cvm::real* pos1_y, const cvm::real* pos1_z, @@ -157,7 +158,7 @@ int build_overlapping_matrix( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), @@ -406,6 +407,7 @@ __global__ void jacobi_4x4_kernel( #undef JACOBI_TOLERANCE int jacobi_4x4( + colvarmodule* cvmodule, double* S_eigvec, double* S_eigval, int* max_reached, @@ -430,7 +432,7 @@ int jacobi_4x4( kernelNodeParams.kernelParams = args; kernelNodeParams.extra = NULL; if (cvm::debug()) { - cvm::log_static("Add " + cvm::to_str(__func__) + " node.\n"); + cvmodule->log("Add " + cvm::to_str(__func__) + " node.\n"); } return checkGPUError(cudaGraphAddKernelNode( &node, graph, dependencies.data(), diff --git a/src/cuda/colvartypes_kernel.h b/src/cuda/colvartypes_kernel.h index 2bdc452db..1c645b0f8 100644 --- a/src/cuda/colvartypes_kernel.h +++ b/src/cuda/colvartypes_kernel.h @@ -9,6 +9,7 @@ namespace colvars_gpu { int build_overlapping_matrix( + colvarmodule* cvmodule, const cvm::real* pos1_x, const cvm::real* pos1_y, const cvm::real* pos1_z, @@ -25,6 +26,7 @@ int build_overlapping_matrix( const std::vector& dependencies); int jacobi_4x4( + colvarmodule* cvmodule, double* S_eigvec, double* S_eigval, int* max_reached, diff --git a/tests/functional/run_colvars_test.cpp b/tests/functional/run_colvars_test.cpp index a95220ad6..d2fe269aa 100644 --- a/tests/functional/run_colvars_test.cpp +++ b/tests/functional/run_colvars_test.cpp @@ -48,6 +48,7 @@ int main(int argc, char *argv[]) { colvarproxy_stub *proxy = new colvarproxy_stub(); colvarmodule *cvmodule = proxy->cvmodule; + fprintf(stderr, "proxy = %p, cvmodule = %p\n", (void*)proxy, (void*)cvmodule); // Initialize simple unit system to test file input err |= proxy->set_unit_system("real", false); @@ -82,8 +83,8 @@ int main(int argc, char *argv[]) { unsigned char * args[2] = { (unsigned char *) "cv", (unsigned char *) "listinputfiles" }; - err |= run_colvarscript_command(proxy->script, 2, args); - cvmodule->log(" " + std::string(get_colvarscript_result())); + err |= run_colvarscript_command(proxy, 2, args); + cvmodule->log(" " + std::string(get_colvarscript_result(proxy))); double const max_gradient_error = proxy->cvmodule->get_max_gradient_error(); if (max_gradient_error > 0.) { diff --git a/tests/functional_gpu/run_colvars_test_cuda.cpp b/tests/functional_gpu/run_colvars_test_cuda.cpp index 6e3f3defe..866fe398e 100644 --- a/tests/functional_gpu/run_colvars_test_cuda.cpp +++ b/tests/functional_gpu/run_colvars_test_cuda.cpp @@ -42,7 +42,7 @@ class colvarproxy_stub_gpu : public colvarproxy { return smp_mode_t::gpu; } std::vector get_available_smp_modes() const override { - std::vector available_modes{ + std::vector available_modes{ smp_mode_t::gpu }; return available_modes; @@ -225,7 +225,7 @@ int colvarproxy_stub_gpu::read_frame_xyz(const char *filename, const bool write_ std::vector positions(atoms_ids.size()); int err = cvmodule->load_coords_xyz(filename, &positions, nullptr, true); // Convert to SOA and copy to GPU - colvarproxy_atoms::atom_buffer_real_t positions_soa; + colvarproxy::atom_buffer_real_t positions_soa; const size_t numAtoms = positions.size(); // if (numAtoms != positions.size()) { // return cvmodule->error("Number of atoms mismatch!\n", COLVARS_ERROR); @@ -253,7 +253,7 @@ int colvarproxy_stub_gpu::read_frame_xyz(const char *filename, const bool write_ if ( !err ) { cvmodule->calc(); cvmodule->it++; - colvarproxy_atoms::atom_buffer_real_t h_applied_forces(3 * numAtoms); + colvarproxy::atom_buffer_real_t h_applied_forces(3 * numAtoms); copy_DtoH(d_mAppliedForces, h_applied_forces.data(), 3 * numAtoms); if (write_force_file) { std::ofstream ofs(force_filename); @@ -343,8 +343,8 @@ int main(int argc, char *argv[]) { unsigned char * args[2] = { (unsigned char *) "cv", (unsigned char *) "listinputfiles" }; - err |= run_colvarscript_command(proxy->script, 2, args); - cvmodule->log(" " + std::string(get_colvarscript_result())); + err |= run_colvarscript_command(proxy, 2, args); + cvmodule->log(" " + std::string(get_colvarscript_result(proxy))); double const max_gradient_error = proxy->cvmodule->get_max_gradient_error(); if (max_gradient_error > 0.) { diff --git a/vmd/src/colvarproxy_vmd.C b/vmd/src/colvarproxy_vmd.C index e23450066..1fa191ae5 100644 --- a/vmd/src/colvarproxy_vmd.C +++ b/vmd/src/colvarproxy_vmd.C @@ -253,7 +253,7 @@ int colvarproxy_vmd::update_input() } else { boundaries_type = boundaries_pbc_triclinic; } - colvarproxy_system::update_pbc_lattice(); + colvarproxy::update_pbc_lattice(); } else { boundaries_type = boundaries_unsupported; }