roots.f90
Go to the documentation of this file.
1 !#############################################################################
2 !# #
3 !# fosite - 3D hydrodynamical simulation program #
4 !# module: roots.f90 #
5 !# #
6 !# Copyright (C) 2006-2018 #
7 !# Tobias Illenseer <tillense@astrophysik.uni-kiel.de> #
8 !# #
9 !# This program is free software; you can redistribute it and/or modify #
10 !# it under the terms of the GNU General Public License as published by #
11 !# the Free Software Foundation; either version 2 of the License, or (at #
12 !# your option) any later version. #
13 !# #
14 !# This program is distributed in the hope that it will be useful, but #
15 !# WITHOUT ANY WARRANTY; without even the implied warranty of #
16 !# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
17 !# NON INFRINGEMENT. See the GNU General Public License for more #
18 !# details. #
19 !# #
20 !# You should have received a copy of the GNU General Public License #
21 !# along with this program; if not, write to the Free Software #
22 !# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
23 !# #
24 !#############################################################################
25 
26 !----------------------------------------------------------------------------!
44 !----------------------------------------------------------------------------!
45 MODULE roots
46  IMPLICIT NONE
47  !--------------------------------------------------------------------------!
48  PRIVATE
50  TYPE roots_typ
51  REAL :: eps,tol,root,dx,dxold,df,d,e
52  REAL :: x(3),f(3)
53  INTEGER :: iter,max_iterations,error
54  LOGICAL :: iterate,do_modified_step
55  END TYPE roots_typ
56  ! exclude interface block from doxygen processing
58  INTERFACE getroot
59  MODULE PROCEDURE getroot_brentdekker
60  END INTERFACE
62  !--------------------------------------------------------------------------!
63  ! some constants
64 ! #define DEBUG_OUTPUT 1
65 #undef DEBUG_OUTPUT
66  INTEGER, PARAMETER :: default_max_iterations = 1000
67  REAL, PARAMETER :: default_accuracy = 4*epsilon(default_accuracy)
68  CHARACTER(LEN=64), PARAMETER, DIMENSION(0:4) :: error_message = (/ &
69  "unknown error ", &
70  "root not bracketed ", &
71  "iteration exceeds maximum ", &
72  "requested accuracy smaller than machine precission ", &
73  "upper limit for iterations should be larger than 1 " /)
74  !--------------------------------------------------------------------------!
75  PUBLIC :: &
76  ! constants
79  ! types
80  roots_typ, &
81  ! methods
82  initroots, &
84  getroot, &
89  getroot_king, &
93  !--------------------------------------------------------------------------!
94 
95 CONTAINS
96 
97  PURE SUBROUTINE initroots(this,x1,x2,f1,f2,dxacc,maxiter)
98  IMPLICIT NONE
99  !------------------------------------------------------------------------!
100  TYPE(roots_typ), INTENT(INOUT) :: this
101  REAL, INTENT(IN) :: x1,x2
102  REAL, INTENT(IN) :: f1,f2
103  REAL,OPTIONAL, INTENT(IN) :: dxacc
104  INTEGER,OPTIONAL, INTENT(IN) :: maxiter
105  !------------------------------------------------------------------------!
106  ! check if root is bracketed
107  IF (f1*f2.GT.0.0) THEN
108  ! f1 and f2 should have opposite signs
109  this%error = 1
110  ELSE
111  IF (x1.LT.x2) THEN
112  this%x(1) = x1
113  this%x(2) = x2
114  this%f(1) = f1
115  this%f(2) = f2
116  ELSE
117  this%x(1) = x2
118  this%x(2) = x1
119  this%f(1) = f2
120  this%f(2) = f1
121  END IF
122 
123  this%dx = abs(this%x(2)-this%x(1))
124  this%dxold = this%dx
125 
126  IF(PRESENT(dxacc)) THEN
127  IF (dxacc.GT.epsilon(dxacc)) THEN
128  this%eps = dxacc
129  ELSE
130  this%error = 3
131  END IF
132  ELSE
133  this%eps = default_accuracy
134  END IF
135 
136  IF(PRESENT(maxiter)) THEN
137  IF (maxiter.GT.1) THEN
138  this%max_iterations = maxiter
139  ELSE
140  this%error = 4
141  END IF
142  ELSE
143  this%max_iterations = default_max_iterations
144  END IF
145 
146  ! only used in Brent-Dekker method
147  this%d = this%x(2)-this%x(1)
148  this%e = this%d
149 
150  this%error = 0
151  this%iter = 0
152  this%iterate = .true.
153  this%do_modified_step = .true.
154  END IF
155 
156  END SUBROUTINE initroots
157 
158 
159  FUNCTION geterrormessage(error) RESULT(msg)
160  IMPLICIT NONE
161  !------------------------------------------------------------------------!
162  INTEGER, INTENT(IN) :: error
163  CHARACTER(LEN=64) :: msg
164  !------------------------------------------------------------------------!
165  SELECT CASE (error)
166  CASE(1,2)
167  msg = error_message(error)
168  CASE DEFAULT
169  msg = error_message(0)
170  END SELECT
171  END FUNCTION geterrormessage
172 
173 
174 #ifndef DEBUG_OUTPUT
175  PURE &
176 #endif
177  SUBROUTINE getroot_generic(this,Stepper,func,x1,x2,dxacc,maxiter,plist,xm)
178  IMPLICIT NONE
179  !------------------------------------------------------------------------!
180  TYPE(Roots_TYP) :: this
181  REAL :: x1,x2
182  REAL, OPTIONAL :: dxacc, plist(:), xm
183  INTEGER, OPTIONAL :: maxiter
184  !------------------------------------------------------------------------!
185  INTENT(IN) :: x1,x2,dxacc,maxiter,xm,plist
186  INTENT(INOUT) :: this
187  !------------------------------------------------------------------------!
188  INTERFACE
189  PURE SUBROUTINE stepper(root)
190  IMPORT roots_typ
191  IMPLICIT NONE
192  TYPE(Roots_TYP), INTENT(INOUT) :: root
193  END SUBROUTINE stepper
194  END INTERFACE
195  INTERFACE
196  PURE SUBROUTINE func(x,fx,plist)
197  IMPLICIT NONE
198  REAL, INTENT(IN) :: x
199  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
200  REAL, INTENT(OUT) :: fx
201  END SUBROUTINE func
202  END INTERFACE
203  !------------------------------------------------------------------------!
204  REAL :: f1,f2
205  !------------------------------------------------------------------------!
206  ! compute function values at the boundaries
207  CALL func(x1,f1,plist)
208  CALL func(x2,f2,plist)
209 
210  ! initialize root finding algorithm
211  CALL initroots(this,x1,x2,f1,f2)
212 
213  IF (this%error.EQ.0) THEN
214  ! initial guess for the root
215  IF (PRESENT(xm)) THEN
216  this%x(3) = xm
217  ELSE
218  this%x(3) = arithmeticmean(this%x(1),this%x(2))
219  END IF
220 #ifdef DEBUG_OUTPUT
221  print '(A3,A18,A10,A18,A18,2(A13,A10))', &
222  "#","x3","f3","dx","tol","x1","f1","x2","f2"
223 #endif
224  ! main loop
225  DO
226  ! compute function value at x3
227  CALL func(this%x(3),this%f(3),plist)
228  ! print debug information if requested
229 #ifdef DEBUG_OUTPUT
230  print '(I3,ES18.10,ES10.2,2(ES18.10),2(ES13.5,ES10.2))', &
231  this%iter,this%x(3),this%f(3),this%dx,this%tol,this%x(1),this%f(1),this%x(2),this%f(2)
232 #endif
233  ! check convergence
234  CALL testconvergence(this)
235  IF (.NOT.this%iterate) EXIT
236 
237  ! determine new estimate for x3
238  CALL stepper(this)
239  END DO
240  END IF
241  END SUBROUTINE getroot_generic
242 
243 #ifndef DEBUG_OUTPUT
244  PURE &
245 #endif
246  SUBROUTINE getroot_newton(funcd,x1,x2,root,error,plist,xm,iterations)
247  IMPLICIT NONE
248  !------------------------------------------------------------------------!
249  REAL, INTENT(IN) :: x1,x2
250  REAL, INTENT(OUT) :: root
251  INTEGER, INTENT(OUT) :: error
252  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
253  REAL, INTENT(IN), OPTIONAL :: xm
254  INTEGER, INTENT(OUT), OPTIONAL :: iterations
255  !------------------------------------------------------------------------!
256  INTERFACE
257  PURE SUBROUTINE funcd(x,fx,dfx,plist)
258  IMPLICIT NONE
259  REAL, INTENT(IN) :: x
260  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
261  REAL, INTENT(OUT) :: fx,dfx
262  END SUBROUTINE funcd
263  END INTERFACE
264  !------------------------------------------------------------------------!
265  TYPE(roots_typ) :: this
266  REAL :: f1,f2,df1,df2
267  !------------------------------------------------------------------------!
268  ! compute function values and derivatives at the boundaries
269  CALL funcd(x1,f1,df1,plist)
270  CALL funcd(x2,f2,df2,plist)
271 
272  ! initialize root finding algorithm
273  CALL initroots(this,x1,x2,f1,f2)
274 
275  IF (this%error.EQ.0) THEN
276  ! initial guess for the root
277  IF (PRESENT(xm)) THEN
278  this%x(3) = xm
279  ELSE
280  this%x(3) = arithmeticmean(this%x(1),this%x(2))
281  END IF
282 #ifdef DEBUG_OUTPUT
283  print '(A3,A18,A10,A18,A18,2(A13,A10))', &
284  "#","x3","f3","dx","tol","x1","f1","x2","f2"
285 #endif
286  ! main loop
287  DO
288  ! compute function value and derivative at x3
289  CALL funcd(this%x(3),this%f(3),this%df,plist)
290  ! print debug information if requested
291 #ifdef DEBUG_OUTPUT
292  print '(I3,ES18.10,ES10.2,2(ES18.10),2(ES13.5,ES10.2))', &
293  this%iter,this%x(3),this%f(3),this%dx,this%tol,this%x(1),this%f(1),this%x(2),this%f(2)
294 #endif
295  ! check convergence
296  CALL testconvergence(this)
297  IF (.NOT.this%iterate) EXIT
298 
299  ! determine new interval for enclosure and estimate x3
300  CALL step_newton(this)
301  END DO
302  END IF
303 
304  root = this%root
305  error = this%error
306  IF (PRESENT(iterations)) iterations = this%iter
307 
308  END SUBROUTINE getroot_newton
309 
310 
311 #ifndef DEBUG_OUTPUT
312  PURE &
313 #endif
314  SUBROUTINE getroot_regulafalsi(func,x1,x2,root,error,plist,xm,iterations)
315  IMPLICIT NONE
316  !------------------------------------------------------------------------!
317  REAL, INTENT(IN) :: x1,x2
318  REAL, INTENT(OUT) :: root
319  INTEGER, INTENT(OUT) :: error
320  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
321  REAL, INTENT(IN), OPTIONAL :: xm
322  INTEGER, INTENT(OUT), OPTIONAL :: iterations
323  !------------------------------------------------------------------------!
324  INTERFACE
325  PURE SUBROUTINE func(x,fx,plist)
326  IMPLICIT NONE
327  REAL, INTENT(IN) :: x
328  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
329  REAL, INTENT(OUT) :: fx
330  END SUBROUTINE func
331  END INTERFACE
332  !------------------------------------------------------------------------!
333  TYPE(roots_typ) :: this
334  !------------------------------------------------------------------------!
335  CALL getroot_generic(this,step_regulafalsi,func,x1,x2, &
337 
338  root = this%root
339  error = this%error
340  IF (PRESENT(iterations)) iterations = this%iter
341 
342  END SUBROUTINE getroot_regulafalsi
343 
344 
345 #ifndef DEBUG_OUTPUT
346  PURE &
347 #endif
348  SUBROUTINE getroot_pegasus(func,x1,x2,root,error,plist,xm,iterations)
349  IMPLICIT NONE
350  !------------------------------------------------------------------------!
351  REAL, INTENT(IN) :: x1,x2
352  REAL, INTENT(OUT) :: root
353  INTEGER, INTENT(OUT) :: error
354  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
355  REAL, INTENT(IN), OPTIONAL :: xm
356  INTEGER, INTENT(OUT), OPTIONAL :: iterations
357  !------------------------------------------------------------------------!
358  INTERFACE
359  PURE SUBROUTINE func(x,fx,plist)
360  IMPLICIT NONE
361  REAL, INTENT(IN) :: x
362  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
363  REAL, INTENT(OUT) :: fx
364  END SUBROUTINE func
365  END INTERFACE
366  !------------------------------------------------------------------------!
367  TYPE(roots_typ) :: this
368  !------------------------------------------------------------------------!
369  CALL getroot_generic(this,step_pegasus,func,x1,x2, &
371 
372  root = this%root
373  error = this%error
374  IF (PRESENT(iterations)) iterations = this%iter
375 
376  END SUBROUTINE getroot_pegasus
377 
378 
379 #ifndef DEBUG_OUTPUT
380  PURE &
381 #endif
382  SUBROUTINE getroot_king(func,x1,x2,root,error,plist,xm,iterations)
383  IMPLICIT NONE
384  !------------------------------------------------------------------------!
385  REAL, INTENT(IN) :: x1,x2
386  REAL, INTENT(OUT) :: root
387  INTEGER, INTENT(OUT) :: error
388  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
389  REAL, INTENT(IN), OPTIONAL :: xm
390  INTEGER, INTENT(OUT), OPTIONAL :: iterations
391  !------------------------------------------------------------------------!
392  INTERFACE
393  PURE SUBROUTINE func(x,fx,plist)
394  IMPLICIT NONE
395  REAL, INTENT(IN) :: x
396  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
397  REAL, INTENT(OUT) :: fx
398  END SUBROUTINE func
399  END INTERFACE
400  !------------------------------------------------------------------------!
401  TYPE(roots_typ) :: this
402  !------------------------------------------------------------------------!
403  CALL getroot_generic(this,step_king,func,x1,x2, &
405 
406  root = this%root
407  error = this%error
408  IF (PRESENT(iterations)) iterations = this%iter
409 
410  END SUBROUTINE getroot_king
411 
412 
413 #ifndef DEBUG_OUTPUT
414  PURE &
415 #endif
416  SUBROUTINE getroot_andersonbjoerk(func,x1,x2,root,error,plist,xm,iterations)
417  IMPLICIT NONE
418  !------------------------------------------------------------------------!
419  REAL, INTENT(IN) :: x1,x2
420  REAL, INTENT(OUT) :: root
421  INTEGER, INTENT(OUT) :: error
422  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
423  REAL, INTENT(IN), OPTIONAL :: xm
424  INTEGER, INTENT(OUT), OPTIONAL :: iterations
425  !------------------------------------------------------------------------!
426  INTERFACE
427  PURE SUBROUTINE func(x,fx,plist)
428  IMPLICIT NONE
429  REAL, INTENT(IN) :: x
430  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
431  REAL, INTENT(OUT) :: fx
432  END SUBROUTINE func
433  END INTERFACE
434  !------------------------------------------------------------------------!
435  TYPE(roots_typ) :: this
436  !------------------------------------------------------------------------!
437  CALL getroot_generic(this,step_andersonbjoerk,func,x1,x2, &
439 
440  root = this%root
441  error = this%error
442  IF (PRESENT(iterations)) iterations = this%iter
443 
444  END SUBROUTINE getroot_andersonbjoerk
445 
446 
447 #ifndef DEBUG_OUTPUT
448  PURE &
449 #endif
450  SUBROUTINE getroot_ridder(func,x1,x2,root,error,plist,xm,iterations)
451  IMPLICIT NONE
452  !------------------------------------------------------------------------!
453  REAL, INTENT(IN) :: x1,x2
454  REAL, INTENT(OUT) :: root
455  INTEGER, INTENT(OUT) :: error
456  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
457  REAL, INTENT(IN), OPTIONAL :: xm
458  INTEGER, INTENT(OUT), OPTIONAL :: iterations
459  !------------------------------------------------------------------------!
460  INTERFACE
461  PURE SUBROUTINE func(x,fx,plist)
462  IMPLICIT NONE
463  REAL, INTENT(IN) :: x
464  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
465  REAL, INTENT(OUT) :: fx
466  END SUBROUTINE func
467  END INTERFACE
468  !------------------------------------------------------------------------!
469  TYPE(roots_typ) :: this
470  !------------------------------------------------------------------------!
471  CALL getroot_generic(this,step_ridder,func,x1,x2, &
473 
474  root = this%root
475  error = this%error
476  IF (PRESENT(iterations)) iterations = this%iter
477 
478  END SUBROUTINE getroot_ridder
479 
480 
481 #ifndef DEBUG_OUTPUT
482  PURE &
483 #endif
484  SUBROUTINE getroot_brentdekker(func,x1,x2,root,error,plist,xm,iterations)
485  IMPLICIT NONE
486  !------------------------------------------------------------------------!
487  REAL, INTENT(IN) :: x1,x2
488  REAL, INTENT(OUT) :: root
489  INTEGER, INTENT(OUT) :: error
490  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
491  REAL, INTENT(IN), OPTIONAL :: xm
492  INTEGER, INTENT(OUT), OPTIONAL :: iterations
493  !------------------------------------------------------------------------!
494  INTERFACE
495  PURE SUBROUTINE func(x,fx,plist)
496  IMPLICIT NONE
497  REAL, INTENT(IN) :: x
498  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
499  REAL, INTENT(OUT) :: fx
500  END SUBROUTINE func
501  END INTERFACE
502  !------------------------------------------------------------------------!
503  TYPE(roots_typ) :: this
504  !------------------------------------------------------------------------!
505  CALL getroot_generic(this,step_brentdekker,func,x1,x2, &
507 
508  root = this%root
509  error = this%error
510  IF (PRESENT(iterations)) iterations = this%iter
511 
512  END SUBROUTINE getroot_brentdekker
513 
514 
515 #ifndef DEBUG_OUTPUT
516  PURE &
517 #endif
518  SUBROUTINE getroot_bisection(func,x1,x2,root,error,plist,xm,iterations)
519  IMPLICIT NONE
520  !------------------------------------------------------------------------!
521  REAL, INTENT(IN) :: x1,x2
522  REAL, INTENT(OUT) :: root
523  INTEGER, INTENT(OUT) :: error
524  REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: plist
525  REAL, INTENT(IN), OPTIONAL :: xm
526  INTEGER, INTENT(OUT), OPTIONAL :: iterations
527  !------------------------------------------------------------------------!
528  INTERFACE
529  PURE SUBROUTINE func(x,fx,plist)
530  IMPLICIT NONE
531  REAL, INTENT(IN) :: x
532  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
533  REAL, INTENT(OUT) :: fx
534  END SUBROUTINE func
535  END INTERFACE
536  !------------------------------------------------------------------------!
537  TYPE(roots_typ) :: this
538  !------------------------------------------------------------------------!
539  CALL getroot_generic(this,step_bisection,func,x1,x2, &
541 
542  root = this%root
543  error = this%error
544  IF (PRESENT(iterations)) iterations = this%iter
545 
546  END SUBROUTINE getroot_bisection
547 
548 
549  PURE SUBROUTINE updatebounds_bisection(this)
550  IMPLICIT NONE
551  !------------------------------------------------------------------------!
552  TYPE(roots_typ), INTENT(INOUT) :: this
553  !------------------------------------------------------------------------!
554  ! check sign
555  IF (this%f(1)*this%f(3).GT.0.0) THEN
556  ! sign(f1) == sign(f3) => x3 < root < x2
557  this%x(1)=this%x(3)
558  this%f(1)=this%f(3)
559  ELSE
560  ! sign(f1) != sign(f3) => x1 < root < x3
561  this%x(2)=this%x(3)
562  this%f(2)=this%f(3)
563  END IF
564  END SUBROUTINE updatebounds_bisection
565 
566 
567  PURE SUBROUTINE step_bisection(this)
568  IMPLICIT NONE
569  !------------------------------------------------------------------------!
570  TYPE(roots_typ), INTENT(INOUT) :: this
571  !------------------------------------------------------------------------!
572  CALL updatebounds_bisection(this)
573  CALL step_arithmeticmean(this)
574  END SUBROUTINE step_bisection
575 
576 
577  PURE SUBROUTINE step_newton(this)
578  IMPLICIT NONE
579  !------------------------------------------------------------------------!
580  TYPE(roots_typ), INTENT(INOUT) :: this
581  !------------------------------------------------------------------------!
582  ! determine new brackets for the root
583 !CDIR IEXPAND
584  CALL updatebounds_bisection(this)
585  this%dxold = this%dx
586  ! check if we are out of bounds
587  ! or if the convergence is to slow
588  IF ( ( (this%df*(this%x(3)-this%x(2))-this%f(3).GE.0.0) &
589  .OR. (this%df*(this%x(3)-this%x(1))-this%f(3).LE.0.0) ) &
590  .OR. (abs(2*this%f(3)).GT.abs(this%dxold*this%df)) ) THEN
591  ! compute new estimate for the route using arithmetic mean value
592 !CDIR IEXPAND
593  CALL step_arithmeticmean(this)
594  ELSE
595  ! compute new estimate for the root using Newton iteration
596  this%dx = this%f(3) / this%df
597  this%x(3) = this%x(3) - this%dx
598  this%dx = abs(this%dx)
599  END IF
600  END SUBROUTINE step_newton
601 
602 
603  PURE SUBROUTINE step_regulafalsi(this)
604  IMPLICIT NONE
605  !------------------------------------------------------------------------!
606  TYPE(roots_typ), INTENT(INOUT) :: this
607  !------------------------------------------------------------------------!
608  ! calculate new interval boundaries
609 !CDIR IEXPAND
610  CALL updatebounds_bisection(this)
611  ! determine new approximation for the root
612 !CDIR IEXPAND
613  CALL step_secantmethod(this)
614  END SUBROUTINE step_regulafalsi
615 
616 
617  PURE SUBROUTINE step_pegasus(this)
618  IMPLICIT NONE
619  !------------------------------------------------------------------------!
620  TYPE(roots_typ), INTENT(INOUT) :: this
621  !------------------------------------------------------------------------!
622  REAL :: g
623  !------------------------------------------------------------------------!
624  ! calculate new interval boundaries
625  IF (this%f(2)*this%f(3).LT.0.0) THEN
626  this%x(1) = this%x(2)
627  this%x(2) = this%x(3)
628  this%f(1) = this%f(2)
629  this%f(2) = this%f(3)
630  ELSE
631  g = this%f(2)/(this%f(3)+this%f(2))
632  this%x(2) = this%x(3)
633  this%f(1) = g*this%f(1)
634  this%f(2) = this%f(3)
635  END IF
636  ! determine new approximation for the root
637 !CDIR IEXPAND
638  CALL step_secantmethod(this)
639  END SUBROUTINE step_pegasus
640 
641 
642  PURE SUBROUTINE step_king(this)
643  IMPLICIT NONE
644  !------------------------------------------------------------------------!
645  TYPE(roots_typ), INTENT(INOUT) :: this
646  REAL :: g
647  !------------------------------------------------------------------------!
648  IF (this%do_modified_step) THEN
649  IF (this%f(2)*this%f(3).LT.0.0) THEN
650  ! interchange (x1,f1) and (x2,f2)
651  g = this%x(1)
652  this%x(1) = this%x(2)
653  this%x(2) = g
654  g = this%f(1)
655  this%f(1) = this%f(2)
656  this%f(2) = g
657  END IF
658  ! Pegasus step
659  IF (this%f(2)*this%f(3).GT.0.0) THEN
660  g = this%f(2)/(this%f(3)+this%f(2))
661  this%x(2) = this%x(3)
662  this%f(1) = g*this%f(1)
663  this%f(2) = this%f(3)
664  END IF
665  this%do_modified_step = .false.
666  ELSE
667  IF (this%f(2)*this%f(3).LT.0.0) THEN
668  this%x(1) = this%x(2)
669  this%f(1) = this%f(2)
670  this%x(2) = this%x(3)
671  this%f(2) = this%f(3)
672  this%do_modified_step = .true.
673  ELSE
674  ! Pegasus step
675  IF (this%f(2)*this%f(3).GT.0.0) THEN
676  g = this%f(2)/(this%f(3)+this%f(2))
677  this%x(2) = this%x(3)
678  this%f(1) = g*this%f(1)
679  this%f(2) = this%f(3)
680  END IF
681  this%do_modified_step = .false.
682  END IF
683  END IF
684  ! determine new approximation for the root
685 !CDIR IEXPAND
686  CALL step_secantmethod(this)
687  END SUBROUTINE step_king
688 
689 
690  PURE SUBROUTINE step_andersonbjoerk(this)
691  IMPLICIT NONE
692  !------------------------------------------------------------------------!
693  TYPE(roots_typ), INTENT(INOUT) :: this
694  !------------------------------------------------------------------------!
695  REAL :: g
696  !------------------------------------------------------------------------!
697  ! calculate new interval boundaries
698  IF (this%f(2)*this%f(3).LT.0.0) THEN
699  this%x(1) = this%x(2)
700  this%x(2) = this%x(3)
701  this%f(1) = this%f(2)
702  this%f(2) = this%f(3)
703  ELSE
704  g = 1.-this%f(3)/this%f(2)
705  IF(g.LE.0.) g = 0.5
706  this%x(2) = this%x(3)
707  this%f(1) = g*this%f(1)
708  this%f(2) = this%f(3)
709  END IF
710  ! determine new approximation for the root
711 !CDIR IEXPAND
712  CALL step_secantmethod(this)
713  END SUBROUTINE step_andersonbjoerk
714 
715 
716  PURE SUBROUTINE step_ridder(this)
717  IMPLICIT NONE
718  !------------------------------------------------------------------------!
719  TYPE(roots_typ), INTENT(INOUT) :: this
720  !------------------------------------------------------------------------!
721  REAL :: denom,dx
722  !------------------------------------------------------------------------!
723  IF (this%do_modified_step) THEN
724  ! compute arithmetic mean of the new boundaries
725  CALL step_bisection(this)
726  ! next update uses Ridders 3 point formula
727  this%do_modified_step = .false.
728  ELSE
729  ! estimate the new step from the arithmetic mean value
730  denom = sqrt(this%f(3)*this%f(3) - this%f(1)*this%f(2)) + tiny(denom)
731  dx = (this%x(3)-this%x(1)) * sign(1.0,this%f(1)-this%f(2))*this%f(3) / denom
732  IF (dx.GT.0.0) THEN
733  this%x(1) = this%x(3)
734  this%f(1) = this%f(3)
735  ELSE
736  this%x(2) = this%x(3)
737  this%f(2) = this%f(3)
738  END IF
739  this%dx = 0.5*this%dx
740  this%x(3) = this%x(3) + dx
741  ! next step is a bisection step
742  this%do_modified_step = .true.
743  END IF
744  END SUBROUTINE step_ridder
745 
746 
747  PURE SUBROUTINE step_brentdekker(this)
748  IMPLICIT NONE
749  !------------------------------------------------------------------------!
750  TYPE(roots_typ), INTENT(INOUT) :: this
751  REAL :: m,p,q
752  !------------------------------------------------------------------------!
753  ! bracket the root
754  IF (this%f(3)*this%f(2).GT.0.0) THEN
755  ! x3, x2 on the same side of the root
756  this%x(2) = this%x(1)
757  this%f(2) = this%f(1)
758  this%d = this%x(1)-this%x(3)
759  this%e = this%d
760  END IF
761  ! root is now bracketed between x3 and x2
762 
763  ! x3 should be closer to the root than x2, i.e. |f3|<|f2|
764  IF (abs(this%f(2)).LT.abs(this%f(3))) THEN
765  ! interchange (x3,f3) and (x2,f2) using (x1,f1) as temporary space
766  this%x(1) = this%x(3)
767  this%x(3) = this%x(2)
768  this%x(2) = this%x(1)
769  this%f(1) = this%f(3)
770  this%f(3) = this%f(2)
771  this%f(2) = this%f(1)
772  END IF
773 
774  m = 0.5*(this%x(2)-this%x(3))
775 
776  IF ((abs(this%e).LT.this%tol) .OR. abs(this%f(1)).LE.abs(this%f(3))) THEN
777  ! convergence too slow -> do bisection step
778  this%d = m
779  this%e = m
780  ELSE
781  ! try interpolation
782  CALL saveinversequadraticinterpolation(this%x(1),this%x(3),this%x(2), &
783  this%f(1),this%f(3),this%f(2),p,q)
784 
785  IF (2*p.LT. min(3*m*q-abs(this%tol*q), abs(this%e*q))) THEN
786  ! interpolation worked store old correction d in e
787  ! and compute new correction d
788  this%e = this%d
789  this%d = p / q
790  ELSE
791  ! interpolation failed, do bisection
792  this%e = m
793  this%d = m
794  END IF
795  END IF
796 
797  this%x(1) = this%x(3)
798  this%f(1) = this%f(3)
799 
800  IF (abs(this%d).GT.this%tol) THEN
801  this%x(3) = this%x(3) + this%d
802  ELSE
803  this%x(3) = this%x(3) + sign(this%tol,m)
804  END IF
805 
806  this%dx = abs(this%x(2)-this%x(3))
807  END SUBROUTINE step_brentdekker
808 
809 
810  PURE SUBROUTINE step_secantmethod(this)
811  IMPLICIT NONE
812  !------------------------------------------------------------------------!
813  TYPE(roots_typ), INTENT(INOUT) :: this
814  !------------------------------------------------------------------------!
815  INTEGER :: one,two
816  !------------------------------------------------------------------------!
817  IF (abs(this%f(1)).GT.abs(this%f(2))) THEN
818  ! x2 is probably the better approximation for the root
819  ! set indices as usual
820  one = 1
821  two = 2
822  ELSE
823  ! x1 is probably the better approximation for the root
824  ! interchange indices
825  one = 2
826  two = 1
827  END IF
828 !CDIR IEXPAND
829  this%dx = linearinterpolation(this%x(one),this%x(two),this%f(one),this%f(two))
830  ! improves convergence
831  IF (abs(this%dx).LE.this%tol) THEN
832  this%dx = 0.8*this%tol*sign(1.0,this%x(one)-this%x(two))
833  END IF
834  ! new estimate for the root
835  this%x(3) = this%x(two) + this%dx
836  ! store this for error control
837  this%dx = abs(this%x(one)-this%x(two))
838  END SUBROUTINE step_secantmethod
839 
840 
841  PURE SUBROUTINE saveinversequadraticinterpolation(a,b,c,fa,fb,fc,db_numer,db_denom)
842  IMPLICIT NONE
843  !------------------------------------------------------------------------!
844  REAL, INTENT(IN) :: a,b,c,fa,fb,fc
845  REAL, INTENT(OUT) :: db_numer,db_denom
846  !------------------------------------------------------------------------!
847  REAL :: fbdivfa,fadivfc,fbdivfc,p,q
848  !------------------------------------------------------------------------!
849  fbdivfa = fb / fa
850  IF ((fa.EQ.fc).OR.(fb.EQ.fc)) THEN
851  ! fallback: linear interpolation
852  p = (c-b) * fbdivfa
853  q = 1.0 - fbdivfa
854  ELSE
855  ! try inverse quadratic interpolation
856  fadivfc = fa / fc
857  fbdivfc = fb / fc
858  p = fbdivfa * ((c-b)*fadivfc*(fadivfc-fbdivfc) - (b-a)*(fbdivfc-1.0) )
859  q = (fadivfc - 1.0) * (fbdivfc - 1.0) * (fbdivfa - 1.0)
860  END IF
861  ! move the sign of the ratio p/q to the denominator q;
862  ! thus the return value of the numerator is always > 0
863  IF (p.GT.0.0) THEN
864  db_numer = p
865  db_denom = -q
866  ELSE
867  db_numer = -p
868  db_denom = q
869  END IF
870  END SUBROUTINE saveinversequadraticinterpolation
871 
872 
873  PURE SUBROUTINE step_arithmeticmean(this)
874  IMPLICIT NONE
875  !------------------------------------------------------------------------!
876  TYPE(roots_typ), INTENT(INOUT) :: this
877  !------------------------------------------------------------------------!
878  ! new estimate for the root
879 !CDIR IEXPAND
880  this%x(3) = arithmeticmean(this%x(1),this%x(2))
881  ! store this for error control
882  this%dx = abs(this%x(2)-this%x(1))
883  END SUBROUTINE step_arithmeticmean
884 
885 
886  PURE FUNCTION arithmeticmean(a,b) RESULT(s)
887  IMPLICIT NONE
888  !------------------------------------------------------------------------!
889  REAL, INTENT(IN) :: a,b
890  REAL :: s
891  !------------------------------------------------------------------------!
892  s = 0.5*(a+b)
893  END FUNCTION arithmeticmean
894 
895 
896  PURE FUNCTION linearinterpolation(x1,x2,f1,f2) RESULT(dx)
897  IMPLICIT NONE
898  !------------------------------------------------------------------------!
899  REAL, INTENT(IN) :: x1,x2,f1,f2
900  REAL :: dx
901  !------------------------------------------------------------------------!
902  dx = (x1-x2)*f2 / (f2 - f1 + tiny(f1))
903  END FUNCTION linearinterpolation
904 
905 
906  PURE SUBROUTINE testconvergence(this)
907  IMPLICIT NONE
908  !------------------------------------------------------------------------!
909  TYPE(roots_typ), INTENT(INOUT) :: this
910  !------------------------------------------------------------------------!
911  IF (this%error.NE.0) THEN
912  ! error occurred => abort iteration
913  this%iterate = .false.
914  ELSE
915  ! check convergence
916  this%tol = this%eps*abs(this%x(3))
917  IF (abs(this%f(3)).LE.tiny(this%f(3)) .OR. this%dx.LE.this%tol) THEN
918  ! converged => store current estimate xm in root and finish iteration
919  this%iterate = .false.
920  this%root = this%x(3)
921  ELSE
922  ! not converged => check iteration limit
923  IF (this%iter.GE.this%MAX_ITERATIONS) THEN
924  ! exceeded => store error code and abort iteration
925  this%error = 2
926  this%iterate = .false.
927  ELSE
928  ! continue iteration
929  this%iter = this%iter + 1
930  this%iterate = .true.
931  END IF
932  END IF
933  END IF
934  END SUBROUTINE testconvergence
935 
936 END MODULE roots
subroutine error(this, modproc, msg, rank, node_info)
Print error message on standard error and terminate the program.
pure subroutine funcd(y, fy, dfy, plist)
Definition: bondi2d.f90:416
pure subroutine updatebounds_bisection(this)
Definition: roots.f90:550
subroutine, public getroot_newton(funcd, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:247
pure subroutine step_arithmeticmean(this)
Definition: roots.f90:874
subroutine getroot_generic(this, Stepper, func, x1, x2, dxacc, maxiter, plist, xm)
Definition: roots.f90:178
character(len=64), dimension(0:4), parameter error_message
Definition: roots.f90:68
subroutine, public getroot_pegasus(func, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:349
pure subroutine step_regulafalsi(this)
Definition: roots.f90:604
subroutine, public getroot_bisection(func, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:519
pure subroutine step_ridder(this)
Definition: roots.f90:717
pure subroutine step_bisection(this)
Definition: roots.f90:568
pure subroutine step_king(this)
Definition: roots.f90:643
subroutine, public getroot_brentdekker(func, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:485
pure subroutine step_brentdekker(this)
Definition: roots.f90:748
integer, parameter, public default_max_iterations
Definition: roots.f90:66
pure subroutine func(x, fx, plist)
Definition: rootstest.f90:191
pure subroutine saveinversequadraticinterpolation(a, b, c, fa, fb, fc, db_numer, db_denom)
Definition: roots.f90:842
pure real function arithmeticmean(a, b)
Definition: roots.f90:887
pure subroutine step_pegasus(this)
Definition: roots.f90:618
pure subroutine testconvergence(this)
Definition: roots.f90:907
subroutine, public getroot_andersonbjoerk(func, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:417
real, parameter, public default_accuracy
Definition: roots.f90:67
pure subroutine step_andersonbjoerk(this)
Definition: roots.f90:691
root finding subroutines
Definition: roots.f90:45
subroutine, public getroot_regulafalsi(func, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:315
basic type for root finding functions
Definition: roots.f90:50
pure subroutine, public initroots(this, x1, x2, f1, f2, dxacc, maxiter)
Definition: roots.f90:98
pure subroutine step_secantmethod(this)
Definition: roots.f90:811
subroutine, public getroot_ridder(func, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:451
pure subroutine step_newton(this)
Definition: roots.f90:578
pure real function linearinterpolation(x1, x2, f1, f2)
Definition: roots.f90:897
character(len=64) function, public geterrormessage(error)
Definition: roots.f90:160
subroutine, public getroot_king(func, x1, x2, root, error, plist, xm, iterations)
Definition: roots.f90:383