diff --git a/src/reactmicp/solver/runner.cpp b/src/reactmicp/solver/runner.cpp index 58d762e..e11c5a2 100644 --- a/src/reactmicp/solver/runner.cpp +++ b/src/reactmicp/solver/runner.cpp @@ -1,231 +1,237 @@ /* ============================================================================= Copyright (c) 2014 - 2016 F. Georget Princeton University All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ============================================================================= */ #include "runner.hpp" #include "timestepper.hpp" #include "timestepper_structs.hpp" #include "reactive_transport_solver.hpp" #include "reactive_transport_solver_structs.hpp" #include "reactmicp/io/reactive_transport.hpp" #include "staggers_base/variables_base.hpp" #include "specmicp_common/timer.hpp" #include "specmicp_common/io/csv_formatter.hpp" #include "specmicp_common/filesystem.hpp" #include namespace specmicp { namespace reactmicp { namespace solver { struct ReactiveTransportRunner::ReactiveTransportRunnerImpl { ReactiveTransportRunnerImpl( ReactiveTransportSolver& solver, scalar_t lower_dt_bound, scalar_t upper_dt_bound, const SimulationInformation& info ): m_solver(solver), m_timestepper(lower_dt_bound, upper_dt_bound, 0, 2.0), m_simulinfo(info) { } index_t m_cnt{0}; ReactiveTransportSolver& m_solver; Timestepper m_timestepper; const SimulationInformation& m_simulinfo; output_f m_output_function{dummy_output}; scalar_t m_output_target; + std::string m_iter_path {}; scalar_t run_until(scalar_t target, VariablesBasePtr variables); }; ReactiveTransportRunner::ReactiveTransportRunner( ReactiveTransportSolver& solver, scalar_t lower_dt_bound, scalar_t upper_dt_bound, const SimulationInformation& info): m_impl(utils::make_pimpl( solver, lower_dt_bound, upper_dt_bound, info) ) {} ReactiveTransportRunner::~ReactiveTransportRunner() = default; void ReactiveTransportRunner::set_output_policy(output_f output_policy) { m_impl->m_output_function = output_policy; } ReactiveTransportOptions& ReactiveTransportRunner::get_options() { return m_impl->m_solver.get_options(); } TimestepperOptions& ReactiveTransportRunner::get_timestepper_options() { return m_impl->m_timestepper.get_options(); } ReactiveTransportPerformance& ReactiveTransportRunner::get_perfs() { return m_impl->m_solver.get_perfs(); } ReactiveTransportTimer& ReactiveTransportRunner::get_timer() { return m_impl->m_solver.get_timer(); } scalar_t ReactiveTransportRunner::run_until( scalar_t target, VariablesBasePtr variables ) { return m_impl->run_until(target, variables); } +std::string ReactiveTransportRunner::get_iter_file_path() +{ + return m_impl->m_iter_path; +} + // Implementation scalar_t ReactiveTransportRunner::ReactiveTransportRunnerImpl::run_until( scalar_t target, VariablesBasePtr variables ) { Timer total_time; VariablesBase* vars = variables.get(); total_time.start(); m_timestepper.set_total_target(target); m_output_target = m_timestepper.get_total()+m_simulinfo.output_step; auto filepath = m_simulinfo.complete_filepath( std::string("iter"), std::string("dat")); if (not m_simulinfo.working_dir.empty() and not utils::is_path_absolute(filepath)) { filepath = utils::complete_path(m_simulinfo.working_dir, filepath); } - + m_iter_path = filepath; io::OutFile out_iter(filepath); io::print_reactmicp_header(out_iter); if (m_simulinfo.print_iter_info) { io::print_reactmicp_performance_long_header(out_iter); } scalar_t dt = m_timestepper.get_options().restart_timestep; auto retcode = ReactiveTransportReturnCode::NotConvergedYet; bool last_solved = true; while(retcode >= ReactiveTransportReturnCode::NotConvergedYet and m_timestepper.get_total() < m_timestepper.get_total_target()) { if (m_timestepper.get_total() > 0) last_solved = false; Timer step_timer; step_timer.start(); m_solver.set_clock(m_timestepper.get_total()); retcode = m_solver.solve_timestep(dt, vars); step_timer.stop(); if (m_simulinfo.print_iter_info) io::print_reactmicp_performance_long( out_iter, m_cnt, m_timestepper.get_total()+dt, m_solver.get_perfs() ); dt = m_timestepper.next_timestep( dt, retcode, m_solver.get_perfs().nb_iterations ); if (retcode <= reactmicp::solver::ReactiveTransportReturnCode::NotConvergedYet) { dt = m_timestepper.get_options().restart_timestep; vars->reset_main_variables(); m_solver.set_clock(m_timestepper.get_total()); retcode = m_solver.solve_timestep(dt, vars); if (m_simulinfo.print_iter_info) io::print_reactmicp_performance_long( out_iter, m_cnt, m_timestepper.get_total()+dt, m_solver.get_perfs() ); if (retcode <= reactmicp::solver::ReactiveTransportReturnCode::NotConvergedYet) vars->reset_main_variables(); dt = m_timestepper.next_timestep( dt, retcode, m_solver.get_perfs().nb_iterations ); } ++m_cnt; // output if (m_timestepper.get_total() > m_output_target) { last_solved = true; m_output_function(m_timestepper.get_total(), variables); m_output_target += m_simulinfo.output_step; } if (retcode == reactmicp::solver::ReactiveTransportReturnCode::UserTermination) break; } if (not last_solved) { m_output_function(m_timestepper.get_total(), variables); } total_time.stop(); io::print_reactmicp_end(out_iter, total_time, m_solver.get_timer()); io::print_resource_usage(out_iter); return m_timestepper.get_total(); } } // end namespace solver } // end namespace reactmicp } // end namespace specmicp diff --git a/src/reactmicp/solver/runner.hpp b/src/reactmicp/solver/runner.hpp index 5b22141..e623d94 100644 --- a/src/reactmicp/solver/runner.hpp +++ b/src/reactmicp/solver/runner.hpp @@ -1,157 +1,162 @@ /* ============================================================================= Copyright (c) 2014 - 2016 F. Georget Princeton University All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ============================================================================= */ #ifndef SPECMICP_REACTMICP_SOLVER_RUNNER_HPP #define SPECMICP_REACTMICP_SOLVER_RUNNER_HPP /*! \file reactmicp/solver/runner.hpp \brief Run the reactive transport solver for several timestep */ #include "specmicp_common/types.hpp" #include "specmicp_common/pimpl_ptr.hpp" #include #include #include namespace specmicp { namespace reactmicp { namespace solver { // forward declarations class ReactiveTransportSolver; struct ReactiveTransportOptions; struct ReactiveTransportPerformance; struct ReactiveTransportTimer; struct TimestepperOptions; class VariablesBase; using VariablesBasePtr = std::shared_ptr; //! \struct SimulationInformation //! \brief Information about the simulation struct SPECMICP_DLL_PUBLIC SimulationInformation { std::string name; //!< Name of the simulation std::string output_prefix; //!< prefix for the output files std::string working_dir {""}; bool print_iter_info{true}; //!< If true, print the iteration informations scalar_t output_step; //!< output step SimulationInformation(std::string name_simul, scalar_t outputstep): name(name_simul), output_prefix(name_simul+"_"), output_step(outputstep) {} //! \brief Complete the name of an output file //! //! \param name base name of the file //! \param suffix the suffix for the name //! \return the complete file name std::string complete_filepath( const std::string& name, const std::string& suffix ) const { return output_prefix+name+"."+suffix; } //! \brief Complete the name of an output file //! //! \param name base name of the file //! \param suffix the suffix for the name //! \return the complete file name std::string complete_filepath( std::string&& name, std::string&& suffix ) const { return output_prefix+name+"."+suffix; } }; //! \brief Signature of an output function using output_f = std::function; //! \brief No output = default inline void dummy_output(scalar_t _, VariablesBasePtr __) {} //! \brief Run the reactive transport solver until a target class SPECMICP_DLL_PUBLIC ReactiveTransportRunner { public: //! //! \param solver the reactive transport solver //! \param lower_dt_bound the timestep lower bound //! \param upper_dt_bound the timestep upper bound //! \param info information about the simulation ReactiveTransportRunner(ReactiveTransportSolver& solver, scalar_t lower_dt_bound, scalar_t upper_dt_bound, const SimulationInformation& info); ~ReactiveTransportRunner(); //! \brief Run the solver until a certain target //! //! \param target the target to reach //! \param variables the variables to use scalar_t run_until(scalar_t target, VariablesBasePtr variables); //! \brief Set the output function void set_output_policy(output_f output_policy); //! \brief Returns the options of the reactive transport solver ReactiveTransportOptions& get_options(); //! \brief Returns the options of the timestepper TimestepperOptions& get_timestepper_options(); //! \brief Returns the performance struct of the reactive transport solver ReactiveTransportPerformance& get_perfs(); //! \brief Returns the timer of the reactive transport solver ReactiveTransportTimer& get_timer(); + //! \brief Return the path to the iter file + //! + //! Empty string if no such file + std::string get_iter_file_path(); + private: struct SPECMICP_DLL_LOCAL ReactiveTransportRunnerImpl; utils::pimpl_ptr m_impl; }; } // end namespace solver } // end namespace reactmicp } // end namespace specmicp #endif // SPECMICP_REACTMICP_SOLVER_RUNNER_HPP