compute_sparsity_random_2 Subroutine

private subroutine compute_sparsity_random_2(me, x)

Compute the sparsity pattern by computing a 2-point jacobian at a specified number of "random" points (num_sparsity_points) in the [xlow_for_sparsity, xhigh_for_sparsity] interval and checking if they are the same.

Arguments

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

vector of variables (size n) (not used here)


Calls

proc~~compute_sparsity_random_2~~CallsGraph proc~compute_sparsity_random_2 numerical_differentiation_module::compute_sparsity_random_2 interface~expand_vector numdiff_utilities_module::expand_vector proc~compute_sparsity_random_2->interface~expand_vector proc~compute_indices numerical_differentiation_module::sparsity_pattern%compute_indices proc~compute_sparsity_random_2->proc~compute_indices proc~compute_jacobian_for_sparsity numerical_differentiation_module::numdiff_type%compute_jacobian_for_sparsity proc~compute_sparsity_random_2->proc~compute_jacobian_for_sparsity proc~destroy_sparsity_pattern numerical_differentiation_module::numdiff_type%destroy_sparsity_pattern proc~compute_sparsity_random_2->proc~destroy_sparsity_pattern proc~divide_interval numdiff_utilities_module::divide_interval proc~compute_sparsity_random_2->proc~divide_interval proc~dsm_wrapper numerical_differentiation_module::sparsity_pattern%dsm_wrapper proc~compute_sparsity_random_2->proc~dsm_wrapper proc~equal_within_tol numdiff_utilities_module::equal_within_tol proc~compute_sparsity_random_2->proc~equal_within_tol proc~generate_dense_sparsity_partition numerical_differentiation_module::numdiff_type%generate_dense_sparsity_partition proc~compute_sparsity_random_2->proc~generate_dense_sparsity_partition proc~get_all_methods_in_class numerical_differentiation_module::get_all_methods_in_class proc~compute_sparsity_random_2->proc~get_all_methods_in_class proc~raise_exception numerical_differentiation_module::numdiff_type%raise_exception proc~compute_sparsity_random_2->proc~raise_exception proc~resize_sparsity_vectors numerical_differentiation_module::numdiff_type%resize_sparsity_vectors proc~compute_sparsity_random_2->proc~resize_sparsity_vectors proc~expand_vector_int numdiff_utilities_module::expand_vector_int interface~expand_vector->proc~expand_vector_int proc~expand_vector_real numdiff_utilities_module::expand_vector_real interface~expand_vector->proc~expand_vector_real proc~compute_sparsity_perturbation_vector numerical_differentiation_module::numdiff_type%compute_sparsity_perturbation_vector proc~compute_jacobian_for_sparsity->proc~compute_sparsity_perturbation_vector proc~perturb_x_and_compute_f numerical_differentiation_module::numdiff_type%perturb_x_and_compute_f proc~compute_jacobian_for_sparsity->proc~perturb_x_and_compute_f proc~select_finite_diff_method numerical_differentiation_module::numdiff_type%select_finite_diff_method proc~compute_jacobian_for_sparsity->proc~select_finite_diff_method proc~destroy_sparsity numerical_differentiation_module::sparsity_pattern%destroy_sparsity proc~destroy_sparsity_pattern->proc~destroy_sparsity interface~unique numdiff_utilities_module::unique proc~divide_interval->interface~unique proc~dsm dsm_module::dsm proc~dsm_wrapper->proc~dsm proc~get_finite_difference_method numerical_differentiation_module::get_finite_difference_method proc~get_all_methods_in_class->proc~get_finite_difference_method proc~resize_sparsity_vectors->interface~expand_vector proc~unique_int numdiff_utilities_module::unique_int interface~unique->proc~unique_int proc~unique_real numdiff_utilities_module::unique_real interface~unique->proc~unique_real proc~compute_perturb_vector numerical_differentiation_module::numdiff_type%compute_perturb_vector proc~compute_sparsity_perturbation_vector->proc~compute_perturb_vector proc~degr dsm_module::degr proc~dsm->proc~degr proc~ido dsm_module::ido proc~dsm->proc~ido proc~numsrt dsm_module::numsrt proc~dsm->proc~numsrt proc~seq dsm_module::seq proc~dsm->proc~seq proc~setr dsm_module::setr proc~dsm->proc~setr proc~slo dsm_module::slo proc~dsm->proc~slo proc~srtdat dsm_module::srtdat proc~dsm->proc~srtdat proc~compute_perturb_vector->proc~raise_exception proc~ido->proc~numsrt proc~unique_int->interface~expand_vector interface~sort_ascending numdiff_utilities_module::sort_ascending proc~unique_int->interface~sort_ascending proc~unique_real->interface~expand_vector proc~unique_real->interface~sort_ascending proc~sort_ascending_int numdiff_utilities_module::sort_ascending_int interface~sort_ascending->proc~sort_ascending_int proc~sort_ascending_real numdiff_utilities_module::sort_ascending_real interface~sort_ascending->proc~sort_ascending_real interface~swap numdiff_utilities_module::swap proc~sort_ascending_int->interface~swap proc~sort_ascending_real->interface~swap proc~swap_int numdiff_utilities_module::swap_int interface~swap->proc~swap_int proc~swap_real numdiff_utilities_module::swap_real interface~swap->proc~swap_real

Source Code

    subroutine compute_sparsity_random_2(me,x)

    implicit none

    class(numdiff_type),intent(inout) :: me
    real(wp),dimension(:),intent(in)  :: x !! vector of variables (size `n`)
                                           !! (not used here)

    type :: jac_type
        !! so we can define an array of jacobian columns
        real(wp),dimension(:),allocatable :: jac !! a column of the jacobian
    end type jac_type

    real(wp),dimension(:),allocatable :: coeffs           !! coefficients for computing `xp`
    real(wp),dimension(:,:),allocatable :: xp             !! perturbed `x` array (size `n,num_sparsity_points`)
    type(jac_type),dimension(:),allocatable :: jac_array  !! array of jacobian columns
    type(sparsity_pattern) :: tmp_sparsity_pattern        !! will accumulate the pattern here
                                                          !! and copy it into the class when
                                                          !! finished.
    integer :: i              !! counter for the number of points
    integer :: j              !! counter
    integer :: icol           !! column counter
    integer :: irow           !! row counter
    real(wp) :: dfdx          !! value of a jacobian element
    integer :: n_icol         !! `icol` size counter
    integer :: n_irow         !! `irow` size counter
    integer :: n_linear_icol  !! `linear_icol` size counter
    integer :: n_linear_irow  !! `linear_irow` size counter
    integer :: n_linear_vals  !! `linear_vals` size counter
    type(meth_array) :: class_meths  !! set of finite diff methods to use
    real(wp),dimension(:),allocatable :: jac !! array of jacobian element values
    integer :: info !! status output form [[dsm]]

    ! initialize:
    call me%destroy_sparsity_pattern()

    if (me%exception_raised) return ! check for exceptions

    ! error check:
    if (.not. allocated(me%xlow_for_sparsity) .or. .not. allocated(me%xhigh_for_sparsity)) then
        call me%raise_exception(20,'compute_sparsity_random_2',&
                                   'the x bounds have not been set.')
        return
    end if

    ! compute the coefficients:
    coeffs = divide_interval(me%num_sparsity_points)

    ! save the initial settings:
    tmp_sparsity_pattern = me%sparsity

    ! we create a provisional sparsity pattern here,
    ! to compute one row at a time:
    me%sparsity%irow = [(irow,irow=1,me%m)]
    me%sparsity%sparsity_computed = .true.
    me%sparsity%num_nonzero_elements = me%m
    call me%sparsity%compute_indices()
    if (me%partition_sparsity_pattern) call me%generate_dense_sparsity_partition()
    n_icol = 0
    n_irow = 0
    n_linear_icol = 0
    n_linear_irow = 0
    n_linear_vals = 0
    allocate(jac(me%num_sparsity_points))

    ! the idea here is to compute the (dense) jacobian
    ! one column at at time, and keep a running track of
    ! the ones that have changed.

    ! first precompute the perturbation arrays for each point:
    allocate(xp(me%n,me%num_sparsity_points))
    do i = 1, me%num_sparsity_points
        xp(:,i) = me%xlow_for_sparsity + (me%xhigh_for_sparsity-me%xlow_for_sparsity)*coeffs(i)
    end do

    ! we will use 2-point methods (simple differences):
    class_meths = get_all_methods_in_class(2)

    do icol = 1, me%n  ! column loop

        ! size the array:
        if (allocated(jac_array)) deallocate(jac_array)
        allocate(jac_array(me%num_sparsity_points))

        ! compute the ith column of the jacobian:
        me%sparsity%icol = [(icol, j=1,me%m)]
        do i = 1, me%num_sparsity_points
            call me%compute_jacobian_for_sparsity( icol, class_meths, xp(:,i), jac_array(i)%jac )
            if (me%exception_raised) return ! check for exceptions
        end do

        ! check each row:
        do irow = 1, me%m

            ! get the jacobian values for this row,col for all the points:
            do j = 1, me%num_sparsity_points
                jac(j) = jac_array(j)%jac(irow)
            end do

            ! put the results into the tmp_sparsity_pattern
            if (equal_within_tol([0.0_wp,jac],me%linear_sparsity_tol)) then
                ! they are all zero
                cycle
            else
                if (me%compute_linear_sparsity_pattern) then
                    if (equal_within_tol(jac,me%linear_sparsity_tol)) then
                        ! this is a linear element (constant value)
                        dfdx = sum(jac) / me%num_sparsity_points ! just take the average and use that
                        call expand_vector(tmp_sparsity_pattern%linear_icol,n_linear_icol,me%chunk_size,val=icol)
                        call expand_vector(tmp_sparsity_pattern%linear_irow,n_linear_irow,me%chunk_size,val=irow)
                        call expand_vector(tmp_sparsity_pattern%linear_vals,n_linear_vals,me%chunk_size,val=dfdx)
                        cycle ! this element will not be added to the nonlinear pattern
                    end if
                end if
                ! otherwise, add it to the nonlinear pattern:
                call expand_vector(tmp_sparsity_pattern%icol,n_icol,me%chunk_size,val=icol)
                call expand_vector(tmp_sparsity_pattern%irow,n_irow,me%chunk_size,val=irow)
            end if
        end do

    end do

    ! copy over the computed pattern:
    me%sparsity = tmp_sparsity_pattern

    ! resize to correct size:
    call me%resize_sparsity_vectors(n_icol,n_irow,n_linear_icol,&
                                        n_linear_irow,n_linear_vals)

    call me%sparsity%compute_indices()
    if (me%partition_sparsity_pattern) then
        call me%sparsity%dsm_wrapper(me%n,me%m,info)
        if (info/=1) then
            call me%raise_exception(21,'compute_sparsity_random_2',&
                                       'error partitioning sparsity pattern.')
            return
        end if
    end if
    me%sparsity%sparsity_computed = .true.

    end subroutine compute_sparsity_random_2