Files
piscal/leafres/testarea/UnivPhotoFit.f
T
2016-02-03 18:52:05 +00:00

410 lines
14 KiB
FortranFixed

subroutine UnivPhotoFit()
implicit none
include '../testarea/LeafGasParams.h'
include '../testarea/LeafGasHybridFit.h'
integer i,j,k,Priornumrubis,Priornumrubp,Priornumtpu,
&Currentnumrubis,Currentnumrubp,Currentnumtpu,Postnumrubis,
&Postnumrubp,Postnumtpu,Postilimittype
double precision term,term1,term2,term3,term4,term5,term6,
&term7,term8,term9
!
if(Prioriknowlimit.eq.1.or.Prioriknowlimit.eq.2)then
ntotsamples=0
do i=1,nFixedPoints
ntotsamples=ntotsamples+1
Prioriphotolimit(ntotsamples)=Fixediphotolimit(i)
enddo
do j=1,numACicurves
do i=1,nACiPoints(j)
ntotsamples=ntotsamples+1
Prioriphotolimit(ntotsamples)=ACiiphotolimit(i,j)
enddo
enddo
do j=1,numALightcurves
do i=1,nALightPoints(j)
ntotsamples=ntotsamples+1
Prioriphotolimit(ntotsamples)=ALightiphotolimit(i,j)
enddo
enddo
do i=1,nFreePoints
ntotsamples=ntotsamples+1
Prioriphotolimit(ntotsamples)=Freeiphotolimit(i)
enddo
call ilimittypestats(ntotsamples,Prioriphotolimit,
&Priorilimittype,Priornumrubis,Priornumrubp,Priornumtpu)
if(bestilimittype.gt.0.and.Priorilimittype.ne.bestilimittype)
&return
!if bestilimittype is specified, we assume the fitting is constained to the limit type specified by bestilimittype
if(Priorilimittype.ge.3)return
!5, 6, 7 are done with Prioriknowlimit=0. We don't consider cases with only rubp and tpu limitations but no rubisco limitations
if(Priornumrubis.gt.0.and.Priornumrubis.lt.minimumrubis)return
if(Priornumrubp.gt.0.and.Priornumrubp.lt.minimumfj)return
if(Priornumtpu.gt.0.and.Priornumtpu.lt.minimumvt)return
do i=1,ntotsamples
Currentiphotolimit(i)=Prioriphotolimit(i)
enddo
endif
Currentilimittype=Priorilimittype
Currentiknowlimit=Prioriknowlimit
!
!-------------Test Area---------------------------------------------
! Currentilimittype=1
! Currentiknowlimit=1
! do i=1,ntotsamples
! if(i.le.6)then
! Currentiphotolimit(i)=1
! else
! if(i.ge.16.and.i.le.26)then
! Currentiphotolimit(i)=2
! else
! Currentiphotolimit(i)=3
! endif
! endif
! enddo
!-------------------------------------------------------------------
call DoUnivPhotoFit()
if(Prioriknowlimit.ne.1.or.Priorilimittype.ge.5)goto 1000
!---------------------------------------------------------
!Enforce the admissibility rule.
!first get the post-fit limit type of each point. (pco2i,anet_obs) should be replaced
!by (pco2i_pred, anet_pred)
do i=1,ntotsamples
call leafunivphotosyn(Currentiknowlimit,Currentilimittype,
&0,aPPFDlf(i),templeaf(i),pco2i_pred(i),po2i(i),chlflphips2(i),
&term,weitresponses(i:i,1:1),weitresponses(i:i,1:1),
&weitresponses(i:i,2:2),weitresponses(i:i,1:1),term1,term2,
&Postiphotolimit(i),term3,term4,term5,term6,term7,term8,term9)
enddo
j=0
do i=1,ntotsamples
if(Postiphotolimit(i).ne.Currentiphotolimit(i))j=j+1
enddo
!if j = 0, the fitting is admissible so go to the wrapup
if(j.eq.0)goto 1000
call ilimittypestats(ntotsamples,Postiphotolimit,
&Postilimittype,Postnumrubis,Postnumrubp,Postnumtpu)
!if minimum number of points is not satisfied, go to penality fit directly.
if(Postnumrubis.gt.0.and.Postnumrubis.lt.minimumrubis)goto 500
if(Postnumrubp.gt.0.and.Postnumrubp.lt.minimumfj)goto 500
if(Postnumtpu.gt.0.and.Postnumtpu.lt.minimumvt)goto 500
!check to see if the fit oscillates.
Currentilimittype=Postilimittype
do i=1,ntotsamples
Currentiphotolimit(i)=Postiphotolimit(i)
enddo
call DoUnivPhotoFit()
do i=1,ntotsamples
call leafunivphotosyn(Currentiknowlimit,Currentilimittype,
&0,aPPFDlf(i),templeaf(i),pco2i_pred(i),po2i(i),chlflphips2(i),
&term,weitresponses(i:i,1:1),weitresponses(i:i,1:1),
&weitresponses(i:i,2:2),weitresponses(i:i,1:1),term1,term2,
&Postiphotolimit(i),term3,term4,term5,term6,term7,term8,term9)
enddo
j=0
do i=1,ntotsamples
if(Postiphotolimit(i).ne.Prioriphotolimit(i))j=j+1
enddo
if(j.eq.0)then
!Osicillation. Treat osicillating points as co-limited
k=ntotsamples
do i=1,ntotsamples
if(Currentiphotolimit(i).ne.Prioriphotolimit(i))then
k=k+1
Currentiphotolimit(k)=Currentiphotolimit(i)
aPPFDlf(k)=aPPFDlf(i)
templeaf(k)=templeaf(i)
po2i(k)=po2i(i)
pco2i(k)=pco2i(i)
anet_obs(k)=anet_obs(i)
chlflphips2(k)=chlflphips2(i)
Currentiphotolimit(i)=Prioriphotolimit(i)
endif
enddo
call ilimittypestats(k,Currentiphotolimit,
&Currentilimittype,Currentnumrubis,Currentnumrubp,Currentnumtpu)
i=ntotsamples
ntotsamples=k
call DoUnivPhotoFit()
sumsquare=sumsquare*dble(i)/dble(k)
ntotsamples=i
goto 1000
else
!no osicillation
Currentilimittype=Priorilimittype
do i=1,ntotsamples
Currentiphotolimit(i)=Prioriphotolimit(i)
enddo
endif
!-------------Penalty function fit-------------------------------------------
500 Currentiknowlimit=2
call DoUnivPhotoFit()
!-------------Wrap up--------------------------------------------------------
1000 if(Prioriknowlimit.eq.0.and.Priorilimittype.le.4)then
call ilimittypestats(ntotsamples,Postiphotolimit,
&Postilimittype,Postnumrubis,Postnumrubp,Postnumtpu)
if(Postnumrubis.gt.0.and.Postnumrubis.lt.minimumrubis-1)
&sumsquare=1.0d+10
if(Postnumrubp.gt.0.and.Postnumrubp.lt.minimumfj-1)
&sumsquare=1.0d+10
if(Postnumtpu.gt.0.and.Postnumtpu.lt.minimumvt-1)
&sumsquare=1.0d+10
endif
term=1.0d0+(subbestsumsquare(Priorilimittype)-sumsquare)
if(term.gt.1.0d0)then
subbestsumsquare(Priorilimittype)=sumsquare
do i=1,ntotunivparams
subbestunivparams(i,Priorilimittype)=univparams(i)
enddo
do i=1,ntotsamples
if(Prioriknowlimit.eq.0)then
subbestiphotolimit(i,Priorilimittype)=Postiphotolimit(i)
else
subbestiphotolimit(i,Priorilimittype)=Prioriphotolimit(i)
endif
enddo
endif
return
end subroutine UnivPhotoFit
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
subroutine DoUnivPhotoFit()
implicit none
include '../testarea/LeafGasParams.h'
include '../testarea/LeafGasHybridFit.h'
integer i,ndim,k,j,iderivative,iwrong,jnon
double precision beta(20),sumsquare0,beta0(20),sumsquarecp,
&betacp(20),ftol,xtol,shortx(maxobs,4),shorty(maxobs,2),ran2,
&ftol_relax
parameter(ftol=1.0d-7,xtol=1.0d-7)
external funkmin_UnivPhotoFit,f1dim_UnivPhotoFit,
&FCN_UnivPhotoFit,ff_pikaia
!find out which parameters to optimize
call UnivParamsAlloc(1)
ndim=0
do i=1,ntotunivparams
univparams(i)=subbestunivparams(i,Currentilimittype)
if(ifixunivparams(i).eq.1)then
ndim=ndim+1
beta(ndim)=univparams(i)
betamin(ndim)=univparamsmin(i)
betamax(ndim)=univparamsmax(i)
endif
enddo
isitbounded=1
call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
do i=1,ndim
beta0(i)=beta(i)
enddo
sumsquare0=sumsquare
ftol_relax=ftol
k=0
if(subbestsumsquare(Currentilimittype).gt.1.0d+9)then
jnon=0
ftol_relax=ftol*100.0d0
endif
30 call nongradopt(ndim,funkmin_UnivPhotoFit,f1dim_UnivPhotoFit,
&beta,betamin,betamax,ftol_relax,sumsquare)
call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
if((sumsquare+1.0d0).eq.sumsquare.or.sumsquare.gt.sumsquare0)then
do i=1,ndim
beta(i)=beta0(i)
enddo
sumsquare=sumsquare0
else
if((sumsquare0-sumsquare).gt.ftol_relax)then
!reset the counter for arriving at a better minimum
k=0
else
!if the same minimum is found, increment the counter
k=k+1
endif
do i=1,ndim
beta0(i)=beta(i)
enddo
sumsquare0=sumsquare
endif
if(subbestsumsquare(Currentilimittype).gt.1.0d+9)then
jnon=jnon+1
!for the first run, try different initial guesses
if(jnon.lt.100.and.k.lt.5)then
if(ran2().gt.0.7d0)then
do i=1,ndim
beta(i)=betamin(i)+ran2()*(betamax(i)-betamin(i))
enddo
else
do i=1,ndim
if(ran2().gt.0.5d0)then
beta(i)=beta(i)+(ran2()**(3.0d0/dble(k+1)))*
&(betamax(i)-beta(i))
else
beta(i)=beta(i)-(ran2()**(3.0d0/dble(k+1)))*
&(beta(i)-betamin(i))
endif
enddo
endif
call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
goto 30
else
if((ftol_relax-ftol).gt.ftol)then
ftol_relax=ftol
goto 30
endif
endif
call RepeatCompassSearch(ndim,beta,sumsquare,betamin,
&betamax,funkmin_UnivPhotoFit,f1dim_UnivPhotoFit,xtol)
call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
if((sumsquare+1.0d0).eq.sumsquare.or.sumsquare.gt.sumsquare0)
&then
do i=1,ndim
beta(i)=beta0(i)
enddo
sumsquare=sumsquare0
endif
do i=1,ndim
betacp(i)=(beta(i)-betamin(i))/(betamax(i)-betamin(i))
enddo
sumsquarecp=sumsquare
isitbounded=0
call pikaia(ff_pikaia,ndim,gacontrol,betacp,sumsquarecp,i)
isitbounded=1
if(i.eq.0)then
do i=1,ndim
betacp(i)=betamin(i)+betacp(i)*(betamax(i)-betamin(i))
enddo
call funkmin_UnivPhotoFit(ndim,betacp,sumsquarecp)
else
do i=1,ndim
betacp(i)=beta(i)
enddo
sumsquarecp=sumsquare
endif
if((sumsquarecp+1.0d0).ne.sumsquarecp.and.
&sumsquare.gt.sumsquarecp)then
do i=1,ndim
beta(i)=betacp(i)
enddo
sumsquare=sumsquarecp
endif
do i=1,ndim
beta0(i)=beta(i)
enddo
sumsquare0=sumsquare
else
return
endif
iderivative=0
if(ifitmode.lt.0)then
iwrong=0
else
iwrong=1
endif
isitbounded=1
k=ifitmode
ifitmode=-1
!ifitmode: =-2, ordinary fitting with pco2i calculated as a function of anet
!ifitmode: =-1, ordinary fitting with anet calculated as a function of pco2i
!ifitmode: =1, orthogonal fitting with anet calculated as a function of pco2i
!ifitmode: =2, orthogonal fitting with pco2i calculated as a function of anet
!for odr_leastsquare, only the predicted value of the response variable is needed, i.e., the cost function value is not needed.
!also, only anet as a function of CO2i is considered (not the other way around) because odr_leastsquare cannot handle the situation
!co2i as a function of anet for tpu limitation when alpha=0
i=1
if(ntotphips2.ge.1)i=2
j=4
if(Currentiknowlimit.eq.-1)then
!fluorescence only fit. chlflphisi2 becomes a forcing variable
i=1
j=5
endif
call odr_leastsquare(ndim,FCN_UnivPhotoFit,beta,ntotsamples,
&forcings(1:ntotsamples,1:j),j,responses(1:ntotsamples,1:i),i,
&weitforcings(1:ntotsamples,1:j),weitresponses(1:ntotsamples,1:i),
&iderivative,shortx(1:ntotsamples,1:j),shorty(1:ntotsamples,1:i),
&sumsquare,iwrong)
isitbounded=1
ifitmode=k
!after odr_leastsquare, forcing variables are destroyed. restore to the origninals
do i=1,ntotsamples
pco2i(i)=pco2i_ori(i)
aPPFDlf(i)=aPPFDlf_ori(i)
templeaf(i)=templeaf_ori(i)
po2i(i)=po2i_ori(i)
chlflphips2(i)=chlflphips2_ori(i)
enddo
call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
if((sumsquare+1.0d0).eq.sumsquare.or.sumsquare.gt.sumsquare0)then
do i=1,ndim
beta(i)=beta0(i)
enddo
sumsquare=sumsquare0
endif
k=0
do i=1,ndim
if(beta(i).lt.betamin(i))k=1
if(beta(i).gt.betamax(i))k=1
enddo
if(k.eq.1)then
do i=1,ndim
betacp(i)=(beta(i)-betamin(i))/(betamax(i)-betamin(i))
enddo
isitbounded=0
call pikaia(ff_pikaia,ndim,gacontrol,betacp,sumsquare,i)
do i=1,ndim
beta(i)=betamin(i)+betacp(i)*(betamax(i)-betamin(i))
enddo
isitbounded=1
call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
endif
j=0
100 jnon=0
105 sumsquare0=sumsquare
do i=1,ndim
beta0(i)=beta(i)
enddo
call nongradopt(ndim,funkmin_UnivPhotoFit,f1dim_UnivPhotoFit,
&beta,betamin,betamax,ftol,sumsquare)
call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
if(jnon.le.2.and.(sumsquare0-sumsquare).gt.ftol)then
jnon=jnon+1
goto 105
endif
if(sumsquare.eq.sumsquare0)goto 110
if(dabs(sumsquare).le.dabs(sumsquare0))then
else
if(dabs(sumsquare).gt.1.0d+20)then
!in case of infinity (division by zero)
do i=1,ndim
beta(i)=beta0(i)
enddo
sumsquare=sumsquare0
else
!designed this way to avoid sumsquare='NAN'
do i=1,ndim
beta(i)=beta0(i)
enddo
sumsquare=sumsquare0
endif
endif
sumsquarecp=sumsquare
do i=1,ndim
betacp(i)=beta(i)
enddo
call RepeatCompassSearch(ndim,betacp,sumsquarecp,betamin,
&betamax,funkmin_UnivPhotoFit,f1dim_UnivPhotoFit,xtol)
call funkmin_UnivPhotoFit(ndim,betacp,sumsquarecp)
if(sumsquare.eq.sumsquarecp)goto 110
if(dabs(sumsquarecp).lt.dabs(sumsquare))then
do i=1,ndim
beta(i)=betacp(i)
enddo
sumsquare=sumsquarecp
endif
j=j+1
if(j.le.2.and.dabs(sumsquare-sumsquare0).gt.ftol)goto 100
!
!------------------------------------------------------
110 call funkmin_UnivPhotoFit(ndim,beta,sumsquare)
return
END subroutine DoUnivPhotoFit