280 subroutine step_richardson(status, y_delta, dy, deq, y, param, a, b, c, p, t_delta)
284 integer,
intent(out) :: status
285 real(kind=
rk),
intent(out) :: y_delta(:), dy(:)
287 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:), t_delta
288 integer,
intent(in) :: p(:)
290 real(kind=
rk) :: t_delta_tmp, t_tmp, y_tmp(
size(y, 1))
291 real(kind=
rk) :: y_delta_small_1(
size(y, 1)), y_delta_small_2(
size(y, 1)), y_delta_big(
size(y, 1))
293 t_delta_tmp = t_delta / 2.0_rk
296 call step_one(status, y_delta_small_1, dy, deq, y_tmp, param, a, b, c, t_delta_tmp)
297 if (status > 0)
return
298 t_tmp = t_tmp + t_delta_tmp
299 y_tmp = y_tmp + y_delta_small_1
300 call step_one(status, y_delta_small_2, dy, deq, y_tmp, param, a, b, c, t_delta_tmp)
301 if (status > 0)
return
303 call step_one(status, y_delta_big, dy, deq, y, param, a, b, c, t_delta)
304 if (status > 0)
return
306 y_delta = y_delta_small_1 + y_delta_small_2 + (y_delta_small_1 + y_delta_small_2 - y_delta_big) / (2**p(1) - 1)
414 subroutine step_dp54(status, y_deltas, dy, deq, y, param, t_delta)
418 integer,
intent(out) :: status
419 real(kind=
rk),
intent(out) :: y_deltas(:,:), dy(:)
421 real(kind=
rk),
intent(in) :: y(:), param(:), t_delta
423 real(kind=
rk) :: k1(
size(y, 1)), k2(
size(y, 1)), k3(
size(y, 1)), k4(
size(y, 1))
424 real(kind=
rk) :: k5(
size(y, 1)), k6(
size(y, 1)), k7(
size(y, 1))
426 call deq(status, k1, y, param)
427 if (status > 0)
return
429 call deq(status, k2, y + t_delta * (k1*1.0_rk/5.0_rk), param)
430 if (status > 0)
return
431 call deq(status, k3, y + t_delta * (k1*3.0_rk/40.0_rk + k2*9.0_rk/40.0_rk), param)
432 if (status > 0)
return
433 call deq(status, k4, y + t_delta * (k1*44.0_rk/45.0_rk - k2*56.0_rk/15.0_rk + k3*32.0_rk/9.0_rk), param)
434 if (status > 0)
return
435 call deq(status, k5, y + t_delta * (k1*19372.0_rk/6561.0_rk - k2*25360.0_rk/2187.0_rk + k3*64448.0_rk/6561.0_rk - k4*212.0_rk/729.0_rk), param)
436 if (status > 0)
return
437 call deq(status, k6, y + t_delta * (k1*9017.0_rk/3168.0_rk - k2*355.0_rk/33.0_rk + k3*46732.0_rk/5247.0_rk + k4*49.0_rk/176.0_rk - k5*5103.0_rk/18656.0_rk), param)
438 if (status > 0)
return
439 call deq(status, k7, y + t_delta * (k1*35.0_rk/384.0_rk + k3*500.0_rk/1113.0_rk + k4*125.0_rk/192.0_rk - k5*2187.0_rk/6784.0_rk + k6*11.0_rk/84.0_rk), param)
440 if (status > 0)
return
441 y_deltas(:,1) = t_delta * (k1*35.0_rk/384.0_rk + k3*500.0_rk/1113.0_rk + k4*125.0_rk/192.0_rk - k5*2187.0_rk/6784.0_rk + k6*11.0_rk/84.0_rk)
442 y_deltas(:,2) = t_delta * (k1*5179.0_rk/57600.0_rk + k3*7571.0_rk/16695.0_rk + k4*393.0_rk/640.0_rk - k5*92097.0_rk/339200.0_rk + k6*187.0_rk/2100.0_rk + k7*1.0_rk/40.0_rk)
486 subroutine fixed_t_steps(status, istats, solution, deq, y, param, a, b, c, p_o, max_pts_o, t_delta_o, t_end_o, t_max_o)
490 integer,
intent(out) :: status, istats(
istats_size)
491 real(kind=
rk),
intent(out) :: solution(:,:)
493 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:)
494 integer,
optional,
intent(in) :: p_o(:), max_pts_o
495 real(kind=
rk),
optional,
intent(in) :: t_delta_o, t_end_o, t_max_o
497 integer :: cur_pnt_idx, y_dim, cur_step, max_steps, p(size(b, 2))
498 real(kind=
rk) :: t_cv, t_delta, y_cv(
size(y, 1)), y_delta(
size(y, 1)), dy(
size(y, 1))
501 max_steps =
size(solution, 2) - 1
503 if (
present(max_pts_o))
then
504 if ((max_steps == 0) .and. (max_pts_o > 1))
then
506 max_steps = max_pts_o - 1
508 max_steps = min(max_pts_o - 1, max_steps)
511 if (
present(t_delta_o))
then
514 if (
present(t_end_o))
then
515 t_delta = (t_end_o - 0.0_rk) / max_steps
521 if (
present(p_o)) p = p_o
529 solution(1, cur_pnt_idx) = t_cv
530 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
532 cur_step = cur_step + 1
534 call step_richardson(status, y_delta, dy, deq, y_cv, param, a, b, c, p, t_delta)
537 call step_one(status, y_delta, dy, deq, y_cv, param, a, b, c, t_delta)
540 if (status > 0)
return
541 y_cv = y_cv + y_delta
542 t_cv = t_cv + t_delta
544 cur_pnt_idx = cur_pnt_idx + 1
545 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = dy
547 solution(1, cur_pnt_idx) = t_cv
548 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
551 if (
present(t_max_o))
then
552 if (t_cv > t_max_o)
exit
554 if (cur_step >= max_steps)
exit
557 call deq(status, dy, y_cv, param)
558 if (status > 0)
return
559 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
627 subroutine fixed_y_steps(status, istats, solution, deq, y, param, a, b, c, y_delta_len_targ, t_delta_max, t_delta_min_o, &
628 & y_delta_len_tol_o, max_bisect_o, no_bisect_error_o, y_delta_len_idxs_o, max_pts_o, y_sol_len_max_o, t_max_o)
632 integer,
intent(out) :: status, istats(
istats_size)
633 real(kind=
rk),
intent(out) :: solution(:,:)
635 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:), y_delta_len_targ, t_delta_max
636 real(kind=
rk),
optional,
intent(in) :: t_delta_min_o, y_delta_len_tol_o, y_sol_len_max_o, t_max_o
637 integer,
optional,
intent(in) :: max_pts_o, max_bisect_o, y_delta_len_idxs_o(:)
638 logical,
optional,
intent(in) :: no_bisect_error_o
640 integer :: max_bisect, max_pts, cur_pnt_idx, biter, y_dim
641 logical :: no_bisect_error
642 real(kind=
rk) :: y_delta_len_tol, t_delta_min, y_sol_len, bs_tmp1_y_delta_len
643 real(kind=
rk) :: bs_tmp1_t_delta, bs_tmp2_t_delta, t_cv, dy(
size(y, 1))
644 real(kind=
rk) :: bs_tmpc_dy(
size(y, 1)), bs_tmp1_dy(
size(y, 1)), bs_tmp2_dy(
size(y, 1))
645 real(kind=
rk) :: bs_tmp2_y_delta_len, bs_tmpc_y_delta_len, bs_tmpc_t_delta
646 real(kind=
rk) :: y_cv(
size(y, 1)), bs_tmp1_y_delta(
size(y, 1))
647 real(kind=
rk) :: bs_tmp2_y_delta(
size(y, 1)), bs_tmpc_y_delta(
size(y, 1))
649 max_pts =
size(solution, 2)
650 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
652 if (
present(t_delta_min_o)) t_delta_min = t_delta_min_o
654 if (
present(max_bisect_o)) max_bisect = max_bisect_o
655 y_delta_len_tol = y_delta_len_targ / 100.0_rk
656 if (
present(y_delta_len_tol_o)) y_delta_len_tol = y_delta_len_tol_o
657 max_pts =
size(solution, 2)
658 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
659 no_bisect_error = .false.
660 if (
present(no_bisect_error_o)) no_bisect_error = no_bisect_error_o
668 solution(1, cur_pnt_idx) = t_cv
669 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
671 cur_pnt_idx = cur_pnt_idx + 1
673 bs_tmp1_t_delta = t_delta_min
674 call step_one(status, bs_tmp1_y_delta, bs_tmp1_dy, deq, y_cv, param, a, b, c, bs_tmp1_t_delta)
676 if (status > 0)
return
677 if (
present(y_delta_len_idxs_o))
then
678 bs_tmp1_y_delta_len = norm2(bs_tmp1_y_delta(y_delta_len_idxs_o))
680 bs_tmp1_y_delta_len = norm2(bs_tmp1_y_delta)
683 bs_tmp2_t_delta = t_delta_max
684 call step_one(status, bs_tmp2_y_delta, bs_tmp2_dy, deq, y_cv, param, a, b, c, bs_tmp2_t_delta)
686 if (status > 0)
return
687 if (
present(y_delta_len_idxs_o))
then
688 bs_tmp2_y_delta_len = norm2(bs_tmp2_y_delta(y_delta_len_idxs_o))
690 bs_tmp2_y_delta_len = norm2(bs_tmp2_y_delta)
693 if (bs_tmp2_y_delta_len < bs_tmp1_y_delta_len)
then
694 bs_tmpc_t_delta = bs_tmp1_t_delta
695 bs_tmp1_t_delta = bs_tmp2_t_delta
696 bs_tmp2_t_delta = bs_tmpc_t_delta
697 bs_tmpc_y_delta_len = bs_tmp1_y_delta_len
698 bs_tmp1_y_delta_len = bs_tmp2_y_delta_len
699 bs_tmp2_y_delta_len = bs_tmpc_y_delta_len
700 bs_tmpc_y_delta = bs_tmp1_y_delta
701 bs_tmp1_y_delta = bs_tmp2_y_delta
702 bs_tmp2_y_delta = bs_tmpc_y_delta
703 bs_tmpc_dy = bs_tmp1_dy
704 bs_tmp1_dy = bs_tmp2_dy
705 bs_tmp2_dy = bs_tmpc_dy
708 bs_tmpc_t_delta = bs_tmp2_t_delta
709 bs_tmpc_y_delta_len = bs_tmp2_y_delta_len
710 bs_tmpc_y_delta = bs_tmp2_y_delta
712 if ((bs_tmp1_y_delta_len < y_delta_len_targ) .and. (bs_tmp2_y_delta_len > y_delta_len_targ))
then
714 do while (abs(bs_tmpc_y_delta_len - y_delta_len_targ) > y_delta_len_tol)
715 if (biter > max_bisect)
then
717 if (no_bisect_error)
then
724 bs_tmpc_t_delta = (bs_tmp1_t_delta + bs_tmp2_t_delta) / 2.0_rk
725 call step_one(status, bs_tmpc_y_delta, bs_tmpc_dy, deq, y_cv, param, a, b, c, bs_tmpc_t_delta)
727 if (status > 0)
return
728 if (
present(y_delta_len_idxs_o))
then
729 bs_tmpc_y_delta_len = norm2(bs_tmpc_y_delta(y_delta_len_idxs_o))
731 bs_tmpc_y_delta_len = norm2(bs_tmpc_y_delta)
733 if (bs_tmpc_y_delta_len < y_delta_len_targ)
then
734 bs_tmp1_y_delta_len = bs_tmpc_y_delta_len
735 bs_tmp1_t_delta = bs_tmpc_t_delta
737 bs_tmp2_y_delta_len = bs_tmpc_y_delta_len
738 bs_tmp2_t_delta = bs_tmpc_t_delta
744 if (no_bisect_error)
then
750 y_cv = y_cv + bs_tmpc_y_delta
751 t_cv = t_cv + bs_tmpc_t_delta
752 solution(1, cur_pnt_idx) = t_cv
753 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = bs_tmpc_dy
754 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
757 if (
present(y_sol_len_max_o))
then
758 y_sol_len = y_sol_len + bs_tmpc_y_delta_len
759 if (y_sol_len > y_sol_len_max_o)
exit
761 if (
present(t_max_o))
then
762 if (t_cv > t_max_o)
exit
764 if (cur_pnt_idx >= max_pts)
exit
767 call deq(status, dy, y_cv, param)
768 if (status > 0)
return
769 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
829 subroutine sloppy_fixed_y_steps(status, istats, solution, deq, y, param, a, b, c, y_delta_len_targ, t_delta_ini, t_max_o, &
830 & t_delta_min_o, t_delta_max_o, y_delta_len_idxs_o, adj_short_o, max_pts_o, y_sol_len_max_o)
834 integer,
intent(out) :: status, istats(
istats_size)
835 real(kind=
rk),
intent(out) :: solution(:,:)
837 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:), y_delta_len_targ, t_delta_ini
838 real(kind=
rk),
optional,
intent(in) :: t_delta_min_o, t_delta_max_o, y_sol_len_max_o, t_max_o
839 integer,
optional,
intent(in) :: max_pts_o, y_delta_len_idxs_o(:), adj_short_o
841 integer :: max_pts, cur_pnt_idx, y_dim
842 real(kind=
rk) :: t_delta_min, y_sol_len, t_cv, t_delta, y_delta_len
843 real(kind=
rk) :: y_cv(
size(y, 1)), y_delta(
size(y, 1)), dy(
size(y, 1))
845 max_pts =
size(solution, 2)
846 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
848 if (
present(t_delta_min_o)) t_delta_min = t_delta_min_o
856 solution(1, cur_pnt_idx) = t_cv
857 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
859 cur_pnt_idx = cur_pnt_idx + 1
861 t_delta = t_delta_ini
862 call step_one(status, y_delta, dy, deq, y_cv, param, a, b, c, t_delta)
864 if (status > 0)
return
865 if (
present(y_delta_len_idxs_o))
then
866 y_delta_len = norm2(y_delta(y_delta_len_idxs_o))
868 y_delta_len = norm2(y_delta)
870 if ((y_delta_len > y_delta_len_targ) .or.
present(adj_short_o))
then
872 t_delta = t_delta_ini * y_delta_len_targ / y_delta_len
873 t_delta = max(t_delta_min, t_delta)
874 if (
present(t_delta_max_o))
then
875 t_delta = min(t_delta_max_o, t_delta)
878 call step_one(status, y_delta, dy, deq, y_cv, param, a, b, c, t_delta)
880 if (status > 0)
return
883 y_cv = y_cv + y_delta
884 t_cv = t_cv + t_delta
885 solution(1, cur_pnt_idx) = t_cv
886 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = dy
887 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
891 if (
present(y_sol_len_max_o))
then
892 if (
present(y_delta_len_idxs_o))
then
893 y_sol_len = y_sol_len + norm2(y_delta(y_delta_len_idxs_o))
895 y_sol_len = y_sol_len + norm2(y_delta)
897 if (y_sol_len > y_sol_len_max_o)
exit
900 if (
present(t_max_o))
then
901 if (t_cv > t_max_o)
exit
904 if (cur_pnt_idx >= max_pts)
exit
907 call deq(status, dy, y_cv, param)
908 if (status > 0)
return
909 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
1005 subroutine adaptive_steps(status, istats, solution, deq, y, param, a, b, c, p, t_max_o, t_end_o, t_delta_ini_o, &
1006 & t_delta_min_o, t_delta_max_o, t_delta_fac_min_o, t_delta_fac_max_o, t_delta_fac_fdg_o, error_tol_abs_o, &
1007 & error_tol_rel_o, max_pts_o, max_bisect_o, no_bisect_error_o, sdf_o, sdf_tol_o, stepp_o)
1011 integer,
intent(out) :: status, istats(
istats_size)
1012 real(kind=
rk),
intent(out) :: solution(:,:)
1014 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:)
1015 integer,
intent(in) :: p(:)
1016 real(kind=
rk),
optional,
intent(in) :: t_max_o, t_end_o, t_delta_ini_o, t_delta_min_o, t_delta_max_o
1017 real(kind=
rk),
optional,
intent(in) :: t_delta_fac_min_o, t_delta_fac_max_o, t_delta_fac_fdg_o
1018 real(kind=
rk),
optional,
intent(in) :: error_tol_abs_o(:), error_tol_rel_o(:), sdf_tol_o
1019 integer,
optional,
intent(in) :: max_pts_o, max_bisect_o
1020 logical,
optional,
intent(in) :: no_bisect_error_o
1024 integer :: max_pts, cur_pnt_idx, adj_cnt, y_dim, comb_err_nzc
1025 integer :: max_bisect, sp_end_run, sp_sdf_flags, bs_itr
1026 logical :: no_bisect_error, t_delta_end_p, comb_err_msk(size(y, 1))
1027 real(kind=
rk) :: t_delta_fac, y_cv(
size(y, 1)), y1_delta(
size(y, 1)), dy(
size(y, 1))
1028 real(kind=
rk) :: y2_delta(
size(y, 1)), t_delta_ini, t_delta_min, y_deltas(
size(y, 1),
size(b, 2))
1029 real(kind=
rk) :: y_delta_delta(
size(y, 1)), t_delta_fac_max, t_delta_fac_min
1030 real(kind=
rk) :: t_delta_fac_fdg, t_delta_nxt, sdf_tol, error_tol_abs(
size(y, 1))
1031 real(kind=
rk) :: error_tol_rel(
size(y, 1)), comb_err_tol(
size(y, 1)), t_cv, t_delta
1032 real(kind=
rk) :: sp_new_t_delta, bs_tmp1_t_delta, bs_tmp2_t_delta, bs_tmp_t_delta
1033 real(kind=
rk) :: bs_tmp_y_delta(
size(y, 1)), bs_tmp1_dist, bs_tmp2_dist, bs_tmp_dist
1036 if (
present(error_tol_abs_o))
then
1037 if (
size(error_tol_abs_o, 1) <
size(y, 1))
then
1038 error_tol_abs = error_tol_abs_o(1)
1040 error_tol_abs = error_tol_abs_o
1044 if (
present(error_tol_rel_o))
then
1045 if (
size(error_tol_rel_o, 1) <
size(y, 1))
then
1046 error_tol_rel = error_tol_rel_o(1)
1048 error_tol_rel = error_tol_rel_o
1052 if (
present(sdf_tol_o)) sdf_tol = sdf_tol_o
1054 if (
present(t_delta_fac_fdg_o)) t_delta_fac_fdg = t_delta_fac_fdg_o
1056 if (
present(max_bisect_o)) max_bisect = max_bisect_o
1058 if (
present(t_delta_fac_max_o)) t_delta_fac_max = t_delta_fac_max_o
1060 if (
present(t_delta_fac_min_o)) t_delta_fac_min = t_delta_fac_min_o
1062 if (
present(t_delta_min_o)) t_delta_min = t_delta_min_o
1063 if (
present(t_delta_ini_o))
then
1064 t_delta_ini = t_delta_ini_o
1067 if (
present(t_delta_max_o)) t_delta_ini = (t_delta_max_o - t_delta_min) / 2
1069 max_pts =
size(solution, 2)
1070 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
1071 no_bisect_error = .false.
1072 if (
present(no_bisect_error_o)) no_bisect_error = no_bisect_error_o
1076 t_delta = t_delta_ini
1080 solution(1, cur_pnt_idx) = t_cv
1081 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
1084 if (cur_pnt_idx >= max_pts)
then
1087 cur_pnt_idx = cur_pnt_idx + 1
1089 t_delta_end_p = .false.
1090 if (
present(t_end_o))
then
1091 if (t_cv+t_delta*1.10_rk >= t_end_o)
then
1092 t_delta = t_end_o - t_cv
1093 t_delta_end_p = .true.
1098 call step_all(status, y_deltas, dy, deq, y_cv, param, a, b(:,1:2), c, t_delta)
1099 y1_delta = y_deltas(:,1)
1100 y2_delta = y_deltas(:,2)
1101 if (adj_cnt > 1)
then
1106 if (status > 0)
return
1108 y_delta_delta = abs(y1_delta-y2_delta)
1109 comb_err_tol = (error_tol_abs + max(abs(solution(2:(y_dim+1), cur_pnt_idx-1)), abs(y_cv + y1_delta)) * error_tol_rel)
1111 comb_err_nzc = count(comb_err_msk)
1112 if (comb_err_nzc == 0)
then
1113 t_delta_fac = t_delta_fac_max
1115 t_delta_fac = (1/sqrt(sum((y_delta_delta / comb_err_tol) ** 2, comb_err_msk) / (comb_err_nzc))) ** (1 + 1/min(p(1), p(2)))
1116 if (t_delta_fac < 1.0_rk) t_delta_fac = t_delta_fac * t_delta_fac_fdg
1117 if (cur_pnt_idx > 2) t_delta_fac = max(t_delta_fac_min, t_delta_fac)
1118 t_delta_fac = min(t_delta_fac_max, t_delta_fac)
1120 t_delta_nxt = t_delta * t_delta_fac
1121 if (
present(t_delta_min_o))
then
1122 t_delta_nxt = max(t_delta_min_o, t_delta_nxt)
1124 if (
present(t_delta_max_o))
then
1125 t_delta_nxt = min(t_delta_max_o, t_delta_nxt)
1128 if (all(y_delta_delta <= comb_err_tol))
exit
1130 t_delta = t_delta_nxt
1131 t_delta_end_p = .false.
1133 if (
present(t_end_o))
then
1134 if (t_cv + t_delta * 2 >= t_end_o)
then
1135 t_delta = (t_end_o - t_cv) / 2.0_rk
1139 if (
present(stepp_o))
then
1140 call stepp_o(status, sp_end_run, sp_sdf_flags, sp_new_t_delta, cur_pnt_idx, solution, t_delta, y1_delta)
1141 if (sp_new_t_delta > 0)
then
1142 if (
present(t_delta_min_o))
then
1143 sp_new_t_delta = max(t_delta_min_o, sp_new_t_delta)
1145 if (
present(t_delta_max_o))
then
1146 sp_new_t_delta = min(t_delta_max_o, sp_new_t_delta)
1148 t_delta = sp_new_t_delta
1149 call step_one(status, y1_delta, dy, deq, y_cv, param, a, b(:,1:1), c, t_delta)
1152 if (sp_sdf_flags > 0)
then
1153 bs_tmp1_t_delta = t_delta_min
1154 call step_one(status, bs_tmp_y_delta, dy, deq, y_cv, param, a, b(:,1:1), c, bs_tmp1_t_delta)
1156 if (status > 0)
return
1157 call sdf_o(status, bs_tmp1_dist, sp_sdf_flags, t_cv+bs_tmp1_t_delta, y_cv+bs_tmp_y_delta)
1158 if (status > 0)
return
1159 bs_tmp2_t_delta = t_delta
1160 call step_one(status, bs_tmp_y_delta, dy, deq, y_cv, param, a, b(:,1:1), c, bs_tmp2_t_delta)
1162 if (status > 0)
return
1163 call sdf_o(status, bs_tmp2_dist, sp_sdf_flags, t_cv+bs_tmp2_t_delta, y_cv+bs_tmp_y_delta)
1164 if (status > 0)
return
1165 if (bs_tmp2_dist < bs_tmp1_dist)
then
1166 bs_tmp_t_delta = bs_tmp1_t_delta
1167 bs_tmp1_t_delta = bs_tmp2_t_delta
1168 bs_tmp2_t_delta = bs_tmp_t_delta
1169 bs_tmp_dist = bs_tmp1_dist
1170 bs_tmp1_dist = bs_tmp2_dist
1171 bs_tmp2_dist = bs_tmp_dist
1173 if (bs_tmp2_dist >= 0)
then
1176 bs_tmp_t_delta = (bs_tmp1_t_delta + bs_tmp2_t_delta) / 2.0_rk
1177 call step_one(status, bs_tmp_y_delta, dy, deq, y_cv, param, a, b(:,1:1), c, bs_tmp_t_delta)
1179 if (status > 0)
return
1180 call sdf_o(status, bs_tmp_dist, sp_sdf_flags, t_cv+bs_tmp_t_delta, y_cv+bs_tmp_y_delta)
1181 if (status > 0)
return
1182 if (abs(bs_tmp_dist) <= sdf_tol)
exit
1183 if (bs_tmp_dist < 0.0_rk)
then
1184 bs_tmp1_t_delta = bs_tmp_t_delta
1185 bs_tmp1_dist = bs_tmp_dist
1187 bs_tmp2_t_delta = bs_tmp_t_delta
1188 bs_tmp2_dist = bs_tmp_dist
1190 bs_itr = bs_itr + 1;
1191 if (bs_itr > max_bisect)
then
1193 if (no_bisect_error)
then
1201 t_delta = bs_tmp_t_delta
1202 y1_delta = bs_tmp_y_delta
1208 y_cv = y_cv + y1_delta
1209 t_cv = t_cv + t_delta
1210 t_delta = t_delta_nxt
1211 solution(1, cur_pnt_idx) = t_cv
1212 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = dy
1213 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
1216 if (
present(stepp_o))
then
1217 if (sp_end_run > 0)
exit
1219 if (
present(t_max_o))
then
1220 if (t_cv > t_max_o)
exit
1222 if (t_delta_end_p)
exit
1225 call deq(status, dy, y_cv, param)
1226 if (status > 0)
return
1227 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
1364 subroutine interpolate_solution(status, istats, solution, src_solution, deq, param, num_src_pts_o, linear_interp_o)
1368 integer,
intent(out) :: status, istats(
istats_size)
1369 real(kind=
rk),
intent(inout) :: solution(:,:)
1370 real(kind=
rk),
intent(in) :: src_solution(:,:)
1371 integer,
optional,
intent(in) :: num_src_pts_o
1373 real(kind=
rk),
intent(in) :: param(:)
1374 logical,
optional,
intent(in) :: linear_interp_o
1376 integer :: new_sol_idx, old_sol_idx, max_idx, num_src_pts, y_dim
1377 logical :: linear_interp
1378 real(kind=
rk) :: t, t0, t1, tu, td
1379 real(kind=
rk),
allocatable :: y0(:), y1(:), dy0(:), dy1(:), yat(:)
1381 linear_interp = .false.
1382 if (
present(linear_interp_o)) linear_interp = linear_interp_o
1383 num_src_pts =
size(src_solution, 2)
1384 if (
present(num_src_pts_o)) num_src_pts = min(num_src_pts_o,
size(src_solution, 2))
1387 y_dim = (
size(src_solution, 1) - 1) /2
1388 max_idx =
size(solution, 2)
1390 do new_sol_idx=1, max_idx
1391 t = solution(1, new_sol_idx)
1392 do while (t > src_solution(1, old_sol_idx))
1393 old_sol_idx = old_sol_idx + 1
1394 if (old_sol_idx > num_src_pts)
then
1400 t0 = src_solution(1, old_sol_idx-1)
1401 t1 = src_solution(1, old_sol_idx)
1402 y0 = src_solution(2:(2+y_dim-1), old_sol_idx-1)
1403 y1 = src_solution(2:(2+y_dim-1), old_sol_idx)
1405 if (linear_interp)
then
1406 yat = (y0 * (t1 - t) + y1 * (t - t0)) / td
1408 dy0 = td * src_solution((2+y_dim):(2+2*y_dim-1), old_sol_idx-1)
1409 dy1 = td * src_solution((2+y_dim):(2+2*y_dim-1), old_sol_idx)
1411 yat = tu * (tu * (tu * (2 * y0 + dy0 - 2 * y1 + dy1) - 2 * dy0 - 3 * y0 + 3 * y1 - dy1) + dy0) + y0
1413 solution(2:(2+y_dim-1), new_sol_idx) = yat
1414 call deq(status, solution((2+y_dim):(2+2*y_dim-1), new_sol_idx), &
1416 if (status > 0)
return