Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sundials Update #3984

Merged
merged 37 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e7a6e68
simplify sundials interface
gardner48 May 30, 2024
bb78892
add evolve function for adaptive stepping
gardner48 May 31, 2024
1ae9702
add back const, add more ImEx RHS funcs
gardner48 May 31, 2024
6488c63
update error messages
gardner48 Jun 1, 2024
3fd8355
remove Rhs wrappers
gardner48 Jun 1, 2024
4184fce
formatting
gardner48 Jun 1, 2024
83ba924
add more SUNDIALS Rhs wrappers
gardner48 Jun 1, 2024
4d8ac21
add mri
gardner48 Jun 2, 2024
b8eb59d
change post_update to pre_rhs_update
gardner48 Jun 2, 2024
a9f544a
rename update to action
gardner48 Jun 4, 2024
e996090
add post step action
gardner48 Jun 4, 2024
5713a0f
attach post_step functions
gardner48 Jun 4, 2024
f4bf762
make init utilities private
gardner48 Jun 4, 2024
9185992
add utilities to unpack/wrap nvectors/multifabs
gardner48 Jun 4, 2024
f848a68
cleanup
gardner48 Jun 4, 2024
d2d2ae3
formatting
gardner48 Jun 4, 2024
3cccc64
change advance to step
gardner48 Jun 4, 2024
6c9a29a
wrap long lines
gardner48 Jun 4, 2024
d499991
fix comment
gardner48 Jun 4, 2024
7b9d542
clean up naming and comments
gardner48 Jun 4, 2024
5ba0231
add evolve for FE and RK
gardner48 Jun 4, 2024
9e85802
add post stage actions
gardner48 Jun 12, 2024
a7fcaa0
add fast stage and step actions
gardner48 Jun 12, 2024
0466cfe
remove unused flag
gardner48 Jun 12, 2024
09e8bbd
move max steps to base class
gardner48 Jun 12, 2024
61fcc1d
initialize adaptive flags, step counter
gardner48 Jun 12, 2024
5e7be65
formatting
gardner48 Jun 17, 2024
65d80ea
change step back to advance
gardner48 Jun 17, 2024
389e082
add set_post_update wrapper
gardner48 Jun 17, 2024
df85dcc
Merge branch 'AMReX-Codes:development' into sundials-update
gardner48 Jun 17, 2024
0f7b758
remove initialize from base class
gardner48 Jun 18, 2024
1d480ae
fix integrate
gardner48 Jun 18, 2024
93dcbc6
fix comment
gardner48 Jun 18, 2024
d1d85d5
use local context in vector constructors
gardner48 Jun 19, 2024
8c38539
correct error message
gardner48 Jun 19, 2024
2db0d85
update to C++ sundials context wrapper
gardner48 Jun 19, 2024
43912e8
move tolerances to base class
gardner48 Jun 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 56 additions & 14 deletions Src/Base/AMReX_FEIntegrator.H
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,92 @@ private:

amrex::Vector<std::unique_ptr<T> > F_nodes;

void initialize_stages (const T& S_data)
// Current (internal) state and time
amrex::Vector<std::unique_ptr<T> > S_current;
amrex::Real time_current;

void initialize_stages (const T& S_data, const amrex::Real time)
{
// Create data for stage RHS
IntegratorOps<T>::CreateLike(F_nodes, S_data);

// Create and initialize data for current state
IntegratorOps<T>::CreateLike(S_current, S_data, true);
IntegratorOps<T>::Copy(*S_current[0], S_data);

// Set the initial time
time_current = time;
}

public:
FEIntegrator () {}

FEIntegrator (const T& S_data)
FEIntegrator (const T& S_data, const amrex::Real time = 0.0)
{
initialize(S_data);
initialize(S_data, time);
}

virtual ~FEIntegrator () {}

void initialize (const T& S_data) override
void initialize (const T& S_data, const amrex::Real time = 0.0)
{
initialize_stages(S_data);
initialize_stages(S_data, time);
}

amrex::Real advance (T& S_old, T& S_new, amrex::Real time, const amrex::Real time_step) override
amrex::Real advance (T& S_old, T& S_new, amrex::Real time, const amrex::Real dt) override
{
BaseT::timestep = time_step;
// Assume before advance() that S_old is valid data at the current time ("time" argument)
// Assume before step() that S_old is valid data at the current time ("time" argument)
// So we initialize S_new by copying the old state.
IntegratorOps<T>::Copy(S_new, S_old);

// Call the pre RHS hook
BaseT::pre_rhs_action(S_new, time);

// F = RHS(S, t)
T& F = *F_nodes[0];
BaseT::rhs(F, S_new, time);
BaseT::Rhs(F, S_new, time);

// S_new += timestep * dS/dt
IntegratorOps<T>::Saxpy(S_new, BaseT::timestep, F);
IntegratorOps<T>::Saxpy(S_new, dt, F);

// Call the post-update hook for S_new
BaseT::post_update(S_new, time + BaseT::timestep);
// Call the post step hook
BaseT::post_step_action(S_new, time + dt);

// Return timestep
return BaseT::timestep;
return dt;
}

void evolve (T& S_out, const amrex::Real time_out) override
{
amrex::Real dt = BaseT::time_step;
bool stop = false;

for (int step_number = 0; step_number < BaseT::max_steps && !stop; ++step_number)
{
// Adjust step size to reach output time
if (time_out - time_current < dt) {
dt = time_out - time_current;
stop = true;
}

// Call the time integrator step
advance(*S_current[0], S_out, time_current, dt);

// Update current state S_current = S_out
IntegratorOps<T>::Copy(*S_current[0], S_out);

// Update time
time_current += dt;

if (step_number == BaseT::max_steps - 1) {
Error("Did not reach output time in max steps.");
}
}
}

virtual void time_interpolate (const T& /* S_new */, const T& /* S_old */, amrex::Real /* timestep_fraction */, T& /* data */) override
{
amrex::Error("Time interpolation not yet supported by forward euler integrator.");
amrex::Error("Time interpolation not yet supported by the forward euler integrator.");
}

virtual void map_data (std::function<void(T&)> Map) override
Expand Down
238 changes: 181 additions & 57 deletions Src/Base/AMReX_IntegratorBase.H
Original file line number Diff line number Diff line change
Expand Up @@ -161,37 +161,120 @@ struct IntegratorOps<T, std::enable_if_t<std::is_same_v<amrex::MultiFab, T> > >
template<class T>
class IntegratorBase
{
private:
/**
* \brief Fun is the right-hand-side function the integrator will use.
*/
std::function<void(T&, const T&, const amrex::Real)> Fun;

/**
* \brief FastFun is the fast timescale right-hand-side function for a multirate integration problem.
*/
std::function<void(T&, T&, const T&, const amrex::Real)> FastFun;

protected:
/**
* \brief Integrator timestep size (Real)
*/
amrex::Real timestep;

/**
* \brief For multirate problems, the ratio of slow timestep size / fast timestep size (int)
*/
int slow_fast_timestep_ratio = 0;

/**
* \brief For multirate problems, the fast timestep size (Real)
*/
Real fast_timestep = 0.0;

/**
* \brief The post_update function is called by the integrator on state data before using it to evaluate a right-hand side.
*/
std::function<void (T&, amrex::Real)> post_update;
/**
* \brief Rhs is the right-hand-side function the integrator will use.
*/
std::function<void(T& rhs, const T& state, const amrex::Real time)> Rhs;

/**
* \brief RhsIm is the implicit right-hand-side function an ImEx integrator
* will use.
*/
std::function<void(T& rhs, const T& state, const amrex::Real time)> RhsIm;

/**
* \brief RhsEx is the explicit right-hand-side function an ImEx integrator
* will use.
*/
std::function<void(T& rhs, const T& state, const amrex::Real time)> RhsEx;

/**
* \brief RhsFast is the fast timescale right-hand-side function a multirate
* integrator will use.
*/
std::function<void(T& rhs, const T& state, const amrex::Real time)> RhsFast;

/**
* \brief The pre_rhs_action function is called by the integrator on state
* data before using it to evaluate a right-hand side.
*/
std::function<void (T&, amrex::Real)> pre_rhs_action;

/**
* \brief The post_stage_action function is called by the integrator on
* the computed stage just after it is computed
*/
std::function<void (T&, amrex::Real)> post_stage_action;

/**
* \brief The post_step_action function is called by the integrator on
* the computed state just after it is computed
*/
std::function<void (T&, amrex::Real)> post_step_action;

/**
* \brief The post_stage_action function is called by the integrator on
* the computed stage just after it is computed
*/
std::function<void (T&, amrex::Real)> post_fast_stage_action;

/**
* \brief The post_step_action function is called by the integrator on
* the computed state just after it is computed
*/
std::function<void (T&, amrex::Real)> post_fast_step_action;

/**
* \brief Flag to enable/disable adaptive time stepping in single rate
* methods or at the slow time scale in multirate methods (bool)
*/
bool use_adaptive_time_step = false;

/**
* \brief Current integrator time step size (Real)
*/
amrex::Real time_step;

/**
* \brief Step size of the last completed step (Real)
*/
amrex::Real previous_time_step;

/**
* \brief Flag to enable/disable adaptive time stepping at the fast time
* scale in multirate methods (bool)
*/
bool use_adaptive_fast_time_step = false;

/**
* \brief Current integrator fast time scale time step size with multirate
* methods (Real)
*/
amrex::Real fast_time_step;

/**
* \brief Number of integrator time steps (Long)
*/
amrex::Long num_steps = 0;

/**
* \brief Max number of internal steps before an error is returned (Long)
*/
int max_steps = 500;

/**
* \brief Relative tolerance for adaptive time stepping (Real)
*/
amrex::Real rel_tol = 1.0e-4;

/**
* \brief Absolute tolerance for adaptive time stepping (Real)
*/
amrex::Real abs_tol = 1.0e-9;

/**
* \brief Relative tolerance for adaptive time stepping at the fast time
* scale (Real)
*/
amrex::Real fast_rel_tol = 1.0e-4;

/**
* \brief Absolute tolerance for adaptive time stepping at the fast time
* scale (Real)
*/
amrex::Real fast_abs_tol = 1.0e-9;


public:
IntegratorBase () = default;
Expand All @@ -200,71 +283,112 @@ public:

virtual ~IntegratorBase () = default;

virtual void initialize (const T& S_data) = 0;

void set_rhs (std::function<void(T&, const T&, const amrex::Real)> F)
{
Fun = F;
Rhs = F;
}

void set_imex_rhs (std::function<void(T&, const T&, const amrex::Real)> Fi,
std::function<void(T&, const T&, const amrex::Real)> Fe)
{
RhsIm = Fi;
RhsEx = Fe;
}

void set_fast_rhs (std::function<void(T&, const T&, const amrex::Real)> F)
{
RhsFast = F;
}

void set_fast_rhs (std::function<void(T&, T&, const T&, const amrex::Real)> F)
void set_pre_rhs_action (std::function<void (T&, amrex::Real)> A)
{
FastFun = F;
pre_rhs_action = A;
}

void set_slow_fast_timestep_ratio (const int timestep_ratio = 1)
void set_post_stage_action (std::function<void (T&, amrex::Real)> A)
{
slow_fast_timestep_ratio = timestep_ratio;
post_stage_action = A;
}

void set_fast_timestep (const Real fast_dt = 1.0)
void set_post_step_action (std::function<void (T&, amrex::Real)> A)
{
fast_timestep = fast_dt;
post_step_action = A;
}

void set_post_update (std::function<void (T&, amrex::Real)> F)
void set_post_fast_stage_action (std::function<void (T&, amrex::Real)> A)
{
post_update = F;
post_fast_stage_action = A;
}

std::function<void (T&, amrex::Real)> get_post_update ()
void set_post_fast_step_action (std::function<void (T&, amrex::Real)> A)
{
return post_update;
post_fast_step_action = A;
}

std::function<void(T&, const T&, const amrex::Real)> get_rhs ()
void set_post_update (std::function<void (T&, amrex::Real)> A)
{
return Fun;
set_post_stage_action(A);
set_post_step_action(A);
}

std::function<void(T&, T&, const T&, const amrex::Real)> get_fast_rhs ()
amrex::Real get_time_step ()
{
return FastFun;
return time_step;
}

int get_slow_fast_timestep_ratio ()
void set_time_step (amrex::Real dt)
{
return slow_fast_timestep_ratio;
time_step = dt;
use_adaptive_time_step = false;
}

Real get_fast_timestep ()
void set_adaptive_step ()
{
return fast_timestep;
use_adaptive_time_step = true;
}

void rhs (T& S_rhs, const T& S_data, const amrex::Real time)
void set_fast_time_step (amrex::Real dt)
{
Fun(S_rhs, S_data, time);
fast_time_step = dt;
use_adaptive_fast_time_step = false;
}

void fast_rhs (T& S_rhs, T& S_extra, const T& S_data, const amrex::Real time)
void set_adaptive_fast_step ()
{
FastFun(S_rhs, S_extra, S_data, time);
use_adaptive_fast_time_step = true;
}

virtual amrex::Real advance (T& S_old, T& S_new, amrex::Real time, amrex::Real dt) = 0;
void set_max_steps (int steps)
{
max_steps = steps;
}

void set_tolerances (amrex::Real rtol, amrex::Real atol)
{
rel_tol = rtol;
abs_tol = atol;
}

void set_fast_tolerances (amrex::Real rtol, amrex::Real atol)
{
fast_rel_tol = rtol;
fast_abs_tol = atol;
}

/**
* \brief Take a single time step from (time, S_old) to (time + dt, S_new)
* with the given step size.
*/
virtual amrex::Real advance (T& S_old, T& S_new, amrex::Real time,
amrex::Real dt) = 0;

/**
* \brief Evolve the current (internal) integrator state to time_out
*/
virtual void evolve (T& S_out, const amrex::Real time_out) = 0;

virtual void time_interpolate (const T& S_new, const T& S_old, amrex::Real timestep_fraction, T& data) = 0;
virtual void time_interpolate (const T& S_new, const T& S_old,
amrex::Real timestep_fraction, T& data) = 0;

virtual void map_data (std::function<void(T&)> Map) = 0;
};
Expand Down
Loading