@@ -8,6 +8,7 @@ module nonlin_test_jacobian
88 implicit none
99 private
1010 public :: test_jacobian_1
11+ public :: test_jacobian_2
1112
1213contains
1314! ******************************************************************************
@@ -44,6 +45,46 @@ subroutine jac1(x, jac, args)
4445 [2 , 2 ])
4546 end subroutine
4647
48+ ! ------------------------------------------------------------------------------
49+ ! FUNCTIONS:
50+ ! x = Y * r * cos(theta)
51+ ! y = Y * r * sin(theta)
52+ subroutine fcn2 (x , f , args )
53+ real (real64), intent (in ), dimension (:) :: x
54+ real (real64), intent (out ), dimension (:) :: f
55+ class(* ), intent (inout ), optional :: args
56+ real (real64) :: r, theta, y
57+ r = x(1 )
58+ theta = x(2 )
59+ select type (args)
60+ type is (real (real64))
61+ y = args
62+ end select
63+ f(1 ) = y * r * cos (theta)
64+ f(2 ) = y * r * sin (theta)
65+ end subroutine
66+
67+ ! JACOBIAN:
68+ ! |Y * cos -Y * r * sin|
69+ ! J = | |
70+ ! |Y * sin Y * r * cos|
71+ subroutine jac2 (x , jac , args )
72+ real (real64), intent (in ), dimension (:) :: x
73+ real (real64), intent (out ), dimension (:,:) :: jac
74+ class(* ), intent (inout ), optional :: args
75+ real (real64) :: r, theta, y
76+ r = x(1 )
77+ theta = x(2 )
78+ select type (args)
79+ type is (real (real64))
80+ y = args
81+ end select
82+ jac = reshape (&
83+ [y * cos (theta), y * sin (theta), &
84+ - y * r * sin (theta), y * r * cos (theta)], &
85+ [2 , 2 ])
86+ end subroutine
87+
4788! ------------------------------------------------------------------------------
4889 function test_jacobian_1 () result(rst)
4990 ! Local Variables
@@ -135,5 +176,97 @@ function test_jacobian_1() result(rst)
135176100 format (A)
136177 end function
137178
179+ ! ------------------------------------------------------------------------------
180+ function test_jacobian_2 () result(rst)
181+ ! Local Variables
182+ type (vecfcn_helper) :: obj
183+ procedure (vecfcn), pointer :: fcn
184+ procedure (jacobianfcn), pointer :: jac
185+ real (real64) :: numjac(2 , 2 ), exact(2 , 2 ), x(2 ), y
186+ logical :: rst
187+ integer (int32) :: i
188+
189+ ! Parameters
190+ real (real64), parameter :: tol = 1.0d-4
191+
192+ ! Initialization
193+ rst = .true.
194+ fcn = > fcn2
195+ jac = > jac2
196+ call obj% set_fcn(fcn, 2 , 2 )
197+ call random_number (y)
198+
199+ ! Test point 1 (0, 0)
200+ x = 0.0d0
201+ call obj% jacobian(x, numjac, args = y)
202+ call jac(x, exact, args = y)
203+ if (.not. assert(numjac, exact, tol)) then
204+ rst = .false.
205+ print 100 , " Test Failed: Jacobian Test 2A"
206+ print 100 , " Expected:"
207+ do i = 1 , size (exact, 1 )
208+ print * , exact(i,:)
209+ end do
210+ print 100 , " Found:"
211+ do i = 1 , size (exact, 1 )
212+ print * , numjac(i,:)
213+ end do
214+ end if
215+
216+ ! Test point 2 (1, 0)
217+ x = [1.0d0 , 0.0d0 ]
218+ call obj% jacobian(x, numjac, args = y)
219+ call jac(x, exact, args = y)
220+ if (.not. assert(numjac, exact, tol)) then
221+ rst = .false.
222+ print 100 , " Test Failed: Jacobian Test 2B"
223+ print 100 , " Expected:"
224+ do i = 1 , size (exact, 1 )
225+ print * , exact(i,:)
226+ end do
227+ print 100 , " Found:"
228+ do i = 1 , size (exact, 1 )
229+ print * , numjac(i,:)
230+ end do
231+ end if
232+
233+ ! Test point 3 (0, 1)
234+ x = [0.0d0 , 1.0d0 ]
235+ call obj% jacobian(x, numjac, args = y)
236+ call jac(x, exact, args = y)
237+ if (.not. assert(numjac, exact, tol)) then
238+ rst = .false.
239+ print 100 , " Test Failed: Jacobian Test 2C"
240+ print 100 , " Expected:"
241+ do i = 1 , size (exact, 1 )
242+ print * , exact(i,:)
243+ end do
244+ print 100 , " Found:"
245+ do i = 1 , size (exact, 1 )
246+ print * , numjac(i,:)
247+ end do
248+ end if
249+
250+ ! Test point 4 (0.5, -0.5)
251+ x = [0.5d0 , - 0.5d0 ]
252+ call obj% jacobian(x, numjac, args = y)
253+ call jac(x, exact, args = y)
254+ if (.not. assert(numjac, exact, tol)) then
255+ rst = .false.
256+ print 100 , " Test Failed: Jacobian Test 2D"
257+ print 100 , " Expected:"
258+ do i = 1 , size (exact, 1 )
259+ print * , exact(i,:)
260+ end do
261+ print 100 , " Found:"
262+ do i = 1 , size (exact, 1 )
263+ print * , numjac(i,:)
264+ end do
265+ end if
266+
267+ ! Formatting
268+ 100 format (A)
269+ end function
270+
138271! ------------------------------------------------------------------------------
139272end module
0 commit comments