get_finite_difference_method Subroutine

private subroutine get_finite_difference_method(id, fd, found)

Return a finite_diff_method given the id code. (the id codes begin at 1, are sequential, and uniquely define the method).

Available methods

Where is the user-defined function of and is a "small" perturbation.

References

  • G. E. Mullges, F. Uhlig, "Numerical Algorithms with Fortran", Springer, 1996.
  • G. W. Griffiths, "Numerical Analysis Using R", Cambridge University Press, 2016.

Note

This is the only routine that has to be changed if a new finite difference method is added.

Note

The order within a class is assumed to be the order that we would prefer to use them (e.g., central diffs are first, etc.) This is used in the select_finite_diff_method routine.

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: id

the id code for the method

type(finite_diff_method), intent(out) :: fd

this method (can be used in compute_jacobian)

logical, intent(out) :: found

true if it was found


Called by

proc~~get_finite_difference_method~~CalledByGraph proc~get_finite_difference_method numerical_differentiation_module::get_finite_difference_method proc~get_all_methods_in_class numerical_differentiation_module::get_all_methods_in_class proc~get_all_methods_in_class->proc~get_finite_difference_method proc~get_finite_diff_formula numerical_differentiation_module::get_finite_diff_formula proc~get_finite_diff_formula->proc~get_finite_difference_method proc~initialize_numdiff numerical_differentiation_module::numdiff_type%initialize_numdiff proc~initialize_numdiff->proc~get_finite_difference_method proc~initialize_numdiff->proc~get_all_methods_in_class proc~compute_sparsity_random_2 numerical_differentiation_module::compute_sparsity_random_2 proc~compute_sparsity_random_2->proc~get_all_methods_in_class

Source Code

    subroutine get_finite_difference_method(id,fd,found)

    implicit none

    integer,intent(in)                   :: id     !! the id code for the method
    type(finite_diff_method),intent(out) :: fd     !! this method (can be used
                                                   !! in [[compute_jacobian]])
    logical,intent(out)                  :: found  !! true if it was found

    found = .true.

    select case (id)

    ! 2 point methods
    case(1)
        ! (f(x+h)-f(x)) / h
        fd = finite_diff_method(id,'2-point forward 1',    2,[1,0],[1,-1],1)
    case(2)
        ! (f(x)-f(x-h)) / h
        fd = finite_diff_method(id,'2-point backward 1',   2,[0,-1],[1,-1],1)

    ! 3 point methods
    case(3)
        ! (f(x+h)-f(x-h)) / (2h)
        fd = finite_diff_method(id,'3-point central',    3,[1,-1],[1,-1],2)
    case(4)
        ! (-3f(x)+4f(x+h)-f(x+2h)) / (2h)
        fd = finite_diff_method(id,'3-point forward 2',    3,[0,1,2],[-3,4,-1],2)
    case(5)
        ! (f(x-2h)-4f(x-h)+3f(x)) / (2h)
        fd = finite_diff_method(id,'3-point backward 2',   3,[-2,-1,0],[1,-4,3],2)

    ! 4 point methods
    case(6)
        ! (-2f(x-h)-3f(x)+6f(x+h)-f(x+2h)) / (6h)
        fd = finite_diff_method(id,'4-point forward 2',  4,[-1,0,1,2],[-2,-3,6,-1],6)
    case(7)
        ! (f(x-2h)-6f(x-h)+3f(x)+2f(x+h)) / (6h)
        fd = finite_diff_method(id,'4-point backward 2', 4,[-2,-1,0,1],[1,-6,3,2],6)
    case(8)
        ! (-11f(x)+18f(x+h)-9f(x+2h)+2f(x+3h)) / (6h)
        fd = finite_diff_method(id,'4-point forward 3',  4,[0,1,2,3],[-11,18,-9,2],6)
    case(9)
        ! (-2f(x-3h)+9f(x-2h)-18f(x-h)+11f(x)) / (6h)
        fd = finite_diff_method(id,'4-point backward 3', 4,[-3,-2,-1,0],[-2,9,-18,11],6)

    ! 5 point methods
    case(10)
        ! (f(x-2h)-8f(x-h)+8f(x+h)-f(x+2h)) / (12h)
        fd = finite_diff_method(id,'5-point central',    5,[-2,-1,1,2],[1,-8,8,-1],12)
    case(11)
        ! (-3f(x-h)-10f(x)+18f(x+h)-6f(x+2h)+f(x+3h)) / (12h)
        fd = finite_diff_method(id,'5-point forward 3',  5,[-1,0,1,2,3],[-3,-10,18,-6,1],12)
    case(12)
        ! (-f(x-3h)+6f(x-2h)-18f(x-h)+10f(x)+3f(x+h)) / (12h)
        fd = finite_diff_method(id,'5-point backward 3', 5,[-3,-2,-1,0,1],[-1,6,-18,10,3],12)
    case(13)
        ! (-25f(x)+48f(x+h)-36f(x+2h)+16f(x+3h)-3f(x+4h)) / (12h)
        fd = finite_diff_method(id,'5-point forward 4',  5,[0,1,2,3,4],[-25,48,-36,16,-3],12)
    case(14)
        ! (3f(x-4h)-16f(x-3h)+36f(x-2h)-48f(x-h)+25f(x)) / (12h)
        fd = finite_diff_method(id,'5-point backward 4', 5,[-4,-3,-2,-1,0],[3,-16,36,-48,25],12)

    ! 6 point methods
    case(15)
        ! (3f(x-2h)-30f(x-h)-20f(x)+60f(x+h)-15f(x+2h)+2f(x+3h)) / (60h)
        fd = finite_diff_method(id,'6-point forward 3',  6,[-2,-1,0,1,2,3],[3,-30,-20,60,-15,2],60)
    case(16)
        ! (-2f(x-3h)+15f(x-2h)-60f(x-h)+20f(x)+30f(x+h)-3f(x+2h)) / (60h)
        fd = finite_diff_method(id,'6-point backward 3', 6,[-3,-2,-1,0,1,2],[-2,15,-60,20,30,-3],60)
    case(17)
        ! (-12f(x-h)-65f(x)+120f(x+h)-60f(x+2h)+20f(x+3h)-3f(x+4h)) / (60h)
        fd = finite_diff_method(id,'6-point forward 4',  6,[-1,0,1,2,3,4],[-12,-65,120,-60,20,-3],60)
    case(18)
        ! (3f(x-4h)-20f(x-3h)+60f(x-2h)-120f(x-h)+65f(x)+12f(x+h)) / (60h)
        fd = finite_diff_method(id,'6-point backward 4', 6,[-4,-3,-2,-1,0,1],[3,-20,60,-120,65,12],60)
    case(19)
        ! (-137f(x)+300f(x+h)-300f(x+2h)+200f(x+3h)-75f(x+4h)+12f(x+5h)) / (60h)
        fd = finite_diff_method(id,'6-point forward 5',  6,[0,1,2,3,4,5],[-137,300,-300,200,-75,12],60)
    case(20)
        ! (-12f(x-5h)+75f(x-4h)-200f(x-3h)+300f(x-2h)-300f(x-h)+137f(x)) / (60h)
        fd = finite_diff_method(id,'6-point backward 5', 6,[-5,-4,-3,-2,-1,0],[-12,75,-200,300,-300,137],60)

    ! 7 point methods
    case(21)
        ! (-f(x-3h)+9f(x-2h)-45f(x-h)+45f(x+h)-9f(x+2h)+f(x+3h)) / (60h)
        fd = finite_diff_method(id,'7-point central', 7,[-3,-2,-1,1,2,3],[-1,9,-45,45,-9,1],60)
    case(22)
        ! (2f(x-2h)-24f(x-h)-35f(x)+80f(x+h)-30f(x+2h)+8f(x+3h)-f(x+4h)) / (60h)
        fd = finite_diff_method(id,'7-point forward 4', 7,[-2,-1,0,1,2,3,4],[2,-24,-35,80,-30,8,-1],60)
    case(23)
        ! (f(x-4h)-8f(x-3h)+30f(x-2h)-80f(x-h)+35f(x)+24f(x+h)-2f(x+2h)) / (60h)
        fd = finite_diff_method(id,'7-point backward 4', 7,[-4,-3,-2,-1,0,1,2],[1,-8,30,-80,35,24,-2],60)
    case(24)
        ! (-10f(x-h)-77f(x)+150f(x+h)-100f(x+2h)+50f(x+3h)-15f(x+4h)+2f(x+5h)) / (60h)
        fd = finite_diff_method(id,'7-point forward 5', 7,[-1,0,1,2,3,4,5],[-10,-77,150,-100,50,-15,2],60)
    case(25)
        ! (-2f(x-5h)+15f(x-4h)-50f(x-3h)+100f(x-2h)-150f(x-h)+77f(x)+10f(x+h)) / (60h)
        fd = finite_diff_method(id,'7-point backward 5', 7,[-5,-4,-3,-2,-1,0,1],[-2,15,-50,100,-150,77,10],60)
    case(26)
        ! (-147f(x)+360f(x+h)-450f(x+2h)+400f(x+3h)-225f(x+4h)+72f(x+5h)-10f(x+6h)) / (60h)
        fd = finite_diff_method(id,'7-point forward 6', 7,[0,1,2,3,4,5,6],[-147,360,-450,400,-225,72,-10],60)
    case(27)
        ! (10f(x-6h)-72f(x-5h)+225f(x-4h)-400f(x-3h)+450f(x-2h)-360f(x-h)+147f(x)) / (60h)
        fd = finite_diff_method(id,'7-point backward 6', 7,[-6,-5,-4,-3,-2,-1,0],[10,-72,225,-400,450,-360,147],60)

    ! 8 point methods
    case(28)
        ! (-4f(x-3h)+42f(x-2h)-252f(x-h)-105f(x)+420f(x+h)-126f(x+2h)+28f(x+3h)-3f(x+4h)) / (420h)
        fd = finite_diff_method(id,'8-point forward 4',  8,[-3,-2,-1,0,1,2,3,4],[-4,42,-252,-105,420,-126,28,-3],420)
    case(29)
        ! (3f(x-4h)-28f(x-3h)+126f(x-2h)-420f(x-h)+105f(x)+252f(x+h)-42f(x+2h)+4f(x+3h)) / (420h)
        fd = finite_diff_method(id,'8-point backward 4', 8,[-4,-3,-2,-1,0,1,2,3],[3,-28,126,-420,105,252,-42,4],420)
    case(30)
        ! (10f(x-2h)-140f(x-h)-329f(x)+700f(x+h)-350f(x+2h)+140f(x+3h)-35f(x+4h)+4f(x+5h)) / (420h)
        fd = finite_diff_method(id,'8-point forward 5',  8,[-2,-1,0,1,2,3,4,5],[10,-140,-329,700,-350,140,-35,4],420)
    case(31)
        ! (-4f(x-5h)+35f(x-4h)-140f(x-3h)+350f(x-2h)-700f(x-h)+329f(x)+140f(x+h)-10f(x+2h)) / (420h)
        fd = finite_diff_method(id,'8-point backward 5', 8,[-5,-4,-3,-2,-1,0,1,2],[-4,35,-140,350,-700,329,140,-10],420)
    case(32)
        ! (-60f(x-h)-609f(x)+1260f(x+h)-1050f(x+2h)+700f(x+3h)-315f(x+4h)+84f(x+5h)-10f(x+6h)) / (420h)
        fd = finite_diff_method(id,'8-point forward 6',  8,[-1,0,1,2,3,4,5,6],[-60,-609,1260,-1050,700,-315,84,-10],420)
    case(33)
        ! (10f(x-6h)-84f(x-5h)+315f(x-4h)-700f(x-3h)+1050f(x-2h)-1260f(x-h)+609f(x)+60f(x+h)) / (420h)
        fd = finite_diff_method(id,'8-point backward 6', 8,[-6,-5,-4,-3,-2,-1,0,1],[10,-84,315,-700,1050,-1260,609,60],420)
    case(34)
        ! (-1089f(x)+2940f(x+h)-4410f(x+2h)+4900f(x+3h)-3675f(x+4h)+1764f(x+5h)-490f(x+6h)+60f(x+7h)) / (420h)
        fd = finite_diff_method(id,'8-point forward 7',  8,[0,1,2,3,4,5,6,7],[-1089,2940,-4410,4900,-3675,1764,-490,60],420)
    case(35)
        ! (-60f(x-7h)+490f(x-6h)-1764f(x-5h)+3675f(x-4h)-4900f(x-3h)+4410f(x-2h)-2940f(x-h)+1089f(x)) / (420h)
        fd = finite_diff_method(id,'8-point backward 7', 8,[-7,-6,-5,-4,-3,-2,-1,0],[-60,490,-1764,3675,-4900,4410,-2940,1089],420)

    ! 9 point methods
    case(36)
        ! (3f(x-4h)-32f(x-3h)+168f(x-2h)-672f(x-h)+672f(x+h)-168f(x+2h)+32f(x+3h)-3f(x+4h)) / (840h)
        fd = finite_diff_method(id,'9-point central',    &
                9,[-4,-3,-2,-1,1,2,3,4],[3,-32,168,-672,672,-168,32,-3],840)
    case(37)
        ! (-5f(x-3h)+60f(x-2h)-420f(x-h)-378f(x)+1050f(x+h)-420f(x+2h)+140f(x+3h)-30f(x+4h)+3f(x+5h)) / (840h)
        fd = finite_diff_method(id,'9-point forward 5',  &
                9,[-3,-2,-1,0,1,2,3,4,5],[-5,60,-420,-378,1050,-420,140,-30,3],840)
    case(38)
        ! (-3f(x-5h)+30f(x-4h)-140f(x-3h)+420f(x-2h)-1050f(x-h)+378f(x)+420f(x+h)-60f(x+2h)+5f(x+3h)) / (840h)
        fd = finite_diff_method(id,'9-point backward 5', &
                9,[-5,-4,-3,-2,-1,0,1,2,3],[-3,30,-140,420,-1050,378,420,-60,5],840)
    case(39)
        ! (15f(x-2h)-240f(x-h)-798f(x)+1680f(x+h)-1050f(x+2h)+560f(x+3h)-210f(x+4h)+48f(x+5h)-5f(x+6h)) / (840h)
        fd = finite_diff_method(id,'9-point forward 6',  &
                9,[-2,-1,0,1,2,3,4,5,6],[15,-240,-798,1680,-1050,560,-210,48,-5],840)
    case(40)
        ! (5f(x-6h)-48f(x-5h)+210f(x-4h)-560f(x-3h)+1050f(x-2h)-1680f(x-h)+798f(x)+240f(x+h)-15f(x+2h)) / (840h)
        fd = finite_diff_method(id,'9-point backward 6', &
                9,[-6,-5,-4,-3,-2,-1,0,1,2],[5,-48,210,-560,1050,-1680,798,240,-15],840)
    case(41)
        ! (-105f(x-h)-1338f(x)+2940f(x+h)-2940f(x+2h)+2450f(x+3h)-1470f(x+4h)+588f(x+5h)-140f(x+6h)+15f(x+7h)) / (840h)
        fd = finite_diff_method(id,'9-point forward 7',  &
                9,[-1,0,1,2,3,4,5,6,7],[-105,-1338,2940,-2940,2450,-1470,588,-140,15],840)
    case(42)
        ! (-15f(x-7h)+140f(x-6h)-588f(x-5h)+1470f(x-4h)-2450f(x-3h)+2940f(x-2h)-2940f(x-h)+1338f(x)+105f(x+h)) / (840h)
        fd = finite_diff_method(id,'9-point backward 7', &
                9,[-7,-6,-5,-4,-3,-2,-1,0,1],[-15,140,-588,1470,-2450,2940,-2940,1338,105],840)
    case(43)
        ! (-2283f(x)+6720f(x+h)-11760f(x+2h)+15680f(x+3h)-14700f(x+4h)+9408f(x+5h)-3920f(x+6h)+960f(x+7h)-105f(x+8h)) / (840h)
        fd = finite_diff_method(id,'9-point forward 8',  &
                9,[0,1,2,3,4,5,6,7,8],[-2283,6720,-11760,15680,-14700,9408,-3920,960,-105],840)
    case(44)
        ! (105f(x-8h)-960f(x-7h)+3920f(x-6h)-9408f(x-5h)+14700f(x-4h)-15680f(x-3h)+11760f(x-2h)-6720f(x-h)+2283f(x)) / (840h)
        fd = finite_diff_method(id,'9-point backward 8', &
                9,[-8,-7,-6,-5,-4,-3,-2,-1,0],[105,-960,3920,-9408,14700,-15680,11760,-6720,2283],840)

    ! 11 point methods
    case(500)
        ! (-2f(x-5h)+25f(x-4h)-150f(x-3h)+600f(x-2h)-2100f(x-h)+2100f(x+h)-600f(x+2h)+150f(x+3h)-25f(x+4h)+2f(x+5h)) / (2520h)
        fd = finite_diff_method(id,'11-point central', &
                11,[-5,-4,-3,-2,-1,1,2,3,4,5],[-2,25,-150,600,-2100,2100,-600,150,-25,2],2520)

    ! 13 point methods
    case(600)
        ! (5f(x-6h)-72f(x-5h)+495f(x-4h)-2200f(x-3h)+7425f(x-2h)-23760f(x-h)+23760f(x+h)-7425f(x+2h)+2200f(x+3h)-495f(x+4h)+72f(x+5h)-5f(x+6h)) / (27720h)
        fd = finite_diff_method(id,'13-point central', &
                13,[-6,-5,-4,-3,-2,-1,1,2,3,4,5,6],&
                   [5,-72,495,-2200,7425,-23760,23760,-7425,2200,-495,72,-5],27720)

    ! 15 point methods
    case(700)
        ! (-15f(x-7h)+245f(x-6h)-1911f(x-5h)+9555f(x-4h)-35035f(x-3h)+105105f(x-2h)-315315f(x-h)+315315f(x+h)-105105f(x+2h)+35035f(x+3h)-9555f(x+4h)+1911f(x+5h)-245f(x+6h)+15f(x+7h)) / (360360h)
        fd = finite_diff_method(id,'15-point central', &
                15,[-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7],&
                   [-15,245,-1911,9555,-35035,105105,-315315,315315,-105105,35035,-9555,1911,-245,15],360360)

    ! 17 point methods
    case(800)
        ! (7f(x-8h)-128f(x-7h)+1120f(x-6h)-6272f(x-5h)+25480f(x-4h)-81536f(x-3h)+224224f(x-2h)-640640f(x-h)+640640f(x+h)-224224f(x+2h)+81536f(x+3h)-25480f(x+4h)+6272f(x+5h)-1120f(x+6h)+128f(x+7h)-7f(x+8h)) / (720720h)
        fd = finite_diff_method(id,'17-point central', &
                17,[-8,-7,-6,-5,-4,-3,-2,-1,1,2,3,4,5,6,7,8],&
                   [7,-128,1120,-6272,25480,-81536,224224,-640640,640640,-224224,81536,-25480,6272,-1120,128,-7],720720)

    case default
        found = .false.
    end select

    end subroutine get_finite_difference_method