select_finite_diff_method Subroutine

private subroutine select_finite_diff_method(me, x, xlow, xhigh, dx, list_of_methods, fd, status_ok)

Select a finite diff method of a given class so that the perturbations of x will not violate the variable bounds.

Type Bound

numdiff_type

Arguments

Type IntentOptional Attributes Name
class(numdiff_type), intent(inout) :: me
real(kind=wp), intent(in) :: x

the variable value

real(kind=wp), intent(in) :: xlow

the variable lower bound

real(kind=wp), intent(in) :: xhigh

the variable upper bound

real(kind=wp), intent(in) :: dx

the perturbation value (>0)

type(meth_array), intent(in) :: list_of_methods

list of available methods to choose from

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

this method can be used

logical, intent(out) :: status_ok

true if it really doesn't violate the bounds (say, the bounds are very close to each other) if status_ok=False, then the first method in the given class is returned in fd.


Called by

proc~~select_finite_diff_method~~CalledByGraph proc~select_finite_diff_method numerical_differentiation_module::numdiff_type%select_finite_diff_method proc~compute_jacobian_for_sparsity numerical_differentiation_module::numdiff_type%compute_jacobian_for_sparsity proc~compute_jacobian_for_sparsity->proc~select_finite_diff_method proc~compute_jacobian_standard numerical_differentiation_module::compute_jacobian_standard proc~compute_jacobian_standard->proc~select_finite_diff_method proc~compute_sparsity_random_2 numerical_differentiation_module::compute_sparsity_random_2 proc~compute_sparsity_random_2->proc~compute_jacobian_for_sparsity

Source Code

    subroutine select_finite_diff_method(me,x,xlow,xhigh,dx,list_of_methods,fd,status_ok)

    implicit none

    class(numdiff_type),intent(inout)    :: me
    real(wp),intent(in)                  :: x               !! the variable value
    real(wp),intent(in)                  :: xlow            !! the variable lower bound
    real(wp),intent(in)                  :: xhigh           !! the variable upper bound
    real(wp),intent(in)                  :: dx              !! the perturbation value (>0)
    type(meth_array),intent(in)          :: list_of_methods !! list of available methods to choose from
    type(finite_diff_method),intent(out) :: fd              !! this method can be used
    logical,intent(out)                  :: status_ok       !! true if it really doesn't violate the bounds
                                                            !! (say, the bounds are very close to each other)
                                                            !! if `status_ok=False`, then the first method in
                                                            !! the given class is returned in `fd`.

    integer  :: i   !! counter
    integer  :: j   !! counter
    real(wp) :: xs  !! if `x` is outside the bounds, this is the value
                    !! on the nearest bound. otherwise equal to `x`.
    real(wp) :: xp  !! perturbed `x` value

    ! initialize:
    status_ok = .false.

    if (me%exception_raised) return ! check for exceptions

    ! make sure it is within the bounds
    xs = min(xhigh,max(xlow,x))

    ! try all the methods in the class:
    do i = 1, size(list_of_methods%meth)
        status_ok = .true. ! will be set to false if any
                           ! perturbation violates the bounds
        ! check each of the perturbations:
        do j = 1, size(list_of_methods%meth(i)%dx_factors)
            xp = xs + list_of_methods%meth(i)%dx_factors(j)*dx
            if (xp < xlow .or. xp > xhigh) then
                status_ok = .false.
                exit
            end if
        end do
        if (status_ok) then   ! this one is OK to use
            fd = list_of_methods%meth(i)
            exit
        end if
    end do

    if (.not. status_ok) then
        ! no method was found that doesn't violate the bounds,
        ! so just return the first one in the list.
        fd = list_of_methods%meth(1)
    end if

    end subroutine select_finite_diff_method