Files
Fortran-docker-mvc/flibs-0.9/flibs/doc/computing/automdiff.man
Tommy Parnell a7037b9e92 init
2017-02-20 16:06:45 -05:00

204 lines
5.0 KiB
Groff

[comment {-*- flibs -*- doctools manpage}]
[manpage_begin automatic_differentiation n 1.0]
[copyright {2006 Arjen Markus <arjenmarkus@sourceforge.net>}]
[moddesc flibs]
[titledesc {Implement the "automatic differentation" technique}]
[description]
The [strong automatic_differentiation] module defines a derived
type that enables you (via overloading common mathematical
functions and operators) to:
[list_begin bullet]
[bullet]
Define a mathematical function in the usual way
[bullet]
Evaluate that function [strong and] its first derivative at the same
time
[list_end]
without having to program that first derivative.
[para]
The module uses real numbers of the kind "wp" as defined in the
auxiliary module [strong select_precision].
[para]
(I was pointed to this technique by Simon Geard, a couple of years ago,
in the context of one of the many language shootouts on the Internet.)
[section "EXAMPLE"]
In numerical methods like Newton-Raphson for finding a root of the
equation "f(x) = 0", you need the first derivative:
[example {
x(k+1) = x(k) - f(x(k)) / f'(x(k))
}]
Rather than implementing the function and its first derivatives as
separate functions, using this module you can dispense with manually
determining the first derivative:
[example {
program root
use automatic_differentation
type(AUTODERIV) :: x
type(AUTODERIV) :: res
integer :: i
!
! First estimate
!
x = derivvar( 1.0_wp )
do i = 1,10
res = f(x)
x = x - res.v / res.dv
enddo
write(*,*) 'Root: ', x.v
contains
type(AUTODERIV) function f(x)
type(AUTODERIV) :: x
f = x + cos(x)
end function f
end program
}]
[section "DATA TYPES AND ROUTINES"]
The module defines a single data type, AUTODERIV, and one specific
function, derivvar().
[list_begin definitions]
[call [cmd "use automatic_differentiation"]]
The name of the module
[call [cmd "type(AUTODERIV)"]]
The type has two fields:
[list_begin arg]
[arg_def "real(wp)" v]
The value of the variable/function (or any intermediate result)
[arg_def "real(wp)" dv]
The first derivative
[list_end]
[nl]
[call [cmd "x = derivvar( value )"]]
Use this function to properly initialise the program
variable x as a "mathematical" variable. (It sets the derivative
of x to 1, because otherwise it would be regarded as a constant).
[list_begin arg]
[arg_def "real(wp)" value]
The value of the "mathematical" variable.
[list_end]
[call [cmd "call find_root( f, xinit, tolerance, root, found )"]]
This subroutine is a simple implementation of the Newton-Raphson
method to find roots. The function f takes one argument, x.
[list_begin arg]
[arg_def "type(AUTODERIV) function" f(x)]
The function must have the interface:
[example {
interface
function f(x)
use automatic_differentiation_type
type(AUTODERIV), intent(in) :: x
type(AUTODERIV) :: f
end function
end interface
}]
Its return value is the function value at point x and its first
derivative.
[arg_def "type(AUTODERIV), intent(in)" xinit]
Initial estimate of the root - the end result may depend on this choice.
[arg_def "real(wp)" tolerance]
Maximum allowable error in the absolute value of the root. If the
difference between the old and the new estimate is smaller than this
value, the iteration stops.
[arg_def "type(AUTODERIV), intent(out)" root]
Final estimate of the root.
[arg_def "logical" found]
Indicator whether a root was found or not. There is a maximum
number of iterations and the root must not grow too large.
[list_end]
[call [cmd "call find_root_iter( fvalue, root, tolerance, found )"]]
This subroutine performs a single iteration in the Newton-Raphson
method to find roots. It can be used to implement a more general version
of [strong find_root], for instance if the interface to the function
contains one or more asjustable parameters.
[list_begin arg]
[arg_def "type(AUTODERIV)" fvalue]
The value of the function (plus its first derivative)
[arg_def "type(AUTODERIV), intent(in)" root]
Current estimate of the root
[arg_def "real(wp)" tolerance]
Maximum allowable error in the absolute value of the root. If the
difference between the old and the new estimate is smaller than this
value, the indicator [strong found] is set to true.
[arg_def "logical" found]
Indicator whether a root was found or not.
[list_end]
[list_end]
[section "POSSIBLE EXTENSIONS"]
You can extend the module in at least two ways:
[list_begin bullet]
[bullet]
Determine the second derivative, the third and so on. This is
straightforward enough, but the formulae will get fairly complex after
the second derivative.
[bullet]
Determine the derivative of a function of two or more variables. This
will require a bit more: such functions have a vector-valued
derivative and each independent variable will have to have a
vector-valued derivative as well. For instance:
[nl]
A function f(x,y) evaluated at (1,2), would take as the actual arguments
x = (1,1,0) (so no variation in the second direction) and y = (2,0,1)
(no variation in the first direction).
[list_end]
[manpage_end]