diff --git a/ode/impl/KokkosODE_BDF_impl.hpp b/ode/impl/KokkosODE_BDF_impl.hpp index f2c595ce29..dbc5a93310 100644 --- a/ode/impl/KokkosODE_BDF_impl.hpp +++ b/ode/impl/KokkosODE_BDF_impl.hpp @@ -145,8 +145,9 @@ 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); } } @@ -154,6 +155,7 @@ struct BDF_system_wrapper2 { 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); @@ -225,7 +227,7 @@ KOKKOS_FUNCTION void update_D(const int order, const scalar_type factor, template -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, @@ -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(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(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(offset, offset + ode.neqs)); // Jacobian matrix offset += ode.neqs; auto tmp_gesv = Kokkos::subview(temp, Kokkos::ALL(), - Kokkos::pair(offset, offset + ode.neqs + 4)); + Kokkos::pair(offset, offset + ode.neqs + 4)); // Buffer space for gesv calculation offset += ode.neqs + 4; std::cout << "Extract subview from temp2" << std::endl; @@ -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(1, order + 1)); + auto subGamma = Kokkos::subview(gamma, Kokkos::pair(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); diff --git a/ode/impl/KokkosODE_Newton_impl.hpp b/ode/impl/KokkosODE_Newton_impl.hpp index 06d2ca473d..1d0a77e96c 100644 --- a/ode/impl/KokkosODE_Newton_impl.hpp +++ b/ode/impl/KokkosODE_Newton_impl.hpp @@ -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::zero(); @@ -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; @@ -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; } diff --git a/ode/unit_test/Test_ODE_BDF.hpp b/ode/unit_test/Test_ODE_BDF.hpp index d1bae053e2..25a08c92ae 100644 --- a/ode/unit_test/Test_ODE_BDF.hpp +++ b/ode/unit_test/Test_ODE_BDF.hpp @@ -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(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