Commit b5f099f3cfce0be73a364dfeea7af3d8cd2f3f3e
1 parent
31f2c259c6
Exists in
master
and in
2 other branches
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
doc/fvn.pdf
No preview for this file type
doc/fvn.tex
... | ... | @@ -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 |