Skip to content

Commit

Permalink
ODE: fixing a few issues
Browse files Browse the repository at this point in the history
Some parameters and formulae were not implemented quite right.
At this point the BDF Step actually converges as expected!
  • Loading branch information
lucbv committed Sep 27, 2023
1 parent e977e18 commit f73c0aa
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 13 deletions.
32 changes: 21 additions & 11 deletions ode/impl/KokkosODE_BDF_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,17 @@ struct BDF_system_wrapper2 {
// f = f(t+dt, y)
mySys.evaluate_function(t, dt, y, f);

// rhs = higher order terms + y_{n+1}^i - y_n - dt*f
for (int eqIdx = 0; eqIdx < neqs; ++eqIdx) {
f(eqIdx) = c * f(eqIdx) - psi(eqIdx) - d(eqIdx);
f(eqIdx) = psi(eqIdx) + d(eqIdx) - c * f(eqIdx);
}
}

template <class vec_type, class mat_type>
KOKKOS_FUNCTION void jacobian(const vec_type& y, const mat_type& jac) const {
mySys.evaluate_jacobian(t, dt, y, jac);

// J = I - dt*(dy/dy)
for (int rowIdx = 0; rowIdx < neqs; ++rowIdx) {
for (int colIdx = 0; colIdx < neqs; ++colIdx) {
jac(rowIdx, colIdx) = -dt * jac(rowIdx, colIdx);
Expand Down Expand Up @@ -225,7 +227,7 @@ KOKKOS_FUNCTION void update_D(const int order, const scalar_type factor,

template <class ode_type, class vec_type,
class mat_type, class scalar_type>
KOKKOS_FUNCTION void BDFStep(ode_type& ode, scalar_type t, scalar_type dt,
KOKKOS_FUNCTION void BDFStep(ode_type& ode, scalar_type t, scalar_type& dt,
scalar_type t_end, int& order, int& num_equal_steps,
const int max_newton_iters,
const scalar_type atol, const scalar_type rtol,
Expand All @@ -251,15 +253,15 @@ KOKKOS_FUNCTION void BDFStep(ode_type& ode, scalar_type t, scalar_type dt,
offset += 8;
auto tempD = Kokkos::subview(temp, Kokkos::ALL(), Kokkos::pair<int, int>(offset, offset + 8));
offset += 8;
auto scale = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset;
auto y_predict = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset;
auto d = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset;
auto psi = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset;
auto error = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset;
auto jac = Kokkos::subview(temp, Kokkos::ALL(), Kokkos::pair<int, int>(offset, offset + ode.neqs));
auto scale = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset; // Scaling coefficients for error calculation
auto y_predict = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset; // Initial guess for y_{n+1}
auto d = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset; // Newton update: y_{n+1}^i - y_n
auto psi = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset; // Higher order terms contribution to rhs
auto error = Kokkos::subview(temp, Kokkos::ALL(), offset + 1); ++offset; // Error estimate
auto jac = Kokkos::subview(temp, Kokkos::ALL(), Kokkos::pair<int, int>(offset, offset + ode.neqs)); // Jacobian matrix
offset += ode.neqs;
auto tmp_gesv = Kokkos::subview(temp, Kokkos::ALL(),
Kokkos::pair<int, int>(offset, offset + ode.neqs + 4));
Kokkos::pair<int, int>(offset, offset + ode.neqs + 4)); // Buffer space for gesv calculation
offset += ode.neqs + 4;

std::cout << "Extract subview from temp2" << std::endl;
Expand Down Expand Up @@ -311,17 +313,25 @@ KOKKOS_FUNCTION void BDFStep(ode_type& ode, scalar_type t, scalar_type dt,
}
scale(eqIdx) = atol + rtol*Kokkos::abs(y_predict(eqIdx));
}
KokkosBlas::Experimental::serial_gemv('T', 1.0 / alpha[order], D, gamma, 0.0, psi);

// Compute psi, the sum of the higher order
// contribution to the residual
auto subD = Kokkos::subview(D, Kokkos::ALL(), Kokkos::pair<int, int>(1, order + 1));
auto subGamma = Kokkos::subview(gamma, Kokkos::pair<int, int>(1, order + 1));
KokkosBlas::Experimental::serial_gemv('N', 1.0 / alpha[order], subD, subGamma, 0.0, psi);

std::cout << "Hello 3" << std::endl;

sys.c = dt / alpha[order];
sys.jacobian(y_new, jac);
std::cout << "c=" << sys.c << ", psi=" << psi(0) << ", y_predict=" << y_predict(0) << std::endl;
std::cout << "jac: " << jac(0, 0) << std::endl;
Kokkos::deep_copy(y_new, y_predict);
KokkosODE::Experimental::newton_solver_status newton_status =
KokkosODE::Experimental::Newton::Solve(sys, param, jac, tmp_gesv, y_new, rhs,
update);

std::cout << "Hello 4" << std::endl;
std::cout << "Newton Status: " << (newton_status == KokkosODE::Experimental::newton_solver_status::NLS_SUCCESS ? "converged" : "not converged") << std::endl;
if(newton_status == KokkosODE::Experimental::newton_solver_status::MAX_ITER) {
dt = 0.5*dt;
update_D(order, 0.5, coeffs, tempD, D);
Expand Down
4 changes: 4 additions & 0 deletions ode/impl/KokkosODE_Newton_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ KOKKOS_FUNCTION KokkosODE::Experimental::newton_solver_status NewtonSolve(
using norm_type = typename Kokkos::Details::InnerProductSpaceTraits<
typename vec_type::non_const_value_type>::mag_type;
sys.residual(y0, rhs);
std::cout << "rhs0= " << rhs(0) << std::endl;
const norm_type norm0 = KokkosBlas::serial_nrm2(rhs);
norm_type norm = Kokkos::ArithTraits<norm_type>::zero();

Expand All @@ -61,6 +62,8 @@ KOKKOS_FUNCTION KokkosODE::Experimental::newton_solver_status NewtonSolve(
// with J=du/dx, rhs=f(u_n+update)-f(u_n)
norm = KokkosBlas::serial_nrm2(rhs);

std::cout << "norm=" << norm << std::endl;

if ((norm < (params.rel_tol * norm0)) ||
(it > 0 ? KokkosBlas::serial_nrm2(update) < params.abs_tol : false)) {
return newton_solver_status::NLS_SUCCESS;
Expand All @@ -83,6 +86,7 @@ KOKKOS_FUNCTION KokkosODE::Experimental::newton_solver_status NewtonSolve(

// update solution // x = x + alpha*update
KokkosBlas::serial_axpy(alpha, update, y0);
std::cout << "newton vector y= " << y0(0) << std::endl;
}
return newton_solver_status::MAX_ITER;
}
Expand Down
25 changes: 23 additions & 2 deletions ode/unit_test/Test_ODE_BDF.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,17 +588,38 @@ void test_adaptive_BDF() {
Logistic mySys(1, 1);

constexpr double t_start = 0.0, t_end = 6.0, atol = 1.0e-6, rtol = 1.0e-4;
constexpr int num_steps = 512, max_newton_iters = 10;
constexpr int num_steps = 512, max_newton_iters = 5;
int order = 1, num_equal_steps = 0;
double dt = (t_end - t_start) / num_steps;

vec_type y0("initial conditions", mySys.neqs), y_new("solution", mySys.neqs);
vec_type rhs("rhs", mySys.neqs), update("update", mySys.neqs);
mat_type temp("buffer1", mySys.neqs, 21 + 2*mySys.neqs + 4), temp2("buffer2", 6, 7);

KokkosODE::Impl::BDFStep(mySys, t_start, (t_end - t_start) / num_steps, t_end, order,
// Initial condition
Kokkos::deep_copy(y0, 0.5);

std::cout << "Initial conditions" << std::endl;
std::cout << " y0=" << y0(0) << ", dt=" << dt << std::endl;

// Initialize D
auto D = Kokkos::subview(temp, Kokkos::ALL(), Kokkos::pair<int, int>(0, 8));
D(0, 0) = y0(0);
mySys.evaluate_function(0, 0, y0, rhs);
D(0, 1) = dt*rhs(0);
Kokkos::deep_copy(rhs, 0);

std::cout << "Initial D: {" << D(0, 0) << ", " << D(0, 1) << ", " << D(0, 2) << ", " << D(0, 3)
<< ", " << D(0, 4) << ", " << D(0, 5) << ", " << D(0, 6) << ", " << D(0, 7) << "}" << std::endl;


KokkosODE::Impl::BDFStep(mySys, t_start, dt, t_end, order,
num_equal_steps, max_newton_iters, atol, rtol, 0.2,
y0, y_new, rhs, update, temp, temp2);

std::cout << "dt: " << dt << std::endl;
std::cout << "y_new: " << y_new(0) << std::endl;

} // test_adaptive_BDF()

} // namespace Test
Expand Down

0 comments on commit f73c0aa

Please sign in to comment.