Main routine.
2008/01/16 | J. SCHOENMAEKERS | NEW
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(optgra), | intent(inout) | :: | me | |||
| real(kind=wp), | intent(inout) | :: | Valvar(me%Numvar) |
VARIABLES VALUE -> NOT SCALED |
||
| real(kind=wp), | intent(out) | :: | Valcon(me%Numcon+1) |
CONSTRAINTS VALUE (1:NUMCON) MERIT VALUE (1+NUMCON) -> NOT SCALED |
||
| integer(kind=ip), | intent(out) | :: | Finopt |
TERMINATION STATUS
|
||
| integer(kind=ip), | intent(out) | :: | Finite |
? |
subroutine ogexec(me,Valvar,Valcon,Finopt,Finite) !! Main routine. !! !! 2008/01/16 | J. SCHOENMAEKERS | NEW class(optgra),intent(inout) :: me real(wp),intent(inout) :: Valvar(me%Numvar) !! VARIABLES VALUE !! -> NOT SCALED real(wp),intent(out) :: Valcon(me%Numcon+1) !! CONSTRAINTS VALUE (1:NUMCON) !! MERIT VALUE (1+NUMCON) !! -> NOT SCALED integer(ip),intent(out) :: Finopt !! TERMINATION STATUS !! !! * 1 = MATCHED & OPTIMAL !! * 2 = MATCHED & NOT OPTIMAL !! * 3 = NOT MATCHED & NOT OPTIMAL !! * 4 = NOT FEASIBL & NOT OPTIMAL !! * -1 = Fatal error (constraints singular) integer(ip),intent(out) :: Finite !! ? character(len=str_len) :: str character(len=name_len) :: nam integer(ip) :: finish , itecor , iteopt, & var , con , typ , len , num , numvio, & itediv , itecnv real(wp) :: val , sca , red , der , fac , old , convio, & varacc , cosnew , cosold , varsav , meamer, & conerr , desnor , norerr , meaerr real(wp) , dimension(:) , allocatable :: varsum real(wp) , dimension(:) , allocatable :: varcor real(wp) , dimension(:) , allocatable :: concor real(wp) , dimension(:,:) , allocatable :: conder_tmp !! JW: created to avoid "array temporary" warning logical :: error ! initialize: allocate (varsum(me%Numvar)) allocate (varcor(me%Numvar)) allocate (concor(me%Numcon+1)) allocate (conder_tmp(me%Numcon+1,me%Numvar)) ! ====================================================================== ! GENERAL ! ---------------------------------------------------------------------- ! LOGLEV = 2 call me%ogwrit(2,"") call me%ogwrit(2,"OPTGRA START") call me%ogwrit(2,"") Finopt = 3 ! initialize with NOT MATCHED & NOT OPTIMAL itecor = 0 iteopt = 0 meaerr = 0.0_wp meamer = 0.0_wp itediv = 0 itecnv = 0 !me%Conopt = 0 concor = 0.0_wp varcor = 0.0_wp desnor = 0.0_wp ! ---------------------------------------------------------------------- me%Varstp = me%Varsnd me%Numite = 0 cosnew = 0.0_wp do var = 1 , me%Numvar varsum(var) = 0.0_wp varcor(var) = 0.0_wp end do ! ====================================================================== ! EQUALTIY CONSTRAINTS IN ACTIVE SET ! ---------------------------------------------------------------------- me%Numact = 0 do con = 1 , me%Numcon ! IF (CONTYP(CON) == -2) CYCLE nam = me%Constr(con) len = me%Conlen(con) write (str,*) "CON/PRI=" , con , me%Conpri(con) , " " , nam(1:len) call me%ogwrit(3,str) me%Conact(con) = 0 if ( me%Consca(con)>=1.0e+09_wp ) me%Contyp(con) = -2 if ( me%Contyp(con)==0 ) then elseif ( me%Contyp(con)==-2 ) then me%Conact(con) = -2 end if end do me%Conact(me%Numcon+1) = -3 me%Conact(me%Numcon+2) = -3 ! ====================================================================== ! SCALE VARIABLES ! ---------------------------------------------------------------------- do var = 1 , me%Numvar me%Varval(var) = Valvar(var)/me%Varsca(var) end do ! ====================================================================== ! HEADER FOR TABLE ! ---------------------------------------------------------------------- if ( me%Tablev>=1 ) write (me%Tablun,'("ITER",1X,"OPT",1X,*(1X,I10))') (var,var=1,me%Numvar) , (con,con=1,me%Numcon) main: do inner: do ! ====================================================================== ! IF (NUMITE >= 52) MATLEV = 3 ! IF (NUMITE >= 55) MATLEV = 2 ! ====================================================================== ! NEW ITERATION ! ---------------------------------------------------------------------- if ( me%Numite>=me%Corite .and. itecor==0 ) then ! correction limit reached Finopt = 3 ! not matched and not optimal Finite = me%Numite ! FINITE=Number of iterations at which termination occurred call me%ogwrit(1,"") write (str,'("OPTGRA: Converged: not ITERAT=",2I4,2D11.3)') & me%Numite , me%Maxite , conerr , desnor call me%ogwrit(1,str) ! Final Pygmo output ! TODO: can this final fitness call be avoided (just for output)? me%Pygfla = 3 ! pygmo flag in COMMON: no covergence call evaluation_func_and_der() exit main elseif ( me%Numite>=me%Maxite .or. (me%Numite-itecor>=me%Optite-1 .and. itecor/=0) ) then ! Maximum iteration reached or after correction phase Finopt = 2 ! matched, but not optimal Finite = iteopt me%Varval = varcor me%Conval = concor call me%ogwrit(1,"") write (str,'("OPTGRA: Converged: mat ITERAT=",2I4,2D11.3)') & me%Numite , me%Maxite , conerr , desnor call me%ogwrit(1,str) call me%ogpwri_end(-Valcon(me%Numcon+1),numvio,convio) ! Final Pygmo output ! TODO: can this final fitness call be avoided (just for output)? me%Pygfla = 2 ! pygmo flag in COMMON: constraints matched call evaluation_func_and_der() exit main end if ! ---------------------------------------------------------------------- me%Numite = me%Numite + 1 ! new iteration ! ---------------------------------------------------------------------- call me%ogwrit(3,"") write (str,'("ITERAT=",I5)')me%Numite call me%ogwrit(2,str) ! ====================================================================== ! GET VALUES AND GRADIENTS ! ====================================================================== if ( me%Senopt<=0 ) then ! No sensitivity analysis, only optimisation call evaluation_func_and_der() elseif ( me%Senopt==+1 .or. me%Senopt==+3 ) then ! sens. WITH CONSTRAINT CALCULATION me%Varval = me%Senvar call me%ogeval(me%Varval,me%Conval,0,conder_tmp) me%Conder(1:me%Numcon+1,:) = conder_tmp elseif ( me%Senopt==+2 .or. me%Senopt==+4 ) then ! sens. WITH CONSTRAINT BIAS me%Varval = me%Senvar do con = 1 , me%Numcon + 1 sca = me%Consca(con) if ( me%Contyp(con)==-1 ) sca = -sca me%Conval(con) = me%Sencon(con) - me%Sendel(con)/sca end do end if if ( me%Senopt==-1 ) then ! intialisation of sensitivity analysis me%Senvar = me%Varval me%Sencon = me%Conval end if ! ====================================================================== ! Do finite-difference check of provided gradients if VARDER=-1 (documented options are 0,1,2,3) if ( me%Varder==-1 .and. me%Senopt<=0 ) then me%Conred(1:me%Numcon+1,:) = me%Conder(1:me%Numcon+1,:) ! CONDER=current constraint derivatives call me%ogeval(me%Varval,me%Conval,2,conder_tmp) me%Conder(1:me%Numcon+1,:) = conder_tmp write (str,'("GRADIENT CHECK")') call me%ogwrit(1,str) do var = 1 , me%Numvar do con = 1 , me%Numcon + 1 fac = me%Varsca(var)/me%Consca(con) fac = 1.0_wp der = me%Conder(con,var)*fac red = me%Conred(con,var)*fac if ( abs(der)<1.0e-6_wp .and. abs(red)<1.0e-6_wp ) cycle if ( abs(der-red)<1.0e-2_wp ) cycle if ( der/=0.0_wp ) then fac = red/der else fac = 0.0_wp end if if ( abs(fac-1.0_wp)<1.0e-2_wp ) cycle write (str,'("VAR/CON/ANA/NUM/A2N=",2I4,3(1X,D13.6))') var , con , red , der , fac call me%ogwrit(1,str) nam = me%Varstr(var) len = me%Varlen(var) write (str,'(" VAR=",A,1X,D13.6)') nam(1:len) , me%Varval(var)*me%Varsca(var) call me%ogwrit(1,str) nam = me%Constr(con) len = me%Conlen(con) write (str,'(" CON=",A,1X,D13.6)') nam(1:len) , me%Conval(con)*me%Consca(con) call me%ogwrit(1,str) end do end do ! CONDER(1:NUMCON+1,:) = CONRED(1:NUMCON+1,:) ! GOTO 9999 end if ! ====================================================================== me%Sender = me%Conder ! SENDER=derivatives for sensitivity analysis??? do var = 1 , me%Numvar if ( me%Vartyp(var)/=1 ) cycle ! VARTYP=1 are sensitivity parameters, VARTYP=0 free params ! WRITE (STR,*) "VAR=",VAR,VARVAL(VAR)*VARSCA(VAR) ! CALL me%ogwrit (2,STR) me%Conder(1:me%Numcon+1,var) = 0.0_wp ! zero derivatives of free parameters??? end do ! ====================================================================== if ( me%Numite==1 ) then me%Vargrd = me%Varval else me%Vargrd = me%Varref end if me%Varref = me%Varval me%Conref = me%Conval ! ====================================================================== varacc = 0.0_wp ! initialise ITERATION SCALED DISTANCE ACCUMULATED ! ====================================================================== cosold = cosnew cosnew = me%Conval(me%Numcon+1) ! cost function value call me%ogwrit(3,"") write (str,'("OPTGRA: VALCOS=",D15.8,1X,D15.8)') cosnew , cosnew - cosold call me%ogwrit(3,str) ! ====================================================================== ! CONSTRAINTS CORRECTION PART ! ---------------------------------------------------------------------- call me%ogcorr(varacc,finish,conerr,norerr,error) if (error) then Finopt = -1 return end if ! ---------------------------------------------------------------------- if ( me%Tablev>=1 ) write (me%Tablun,'(I4,1X,"COR",1X,*(1X,D10.3))') & me%Numite , (me%Varval(var),var=1,me%Numvar) , (me%Conval(con),con=1,me%Numcon) ! ---------------------------------------------------------------------- if ( me%Senopt/=0 ) then if ( finish/=0 ) exit inner Finopt = 0 exit main end if ! ---------------------------------------------------------------------- if ( finish==0 ) then me%Numact = 0 old = meaerr itediv = itediv + 1 num = min(itediv,me%Divite) meaerr = (meaerr*(num-1)+norerr)/num ! WRITE (STR,*) "MEAERR=",MEAERR ! CALL me%ogwrit (2,STR) if ( itediv<me%Divite .or. meaerr<=old ) cycle finish = -1 end if ! ---------------------------------------------------------------------- if ( finish==-1 ) then Finopt = 4 Finite = me%Numite call me%ogwrit(1,"") write (str,'("OPTGRA: Converged: unf ITERAT=",2I4,2D11.3)') & me%Numite , me%Maxite , conerr , desnor call me%ogwrit(1,str) ! Final Pygmo output ! TODO: can this final fitness call be avoided (just for output)? me%Pygfla = 4 ! pygmo flag in COMMON: infeasible call evaluation_func_and_der() exit main end if ! ---------------------------------------------------------------------- itediv = 0 iteopt = me%Numite if ( itecor==0 .or. concor(me%Numcon+1)<me%Conval(me%Numcon+1) ) then varcor = me%Varval concor = me%Conval end if if ( itecor==0 ) itecor = me%Numite ! ---------------------------------------------------------------------- old = meamer itecnv = itecnv + 1 num = min(itecnv,me%Cnvite) meamer = (meamer*(num-1)+concor(me%Numcon+1))/num ! WRITE (STR,*) "MEAMER=",ITECNV,NUM,MEAMER,OLD,OLD/MEAMER ! CALL me%ogwrit (-1,STR) if ( itecnv>=me%Cnvite .and. meamer<old ) then Finopt = 2 Finite = iteopt me%Varval = varcor me%Conval = concor call me%ogwrit(1,"") write (str,'("OPTGRA: Converged: mat ITERAT=",2I4,2D11.3)') & me%Numite , me%Maxite , conerr , desnor call me%ogwrit(1,str) ! Final Pygmo output ! TODO: can this final fitness call be avoided (just for output)? me%Pygfla = 2 ! pygmo flag in COMMON: matched call evaluation_func_and_der() exit main end if exit inner end do inner ! ====================================================================== ! OPTIMIZATION PART ! ---------------------------------------------------------------------- if ( me%Senopt<+3 ) then varsav = me%Varmax me%Varmax = me%Varmax*10.0e-1_wp call me%ogopti(varacc,finish,desnor,error) if (error) then Finopt = -1 return end if me%Varmax = varsav end if ! ---------------------------------------------------------------------- if ( me%Senopt/=0 ) then call me%ogwrit(1,"") if ( finish==0 ) then Finopt = 0 call me%ogwrit(1,"OPTGRA sensitivity converged: not") else Finopt = 1 call me%ogwrit(1,"OPTGRA sensitivity converged: yes") end if exit main end if ! ---------------------------------------------------------------------- if ( finish==0 ) cycle main ! ====================================================================== ! NOT CONVERGED ! ---------------------------------------------------------------------- if ( varacc/=0.0_wp ) cycle main ! ====================================================================== ! CONVERGED ! ---------------------------------------------------------------------- Finopt = 1 Finite = me%Numite call me%ogwrit(1,"") write (str,'("OPTGRA: Converged: yes ITERAT=",2I4,2D11.3)') & me%Numite , me%Maxite , conerr , desnor call me%ogwrit(1,str) call me%ogwrit(3,"") ! Final Pygmo output ! TODO: can this final fitness call be avoided (just for output)? me%Pygfla = 1 ! covergence call evaluation_func_and_der() exit main end do main ! WRITE (STR,*) "DIF=",NORM2(VARVAL-VARREF) ! CALL me%ogwrit (1,STR) ! ====================================================================== ! DESCALE VARIABLES ! ---------------------------------------------------------------------- ! CALL OGWMAT (3) ! CALL me%ogeval (VARVAL, VALCON, 0, CONDER) do var = 1 , me%Numvar Valvar(var) = me%Varval(var)*me%Varsca(var) end do ! IF (SENOPT /= 0) THEN ! CALL me%ogeval (VARVAL, VALCON, 0, CONDER) ! end if ! ====================================================================== ! DESCALE VALUES ! ---------------------------------------------------------------------- do con = 1 , me%Numcon + 1 typ = me%Contyp(con) sca = me%Consca(con) if ( typ==-1 ) sca = -sca Valcon(con) = me%Conval(con)*sca end do ! ====================================================================== call me%ogwrit(3,"") call me%ogwrit(3,"STATUS OF CONSTRAINTS:") call me%ogwrit(3,"") call me%ogwrit(3," ACT PAS NON COST___VAL CONSTRAINT") do con = 1 , me%Numcon if ( me%Contyp(con)==-2 ) cycle nam = me%Constr(con) len = me%Conlen(con) val = me%Conval(con) if ( me%Conact(con)>0 ) then write (str,'( I4,5X,6X,D10.3,1X,A)') con , val , nam(1:len) call me%ogwrit(3,str) elseif ( me%Conact(con)==0 ) then write (str,'( 5X,I4,6X,D10.3,1X,A)') con , val , nam(1:len) call me%ogwrit(3,str) elseif ( me%Conact(con)<0 ) then write (str,'(10X,I4,1X,D10.3,1X,A)') con , val , nam(1:len) call me%ogwrit(3,str) end if end do deallocate (varsum) deallocate (varcor) deallocate (concor) deallocate (conder_tmp) ! ---------------------------------------------------------------------- call me%ogwrit(2,"") call me%ogwrit(2,"OPTGRA END") call me%ogwrit(2,"") contains subroutine evaluation_func_and_der() !! evaluate the function and derivatives call me%ogeval(me%Varval,me%Conval,me%Varder,conder_tmp) me%Conder(1:me%Numcon+1,:) = conder_tmp end subroutine evaluation_func_and_der end subroutine ogexec