Skip to content

Commit ecd9ece

Browse files
committed
added 6-point methods and updated readme.
1 parent 9eb679a commit ecd9ece

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

README.md

+8-5
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ This is currently an experimental work in progress and is not production ready.
1212
- [x] Specified by the user
1313
- [x] Assume all elements `true`
1414
- [x] Three random points within variable bounds
15-
- [ ] Add additional finite different gradient methods
16-
- [x] 2-point (backward, forward) differences
17-
- [x] 3-point (backward, central, forward) differences
18-
- [x] 4-point (backward 1, backward 2, forward 1, forward 2) differences
19-
- [ ] Higher-order differences...
15+
- [x] Various order finite different gradient methods
16+
- [x] 2-point (backward, forward)
17+
- [x] 3-point (backward, central, forward)
18+
- [x] 4-point (backward 1, backward 2, forward 1, forward 2)
19+
- [x] 5-point (backward 1, backward 2, central, forward 1, forward 2)
20+
- [x] 6-point (backward 1, backward 2, backward 3, forward 1, forward 2, forward 3)
2021
- [x] Perturbations should respect variable bounds
22+
- [x] Neville's process
2123
- [x] Ability to use different methods for different columns
2224
- [x] Jacobian partitioning to compute multiple columns at the same time
25+
- [ ] Estimate the optimal perturbation step size
2326
- [ ] Computing the linear sparsity pattern (constant elements of Jacobian)
2427
- [ ] Add other gradient methods?
2528
- [ ] Also compute Hessian matrix?

src/numerical_differentiation_module.f90

+29-5
Original file line numberDiff line numberDiff line change
@@ -453,14 +453,20 @@ end subroutine get_finite_diff_formula
453453
! * \( (-f(x-3h)+6f(x-2h)-18f(x-h)+10f(x)+3f(x+h)) / (12h) \)
454454
! * \( (-25f(x)+48f(x+h)-36f(x+2h)+16f(x+3h)-3f(x+4h)) / (12h) \)
455455
! * \( (3f(x-4h)-16f(x-3h)+36f(x-2h)-48f(x-h)+25f(x)) / (12h) \)
456+
! * \( (3f(x-2h)-30f(x-h)-20f(x)+60f(x+h)-15f(x+2h)+2f(x+3h)) / (60h) ])
457+
! * \( (-2f(x-3h)+15f(x-2h)-60f(x-h)+20f(x)+30f(x+h)-3f(x+2h)) / (60h) ])
458+
! * \( (-12f(x-h)-65f(x)+120f(x+h)-60f(x+2h)+20f(x+3h)-3f(x+4h)) / (60h) ])
459+
! * \( (3f(x-4h)-20f(x-3h)+60f(x-2h)-120f(x-h)+65f(x)+12f(x+h)) / (60h) ])
460+
! * \( (-137f(x)+300f(x+h)-300f(x+2h)+200f(x+3h)-75f(x+4h)+12f(x+5h)) / (60h) ])
461+
! * \( (-12f(x-5h)+75f(x-4h)-200f(x-3h)+300f(x-2h)-300f(x-h)+137f(x)) / (60h) ])
456462
!
457463
! Where \(f(x)\) is the user-defined function of \(x\)
458464
! and \(h\) is a "small" perturbation.
459465
!
460466
!@note This is the only routine that has to be changed if a new
461467
! finite difference method is added.
462468
!
463-
!@note The order within a class is assumed to be the order that we would perfer
469+
!@note The order within a class is assumed to be the order that we would prefer
464470
! to use them (e.g., central diffs are first, etc.) This is used in
465471
! the [[select_finite_diff_method]] routine.
466472

@@ -469,7 +475,8 @@ subroutine get_finite_difference_method(id,fd,found)
469475
implicit none
470476

471477
integer,intent(in) :: id !! the id code for the method
472-
type(finite_diff_method),intent(out) :: fd !! this method (can be used in [[compute_jacobian]])
478+
type(finite_diff_method),intent(out) :: fd !! this method (can be used
479+
!! in [[compute_jacobian]])
473480
logical,intent(out) :: found !! true if it was found
474481

475482
found = .true.
@@ -517,6 +524,24 @@ subroutine get_finite_difference_method(id,fd,found)
517524
case(14)
518525
! (3f(x-4h)-16f(x-3h)+36f(x-2h)-48f(x-h)+25f(x)) / (12h)
519526
fd = finite_diff_method(id,'5-point backward 1', 5,[-4,-3,-2,-1,0],[3,-16,36,-48,25],12)
527+
case(15)
528+
! (3f(x-2h)-30f(x-h)-20f(x)+60f(x+h)-15f(x+2h)+2f(x+3h)) / (60h)
529+
fd = finite_diff_method(id,'6-point forward 3', 6,[-2,-1,0,1,2,3],[3,-30,-20,60,-15,2],60)
530+
case(16)
531+
! (-2f(x-3h)+15f(x-2h)-60f(x-h)+20f(x)+30f(x+h)-3f(x+2h)) / (60h)
532+
fd = finite_diff_method(id,'6-point backward 3', 6,[-3,-2,-1,0,1,2],[-2,15,-60,20,30,-3],60)
533+
case(17)
534+
! (-12f(x-h)-65f(x)+120f(x+h)-60f(x+2h)+20f(x+3h)-3f(x+4h)) / (60h)
535+
fd = finite_diff_method(id,'6-point forward 2', 6,[-1,0,1,2,3,4],[-12,-65,120,-60,20,-3],60)
536+
case(18)
537+
! (3f(x-4h)-20f(x-3h)+60f(x-2h)-120f(x-h)+65f(x)+12f(x+h)) / (60h)
538+
fd = finite_diff_method(id,'6-point backward 2', 6,[-4,-3,-2,-1,0,1],[3,-20,60,-120,65,12],60)
539+
case(19)
540+
! (-137f(x)+300f(x+h)-300f(x+2h)+200f(x+3h)-75f(x+4h)+12f(x+5h)) / (60h)
541+
fd = finite_diff_method(id,'6-point forward 1', 6,[0,1,2,3,4,5],[-137,300,-300,200,-75,12],60)
542+
case(20)
543+
! (-12f(x-5h)+75f(x-4h)-200f(x-3h)+300f(x-2h)-300f(x-h)+137f(x)) / (60h)
544+
fd = finite_diff_method(id,'6-point backward 1', 6,[-5,-4,-3,-2,-1,0],[-12,75,-200,300,-300,137],60)
520545
case default
521546
found = .false.
522547
end select
@@ -526,7 +551,8 @@ end subroutine get_finite_difference_method
526551

527552
!*******************************************************************************
528553
!>
529-
! Returns all the methods with the given `class`.
554+
! Returns all the methods with the given `class`
555+
! (i.e., number of points in the formula).
530556

531557
function get_all_methods_in_class(class) result(list_of_methods)
532558

@@ -795,14 +821,12 @@ subroutine set_numdiff_bounds(me,xlow,xhigh)
795821
else if (any(xlow>=xhigh)) then
796822
error stop 'Error: all xlow must be < xhigh'
797823
else
798-
799824
if (allocated(me%xlow)) deallocate(me%xlow)
800825
if (allocated(me%xhigh)) deallocate(me%xhigh)
801826
allocate(me%xlow(me%n))
802827
allocate(me%xhigh(me%n))
803828
me%xlow = xlow
804829
me%xhigh = xhigh
805-
806830
end if
807831

808832
end subroutine set_numdiff_bounds

src/tests/test1.f90

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ program test1
3131
integer,parameter :: cache_size = 0 !! `0` indicates not to use cache
3232
!integer,parameter :: cache_size = 1000 ! use cache
3333

34-
do i=1,14 ! try different finite diff methods
34+
do i=1,20 ! try different finite diff methods
3535

3636
func_evals = 0
3737
call my_prob%initialize(n,m,xlow,xhigh,perturb_mode,dpert,&
@@ -66,7 +66,7 @@ program test1
6666

6767
end do
6868

69-
do i=1,14 ! try different finite diff methods
69+
do i=1,20 ! try different finite diff methods
7070

7171
func_evals = 0
7272
call my_prob%initialize(n,m,xlow,xhigh,perturb_mode,dpert,&
@@ -118,7 +118,7 @@ program test1
118118
write(output_unit,'(A)') formula
119119
write(output_unit,'(A)') ''
120120

121-
do i=2,5
121+
do i=2,6
122122

123123
write(output_unit,'(A)') ''
124124
write(output_unit,'(A)') '-------------------'
@@ -140,7 +140,7 @@ program test1
140140

141141
end do
142142

143-
do i=2,5
143+
do i=2,6
144144

145145
write(output_unit,'(A)') ''
146146
write(output_unit,'(A)') '-------------------'

0 commit comments

Comments
 (0)