Commit b5f099f3cfce0be73a364dfeea7af3d8cd2f3f3e

Authored by wdaniau
1 parent 31f2c259c6

Added documentation for fvn_lm

git-svn-id: https://lxsd.femto-st.fr/svn/fvn@80 b657c933-2333-4658-acf2-d3c7c2708721

Showing 2 changed files with 169 additions and 4 deletions Side-by-side Diff

No preview for this file type
... ... @@ -295,7 +295,7 @@
295 295 \item \texttt{n} (in) is an integer equal to the matrix rank
296 296 \item \texttt{nz} (in) is an integer equal to the number of non-zero elements
297 297 \item \texttt{T(nz) or Tx(nz),Tz(nz)} (in) is a real array (or two real arrays for real/imaginary in case of a complex system) containing the non-zero elements
298   - \item \textt{Ti(nz)},\texttt{Tj(nz)} (in) are the indexes of the corresponding element of \texttt{T} in the original matrix, this has to be 0-based as in C.
  298 + \item \texttt{Ti(nz)},\texttt{Tj(nz)} (in) are the indexes of the corresponding element of \texttt{T} in the original matrix, this has to be 0-based as in C.
299 299 \item \texttt{B(n) or Bx(n),Bz(n)} (in) is a real array or two real arrays for real/imaginary in case of a complex system) containing the second member of the equation.
300 300 \item \texttt{x(n)} (out) is a complex/real array containing the solution
301 301 \item \texttt{status} (out) is an integer which contain non-zero is something went wrong
... ... @@ -387,7 +387,7 @@
387 387 \item \texttt{n} (in) is an integer equal to the matrix rank
388 388 \item \texttt{nz} (in) is an integer equal to the number of non-zero elements
389 389 \item \texttt{T(nz) or Tx(nz),Tz(nz)} (in) is a real array (or two real arrays for real/imaginary in case of a complex system) containing the non-zero elements
390   - \item \textt{Ti(nz)},\texttt{Tj(nz)} (in) are the indexes of the corresponding element of \texttt{T} in the original matrix, it has to be 0-based as in C.
  390 + \item \texttt{Ti(nz)},\texttt{Tj(nz)} (in) are the indexes of the corresponding element of \texttt{T} in the original matrix, it has to be 0-based as in C.
391 391 \item \texttt{det} (out), a real(8) array of dimension 2 for dl and di specific interface (real systems) and dimension 3 for zl and zi interface (complex systems)
392 392 \item \texttt{status} (out) is an integer which contain non-zero is something went wrong
393 393 \end{itemize}
... ... @@ -913,7 +913,7 @@
913 913 \end{verbatim}
914 914 The results are plotted on figure \ref{lsp} .
915 915  
916   -\begin{figure}
  916 +\begin{figure}[ht]
917 917 \begin{center}
918 918 \includegraphics[width=0.9\textwidth]{lsp.pdf}
919 919 \caption{Least Square Polynomial}
920 920  
921 921  
922 922  
... ... @@ -921,10 +921,175 @@
921 921 \end{center}
922 922 \end{figure}
923 923  
  924 +\section{General least square fitting}
  925 +fvn provides a routine performing a general least square fitting using Levenberg-Marquardt algorithm. It uses routine \verb'lmdif' from \verb'MINPACK' (\url{http://www.netlib.org/minpack}). The used version has been converted to fortran90 by Alan Miller \verb'amiller @ bigpond.net.au'.
  926 +\newline
  927 +The purpose of \verb'fvn_lm' is to minimize the sum of the squares of m nonlinear
  928 +functions in n variables by a modification of the Levenberg-Marquardt
  929 +algorithm. This is done by using the more general least-squares
  930 +solver lmdif. The user must provide a subroutine which calculates the
  931 +functions. The jacobian is then calculated by a forward-difference
  932 +approximation.
924 933  
  934 +\begin{verbatim}
  935 +Module : use fvn_misc
  936 +call fvn_lm(fcn,m,n,a,info,tol)
  937 +\end{verbatim}
  938 +\begin{itemize}
  939 +\item fcn is the user-supplied subroutine which calculates
  940 + the functions. fcn must follow the following interface that must
  941 + be declared in the calling subroutine :
  942 +\begin{verbatim}
  943 + interface
  944 + subroutine fcn(m,n,a,fvec,iflag)
  945 + use fvn_common
  946 + integer(ip_kind), intent(in) :: m
  947 + integer(ip_kind), intent(in) :: n
  948 + real(dp_kind), dimension(:), intent(in) :: a
  949 + real(dp_kind), dimension(:), intent(inout) :: fvec
  950 + integer(ip_kind), intent(inout) :: iflag
  951 + end subroutine
  952 + end interface
  953 +
  954 +\end{verbatim}
925 955  
  956 + This is the function which calculate the differences for which which square sum
  957 + will be minimized outputing this difference in vector fvec.
  958 + Parameters of fcn are as follows :
  959 +\begin{itemize}
  960 + \item m : positive integer input variable set to the number of functions
  961 + (number of measurement points)
  962 + \item n : positive integer input variable set to the number of variables
  963 + (number of parameters in the function to fit)
  964 + \item a : vector of length n containing parameters for which fcn should
  965 + perform the calculation
  966 + \item fvec : vector of length m containing the resulting evaluation
  967 + \item iflag : integer normally not used, can be used to exit the
  968 + the algorithm by setting it to a negative value
  969 +\end{itemize}
  970 +
  971 +\item m : positive integer input variable set to the number of functions
  972 + (number of measurement points)
  973 +\item n : positive integer input variable set to the number of variables
  974 + (number of parameters in the function to fit)
  975 +\item a(n) : vector of length n, on input must contains an initial guess (or unity vector)
  976 + and on output the solution vector
  977 +\item info : is an output positive integer
  978 +\begin{itemize}
  979 + \item info = 0 improper input parameters.
  980 + \item info = 1 algorithm estimates that the relative error
  981 + in the sum of squares is at most tol.
  982 + \item info = 2 algorithm estimates that the relative error
  983 + between x and the solution is at most tol.
  984 + \item info = 3 conditions for info = 1 and info = 2 both hold.
  985 + \item info = 4 fvec is orthogonal to the columns of the
  986 + jacobian to machine precision.
  987 + \item info = 5 number of calls to fcn has reached or exceeded 200*(n+1).
  988 + \item info = 6 tol is too small. no further reduction in
  989 + the sum of squares is possible.
  990 + \item info = 7 tol is too small. No further improvement in
  991 + the approximate solution x is possible.
  992 +\end{itemize}
  993 +
  994 +\item tol : is an optional positive value. Termination occurs when the
  995 + algorithm estimates either that the relative error in the sum of
  996 + squares is at most tol or that the relative error between x and the
  997 + solution is at most tol. If not provided default value is :
  998 + sqrt(epsilon(0.0d0))
  999 +\end{itemize}
  1000 +
  1001 +\subsection*{Example}
  1002 +Here's a simple example solving the same problem as for the least square polynomial example but using \verb'fvn_lm' instead :
  1003 +\begin{verbatim}
  1004 +module excursion
  1005 +real(8), dimension(:), pointer :: xm => NULL()
  1006 +real(8), dimension(:), pointer :: ym => NULL()
  1007 +end module
  1008 +
  1009 +
  1010 +program gls
  1011 +use fvn_misc
  1012 +use excursion
  1013 +implicit none
  1014 +
  1015 + interface
  1016 + subroutine zef(m, n, x, fvec, iflag)
  1017 + integer(4), intent(in) :: m,n
  1018 + real(8), dimension(:), intent(in) :: x
  1019 + real(8), dimension(:), intent(inout) :: fvec
  1020 + integer(4), intent(inout) :: iflag
  1021 + end subroutine
  1022 + end interface
  1023 +
  1024 +
  1025 + integer,parameter :: npoints=13,deg=3
  1026 + integer :: status,i
  1027 + real(kind=dp_kind) :: xstep,xc,yc
  1028 + real(kind=dp_kind) :: coeff(deg+1)
  1029 + real(kind=dp_kind) :: fvec(npoints)
  1030 + integer(4) :: iwa(deg+1)
  1031 + integer(4) :: info
  1032 + real(8) :: tol
  1033 +
  1034 + allocate(xm(npoints),ym(npoints))
  1035 +
  1036 + xm = (/ -3.8,-2.7,-2.2,-1.9,-1.1,-0.7,0.5,1.7,2.,2.8,3.2,3.8,4. /)
  1037 + ym = (/ -3.1,-2.,-0.9,0.8,1.8,0.4,2.1,1.8,3.2,2.8,3.9,5.2,7.5 /)
  1038 + open(2,file='fvn_lsp_double_mesure.dat')
  1039 + open(3,file='fvn_lm.dat')
  1040 + do i=1,npoints
  1041 + write(2,44) xm(i),ym(i)
  1042 + end do
  1043 + close(2)
  1044 +
  1045 + coeff=1.
  1046 + call fvn_lm(zef,npoints,deg+1,coeff,info)
  1047 + write(*,*) "info : ",info
  1048 +
  1049 + xstep=(xm(npoints)-xm(1))/1000.
  1050 + do i=1,1000
  1051 + xc=xm(1)+(i-1)*xstep
  1052 + yc=poly(xc,coeff)
  1053 + write(3,44) xc,yc
  1054 + end do
  1055 + close(3)
  1056 +write(*,*) "All done, plot results with gnuplot using command :"
  1057 +write(*,*) "pl 'fvn_lsp_double_mesure.dat' u 1:2 w p,'fvn_lm.dat' u 1:2 w l"
  1058 +44 FORMAT(4(1X,1PE22.14))
  1059 +contains
  1060 +function poly(x,coeff)
  1061 + use fvn_common
  1062 + implicit none
  1063 + real(kind=dp_kind) :: x
  1064 + real(kind=dp_kind) :: coeff(deg+1)
  1065 + real(kind=dp_kind) :: poly
  1066 + integer :: i
  1067 + poly=0.
  1068 + do i=1,deg+1
  1069 + poly=poly+coeff(i)*x**(i-1)
  1070 + end do
  1071 +end function
  1072 +end program
  1073 +
  1074 +subroutine zef(m, n, x, fvec, iflag)
  1075 + use excursion
  1076 + implicit none
  1077 + integer(4), intent(in) :: m,n
  1078 + real(8), dimension(:), intent(in) :: x
  1079 + real(8), dimension(:), intent(inout) :: fvec
  1080 + integer(4), intent(inout) :: iflag
  1081 +
  1082 + integer(4) :: i
  1083 +
  1084 + do i=1,m
  1085 + fvec(i)=ym(i)-(x(1)+x(2)*xm(i)+x(3)*xm(i)**2+x(4)*xm(i)**3)
  1086 + enddo
  1087 +end subroutine
  1088 +\end{verbatim}
  1089 +Note the need to use a supplementary module \verb'excursion', to allow the subroutine \verb'zef' to have access to the measurement points.
  1090 +
926 1091 \section{Zero finding}
927   -fvn provide a routine for finding zeros of a complex function using Muller algorithm (only for double complex type). It is based on a version provided on the web by Hans D Mittelmann \url{http://plato.asu.edu/ftp/other\_software/muller.f}.
  1092 +fvn provides a routine for finding zeros of a complex function using Muller algorithm (only for double complex type). It is based on a version provided on the web by Hans D Mittelmann \url{http://plato.asu.edu/ftp/other\_software/muller.f}.
928 1093  
929 1094 \begin{verbatim}
930 1095 Module : use fvn_misc