!--------------------------------------- LICENCE BEGIN ----------------------------------- !Environment Canada - Atmospheric Science and Technology License/Disclaimer, ! version 3; Last Modified: May 7, 2008. !This is free but copyrighted software; you can use/redistribute/modify it under the terms !of the Environment Canada - Atmospheric Science and Technology License/Disclaimer !version 3 or (at your option) any later version that should be found at: !http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html ! !This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; !without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. !See the above mentioned License/Disclaimer for more details. !You should have received a copy of the License/Disclaimer along with this software; !if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec), !CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca !-------------------------------------- LICENCE END --------------------------------------subroutine n1qn3 (simul,prosca,dtonb,dtcab,n,x,f,g,dxmin,df1, 2,2 / epsg,impres,io,mode,niter,nsim,iz,dz,ndz, / izs,rzs,dzs) c---- c c N1QN3, Version 2.0c, June 1995 c Jean Charles Gilbert, Claude Lemarechal, INRIA. c c Double precision version of M1QN3. c c N1qn3 has two running modes: the SID (Scalar Initial Scaling) mode c and the DIS (Diagonal Initial Scaling) mode. Both do not require c the same amount of storage, the same subroutines, ... c In the description below, items that differ in the DIS mode with c respect to the SIS mode are given in brakets. c c Use the following subroutines: c N1QN3A c DDD, DDDS c NLIS0 + DCUBE (Dec 88) c MUPDTS, DYSTBL. c c The following routines are proposed to the user in case the c Euclidean scalar product is used: c DUCLID, DTONBE, DTCABE. c c La sous-routine N1QN3 est une interface entre le programme c appelant et la sous-routine N1QN3A, le minimiseur proprement dit. c c Le module PROSCA est sense realiser le produit scalaire de deux c vecteurs de Rn; le module DTONB est sense realiser le changement c de coordonnees correspondant au changement de bases: base c euclidienne -> base orthonormale (pour le produit scalaire c PROSCA); le module CTBAB fait la transformation inverse: base c orthonormale -> base euclidienne. c c Iz is an integer working zone for N1QN3A, its dimension is 5. c It is formed of 5 scalars that are set by the optimizer: c - the dimension of the problem, c - a identifier of the scaling mode, c - the number of updates, c - two pointers. c c Dz est la zone de travail pour N1QN3A, de dimension ndz. c Elle est subdivisee en c 3 [ou 4] vecteurs de dimension n: d,gg,[diag,]aux c m vecteurs de dimension n: ybar c m vecteurs de dimension n: sbar c c m est alors le plus grand entier tel que c m*(2*n+1)+3*n .le. ndz [m*(2*n+1)+4*n .le. ndz)] c soit m := (ndz-3*n) / (2*n+1) [m := (ndz-4*n) / (2*n+1)]. c Il faut avoir m >= 1, donc ndz >= 5n+1 [ndz >= 6n+1]. c c A chaque iteration la metrique est formee a partir d'un multiple c de l'identite [d'une matrice diagonale] D qui est mise a jour m c fois par la formule de BFGS en utilisant les m couples {y,s} les c plus recents. c c---- c c arguments c integer n,impres,io,mode,niter,nsim,iz(5),ndz,izs(1) real rzs(1) double precision x(n),f,g(n),dxmin,df1,epsg,dz(ndz),dzs(1) external simul,prosca,dtonb,dtcab c c variables locales c logical inmemo,sscale integer ntravu,id,igg,idiag,iaux,iybar,isbar,m,mmemo double precision d1,d2,ps c c---- impressions initiales et controle des arguments c write(io,*) '--------------------------------------------------' write(io,*) 'N1QN3: calling modified MPI version of modulopt!!!' write(io,*) '--------------------------------------------------' if (impres.ge.1) / write (io,900) n,dxmin,df1,epsg,niter,nsim,impres 900 format (/" N1QN3 (Version 2.0c, June 1995): entry point"/ / 5x,"dimension of the problem (n):",i9/ / 5x,"absolute precision on x (dxmin):",d9.2/ / 5x,"expected decrease for f (df1):",d9.2/ / 5x,"relative precision on g (epsg):",d9.2/ / 5x,"maximal number of iterations (niter):",i6/ / 5x,"maximal number of simulations (nsim):",i6/ / 5x,"printing level (impres):",i4) if (n.le.0.or.niter.le.0.or.nsim.le.0.or.dxmin.le.0.d+0.or. & epsg.le.0.d+0.or.epsg.gt.1.d+0.or.mode.lt.0.or.mode.gt.3) then mode=2 if (impres.ge.1) write (io,901) 901 format (/" >>> n1qn3: inconsistent call") return endif c c---- what method c if (mod(mode,2).eq.0) then if (impres.ge.1) write (io,920) 920 format (/" n1qn3: Diagonal Initial Scaling mode") sscale=.false. else if (impres.ge.1) write (io,921) 921 format (/" n1qn3: Scalar Initial Scaling mode") sscale=.true. endif c if ((ndz.lt.5*n+1).or.((.not.sscale).and.(ndz.lt.6*n+1))) then mode=2 if (impres.ge.1) write (io,902) 902 format (/" >>> n1qn3: not enough memory allocated") return endif c c---- Compute m c call mupdts
(sscale,inmemo,n,m,ndz) c c --- Check the value of m (if (y,s) pairs in core, m will be >= 1) c if (m.lt.1) then mode=2 if (impres.ge.1) write (io,9020) 9020 format (/" >>> n1qn3: m is set too small in mupdts") return endif c c --- mmemo = number of (y,s) pairs in core memory c mmemo=1 if (inmemo) mmemo=m c ntravu=2*(2+mmemo)*n if (sscale) ntravu=ntravu-n if (impres.ge.1) write (io,903) ndz,ntravu,m 903 format (/5x,"allocated memory (ndz) :",i9/ / 5x,"used memory : ",i9/ / 5x,"number of updates : ",i9) if (ndz.lt.ntravu) then mode=2 if (impres.ge.1) write (io,902) return endif c if (impres.ge.1) then if (inmemo) then write (io,907) else write (io,908) endif endif 907 format (5x,"(y,s) pairs are stored in core memory") 908 format (5x,"(y,s) pairs are stored by the user") c c---- cold start or warm restart ? c check iz: iz(1)=n, iz(2)=(0 if DIS, 1 if SIS), c iz(3)=m, iz(4)=jmin, iz(5)=jmax c if (mode/2.eq.0) then if (impres.ge.1) write (io,922) else iaux=0 if (sscale) iaux=1 ! if (iz(1).ne.n.or.iz(2).ne.iaux.or.iz(3).ne.m.or.iz(4).lt.1 ! & .or.iz(5).lt.1.or.iz(4).gt.iz(3).or.iz(5).gt.iz(3)) then if (iz(2).ne.iaux.or.iz(3).ne.m.or.iz(4).lt.1 & .or.iz(5).lt.1.or.iz(4).gt.iz(3).or.iz(5).gt.iz(3)) then mode=2 write(*,*) 'iz=',iz(:) write(*,*) 'n,iaux,m=',n,iaux,m if (impres.ge.1) write (io,923) return endif if (impres.ge.1) write (io,924) endif 922 format (/" n1qn3: cold start"/,1x) 923 format (/" >>> n1qn3: inconsistent iz for a warm restart") 924 format (/" n1qn3: warm restart"/,1x) iz(1)=n iz(2)=0 if (sscale) iz(2)=1 iz(3)=m c c---- split the working zone dz c idiag=1 iybar=idiag+n if (sscale) iybar=1 isbar=iybar+n*mmemo id=isbar+n*mmemo igg=id+n iaux=igg+n c c---- call the optimization code c call n1qn3a
(simul,prosca,dtonb,dtcab,n,x,f,g,dxmin,df1,epsg, / impres,io,mode,niter,nsim,inmemo,iz(3),iz(4),iz(5), / dz(id),dz(igg),dz(idiag),dz(iaux), / dz(iybar),dz(isbar),izs,rzs,dzs) c c---- impressions finales c if (impres.ge.1) write (io,905) mode,niter,nsim,epsg 905 format (/,1x,79("-")/ / /" n1qn3: output mode is ",i2 / /5x,"number of iterations: ",i4 / /5x,"number of simulations: ",i6 / /5x,"realized relative precision on g: ",d9.2) call prosca (n,x,x,ps,izs,rzs,dzs) d1=dsqrt(ps) call prosca (n,g,g,ps,izs,rzs,dzs) d2=dsqrt(ps) if (impres.ge.1) write (io,906) d1,f,d2 906 format (5x,"norm of x = ",d15.8 / /5x,"f = ",d15.8 / /5x,"norm of g = ",d15.8) return end