diff --git a/src/numerical_differentiation_module.f90 b/src/numerical_differentiation_module.f90 index 9245558..34b7503 100644 --- a/src/numerical_differentiation_module.f90 +++ b/src/numerical_differentiation_module.f90 @@ -156,11 +156,13 @@ module numerical_differentiation_module procedure,public :: initialize => initialize_numdiff !! initialize the class procedure,public :: diff_initialize => initialize_numdiff_for_diff !! initialize the class - procedure,public :: compute_jacobian !! main routine to compute the Jacobian - !! using the selected options. It - !! returns the sparse (vector) form. - procedure,public :: compute_jacobian_dense !! return the dense `size(m,n)` - !! matrix form of the Jacobian. + procedure,public :: compute_jacobian !! main routine to compute the Jacobian + !! using the selected options. It + !! returns the sparse (vector) form. + procedure,public :: compute_jacobian_dense !! return the dense `size(m,n)` + !! matrix form of the Jacobian. + procedure,public :: compute_jacobian_times_vector !! returns the product of the Jacobian + !! matrix and an input vector procedure,public :: destroy => destroy_numdiff_type !! destroy the class procedure,public :: print_sparsity_pattern !! print the sparsity pattern in vector form to a file procedure,public :: print_sparsity_matrix !! print the sparsity pattern in matrix form to a file @@ -1324,6 +1326,54 @@ subroutine perturb_x_and_compute_f(me,x,dx_factor,dx,& end subroutine perturb_x_and_compute_f !******************************************************************************* +!******************************************************************************* +!> +! Returns the product `J*v`, where `J` is the `m x n` Jacobian matrix +! and `v` is an `n x 1` vector. + + subroutine compute_jacobian_times_vector(me,x,v,z) + + implicit none + + class(numdiff_type),intent(inout) :: me + real(wp),dimension(:),intent(in) :: x !! vector of variables (size `n`) + real(wp),dimension(:),intent(in) :: v !! vector (size `n`) + real(wp),dimension(:),intent(out) :: z !! The product `J*v` (size `m`) + + real(wp),dimension(:),allocatable :: jac !! sparse jacobian vector + integer :: i !! counter + integer :: r !! row number in full jacobian + integer :: c !! column number in full jacobian + + ! first compute the jacobian in sparse vector form: + call me%compute_jacobian(x,jac) + + ! initialize output vector: + z = 0.0_wp + + if (allocated(jac)) then + + ! J v z + ! --- - - + ! X0X X X + ! 0X0 * X = X + ! 00X X X + ! 00X X + + ! multiplication by input v: + do i = 1, me%sparsity%num_nonzero_elements + r = me%sparsity%irow(i) + c = me%sparsity%icol(i) + z(r) = z(r) + jac(i)*v(c) + end do + + deallocate(jac) + + end if + + end subroutine compute_jacobian_times_vector +!******************************************************************************* + !******************************************************************************* !> ! Compute the Jacobian. @@ -1451,9 +1501,9 @@ end subroutine compute_jacobian_standard !******************************************************************************* !> -! Compute the Jacobian one element at a time using the [[diff]] algorithm. -! This takes a very large number of function evaluations, but should give -! a very accurate answer. +! Compute the Jacobian one element at a time using the Neville's process +! algorithm [[diff]]. This takes a very large number of function evaluations, +! but should give a very accurate answer. subroutine compute_jacobian_with_diff(me,x,dx,jac) diff --git a/src/utilities_module.f90 b/src/utilities_module.f90 index c4e1a4e..c75ca9d 100644 --- a/src/utilities_module.f90 +++ b/src/utilities_module.f90 @@ -100,7 +100,7 @@ function unique(vec,chunk_size) result(ivec_unique) end do call expand_vector(ivec_unique,n,chunk_size,finished=.true.) end if - + end function unique !*******************************************************************************