!We consider four types of leaf gas exchange measurements. These four types must be clearly indicated in the input:
!1. Points whose limitation states are known from other means (e.g. chlorophyll fluorescence): these points will be called fixed points and 
!	their limitation states will not be changed by the parameter estimation program.
!2. Points from conventional CO2 response measurements (A/Ci curves) that are done without fluorescence. Limitation states are not known but follow
!	the order of Rubisco, RuBP and TPU along the CO2i axis as suggested in Gu et al. (2010) PCE paper. We call these points ACi points.
!	The ACi points must be already ordered from low to high CO2i.
!3. Points from conventional light response measurements (A/PAR curves) that are done without fluorescence. Limitation states are not known but follow
!	the order of RuBP, Rubisco and TPU along the PAR axis. We call these points ALight points. The ALight points must be already ordered from low to high PAR.
!4. Points whose limitation states follow no order. We call these points free points. They are obtained with no control of environmental conditions.
      subroutine HybridCombinatorial()
      implicit none
      include '../testarea/LeafGasParams.h'
      include '../testarea/LeafGasHybridFit.h'
      integer i,ilastrubis1,ilastrubp1,ilastrubis2,ilastrubp2,
     &ilastrubis3,ilastrubp3,ilastrubis4,ilastrubp4,
     &ilastrubis5,ilastrubp5,ilastrubis6,ilastrubp6,
     &ilastrubis7,ilastrubp7,ilastrubis8,ilastrubp8,
     &ilastrubis9,ilastrubp9,ilastrubis10,ilastrubp10,
     &ilastrubis11,ilastrubp11,ilastrubis12,ilastrubp12,
     &ilastrubis13,ilastrubp13,ilastrubis14,ilastrubp14,
     &ilastrubis15,ilastrubp15,k1,k2,k3,k4,k5,k6,k7,k8,
     &k9,k10,k11,k12,k13,k14,k15,ilasttpu1,ilasttpu2,
     &ilasttpu3,ilasttpu4,ilasttpu5,ilasttpu6,ilasttpu7,
     &ilasttpu8,ilasttpu9,ilasttpu10,ilasttpu11,ilasttpu12,
     &ilasttpu13,ilasttpu14,ilasttpu15
      double precision rdlight,atp,resistwp,resistch,stargamma,
     &realizedfjelect,term
!
!common block variables:idokco,idoalpha,minimumrubis,minimumfj,minimumvt,nACiPoints,ACiiphotolimit(nACiPoints)
      minimumfj=3
      if(idokc.eq.0.and.idoko.eq.0)then
        minimumrubis=3
      else
        if(idokc.eq.0.or.idoko.eq.0)then
          minimumrubis=4
        else
          minimumrubis=5
        endif
      endif
      if((nFixedPoints+numACicurves+nFreePoints).eq.0)minimumrubis=2
      if(idoalpha.eq.0)then
        minimumvt=2
      else
        minimumvt=3
      endif
      i=0
      do k1=1,numACicurves
        do k2=nendaci(k1)+1,nACiPoints(k1)
          i=i+1
        enddo
      enddo
      if(i.gt.0)minimumvt=i
!
      ntotunivparams=13
      univparamsmin(1)=resistwp25min
      univparamsmax(1)=resistwp25max  
      univparamsmin(2)=resistch25min
      univparamsmax(2)=resistch25max 
      univparamsmin(3)=rdlight25min
      univparamsmax(3)=rdlight25max 
      univparamsmin(4)=stargamma25min
      univparamsmax(4)=stargamma25max
      univparamsmin(5)=vcmax25min
      univparamsmax(5)=vcmax25max
      univparamsmin(6)=fkc25min
      univparamsmax(6)=fkc25max
      univparamsmin(7)=fko25min
      univparamsmax(7)=fko25max
      univparamsmin(8)=fjmax25min
      univparamsmax(8)=fjmax25max
      univparamsmin(9)=tpu25min
      univparamsmax(9)=tpu25max
      univparamsmin(10)=alpha25min
      univparamsmax(10)=alpha25max
      univparamsmin(11)=phifactormin
      univparamsmax(11)=phifactormax
      univparamsmin(12)=thetafactormin
      univparamsmax(12)=thetafactormax
      univparamsmin(13)=betaPSIImin
      univparamsmax(13)=betaPSIImax

      bestilimittype=-9999
      do ilastrubis1=1,7
        subbestsumsquare(ilastrubis1)=1.0d+100
        subbestunivparams(1,ilastrubis1)=resistwp25_ori
        subbestunivparams(2,ilastrubis1)=resistch25_ori
        subbestunivparams(3,ilastrubis1)=rdlight25_ori
        subbestunivparams(4,ilastrubis1)=stargamma25_ori
        subbestunivparams(5,ilastrubis1)=vcmax25_ori
        subbestunivparams(6,ilastrubis1)=fkc25_ori
        subbestunivparams(7,ilastrubis1)=fko25_ori
        subbestunivparams(8,ilastrubis1)=fjmax25_ori
        subbestunivparams(9,ilastrubis1)=tpu25_ori
        subbestunivparams(10,ilastrubis1)=alpha25_ori
        subbestunivparams(11,ilastrubis1)=phifactor_ori
        subbestunivparams(12,ilastrubis1)=thetafactor_ori
        subbestunivparams(13,ilastrubis1)=betaPSII_ori
        do i=1,ntotsamples
          subbestiphotolimit(i,ilastrubis1)=-9999
        enddo
      enddo
      do i=1,ntotsamples
        forcings(i,1)=pco2i_ori(i)
        forcings(i,2)=aPPFDlf_ori(i)
        forcings(i,3)=templeaf_ori(i)
        forcings(i,4)=po2i_ori(i)
        responses(i,1)=anet_obs(i)
        weitforcings(i,1)=1.0d0
        weitforcings(i,2)=1.0d0
        weitforcings(i,3)=1.0d0
        weitforcings(i,4)=1.0d0
        weitresponses(i,1)=1.0d0
        if(ntotphips2.ge.1)then
          if(chlflphips2_ori(i).gt.0.0d0)then
!for least square regression
            responses(i,2)=chlflphips2_ori(i)
!a factor of 50 makes PhiPSII comparable to Anet in magnitude
            weitresponses(i,2)=50.0d0
          else
            responses(i,2)=chlflphips2_ori(i)
            weitresponses(i,2)=0.0d0
          endif
        endif
        if(Prioriknowlimit.eq.-1)then
!fluorescence fit only. chlflphips2 becomes a response variable
          forcings(i,5)=chlflphips2_ori(i)
          weitforcings(i,5)=1.0d0
          if(chlflphips2_ori(i).le.0.0d0)then
            weitforcings(i,5)=0.0d0
            weitresponses(i,1)=0.0d0
          endif
        endif
      enddo
      do i=1,12
        gacontrol(i)=-1.0d0
      enddo
      gacontrol(1)=250.0d0
      gacontrol(2)=5000.0d0
      gacontrol(3)=8.0d0

!Priorilimittype: indicator for the choice of overall mixtures of limitation types 
!         = 1, Rubisco+RuBP+TPU
!         = 2, Rubisco+RuBP
!         = 3, Rubisco+TPU
!         = 4, RuBP+TPU
!         = 5, Rubisco Only
!         = 6, RuBP Only
!         = 7, TPU Only

!Prioriknowlimit: indicator for how the limitation type of each point is set before the fitting 
!         = 0, the limitation type of each individual point has not been pre-set when mixed 
!                limitation states are present in the dataset. When Priorilimittype = 5, 6, 7,
!                all points are limited by one type.
!         = 1, the limit type of each individual point has been pre-set. Don't allow the fitting
!              algorithm to change the limitation type of each point during the first fit. But
!              check the admissibility after the first fit. If the admissibility is violated,
!              treat the osicilation points as colimited; if there is no osicilation, use the penalty
!              approach to refit.
!         = 2, the limit type of each individual point has been pre-set. Allow the fitting
!              algorithm to change the limitation type of each point during the fit. Penalize any fit
!              that results in any point to have a limitation type different from the pre-set type.
!         =-1, only do a fluorescence fit
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
      if(Prioriknowlimit.eq.-1)then
!fluorescence only fit
        Priorilimittype=6
        Currentilimittype=Priorilimittype
        Currentiknowlimit=Prioriknowlimit
!we pass UnivPhotoFit and call DoUnivPhotoFit directly
        call DoUnivPhotoFit()
        if(numALightcurves.gt.0.and.idorch.eq.1)then
          call fluorescencejmax()
        endif
        return
      endif
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
      Prioriknowlimit=0
      bestsumsquare=1.0d+100
      do Priorilimittype=1,7
        call UnivPhotoFit()
        if(subbestsumsquare(Priorilimittype).le.bestsumsquare)then
          bestilimittype=Priorilimittype
          bestsumsquare=subbestsumsquare(Priorilimittype)
          do i=1,ntotunivparams
            bestunivparams(i)=subbestunivparams(i,Priorilimittype)
          enddo
          do i=1,ntotsamples
            bestiphotolimit(i)=subbestiphotolimit(i,Priorilimittype)
          enddo
        endif
      enddo
!      goto 1000
      bestilimittype=-9999
      Prioriknowlimit=1
      Priorilimittype=-9999
!
c     gacontrol( 1) - number of individuals in a population (default
c                      is 100)
c     gacontrol( 2) - number of generations over which solution is
c                      to evolve (default is 500)
c     gacontrol( 3) - number of significant digits (i.e., number of
c                      genes) retained in chromosomal encoding (default
c                      is 6)  (Note: This number is limited by the
c                      machine floating point precision.  Most 32-bit
c                      floating point representations have only 6 full
c                      digits of precision.  To achieve greater preci-
c                      sion this routine could be converted to double
c                      precision, but note that this would also require
c                      a double precision random number generator, which
c                      likely would not have more than 9 digits of
c                      precision if it used 4-byte integers internally.)
c     gacontrol( 4) - crossover probability; must be  <= 1.0 (default
c                      is 0.85). If crossover takes place, either one
c                      or two splicing points are used, with equal
c                      probabilities
c     gacontrol( 5) - mutation mode; 1/2/3/4/5 (default is 2)
c                      1=one-point mutation, fixed rate
c                      2=one-point, adjustable rate based on fitness 
c                      3=one-point, adjustable rate based on distance
c                      4=one-point+creep, fixed rate
c                      5=one-point+creep, adjustable rate based on fitness
c                      6=one-point+creep, adjustable rate based on distance
c     gacontrol( 6) - initial mutation rate; should be small (default
c                      is 0.005) (Note: the mutation rate is the proba-
c                      bility that any one gene locus will mutate in
c                      any one generation.)
c     gacontrol( 7) - minimum mutation rate; must be >= 0.0 (default
c                      is 0.0005)
c     gacontrol( 8) - maximum mutation rate; must be <= 1.0 (default
c                      is 0.25)
c     gacontrol( 9) - relative fitness differential; range from 0
c                      (none) to 1 (maximum).  (default is 1.)
c     gacontrol(10) - reproduction plan; 1/2/3=Full generational
c                      replacement/Steady-state-replace-random/Steady-
c                      state-replace-worst (default is 3)
c     gacontrol(11) - elitism flag; 0/1=off/on (default is 0)
c                      (Applies only to reproduction plans 1 and 2)
c     gacontrol(12) - printed output 0/1/2=None/Minimal/Verbose
c                      (default is 0)
c
      if(numACicurves.eq.0)then
!no conventional A/Ci curves. go to light response curves directly.
        call ALightCombinatorial()
        goto 1000
      endif
!Assume rubisco, rubp and tpu limitations in the order of (rubisco, rubp, tpu) but any limitation can be missing in any ACi curves.
!The nACiPoints points of each ACi curve must have been already ordered from low to high Ci within each individual ACi curve.
      do ilastrubis1=0,nendaci(1)
        do i=1,ilastrubis1
          ACiiphotolimit(i,1)=1
        enddo
        k1=max0(nstartaci(1)-1,ilastrubis1)
      do 1 ilasttpu1=k1,nendaci(1)
        do i=ilasttpu1+1,nACiPoints(1)
          ACiiphotolimit(i,1)=3
        enddo
        do i=ilastrubis1+1,ilasttpu1
          ACiiphotolimit(i,1)=2
        enddo
        if(numACicurves.eq.1)then
          call ALightCombinatorial()
          goto 1
        endif

      do ilastrubis2=0,nendaci(2)
        do i=1,ilastrubis2
          ACiiphotolimit(i,2)=1
        enddo
        k2=max0(nstartaci(2)-1,ilastrubis2)
      do 2 ilasttpu2=k2,nendaci(2)
        do i=ilasttpu2+1,nACiPoints(2)
          ACiiphotolimit(i,2)=3
        enddo
        do i=ilastrubis2+1,ilasttpu2
          ACiiphotolimit(i,2)=2
        enddo
        if(numACicurves.eq.2)then
          call ALightCombinatorial()
          goto 2
        endif

      do ilastrubis3=0,nendaci(3)
        do i=1,ilastrubis3
          ACiiphotolimit(i,3)=1
        enddo
        k3=max0(nstartaci(3)-1,ilastrubis3)
      do 3 ilasttpu3=k3,nendaci(3)
        do i=ilasttpu3+1,nACiPoints(3)
          ACiiphotolimit(i,3)=3
        enddo
        do i=ilastrubis3+1,ilasttpu3
          ACiiphotolimit(i,3)=2
        enddo
        if(numACicurves.eq.3)then
          call ALightCombinatorial()
          goto 3
        endif

      do ilastrubis4=0,nendaci(4)
        do i=1,ilastrubis4
          ACiiphotolimit(i,4)=1
        enddo
        k4=max0(nstartaci(4)-1,ilastrubis4)
      do 4 ilasttpu4=k4,nendaci(4)
        do i=ilasttpu4+1,nACiPoints(4)
          ACiiphotolimit(i,4)=3
        enddo
        do i=ilastrubis4+1,ilasttpu4
          ACiiphotolimit(i,4)=2
        enddo
        if(numACicurves.eq.4)then
          call ALightCombinatorial()
          goto 4
        endif

      do ilastrubis5=0,nendaci(5)
        do i=1,ilastrubis5
          ACiiphotolimit(i,5)=1
        enddo
        k5=max0(nstartaci(5)-1,ilastrubis5)
      do 5 ilasttpu5=k5,nendaci(5)
        do i=ilasttpu5+1,nACiPoints(5)
          ACiiphotolimit(i,5)=3
        enddo
        do i=ilastrubis5+1,ilasttpu5
          ACiiphotolimit(i,5)=2
        enddo
        if(numACicurves.eq.5)then
          call ALightCombinatorial()
          goto 5
        endif

      do ilastrubis6=0,nendaci(6)
        do i=1,ilastrubis6
          ACiiphotolimit(i,6)=1
        enddo
        k6=max0(nstartaci(6)-1,ilastrubis6)
      do 6 ilasttpu6=k6,nendaci(6)
        do i=ilasttpu6+1,nACiPoints(6)
          ACiiphotolimit(i,6)=3
        enddo
        do i=ilastrubis6+1,ilasttpu6
          ACiiphotolimit(i,6)=2
        enddo
        if(numACicurves.eq.6)then
          call ALightCombinatorial()
          goto 6
        endif

      do ilastrubis7=0,nendaci(7)
        do i=1,ilastrubis7
          ACiiphotolimit(i,7)=1
        enddo
        k7=max0(nstartaci(7)-1,ilastrubis7)
      do 7 ilasttpu7=k7,nendaci(7)
        do i=ilasttpu7+1,nACiPoints(7)
          ACiiphotolimit(i,7)=3
        enddo
        do i=ilastrubis7+1,ilasttpu7
          ACiiphotolimit(i,7)=2
        enddo
        if(numACicurves.eq.7)then
          call ALightCombinatorial()
          goto 7
        endif

      do ilastrubis8=0,nendaci(8)
        do i=1,ilastrubis8
          ACiiphotolimit(i,8)=1
        enddo
        k8=max0(nstartaci(8)-1,ilastrubis8)
      do 8 ilasttpu8=k8,nendaci(8)
        do i=ilasttpu8+1,nACiPoints(8)
          ACiiphotolimit(i,8)=3
        enddo
        do i=ilastrubis8+1,ilasttpu8
          ACiiphotolimit(i,8)=2
        enddo
        if(numACicurves.eq.8)then
          call ALightCombinatorial()
          goto 8
        endif

      do ilastrubis9=0,nendaci(9)
        do i=1,ilastrubis9
          ACiiphotolimit(i,9)=1
        enddo
        k9=max0(nstartaci(9)-1,ilastrubis9)
      do 9 ilasttpu9=k9,nendaci(9)
        do i=ilasttpu9+1,nACiPoints(9)
          ACiiphotolimit(i,9)=3
        enddo
        do i=ilastrubis9+1,ilasttpu9
          ACiiphotolimit(i,9)=2
        enddo
        if(numACicurves.eq.9)then
          call ALightCombinatorial()
          goto 9
        endif

      do ilastrubis10=0,nendaci(10)
        do i=1,ilastrubis10
          ACiiphotolimit(i,10)=1
        enddo
        k10=max0(nstartaci(10)-1,ilastrubis10)
      do 10 ilasttpu10=k10,nendaci(10)
        do i=ilasttpu10+1,nACiPoints(10)
          ACiiphotolimit(i,10)=3
        enddo
        do i=ilastrubis10+1,ilasttpu10
          ACiiphotolimit(i,10)=2
        enddo
        if(numACicurves.eq.10)then
          call ALightCombinatorial()
          goto 10
        endif

      do ilastrubis11=0,nendaci(11)
        do i=1,ilastrubis11
          ACiiphotolimit(i,11)=1
        enddo
        k11=max0(nstartaci(11)-1,ilastrubis11)
      do 11 ilasttpu11=k11,nendaci(11)
        do i=ilasttpu11+1,nACiPoints(11)
          ACiiphotolimit(i,11)=3
        enddo
        do i=ilastrubis11+1,ilasttpu11
          ACiiphotolimit(i,11)=2
        enddo
        if(numACicurves.eq.11)then
          call ALightCombinatorial()
          goto 11
        endif

      do ilastrubis12=0,nendaci(12)
        do i=1,ilastrubis12
          ACiiphotolimit(i,12)=1
        enddo
        k12=max0(nstartaci(12)-1,ilastrubis12)
      do 12 ilasttpu12=k12,nendaci(12)
        do i=ilasttpu12+1,nACiPoints(12)
          ACiiphotolimit(i,12)=3
        enddo
        do i=ilastrubis12+1,ilasttpu12
          ACiiphotolimit(i,12)=2
        enddo
        if(numACicurves.eq.12)then
          call ALightCombinatorial()
          goto 12
        endif

      do ilastrubis13=0,nendaci(13)
        do i=1,ilastrubis13
          ACiiphotolimit(i,13)=1
        enddo
        k13=max0(nstartaci(13)-1,ilastrubis13)
      do 13 ilasttpu13=k13,nendaci(13)
        do i=ilasttpu13+1,nACiPoints(13)
          ACiiphotolimit(i,13)=3
        enddo
        do i=ilastrubis13+1,ilasttpu13
          ACiiphotolimit(i,13)=2
        enddo
        if(numACicurves.eq.13)then
          call ALightCombinatorial()
          goto 13
        endif

      do ilastrubis14=0,nendaci(14)
        do i=1,ilastrubis14
          ACiiphotolimit(i,14)=1
        enddo
        k14=max0(nstartaci(14)-1,ilastrubis14)
      do 14 ilasttpu14=k14,nendaci(14)
        do i=ilasttpu14+1,nACiPoints(14)
          ACiiphotolimit(i,14)=3
        enddo
        do i=ilastrubis14+1,ilasttpu14
          ACiiphotolimit(i,14)=2
        enddo
        if(numACicurves.eq.14)then
          call ALightCombinatorial()
          goto 14
        endif

      do ilastrubis15=0,nendaci(15)
        do i=1,ilastrubis15
          ACiiphotolimit(i,15)=1
        enddo
        k15=max0(nstartaci(15)-1,ilastrubis15)
      do 15 ilasttpu15=k15,nendaci(15)
        do i=ilasttpu15+1,nACiPoints(15)
          ACiiphotolimit(i,15)=3
        enddo
        do i=ilastrubis15+1,ilasttpu15
          ACiiphotolimit(i,15)=2
        enddo
        if(numACicurves.eq.15)then
          call ALightCombinatorial()
          goto 15
        endif
15    continue
      enddo
14    continue
      enddo
13    continue
      enddo
12    continue
      enddo
11    continue
      enddo
10    continue
      enddo
9     continue
      enddo
8     continue
      enddo
7     continue
      enddo
6     continue
      enddo
5     continue
      enddo
4     continue
      enddo
3     continue
      enddo
2     continue
      enddo
1     continue
      enddo
      bestsumsquare=1.0d+100
      do Priorilimittype=1,7
        if(subbestsumsquare(Priorilimittype).le.bestsumsquare)then
          bestilimittype=Priorilimittype
          bestsumsquare=subbestsumsquare(Priorilimittype)
          do i=1,ntotunivparams
            bestunivparams(i)=subbestunivparams(i,Priorilimittype)
          enddo
          do i=1,ntotsamples
            bestiphotolimit(i)=subbestiphotolimit(i,Priorilimittype)
          enddo
        endif
      enddo
1000  do i=1,ntotunivparams
        univparams(i)=bestunivparams(i)
      enddo
      call UnivParamsAlloc(2)
      call ilimittypestats(ntotsamples,bestiphotolimit,
     &bestilimittype,bestnumrubis,bestnumrubp,bestnumtpu)
      if(bestnumrubis.eq.0)then
        vcmax25=-9999
        if(idokc.eq.1)fkc25=-9999.0d0
        if(idoko.eq.1)fko25=-9999.0d0
      endif
      if(bestnumrubp.eq.0)fjmax25=-9999
      if(bestnumtpu.eq.0)then
        tpu25=-9999
        if(idoalpha.eq.1)alpha25=-9999
      endif
      do i=1,ntotsamples
        ilastrubp1=bestiphotolimit(i)+4
        call leafunivphotosyn(Prioriknowlimit,ilastrubp1,ifitmode,
     &aPPFDlf(i),templeaf(i),pco2i(i),po2i(i),chlflphips2(i),
     &anet_obs(i),weitresponses(i:i,1:1),weitresponses(i:i,1:1),
     &weitresponses(i:i,2:2),weitresponses(i:i,1:1),
     &pco2i_pred(i),anet_pred(i),Postiphotolimit(i),pco2c(i),
     &PhiPSII_pred(i),anet_pred_flu(i),pco2i_pred_flu(i),
     &pco2c_anet_flu(i),pco2c_pco2i_flu(i),term)
        if(chlflphips2(i).lt.0.0d0)then
          anet_pred_flu(i)=-9999.0d0
          pco2i_pred_flu(i)=-9999.0d0
          pco2c_anet_flu(i)=-9999.0d0
          pco2c_pco2i_flu(i)=-9999.0d0
        else
          if(iabs(ifitmode).eq.1)then
            pco2i_pred_flu(i)=-9999.0d0
            pco2c_pco2i_flu(i)=-9999.0d0
          endif
          if(iabs(ifitmode).eq.2)then
            anet_pred_flu(i)=-9999.0d0
            pco2c_anet_flu(i)=-9999.0d0
          endif
        endif
      enddo
      return
      end subroutine HybridCombinatorial
