274 subroutine step_richardson(status, y_delta, dy, deq, t, y, param, a, b, c, p, t_delta)
278 integer,
intent(out) :: status
279 real(kind=
rk),
intent(out) :: y_delta(:), dy(:)
281 real(kind=
rk),
intent(in) :: t
282 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:), t_delta
283 integer,
intent(in) :: p(:)
285 real(kind=
rk) :: t_delta_tmp, t_tmp, y_tmp(
size(y, 1))
286 real(kind=
rk) :: y_delta_small_1(
size(y, 1)), y_delta_small_2(
size(y, 1)), y_delta_big(
size(y, 1))
288 t_delta_tmp = t_delta / 2.0_rk
291 call step_one(status, y_delta_small_1, dy, deq, t_tmp, y_tmp, param, a, b, c, t_delta_tmp)
292 if (status > 0)
return
293 t_tmp = t_tmp + t_delta_tmp
294 y_tmp = y_tmp + y_delta_small_1
295 call step_one(status, y_delta_small_2, dy, deq, t_tmp, y_tmp, param, a, b, c, t_delta_tmp)
296 if (status > 0)
return
298 call step_one(status, y_delta_big, dy, deq, t, y, param, a, b, c, t_delta)
299 if (status > 0)
return
301 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)
366 subroutine step_rkf45(status, y_deltas, dy, deq, t, y, param, t_delta)
370 integer,
intent(out) :: status
371 real(kind=
rk),
intent(out) :: y_deltas(:,:), dy(:)
373 real(kind=
rk),
intent(in) :: t
374 real(kind=
rk),
intent(in) :: y(:), param(:), t_delta
376 real(kind=
rk) :: k1(
size(y, 1)), k2(
size(y, 1)), k3(
size(y, 1))
377 real(kind=
rk) :: k4(
size(y, 1)), k5(
size(y, 1)), k6(
size(y, 1))
379 call deq(status, k1, t, y, param)
380 if (status > 0)
return
382 call deq(status, k2, t + t_delta*1.0_rk/4.0_rk, y + t_delta * ( k1*1.0_rk/4.0_rk), param)
383 if (status > 0)
return
384 call deq(status, k3, t + t_delta*3.0_rk/8.0_rk, y + t_delta * ( k1*3.0_rk/32.0_rk + k2*9.0_rk/32.0_rk), param)
385 if (status > 0)
return
386 call deq(status, k4, t + t_delta*12.0_rk/13.0_rk, y + t_delta * ( k1*1932.0_rk/2197.0_rk - k2*7200.0_rk/2197.0_rk + k3*7296.0_rk/2197.0_rk), param)
387 if (status > 0)
return
388 call deq(status, k5, t + t_delta, y + t_delta * ( k1*439.0_rk/216.0_rk - k2*8.0_rk + k3*3680.0_rk/513.0_rk - k4*845.0_rk/4104.0_rk), param)
389 if (status > 0)
return
390 call deq(status, k6, t + t_delta*1.0_rk/2.0_rk, y + t_delta * (-k1*8.0_rk/27.0_rk + k2*2.0_rk - k3*3544.0_rk/2565.0_rk + k4*1859.0_rk/4104.0_rk - k5*11.0_rk/40.0_rk), param)
391 if (status > 0)
return
392 y_deltas(:,1) = t_delta * (k1*25.0_rk/216.0_rk + k3*1408.0_rk/2565.0_rk + k4*2197.0_rk/4104.0_rk - k5*1.0_rk/5.0_rk)
393 y_deltas(:,2) = t_delta * (k1*16.0_rk/135.0_rk + k3*6656.0_rk/12825.0_rk + k4*28561.0_rk/56430.0_rk - k5*9.0_rk/50.0_rk + k6*2.0_rk/55.0_rk)
414 subroutine step_dp54(status, y_deltas, dy, deq, t, y, param, t_delta)
418 integer,
intent(out) :: status
419 real(kind=
rk),
intent(out) :: y_deltas(:,:), dy(:)
421 real(kind=
rk),
intent(in) :: t
422 real(kind=
rk),
intent(in) :: y(:), param(:), t_delta
424 real(kind=
rk) :: k1(
size(y, 1)), k2(
size(y, 1)), k3(
size(y, 1)), k4(
size(y, 1))
425 real(kind=
rk) :: k5(
size(y, 1)), k6(
size(y, 1)), k7(
size(y, 1))
427 call deq(status, k1, t, y, param)
428 if (status > 0)
return
430 call deq(status, k2, t+t_delta*1.0_rk/5.0_rk, y + t_delta * (k1*1.0_rk/5.0_rk), param)
431 if (status > 0)
return
432 call deq(status, k3, t+t_delta*3.0_rk/10.0_rk, y + t_delta * (k1*3.0_rk/40.0_rk + k2*9.0_rk/40.0_rk), param)
433 if (status > 0)
return
434 call deq(status, k4, t+t_delta*4.0_rk/5.0_rk, 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)
435 if (status > 0)
return
436 call deq(status, k5, t+t_delta*8.0_rk/9.0_rk, 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)
437 if (status > 0)
return
438 call deq(status, k6, t+t_delta, 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)
439 if (status > 0)
return
440 call deq(status, k7, t+t_delta, 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)
441 if (status > 0)
return
442 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)
443 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)
488 subroutine fixed_t_steps(status, istats, solution, deq, t, y, param, a, b, c, p_o, max_pts_o, t_delta_o, t_end_o, t_max_o)
492 integer,
intent(out) :: status, istats(
istats_size)
493 real(kind=
rk),
intent(out) :: solution(:,:)
495 real(kind=
rk),
intent(in) :: t
496 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:)
497 integer,
optional,
intent(in) :: p_o(:), max_pts_o
498 real(kind=
rk),
optional,
intent(in) :: t_delta_o, t_end_o, t_max_o
500 integer :: cur_pnt_idx, y_dim, cur_step, max_steps, p(size(b, 2))
501 real(kind=
rk) :: t_cv, t_delta, y_cv(
size(y, 1)), y_delta(
size(y, 1)), dy(
size(y, 1))
504 max_steps =
size(solution, 2) - 1
506 if (
present(max_pts_o))
then
507 if ((max_steps == 0) .and. (max_pts_o > 1))
then
509 max_steps = max_pts_o - 1
511 max_steps = min(max_pts_o - 1, max_steps)
514 if (
present(t_delta_o))
then
517 if (
present(t_end_o))
then
518 t_delta = (t_end_o - t) / max_steps
524 if (
present(p_o)) p = p_o
532 solution(1, cur_pnt_idx) = t_cv
533 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
535 cur_step = cur_step + 1
537 call step_richardson(status, y_delta, dy, deq, t_cv, y_cv, param, a, b, c, p, t_delta)
540 call step_one(status, y_delta, dy, deq, t_cv, y_cv, param, a, b, c, t_delta)
543 if (status > 0)
return
544 y_cv = y_cv + y_delta
545 t_cv = t_cv + t_delta
547 cur_pnt_idx = cur_pnt_idx + 1
548 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = dy
550 solution(1, cur_pnt_idx) = t_cv
551 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
554 if (
present(t_max_o))
then
555 if (t_cv > t_max_o)
exit
557 if (cur_step >= max_steps)
exit
560 call deq(status, dy, t_cv, y_cv, param)
561 if (status > 0)
return
562 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
631 subroutine fixed_y_steps(status, istats, solution, deq, t, y, param, a, b, c, y_delta_len_targ, t_delta_max, t_delta_min_o, &
632 & 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)
636 integer,
intent(out) :: status, istats(
istats_size)
637 real(kind=
rk),
intent(out) :: solution(:,:)
639 real(kind=
rk),
intent(in) :: t
640 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:), y_delta_len_targ, t_delta_max
641 real(kind=
rk),
optional,
intent(in) :: t_delta_min_o, y_delta_len_tol_o, y_sol_len_max_o, t_max_o
642 integer,
optional,
intent(in) :: max_pts_o, max_bisect_o, y_delta_len_idxs_o(:)
643 logical,
optional,
intent(in) :: no_bisect_error_o
645 integer :: max_bisect, max_pts, cur_pnt_idx, biter, y_dim
646 logical :: no_bisect_error
647 real(kind=
rk) :: y_delta_len_tol, t_delta_min, y_sol_len, bs_tmp1_y_delta_len
648 real(kind=
rk) :: bs_tmp1_t_delta, bs_tmp2_t_delta, t_cv, dy(
size(y, 1))
649 real(kind=
rk) :: bs_tmpc_dy(
size(y, 1)), bs_tmp1_dy(
size(y, 1)), bs_tmp2_dy(
size(y, 1))
650 real(kind=
rk) :: bs_tmp2_y_delta_len, bs_tmpc_y_delta_len, bs_tmpc_t_delta
651 real(kind=
rk) :: y_cv(
size(y, 1)), bs_tmp1_y_delta(
size(y, 1))
652 real(kind=
rk) :: bs_tmp2_y_delta(
size(y, 1)), bs_tmpc_y_delta(
size(y, 1))
654 max_pts =
size(solution, 2)
655 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
657 if (
present(t_delta_min_o)) t_delta_min = t_delta_min_o
659 if (
present(max_bisect_o)) max_bisect = max_bisect_o
660 y_delta_len_tol = y_delta_len_targ / 100.0_rk
661 if (
present(y_delta_len_tol_o)) y_delta_len_tol = y_delta_len_tol_o
662 max_pts =
size(solution, 2)
663 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
664 no_bisect_error = .false.
665 if (
present(no_bisect_error_o)) no_bisect_error = no_bisect_error_o
673 solution(1, cur_pnt_idx) = t_cv
674 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
676 cur_pnt_idx = cur_pnt_idx + 1
678 bs_tmp1_t_delta = t_delta_min
679 call step_one(status, bs_tmp1_y_delta, bs_tmp1_dy, deq, t_cv, y_cv, param, a, b, c, bs_tmp1_t_delta)
681 if (status > 0)
return
682 if (
present(y_delta_len_idxs_o))
then
683 bs_tmp1_y_delta_len = norm2(bs_tmp1_y_delta(y_delta_len_idxs_o))
685 bs_tmp1_y_delta_len = norm2(bs_tmp1_y_delta)
688 bs_tmp2_t_delta = t_delta_max
689 call step_one(status, bs_tmp2_y_delta, bs_tmp2_dy, deq, t_cv, y_cv, param, a, b, c, bs_tmp2_t_delta)
691 if (status > 0)
return
692 if (
present(y_delta_len_idxs_o))
then
693 bs_tmp2_y_delta_len = norm2(bs_tmp2_y_delta(y_delta_len_idxs_o))
695 bs_tmp2_y_delta_len = norm2(bs_tmp2_y_delta)
698 if (bs_tmp2_y_delta_len < bs_tmp1_y_delta_len)
then
699 bs_tmpc_t_delta = bs_tmp1_t_delta
700 bs_tmp1_t_delta = bs_tmp2_t_delta
701 bs_tmp2_t_delta = bs_tmpc_t_delta
702 bs_tmpc_y_delta_len = bs_tmp1_y_delta_len
703 bs_tmp1_y_delta_len = bs_tmp2_y_delta_len
704 bs_tmp2_y_delta_len = bs_tmpc_y_delta_len
705 bs_tmpc_y_delta = bs_tmp1_y_delta
706 bs_tmp1_y_delta = bs_tmp2_y_delta
707 bs_tmp2_y_delta = bs_tmpc_y_delta
708 bs_tmpc_dy = bs_tmp1_dy
709 bs_tmp1_dy = bs_tmp2_dy
710 bs_tmp2_dy = bs_tmpc_dy
713 bs_tmpc_t_delta = bs_tmp2_t_delta
714 bs_tmpc_y_delta_len = bs_tmp2_y_delta_len
715 bs_tmpc_y_delta = bs_tmp2_y_delta
717 if ((bs_tmp1_y_delta_len < y_delta_len_targ) .and. (bs_tmp2_y_delta_len > y_delta_len_targ))
then
719 do while (abs(bs_tmpc_y_delta_len - y_delta_len_targ) > y_delta_len_tol)
720 if (biter > max_bisect)
then
722 if (no_bisect_error)
then
729 bs_tmpc_t_delta = (bs_tmp1_t_delta + bs_tmp2_t_delta) / 2.0_rk
730 call step_one(status, bs_tmpc_y_delta, bs_tmpc_dy, deq, t_cv, y_cv, param, a, b, c, bs_tmpc_t_delta)
732 if (status > 0)
return
733 if (
present(y_delta_len_idxs_o))
then
734 bs_tmpc_y_delta_len = norm2(bs_tmpc_y_delta(y_delta_len_idxs_o))
736 bs_tmpc_y_delta_len = norm2(bs_tmpc_y_delta)
738 if (bs_tmpc_y_delta_len < y_delta_len_targ)
then
739 bs_tmp1_y_delta_len = bs_tmpc_y_delta_len
740 bs_tmp1_t_delta = bs_tmpc_t_delta
742 bs_tmp2_y_delta_len = bs_tmpc_y_delta_len
743 bs_tmp2_t_delta = bs_tmpc_t_delta
749 if (no_bisect_error)
then
755 y_cv = y_cv + bs_tmpc_y_delta
756 t_cv = t_cv + bs_tmpc_t_delta
757 solution(1, cur_pnt_idx) = t_cv
758 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = bs_tmpc_dy
759 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
762 if (
present(y_sol_len_max_o))
then
763 y_sol_len = y_sol_len + bs_tmpc_y_delta_len
764 if (y_sol_len > y_sol_len_max_o)
exit
766 if (
present(t_max_o))
then
767 if (t_cv > t_max_o)
exit
769 if (cur_pnt_idx >= max_pts)
exit
772 call deq(status, dy, t_cv, y_cv, param)
773 if (status > 0)
return
774 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
835 subroutine sloppy_fixed_y_steps(status, istats, solution, deq, t, y, param, a, b, c, y_delta_len_targ, t_delta_ini, t_max_o, &
836 & t_delta_min_o, t_delta_max_o, y_delta_len_idxs_o, adj_short_o, max_pts_o, y_sol_len_max_o)
840 integer,
intent(out) :: status, istats(
istats_size)
841 real(kind=
rk),
intent(out) :: solution(:,:)
843 real(kind=
rk),
intent(in) :: t
844 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:), y_delta_len_targ, t_delta_ini
845 real(kind=
rk),
optional,
intent(in) :: t_delta_min_o, t_delta_max_o, y_sol_len_max_o, t_max_o
846 integer,
optional,
intent(in) :: max_pts_o, y_delta_len_idxs_o(:), adj_short_o
848 integer :: max_pts, cur_pnt_idx, y_dim
849 real(kind=
rk) :: t_delta_min, y_sol_len, t_cv, t_delta, y_delta_len
850 real(kind=
rk) :: y_cv(
size(y, 1)), y_delta(
size(y, 1)), dy(
size(y, 1))
852 max_pts =
size(solution, 2)
853 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
855 if (
present(t_delta_min_o)) t_delta_min = t_delta_min_o
863 solution(1, cur_pnt_idx) = t_cv
864 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
866 cur_pnt_idx = cur_pnt_idx + 1
868 t_delta = t_delta_ini
869 call step_one(status, y_delta, dy, deq, t_cv, y_cv, param, a, b, c, t_delta)
871 if (status > 0)
return
872 if (
present(y_delta_len_idxs_o))
then
873 y_delta_len = norm2(y_delta(y_delta_len_idxs_o))
875 y_delta_len = norm2(y_delta)
877 if ((y_delta_len > y_delta_len_targ) .or.
present(adj_short_o))
then
879 t_delta = t_delta_ini * y_delta_len_targ / y_delta_len
880 t_delta = max(t_delta_min, t_delta)
881 if (
present(t_delta_max_o))
then
882 t_delta = min(t_delta_max_o, t_delta)
885 call step_one(status, y_delta, dy, deq, t_cv, y_cv, param, a, b, c, t_delta)
887 if (status > 0)
return
890 y_cv = y_cv + y_delta
891 t_cv = t_cv + t_delta
892 solution(1, cur_pnt_idx) = t_cv
893 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = dy
894 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
898 if (
present(y_sol_len_max_o))
then
899 if (
present(y_delta_len_idxs_o))
then
900 y_sol_len = y_sol_len + norm2(y_delta(y_delta_len_idxs_o))
902 y_sol_len = y_sol_len + norm2(y_delta)
904 if (y_sol_len > y_sol_len_max_o)
exit
907 if (
present(t_max_o))
then
908 if (t_cv > t_max_o)
exit
911 if (cur_pnt_idx >= max_pts)
exit
914 call deq(status, dy, t_cv, y_cv, param)
915 if (status > 0)
return
916 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
1013 subroutine adaptive_steps(status, istats, solution, deq, t, y, param, a, b, c, p, t_max_o, t_end_o, t_delta_ini_o, &
1014 & 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, &
1015 & error_tol_rel_o, max_pts_o, max_bisect_o, no_bisect_error_o, sdf_o, sdf_tol_o, stepp_o)
1019 integer,
intent(out) :: status, istats(
istats_size)
1020 real(kind=
rk),
intent(out) :: solution(:,:)
1022 real(kind=
rk),
intent(in) :: t
1023 real(kind=
rk),
intent(in) :: y(:), param(:), a(:,:), b(:,:), c(:)
1024 integer,
intent(in) :: p(:)
1025 real(kind=
rk),
optional,
intent(in) :: t_max_o, t_end_o, t_delta_ini_o, t_delta_min_o, t_delta_max_o
1026 real(kind=
rk),
optional,
intent(in) :: t_delta_fac_min_o, t_delta_fac_max_o, t_delta_fac_fdg_o
1027 real(kind=
rk),
optional,
intent(in) :: error_tol_abs_o(:), error_tol_rel_o(:), sdf_tol_o
1028 integer,
optional,
intent(in) :: max_pts_o, max_bisect_o
1029 logical,
optional,
intent(in) :: no_bisect_error_o
1033 integer :: max_pts, cur_pnt_idx, adj_cnt, y_dim, comb_err_nzc
1034 integer :: max_bisect, sp_end_run, sp_sdf_flags, bs_itr
1035 logical :: no_bisect_error, t_delta_end_p, comb_err_msk(size(y, 1))
1036 real(kind=
rk) :: t_delta_fac, y_cv(
size(y, 1)), y1_delta(
size(y, 1)), dy(
size(y, 1))
1037 real(kind=
rk) :: y2_delta(
size(y, 1)), t_delta_ini, t_delta_min, y_deltas(
size(y, 1),
size(b, 2))
1038 real(kind=
rk) :: y_delta_delta(
size(y, 1)), t_delta_fac_max, t_delta_fac_min
1039 real(kind=
rk) :: t_delta_fac_fdg, t_delta_nxt, sdf_tol, error_tol_abs(
size(y, 1))
1040 real(kind=
rk) :: error_tol_rel(
size(y, 1)), comb_err_tol(
size(y, 1)), t_cv, t_delta
1041 real(kind=
rk) :: sp_new_t_delta, bs_tmp1_t_delta, bs_tmp2_t_delta, bs_tmp_t_delta
1042 real(kind=
rk) :: bs_tmp_y_delta(
size(y, 1)), bs_tmp1_dist, bs_tmp2_dist, bs_tmp_dist
1045 if (
present(error_tol_abs_o))
then
1046 if (
size(error_tol_abs_o, 1) <
size(y, 1))
then
1047 error_tol_abs = error_tol_abs_o(1)
1049 error_tol_abs = error_tol_abs_o
1053 if (
present(error_tol_rel_o))
then
1054 if (
size(error_tol_rel_o, 1) <
size(y, 1))
then
1055 error_tol_rel = error_tol_rel_o(1)
1057 error_tol_rel = error_tol_rel_o
1061 if (
present(sdf_tol_o)) sdf_tol = sdf_tol_o
1063 if (
present(t_delta_fac_fdg_o)) t_delta_fac_fdg = t_delta_fac_fdg_o
1065 if (
present(max_bisect_o)) max_bisect = max_bisect_o
1067 if (
present(t_delta_fac_max_o)) t_delta_fac_max = t_delta_fac_max_o
1069 if (
present(t_delta_fac_min_o)) t_delta_fac_min = t_delta_fac_min_o
1071 if (
present(t_delta_min_o)) t_delta_min = t_delta_min_o
1072 if (
present(t_delta_ini_o))
then
1073 t_delta_ini = t_delta_ini_o
1076 if (
present(t_delta_max_o)) t_delta_ini = (t_delta_max_o - t_delta_min) / 2
1078 max_pts =
size(solution, 2)
1079 if (
present(max_pts_o)) max_pts = min(max_pts, max_pts_o);
1080 no_bisect_error = .false.
1081 if (
present(no_bisect_error_o)) no_bisect_error = no_bisect_error_o
1085 t_delta = t_delta_ini
1089 solution(1, cur_pnt_idx) = t_cv
1090 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
1093 if (cur_pnt_idx >= max_pts)
then
1096 cur_pnt_idx = cur_pnt_idx + 1
1098 t_delta_end_p = .false.
1099 if (
present(t_end_o))
then
1100 if (t_cv+t_delta*1.10_rk >= t_end_o)
then
1101 t_delta = t_end_o - t_cv
1102 t_delta_end_p = .true.
1107 call step_all(status, y_deltas, dy, deq, t_cv, y_cv, param, a, b(:,1:2), c, t_delta)
1108 y1_delta = y_deltas(:,1)
1109 y2_delta = y_deltas(:,2)
1110 if (adj_cnt > 1)
then
1115 if (status > 0)
return
1117 y_delta_delta = abs(y1_delta-y2_delta)
1118 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)
1120 comb_err_nzc = count(comb_err_msk)
1121 if (comb_err_nzc == 0)
then
1122 t_delta_fac = t_delta_fac_max
1124 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)))
1125 if (t_delta_fac < 1.0_rk) t_delta_fac = t_delta_fac * t_delta_fac_fdg
1126 if (cur_pnt_idx > 2) t_delta_fac = max(t_delta_fac_min, t_delta_fac)
1127 t_delta_fac = min(t_delta_fac_max, t_delta_fac)
1129 t_delta_nxt = t_delta * t_delta_fac
1130 if (
present(t_delta_min_o))
then
1131 t_delta_nxt = max(t_delta_min_o, t_delta_nxt)
1133 if (
present(t_delta_max_o))
then
1134 t_delta_nxt = min(t_delta_max_o, t_delta_nxt)
1137 if (all(y_delta_delta <= comb_err_tol))
exit
1139 t_delta = t_delta_nxt
1140 t_delta_end_p = .false.
1142 if (
present(t_end_o))
then
1143 if (t_cv + t_delta * 2 >= t_end_o)
then
1144 t_delta = (t_end_o - t_cv) / 2.0_rk
1148 if (
present(stepp_o))
then
1149 call stepp_o(status, sp_end_run, sp_sdf_flags, sp_new_t_delta, cur_pnt_idx, solution, t_delta, y1_delta)
1150 if (sp_new_t_delta > 0)
then
1151 if (
present(t_delta_min_o))
then
1152 sp_new_t_delta = max(t_delta_min_o, sp_new_t_delta)
1154 if (
present(t_delta_max_o))
then
1155 sp_new_t_delta = min(t_delta_max_o, sp_new_t_delta)
1157 t_delta = sp_new_t_delta
1158 call step_one(status, y1_delta, dy, deq, t_cv, y_cv, param, a, b(:,1:1), c, t_delta)
1161 if (sp_sdf_flags > 0)
then
1162 bs_tmp1_t_delta = t_delta_min
1163 call step_one(status, bs_tmp_y_delta, dy, deq, t_cv, y_cv, param, a, b(:,1:1), c, bs_tmp1_t_delta)
1165 if (status > 0)
return
1166 call sdf_o(status, bs_tmp1_dist, sp_sdf_flags, t_cv+bs_tmp1_t_delta, y_cv+bs_tmp_y_delta)
1167 if (status > 0)
return
1168 bs_tmp2_t_delta = t_delta
1169 call step_one(status, bs_tmp_y_delta, dy, deq, t_cv, y_cv, param, a, b(:,1:1), c, bs_tmp2_t_delta)
1171 if (status > 0)
return
1172 call sdf_o(status, bs_tmp2_dist, sp_sdf_flags, t_cv+bs_tmp2_t_delta, y_cv+bs_tmp_y_delta)
1173 if (status > 0)
return
1174 if (bs_tmp2_dist < bs_tmp1_dist)
then
1175 bs_tmp_t_delta = bs_tmp1_t_delta
1176 bs_tmp1_t_delta = bs_tmp2_t_delta
1177 bs_tmp2_t_delta = bs_tmp_t_delta
1178 bs_tmp_dist = bs_tmp1_dist
1179 bs_tmp1_dist = bs_tmp2_dist
1180 bs_tmp2_dist = bs_tmp_dist
1182 if (bs_tmp2_dist >= 0)
then
1185 bs_tmp_t_delta = (bs_tmp1_t_delta + bs_tmp2_t_delta) / 2.0_rk
1186 call step_one(status, bs_tmp_y_delta, dy, deq, t_cv, y_cv, param, a, b(:,1:1), c, bs_tmp_t_delta)
1188 if (status > 0)
return
1189 call sdf_o(status, bs_tmp_dist, sp_sdf_flags, t_cv+bs_tmp_t_delta, y_cv+bs_tmp_y_delta)
1190 if (status > 0)
return
1191 if (abs(bs_tmp_dist) <= sdf_tol)
exit
1192 if (bs_tmp_dist < 0.0_rk)
then
1193 bs_tmp1_t_delta = bs_tmp_t_delta
1194 bs_tmp1_dist = bs_tmp_dist
1196 bs_tmp2_t_delta = bs_tmp_t_delta
1197 bs_tmp2_dist = bs_tmp_dist
1199 bs_itr = bs_itr + 1;
1200 if (bs_itr > max_bisect)
then
1202 if (no_bisect_error)
then
1210 t_delta = bs_tmp_t_delta
1211 y1_delta = bs_tmp_y_delta
1217 y_cv = y_cv + y1_delta
1218 t_cv = t_cv + t_delta
1219 t_delta = t_delta_nxt
1220 solution(1, cur_pnt_idx) = t_cv
1221 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx-1) = dy
1222 solution(2:(2+y_dim-1), cur_pnt_idx) = y_cv
1225 if (
present(stepp_o))
then
1226 if (sp_end_run > 0)
exit
1228 if (
present(t_max_o))
then
1229 if (t_cv > t_max_o)
exit
1231 if (t_delta_end_p)
exit
1234 call deq(status, dy, t_cv, y_cv, param)
1235 if (status > 0)
return
1236 solution((2+y_dim):(2+2*y_dim-1), cur_pnt_idx) = dy
1375 subroutine interpolate_solution(status, istats, solution, src_solution, deq, param, num_src_pts_o, linear_interp_o)
1379 integer,
intent(out) :: status, istats(
istats_size)
1380 real(kind=
rk),
intent(inout) :: solution(:,:)
1381 real(kind=
rk),
intent(in) :: src_solution(:,:)
1382 integer,
optional,
intent(in) :: num_src_pts_o
1384 real(kind=
rk),
intent(in) :: param(:)
1385 logical,
optional,
intent(in) :: linear_interp_o
1387 integer :: new_sol_idx, old_sol_idx, max_idx, num_src_pts, y_dim
1388 logical :: linear_interp
1389 real(kind=
rk) :: t, t0, t1, tu, td
1390 real(kind=
rk),
allocatable :: y0(:), y1(:), dy0(:), dy1(:), yat(:)
1392 linear_interp = .false.
1393 if (
present(linear_interp_o)) linear_interp = linear_interp_o
1394 num_src_pts =
size(src_solution, 2)
1395 if (
present(num_src_pts_o)) num_src_pts = min(num_src_pts_o,
size(src_solution, 2))
1398 y_dim = (
size(src_solution, 1) - 1) /2
1399 max_idx =
size(solution, 2)
1401 do new_sol_idx=1, max_idx
1402 t = solution(1, new_sol_idx)
1403 do while (t > src_solution(1, old_sol_idx))
1404 old_sol_idx = old_sol_idx + 1
1405 if (old_sol_idx > num_src_pts)
then
1411 t0 = src_solution(1, old_sol_idx-1)
1412 t1 = src_solution(1, old_sol_idx)
1413 y0 = src_solution(2:(2+y_dim-1), old_sol_idx-1)
1414 y1 = src_solution(2:(2+y_dim-1), old_sol_idx)
1416 if (linear_interp)
then
1417 yat = (y0 * (t1 - t) + y1 * (t - t0)) / td
1419 dy0 = td * src_solution((2+y_dim):(2+2*y_dim-1), old_sol_idx-1)
1420 dy1 = td * src_solution((2+y_dim):(2+2*y_dim-1), old_sol_idx)
1422 yat = tu * (tu * (tu * (2 * y0 + dy0 - 2 * y1 + dy1) - 2 * dy0 - 3 * y0 + 3 * y1 - dy1) + dy0) + y0
1424 solution(2:(2+y_dim-1), new_sol_idx) = yat
1425 call deq(status, solution((2+y_dim):(2+2*y_dim-1), new_sol_idx), &
1428 if (status > 0)
return