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