!This version of Anet_Final uses resistance instead of conductance. It considers the fact that
!CO2 from mitochodria (dark respiration and photorespiration) has different diffusion path ways than
!intercellular CO2
      subroutine Anet_Final(vcmax,jrubp,vtpu,resistwp,resistch,
     &stargamma,kco,co2i,alpha,rd,ilimittype,iminimum,anet,co2c,
     &realizedfjelect)
      implicit none
!
!Calculates the net assimilation rate once all parameters are given at measurement conditions
!------------------ Inputs -----------------------------------
!ilimittype: limitation types to evaluate
!            1 = Rubisco,RuBp and TPU limitations
!            2 = Rubisco and RuBp limitations only
!            3 = Rubisco and TPU limitations only
!            4 = RuBp and TPU limitations only
!            5 = Rubisco limitation only
!            6 = RuBp limitation only
!            7 = TPU limitation only
!vcmax (if ilimittype=1,2,3,5), maximum carboxylation rate limited by Rubisco (umol m-2 s-1) 
!jrubp (if ilimittype=1,2,4,6), electron transport rate (umol m-2 s-1)
!vtpu (if ilimittype=1,3,4,7), triose phosphate export rate from chloroplast (umol m-2 s-1)
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!kco,(if ilimittype=1,2,3,5), Kc(1+O/Ko), (Pa)
!co2i, intercellular CO2 partial pressure (Pa)
!alpha, (if ilimittype=1,3,4,7), fraction of glycolate carbon not returned to the chloroplast (0-1, dimensionless)
!rd, mitochondrial respiration in the light (umol m-2 s-1). 
!------------------ Outputs ----------------------------------
!anet: the net assimilation rate (umol m-2 s-1)
!iminimum, which limitation type is actually present Rubisco (1), RuBp(2), and TPU (3)
!realizedfjelect: the realized electron transport rate <= jrubp (=when RuBP regeneration limits photosynthesis). 
      integer ilimittype,iminimum,idorubisco,idorubp,idotpu
      double precision vcmax,jrubp,vtpu,gmeso,stargamma,kco,co2i,
     &alpha,rd,anet,wc,wj,wp,anetc,anetj,anettpu,term,term1,term2,co2c,
     &co2c_wc,co2c_wj,co2c_wp,rwp,resistwp,rch,resistch,realizedfjelect
!---------------------------------rwp=dmax1(0.0d0,resistwp)---------------------------------
      anetc=1.0d+20
      anetj=1.0d+20
      anettpu=1.0d+20
      wc=1.0d+10
      wj=1.0d+15
      wp=1.0d+20
      realizedfjelect=-9999.0d0
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
!This way of initialization is deliberate. If co2c <0, the priority of limitation
!state is Rubisco, RuBP regeneration, TPU
      idorubisco=0
      idorubp=0
      idotpu=0
      iminimum=0
      if(ilimittype.le.3.or.ilimittype.eq.5)then
        idorubisco=1
      endif
      if(ilimittype.le.2.or.ilimittype.eq.4.or.
     &  ilimittype.eq.6)then
        idorubp=1
      endif
      if(ilimittype.eq.1.or.ilimittype.eq.3.or.
     &  ilimittype.eq.4.or.ilimittype.eq.7)then
        idotpu=1
      endif
      if(idorubisco.eq.1)then
        call findco2c(vcmax,kco,co2i,rd,stargamma,rwp,rch,co2c_wc)
        wc=co2c_wc*vcmax/(co2c_wc+kco)
        anetc=(co2c_wc-stargamma)*vcmax/(co2c_wc+kco)-rd
      endif
      if(idorubp.eq.1)then
        if(stargamma.eq.0.0d0)then
          co2c_wj=co2i+rd*rwp-0.25d0*jrubp*(rwp+rch)
        else
          term1=0.25d0*jrubp
          term2=2.0d0*stargamma
          call findco2c(term1,term2,co2i,rd,stargamma,rwp,rch,co2c_wj)
        endif
        wj=co2c_wj*0.25d0*jrubp/(co2c_wj+2.0d0*stargamma)
        anetj=(co2c_wj-stargamma)*0.25d0*jrubp/
     &          (co2c_wj+2.0d0*stargamma)-rd
      endif
      if(idotpu.eq.1)then
!assumptions:
!Carboxylation rate cannot be negative. That means, if 
!co2i is less than or equal to (1.0d0+3.0d0*alpha)*stargamma, then
!the TPU limitation state cannot occur. Under this situation, set wp to infinite
        term1=3.0d0*vtpu
        term2=-(1.0d0+3.0d0*alpha)*stargamma
        call findco2c(term1,term2,co2i,rd,stargamma,rwp,rch,co2c_wp)
        term=co2c_wp-(1.0d0+3.0d0*alpha)*stargamma
        if(term.gt.1.0d-12)then
          wp=co2c_wp*3.0d0*vtpu/term
          anettpu=(co2c_wp-stargamma)*3.0d0*vtpu/term-rd
        else
          co2c_wp=-9999.0d0
          if(alpha.eq.0.0d0)anettpu=3.0d0*vtpu-rd
        endif
      endif
      if(ilimittype.ge.5)then
        if(ilimittype.eq.5)then
          iminimum=1
          anet=anetc
          co2c=co2c_wc
        endif
        if(ilimittype.eq.6)then
          iminimum=2
          anet=anetj
          co2c=co2c_wj
        endif
        if(ilimittype.eq.7)then
          iminimum=3
          anet=anettpu
          co2c=co2c_wp
        endif
      else
        if(wc.lt.wj)then
          if(wc.le.wp)then
            anet=anetc
            co2c=co2c_wc
            iminimum=1
          else
            anet=anettpu
            co2c=co2c_wp
            iminimum=3
          endif
        else
          if(wj.le.wp)then
            anet=anetj
            co2c=co2c_wj
            iminimum=2
          else
            anet=anettpu
            co2c=co2c_wp
            iminimum=3
          endif
        endif
      endif
      if(iminimum.eq.2)then
        realizedfjelect=jrubp
      else
        if(co2c.eq.stargamma)then
          realizedfjelect=0.0d0
        else
          realizedfjelect=
     &(anet+rd)*(4.0d0*co2c+8.0d0*stargamma)/(co2c-stargamma)
        endif
      endif
      return
      end subroutine Anet_Final
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine findco2c(vcmax,kco,co2i,rd,stargamma,rwp,rch,
     &co2c)
!kco and vcmax are generic and the formulation applies to rubp and tpu too
      implicit none
      double precision vcmax,kco,co2i,rd,stargamma,rwp,rch,co2c,
     &b,c,b24ac,p,q,w
      co2c=-9999.0d0
      b=kco-co2i-rd*rwp+vcmax*(rwp+rch)
      c=-(co2i+rd*rwp)*kco-vcmax*rwp*stargamma
      b24ac=b*b-4.0d0*c
      if(b24ac.ge.0.0d0)then
        co2c=(-b+dsqrt(b24ac))*0.5d0
!        write(*,*)(-b+dsqrt(b24ac))*0.5d0,(-b-dsqrt(b24ac))*0.5d0
!        p=-rd*rwp+vcmax*(rwp+rch)
!        q=rd*rwp*kco+vcmax*rwp*stargamma
!        w=4.0d0*(p*kco+q)
!        if(w.le.0.0d0)then
!          if((kco+co2i-p).le.(-dsqrt(-w)))co2c=(-b-dsqrt(b24ac))*0.5d0
!        endif
!        if((kco+co2i-p).lt.0.0d0)co2c=(-b-dsqrt(b24ac))*0.5d0
      endif
      return
      end
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine der_findco2c(vcmax,kco,co2i,rd,stargamma,rwp,
     &rch,co2c,der_vcmax,der_kco,der_co2i,der_rd,der_stargamma,
     &der_rwp,der_rch)
!kco and vcmax are generic and the formulation applies to rubp and tpu too
      implicit none
      double precision vcmax,kco,co2i,rd,stargamma,rwp,rch,co2c,
     &b,c,b24ac,p,q,w,fsign,der_vcmax,der_kco,der_co2i,der_rd,
     &der_stargamma,der_rwp,der_rch,term,der_b,der_c
      co2c=-9999.0d0
      der_vcmax=0.0d0
      der_kco=0.0d0
      der_co2i=0.0d0
      der_rd=0.0d0
      der_stargamma=0.0d0
      der_rwp=0.0d0
      der_rch=0.0d0
      b=kco-co2i-rd*rwp+vcmax*(rwp+rch)
      c=-(co2i+rd*rwp)*kco-vcmax*rwp*stargamma
      b24ac=b*b-4.0d0*c
      if(b24ac.ge.0.0d0)then
        fsign=1.0d0
!        p=-rd*rwp+vcmax*(rwp+rch)
!        q=rd*rwp*kco+vcmax*rwp*stargamma
!        w=4.0d0*(p*kco+q)
!        if(w.le.0.0d0)then
!          if((kco+co2i-p).le.(-dsqrt(-w)))fsign=-1.0d0
!        endif
!        if((kco+co2i-p).lt.0.0d0)fsign=-1.0d0

        term=dsqrt(b24ac)
        co2c=(-b+fsign*term)*0.5d0
        der_b=(-1.0d0+fsign*b/term)*0.5d0
        der_c=-fsign/term
        der_vcmax=der_b*(rwp+rch)-der_c*rwp*stargamma
        der_kco=der_b-der_c*(co2i+rd*rwp)
        der_co2i=-der_b-der_c*kco
        der_rd=-der_b*rwp-der_c*rwp*kco
        der_stargamma=-der_c*vcmax*rwp
        der_rwp=der_b*(vcmax-rd)-der_c*(rd*kco+vcmax*stargamma)
        der_rch=der_b*vcmax
      endif
      return
      end
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine Anet_Final_der(vcmax,jrubp,vtpu,resistwp,
     &resistch,stargamma,kco,co2i,alpha,rd,ilimittype,der_vcmax,
     &der_jrubp,der_vtpu,der_rwp,der_rch,der_stargamma,der_kco,
     &der_alpha,der_rd,der_co2i,anet,co2c,realizedfjelect)
      implicit none
!Calculates the derivatives of parameters and the net assimilation rate 
!once all parameters are given at measurement conditions.
!------------------ Inputs -----------------------------------
!ilimittype: limitation types to evaluate
!            1 = Rubisco,RuBp and TPU limitations
!            2 = Rubisco and RuBp limitations only
!            3 = Rubisco and TPU limitations only
!            4 = RuBp and TPU limitations only
!            5 = Rubisco limitation only
!            6 = RuBp limitation only
!            7 = TPU limitation only
!vcmax (if ilimittype=1,2,3,5), maximum carboxylation rate limited by Rubisco (umol m-2 s-1) 
!jrubp (if ilimittype=1,2,4,6), electron transport rate (umol m-2 s-1)
!vtpu (if ilimittype=1,3,4,7), triose phosphate export rate from chloroplast (umol m-2 s-1)
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!kco,(if ilimittype=1,2,3,5), Kc(1+O/Ko), (Pa)
!co2i, intercellular CO2 partial pressure (Pa)
!starco2i,(if ilimittype=1,2,3,5), intercellular CO2 partial pressure at which Ac = 0. At this point, 
!   chloroplastic CO2 partial pressure equals the intercellular partial pressure (Pa). If less than
!   zero, rd must be an input.
!alpha, (if ilimittype=1,3,4,7), fraction of glycolate carbon not returned to the chloroplast (0-1, dimensionless)
!rd, (if ilimittype=4,6,7),mitochondrial respiration in the light (umol m-2 s-1). if starco2i is less than
!zero, rd must be an input under all limitation types
!
!------------------ Outputs ----------------------------------
!rd, (if ilimittype=1,2,3,5 when starco2i is greater than zero),mitochondrial respiration in the light (umol m-2 s-1)
!anet: the net assimilation rate (umol m-2 s-1)
!iminimum, which limitation type is actually present Rubisco (1), RuBp(2), and TPU (3)
!realizedfjelect: the realized electron transport rate <= jrubp (=when RuBP regeneration limits photosynthesis). 
      integer ilimittype,iminimum
      double precision vcmax,jrubp,vtpu,gmeso,stargamma,kco,co2i,
     &alpha,rd,anet,der_vcmax,der_jrubp,der_vtpu,der_rwp,der_rch,
     &der_stargamma,der_kco,der_alpha,der_rd,t1,t2,co2c,rwp,
     &rch,resistwp,resistch,dCc_t1,dCc_t2,dCc_co2i,dCc_rd,
     &dCc_stargamma,der_co2i,der_Cc,der_t1,der_t2,dCc_rwp,dCc_rch,
     &realizedfjelect
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
      call Anet_Final(vcmax,jrubp,vtpu,rwp,rch,stargamma,
     &kco,co2i,alpha,rd,ilimittype,iminimum,anet,co2c,
     &realizedfjelect)
!We now know which limitation type is at work. Calculate the derivatives
      der_vcmax=0.0d0
      der_jrubp=0.0d0
      der_vtpu=0.0d0
      der_rwp=0.0d0
      der_rch=0.0d0
      der_stargamma=0.0d0
      der_kco=0.0d0
      der_alpha=0.0d0
      der_co2i=0.0d0
      der_rd=-1.0d0
      if(iminimum.eq.1)then
        t1=vcmax
        t2=kco
      endif
      if(iminimum.eq.2)then
        t1=0.25d0*jrubp
        t2=2.0d0*stargamma
      endif
      if(iminimum.eq.3)then
        t1=3.0d0*vtpu
        t2=-(1.0d0+3.0d0*alpha)*stargamma
      endif
      der_t1=(co2c-stargamma)/(co2c+t2)
      der_t2=-(co2c-stargamma)*t1/((co2c+t2)*(co2c+t2))
      der_stargamma=-t1/(co2c+t2)
      der_Cc=t1/(co2c+t2)*(1.0d0-(co2c-stargamma)/(co2c+t2))
      der_co2i=der_Cc
      call der_findco2c(t1,t2,co2i,rd,stargamma,rwp,
     &rch,co2c,dCc_t1,dCc_t2,dCc_co2i,dCc_rd,dCc_stargamma,
     &dCc_rwp,dCc_rch)
      der_t1=der_t1+der_Cc*dCc_t1
      der_t2=der_t2+der_Cc*dCc_t2
      der_stargamma=der_stargamma+der_Cc*dCc_stargamma
      der_rd=der_rd+der_Cc*dCc_rd
      der_co2i=der_Cc*dCc_co2i
      der_rwp=der_Cc*dCc_rwp
      der_rch=der_Cc*dCc_rch
!now change back
      if(iminimum.eq.1)then
        der_vcmax=der_t1
        der_kco=der_t2
      endif
      if(iminimum.eq.2)then
        der_jrubp=der_t1*0.25d0
        der_stargamma=der_stargamma+der_t2*2.0d0
      endif
      if(iminimum.eq.3)then
        der_vtpu=der_t1*3.0d0
        der_stargamma=der_stargamma-der_t2*(1.0d0+3.0d0*alpha)
        der_alpha=-der_t2*3.0d0*stargamma
      endif
      return
      end subroutine Anet_Final_der
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine Anet_Final_der2(vcmax,jrubp,vtpu,resistwp,
     &resistch,stargamma,kco,co2i,alpha,rd,ilimittype,der_vcmax,
     &der_jrubp,der_vtpu,der_rwp,der_rch,der_stargamma,der_kco,
     &der_alpha,der_rd,der_co2i,der2_vcmax,der2_jrubp,der2_vtpu,
     &der2_rwp,der2_rch,der2_stargamma,der2_kco,der2_alpha,
     &der2_rd,der2_co2i,anet,co2c,realizedfjelect)
      implicit none
!Calculates the derivatives of parameters and the net assimilation rate 
!once all parameters are given at measurement conditions.
!------------------ Inputs -----------------------------------
!ilimittype: limitation types to evaluate
!            1 = Rubisco,RuBp and TPU limitations
!            2 = Rubisco and RuBp limitations only
!            3 = Rubisco and TPU limitations only
!            4 = RuBp and TPU limitations only
!            5 = Rubisco limitation only
!            6 = RuBp limitation only
!            7 = TPU limitation only
!vcmax (if ilimittype=1,2,3,5), maximum carboxylation rate limited by Rubisco (umol m-2 s-1) 
!jrubp (if ilimittype=1,2,4,6), electron transport rate (umol m-2 s-1)
!vtpu (if ilimittype=1,3,4,7), triose phosphate export rate from chloroplast (umol m-2 s-1)
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!kco,(if ilimittype=1,2,3,5), Kc(1+O/Ko), (Pa)
!co2i, intercellular CO2 partial pressure (Pa)
!starco2i,(if ilimittype=1,2,3,5), intercellular CO2 partial pressure at which Ac = 0. At this point, 
!   chloroplastic CO2 partial pressure equals the intercellular partial pressure (Pa). If less than
!   zero, rd must be an input.
!alpha, (if ilimittype=1,3,4,7), fraction of glycolate carbon not returned to the chloroplast (0-1, dimensionless)
!rd, mitochondrial respiration in the light (umol m-2 s-1)
!
!------------------ Outputs ----------------------------------
!anet: the net assimilation rate (umol m-2 s-1)
!iminimum, which limitation type is actually present Rubisco (1), RuBp(2), and TPU (3)
!realizedfjelect: the realized electron transport rate <= jrubp (=when RuBP regeneration limits photosynthesis). 
      integer ilimittype,iminimum
      double precision vcmax,jrubp,vtpu,resistwp,resistch,
     &stargamma,kco,co2i,alpha,rd,der_vcmax,der_jrubp,der_vtpu,
     &der_rwp,der_rch,der_stargamma,der_kco,der_alpha,der_rd,der_co2i,
     &der2_vcmax,der2_jrubp,der2_vtpu,der2_rwp,der2_rch,der2_stargamma,
     &der2_kco,der2_alpha,der2_rd,der2_co2i,anet,co2c,rwp,rch,t1,t2,t3,
     &der_t1,der_t2,der_Cc,der2_t1,der2_t2,der2_Cc,der2_Cct1,der2_Cct2,
     &der2_Ccstargamma,der2_t2stargamma,der2_Ccrd,dCc_t1,dCc_t2,dCc_rd,
     &dCc2_rd,dCc_stargamma,dCc_rwp,dCc2_rwp,dCc_rch,dCc2_rch,dCc_co2i,
     &dCc2_t1,dCc2_t2,dCc2_co2i,dCc2_stargamma,dCc2_t2stargamma,
     &der2_t2_0,realizedfjelect
!------------------------------------------------------------------
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
      call Anet_Final(vcmax,jrubp,vtpu,rwp,rch,stargamma,
     &kco,co2i,alpha,rd,ilimittype,iminimum,anet,co2c,
     &realizedfjelect)
!We now know which limitation type is at work. Calculate the derivatives
!first derivatives
      der_vcmax=0.0d0
      der_jrubp=0.0d0
      der_vtpu=0.0d0
      der_rwp=0.0d0
      der_rch=0.0d0
      der_stargamma=0.0d0
      der_kco=0.0d0
      der_alpha=0.0d0
      der_rd=-1.0d0
!second derivatives
      der2_vcmax=0.0d0
      der2_jrubp=0.0d0
      der2_vtpu=0.0d0
      der2_rwp=0.0d0
      der2_rch=0.0d0
      der2_stargamma=0.0d0
      der2_kco=0.0d0
      der2_alpha=0.0d0
      der2_rd=0.0d0
      if(iminimum.eq.1)then
        t1=vcmax
        t2=kco
      endif
      if(iminimum.eq.2)then
        t1=0.25d0*jrubp
        t2=2.0d0*stargamma
      endif
      if(iminimum.eq.3)then
        t1=3.0d0*vtpu
        t2=-(1.0d0+3.0d0*alpha)*stargamma
      endif
      der_t1=(co2c-stargamma)/(co2c+t2)
      der_t2=-(co2c-stargamma)*t1/((co2c+t2)*(co2c+t2))
      der_stargamma=-t1/(co2c+t2)
      der_Cc=t1/(co2c+t2)*(1.0d0-(co2c-stargamma)/(co2c+t2))
      der_co2i=der_Cc
      der2_Cc=(2.0d0*t1/((co2c+t2)**2))*
     &((co2c-stargamma)/(co2c+t2)-1.0d0)
      der2_t2=2.0d0*(co2c-stargamma)*t1/((co2c+t2)**3)
      der2_t2_0=der2_t2
      der2_Cct1=(1.0d0-(co2c-stargamma)/(co2c+t2))/(co2c+t2)
      der2_Cct2=(t1/((co2c+t2)**2))*
     &(2.0d0*(co2c-stargamma)/(co2c+t2)-1.0d0)
      der2_Ccstargamma=t1/((co2c+t2)**2)
      der2_t2stargamma=t1/((co2c+t2)**2)
      der2_co2i=der2_Cc
      der2_rd=0.0d0
      der2_t1=0.0d0
      der2_stargamma=0.0d0
      der2_Ccrd=0.0d0
      call der2_findco2c(t1,t2,co2i,rd,stargamma,rwp,rch,co2c,dCc_t1,
     &dCc_t2,dCc_co2i,dCc_rd,dCc_stargamma,dCc_rwp,dCc_rch,dCc2_t1,
     &dCc2_t2,dCc2_co2i,dCc2_rd,dCc2_stargamma,dCc2_rwp,dCc2_rch,
     &dCc2_t2stargamma)
      der_t1=der_t1+der_Cc*dCc_t1
      der_t2=der_t2+der_Cc*dCc_t2
      der_stargamma=der_stargamma+der_Cc*dCc_stargamma
      der_rd=der_rd+der_Cc*dCc_rd
      der_co2i=der_Cc*dCc_co2i
      der_rwp=der_Cc*dCc_rwp
      der_rch=der_Cc*dCc_rch
      der2_t1=
     &2.0d0*der2_Cct1*dCc_t1+der2_Cc*(dCc_t1**2)+der_Cc*dCc2_t1
      der2_t2=der2_t2+
     &2.0d0*der2_Cct2*dCc_t2+der2_Cc*(dCc_t2**2)+der_Cc*dCc2_t2
      der2_rd=der2_Cc*(dCc_rd**2)+der_Cc*dCc2_rd
      der2_rwp=der2_Cc*(dCc_rwp**2)+der_Cc*dCc2_rwp
      der2_rch=der2_Cc*(dCc_rch**2)+der_Cc*dCc2_rch
      der2_co2i=der2_Cc*(dCc_co2i**2)+der_Cc*dCc2_co2i
      if(iminimum.eq.1)then
        der2_stargamma=
     &2.0d0*der2_Ccstargamma*dCc_stargamma+der2_Cc*(dCc_stargamma**2)+
     &der_Cc*dCc2_stargamma
        der_vcmax=der_t1
        der_kco=der_t2
        der2_vcmax=der2_t1
        der2_kco=der2_t2
      endif
      if(iminimum.eq.2)then
        dCc_stargamma=dCc_stargamma+dCc_t2*2.0d0
        dCc2_stargamma=dCc2_stargamma+
     &2.0d0*dCc2_t2stargamma*2.0d0+dCc2_t2*4.0d0
        der_jrubp=der_t1*0.25d0
        der_stargamma=der_stargamma+der_t2*2.0d0
        der2_jrubp=der2_t1*0.25d0*0.25d0
        der2_stargamma=2.0d0*der2_Ccstargamma*dCc_stargamma+
     &der2_Cc*(dCc_stargamma**2)+der_Cc*dCc2_stargamma+
     &4.0d0*(der2_t2stargamma+der2_Cct2*dCc_stargamma)+der2_t2_0*4.0d0
      endif
      if(iminimum.eq.3)then
        t3=-(1.0d0+3.0d0*alpha)
        dCc_stargamma=dCc_stargamma+dCc_t2*t3
        dCc2_stargamma=dCc2_stargamma+
     &2.0d0*dCc2_t2stargamma*t3+dCc2_t2*t3*t3
        der_vtpu=der_t1*3.0d0
        der_stargamma=der_stargamma+der_t2*t3
        der_alpha=-der_t2*3.0d0*stargamma
        der2_vtpu=der2_t1*3.0d0*3.0d0
        der2_stargamma=2.0d0*der2_Ccstargamma*dCc_stargamma+
     &der2_Cc*(dCc_stargamma**2)+der_Cc*dCc2_stargamma+
     &2.0d0*(der2_t2stargamma+der2_Cct2*dCc_stargamma)*t3+
     &der2_t2_0*t3*t3
        der2_alpha=der2_t2*9.0d0*stargamma**2
      endif
      return
      end
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine der2_findco2c(vcmax,kco,co2i,rd,stargamma,rwp,
     &rch,co2c,der_vcmax,der_kco,der_co2i,der_rd,der_stargamma,
     &der_rwp,der_rch,der2_vcmax,der2_kco,der2_co2i,der2_rd,
     &der2_stargamma,der2_rwp,der2_rch,der2_kcostargamma)
!kco and vcmax are generic and the formulation applies to rubp and tpu too
!after the transformation factors are applied
      implicit none
      integer iwhichroot
      double precision vcmax,kco,co2i,rd,stargamma,rwp,rch,co2c,
     &der_vcmax,der_kco,der_co2i,der_rd,der_stargamma,der_rwp,
     &der_rch,der2_vcmax,der2_kco,der2_co2i,der2_rd,der2_stargamma,
     &der2_rwp,der2_rch,der2_kcostargamma,derb_vcmax,derb_kco,derb_co2i,
     &derb_rd,derb_stargamma,derb_rwp,derb_rch,derc_vcmax,derc_kco,
     &derc_co2i,derc_rd,derc_stargamma,derc_rwp,derc_rch,b,c,b24ac,
     &term,der_b,der_c,der2_b,der2_c,der2_bc,p,q,w,der2implicit
      co2c=-9999.0d0
      der_vcmax=0.0d0
      der_kco=0.0d0
      der_co2i=0.0d0
      der_rd=0.0d0
      der_stargamma=0.0d0
      der_rwp=0.0d0
      der_rch=0.0d0
      der2_kco=0.0d0
      der2_co2i=0.0d0
      der2_rd=0.0d0
      der2_stargamma=0.0d0
      der2_rwp=0.0d0
      der2_rch=0.0d0
      der2_kcostargamma=0.0d0
      b=kco-co2i-rd*rwp+vcmax*(rwp+rch)
      c=-(co2i+rd*rwp)*kco-vcmax*rwp*stargamma
      derb_vcmax=rwp+rch
      derb_kco=1.0d0
      derb_co2i=-1.0d0
      derb_rd=-rwp
      derb_stargamma=0.0d0
      derb_rwp=vcmax-rd
      derb_rch=vcmax
      derc_vcmax=-rwp*stargamma
      derc_kco=-(co2i+rd*rwp)
      derc_co2i=-kco
      derc_rd=-rwp*kco
      derc_stargamma=-vcmax*rwp
      derc_rwp=-rd*kco-vcmax*stargamma
      derc_rch=0.0d0
      b24ac=b*b-4.0d0*c
      if(b24ac.ge.0.0d0)then
        iwhichroot=1
!        p=-rd*rwp+vcmax*(rwp+rch)
!        q=rd*rwp*kco+vcmax*rwp*stargamma
!        w=4.0d0*(p*kco+q)
!        if(w.le.0.0d0)then
!          if((kco+co2i-p).le.(-dsqrt(-w)))iwhichroot=-1
!        endif
!        if((kco+co2i-p).lt.0.0d0)iwhichroot=-1

        call der2_simpquadroot(iwhichroot,b,c,co2c,der_b,der_c,der2_b,
     &der2_c,der2_bc)
        der_vcmax=der_b*derb_vcmax+der_c*derc_vcmax
        der_kco=der_b*derb_kco+der_c*derc_kco
        der_co2i=der_b*derb_co2i+der_c*derc_co2i
        der_rd=der_b*derb_rd+der_c*derc_rd
        der_stargamma=der_b*derb_stargamma+der_c*derc_stargamma
        der_rwp=der_b*derb_rwp+der_c*derc_rwp
        der_rch=der_b*derb_rch+der_c*derc_rch
        der2_vcmax=der2implicit(der2_b,der2_c,der2_bc,
     &derb_vcmax,derc_vcmax)
        der2_kco=der2implicit(der2_b,der2_c,der2_bc,derb_kco,derc_kco)
        der2_co2i=der2implicit(der2_b,der2_c,der2_bc,
     &derb_co2i,derc_co2i)
        der2_rd=der2implicit(der2_b,der2_c,der2_bc,derb_rd,derc_rd)
        der2_stargamma=der2implicit(der2_b,der2_c,der2_bc,
     &derb_stargamma,derc_stargamma)
        der2_rwp=der2implicit(der2_b,der2_c,der2_bc,derb_rwp,derc_rwp)
        der2_rch=der2implicit(der2_b,der2_c,der2_bc,derb_rch,derc_rch)
        der2_kcostargamma=
     &der2_bc*derc_stargamma*derb_kco+der2_c*derc_stargamma*derc_kco
      endif
      return
      end
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine der2_simpquadroot(iwhichroot,b,c,root,
     &  der_b,der_c,der2_b,der2_c,der2_bc)
      implicit none
      double precision b,c,root,der_b,der_c,b24c,
     &  der2_b,der2_c,der2_bc,term
      integer iwhichroot
!root for x2+bx+c=0
      b24c=b*b-4.0d0*c
      if(b24c.lt.0.0d0)then
        root=-9999.0d0
        der_b=-9999.0d0
        der_c=-9999.0d0
        der2_b=-9999.0d0
        der2_c=-9999.0d0
        der2_bc=-9999.0d0
      else
        term=1.0d0/((b*b-4.0d0*c)*dsqrt(b24c))
        if(iwhichroot.lt.0)then
          root=0.5d0*(-b-dsqrt(b24c))
          der_b=0.5d0*(-1.0d0-b/dsqrt(b24c))
          der_c=1.0d0/dsqrt(b24c)
          der2_b=2.0d0*c*term
          der2_c=2.0d0*term
          der2_bc=-b*term
        else
          root=0.5d0*(-b+dsqrt(b24c))
          der_b=0.5d0*(-1.0d0+b/dsqrt(b24c))
          der_c=-1.0d0/dsqrt(b24c)
          der2_b=-2.0d0*c*term
          der2_c=-2.0d0*term
          der2_bc=b*term
        endif
      endif
      return
      end
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
      double precision function der2implicit(der2_b,der2_c,
     &  der2_bc,derb_p,derc_p)
      implicit none
      double precision der2_b,der2_c,
     &  der2_bc,derb_p,derc_p
      der2implicit=der2_b*derb_p*derb_p+
     &  2.0d0*der2_bc*derb_p*derc_p+der2_c*derc_p*derc_p
      return
      end
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
      subroutine der_simpquadroot(iwhichroot,b,c,root,
     &           der_b,der_c)
      implicit none
      double precision b,c,root,der_b,der_c,b24c
      integer iwhichroot
!x2+bx+c=0     
      b24c=b*b-4.0d0*c
      if(b24c.gt.0.0d0)then
        if(iwhichroot.lt.0)then
          root=0.5d0*(-b-dsqrt(b24c))
          der_b=0.5d0*(-1.0d0-b/dsqrt(b24c))
          der_c=1.0d0/dsqrt(b24c)
        else
          root=0.5d0*(-b+dsqrt(b24c))
          der_b=0.5d0*(-1.0d0+b/dsqrt(b24c))
          der_c=-1.0d0/dsqrt(b24c)
        endif
      else
        if(b24c.lt.0.0d0)then
          root=-9999.0d0
          der_b=-9999.0d0
          der_c=-9999.0d0
        else
         root=-b
         der_b=-1.0d0
         der_c=0.0d0
        endif
      endif
      return
      end
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
      subroutine EqualPoints(vcmax,jrubp,vtpu,resistwp,
     &resistch,stargamma,kc,ko,oxypres,alpha,rd,ilimittype,
     &co2iRubismax,co2iRuBpmax,anetRubismax,anetRuBpmax)
      implicit none
!Calculates the CO2i points where limitations of Rubisco, RuBp and Tpu are equal.
!------------------ Inputs -----------------------------------
!ilimittype: limitation types to evaluate
!            1 = Rubisco,RuBp and TPU limitations
!            2 = Rubisco and RuBp limitations only
!            3 = Rubisco and TPU limitations only
!            4 = RuBp and TPU limitations only
!            5 = Rubisco limitation only
!            6 = RuBp limitation only
!            7 = TPU limitation only
!vcmax (if ilimittype=1,2,3,5), maximum carboxylation rate limited by Rubisco (umol m-2 s-1) 
!jrubp (if ilimittype=1,2,4,6), electron transport rate (umol m-2 s-1)
!vtpu (if ilimittype=1,3,4,7), triose phosphate export rate from chloroplast (umol m-2 s-1)
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!kc:      the Michaelis constant for CO2 [Pa]
!ko:      the Michaelis constant for O2 [Pa]
!oxypres: Oxygen partial pressure (Pa)
!alpha, (if ilimittype=1,3,4,7), fraction of glycolate carbon not returned to the chloroplast (0-1, dimensionless)
!rd, mitochondrial respiration in the light (umol m-2 s-1). 
!------------------ Outputs ----------------------------------
!anetRubisRuBp,anetRuBpTpu,anetRubisTpu: the net assimilation rates at equal points (umol m-2 s-1)
!co2iRubisRuBp,co2iRuBpTpu,co2iRubisTpu: equal points

      integer ilimittype
      double precision vcmax,jrubp,vtpu,resistwp,resistch,
     &rwp,rch,stargamma,kc,ko,oxypres,kco,co2i,alpha,rd,
     &co2iRubismax,co2iRuBpmax,anetRubismax,anetRuBpmax,term1
!------------------------------------------------------------------
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
      anetRubismax=-9999.0d0
      anetRuBpmax=-9999.0d0
      co2iRubismax=-9999.0d0
      co2iRuBpmax=-9999.0d0
      kco=kc*(1.0d0+oxypres/ko)
      term1=-(1.0d0+3.0d0*alpha)*stargamma
      if(ilimittype.eq.1)then
        co2iRubismax=(2.0d0*stargamma*vcmax-
     &        kco*0.25d0*jrubp)/(0.25d0*jrubp-vcmax)
        anetRubismax=(co2iRubismax-stargamma)*vcmax/
     &        (co2iRubismax+kco)-rd
        co2iRuBpmax=(2.0d0*stargamma*3.0d0*vtpu-
     &        term1*0.25d0*jrubp)/(0.25d0*jrubp-3.0d0*vtpu)
        anetRuBpmax=(co2iRuBpmax-stargamma)*0.25d0*jrubp/
     &        (co2iRuBpmax+2.0d0*stargamma)-rd
      endif
      if(ilimittype.eq.2)then
        co2iRubismax=(2.0d0*stargamma*vcmax-
     &        kco*0.25d0*jrubp)/(0.25d0*jrubp-vcmax)
        anetRubismax=(co2iRubismax-stargamma)*vcmax/
     &        (co2iRubismax+kco)-rd
      endif
      if(ilimittype.eq.3)then
        co2iRubismax=(term1*vcmax-
     &        kco*3.0d0*vtpu)/(3.0d0*vtpu-vcmax)
        anetRubismax=(co2iRubismax-stargamma)*vcmax/
     &        (co2iRubismax+kco)-rd
      endif
      if(ilimittype.eq.4)then
        co2iRuBpmax=(2.0d0*stargamma*3.0d0*vtpu-
     &        term1*0.25d0*jrubp)/(0.25d0*jrubp-3.0d0*vtpu)
        anetRuBpmax=(co2iRuBpmax-stargamma)*0.25d0*jrubp/
     &        (co2iRuBpmax+2.0d0*stargamma)-rd
      endif
      if(rwp.gt.0.0d0.or.rch.gt.0.0d0)then
        if(ilimittype.eq.1.or.ilimittype.eq.2.or.ilimittype.eq.3)
     &co2iRubismax=co2iRubismax+anetRubismax*rwp+rch*
     &co2iRubismax*vcmax/(co2iRubismax+kco)
        if(ilimittype.eq.1.or.ilimittype.eq.4)co2iRuBpmax=
     &co2iRuBpmax+anetRuBpmax*rwp+rch*co2iRuBpmax*0.25d0*jrubp/
     &(co2iRuBpmax+2.0d0*stargamma)
      endif
      return
      end subroutine EqualPoints
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine Params_Ci(vcmax,jrubp,vtpu,resistwp,resistch,
     &stargamma,kco,alpha,rd,ilimittype,cic,anetcic,cij,anetcij)
      implicit none
!
!Calculates vcmax and tpu when the CO2i thresholds are known.
!------------------ Inputs -----------------------------------
!ilimittype: limitation types to evaluate
!   1 = Rubisco,RuBp and TPU limitations, 
!   2 = Rubisco and RuBp limitations only
!   3 = Rubisco and TPU limitations only
!   4 = RuBp and TPU limitations only
!            
!jrubp (except for ilimittype=3), electron transport rate (umol m-2 s-1)
!vtpu (when ilimittype=3 only), triose phosphate export rate from chloroplast (umol m-2 s-1)
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!kco,(if ilimittype=1,2,3), Kc(1+O/Ko), (Pa)
!alpha, (if ilimittype=1,3,4), fraction of glycolate carbon not returned to the chloroplast (0-1, dimensionless)
!rd, mitochondrial respiration in the light (umol m-2 s-1).
!cic, CO2i at rubisco and rubp limited intersection (Pa) or at rubisco and tpu limited intersection
!cij, CO2i at rubp and tpu limited intersection (Pa) 
!------------------ Outputs ----------------------------------
!vcmax (when ilimittype=1,2,3 only), maximum carboxylation rate limited by Rubisco (umol m-2 s-1) 
!vtpu (when ilimittype=1,4 only), triose phosphate export rate from chloroplast (umol m-2 s-1)
!anetcic: net assimilation rate at cic (umol m-2 s-1). 
!anetcij: net assimilation rate at cij (umol m-2 s-1). 

      integer ilimittype,idogi,i,j,k
      double precision vcmax,jrubp,vtpu,resistwp,resistch,rwp,rch,
     &stargamma,kco,co2i,alpha,rd,term1,cic,cij,anetcic,anetcij,
     &co2cic,co2cij,realizedfjelect
!------------------------------------------------------------------
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
      term1=-(1.0d0+3.0d0*alpha)*stargamma
      if(ilimittype.eq.1.or.ilimittype.eq.2)then
        call Anet_Final(vcmax,jrubp,vtpu,rwp,rch,stargamma,
     &kco,cic,alpha,rd,6,i,anetcic,co2cic,realizedfjelect)
      endif
      if(ilimittype.eq.1.or.ilimittype.eq.4)then
        call Anet_Final(vcmax,jrubp,vtpu,rwp,rch,stargamma,
     &kco,cij,alpha,rd,6,i,anetcij,co2cij,realizedfjelect)
      endif
      if(ilimittype.eq.3)then
        call Anet_Final(vcmax,jrubp,vtpu,rwp,rch,stargamma,
     &kco,cic,alpha,rd,7,i,anetcic,co2cic,realizedfjelect)
      endif
      if(ilimittype.eq.1.or.ilimittype.eq.2.or.ilimittype.eq.3)
     &vcmax=(anetcic+rd)*(co2cic+kco)/(co2cic-stargamma)
      if(ilimittype.eq.1.or.ilimittype.eq.4)then
        if(alpha.gt.0.0d0)then
          vtpu=(anetcij+rd)*(co2cij+term1)/(co2cij-stargamma)
          vtpu=vtpu/3.0d0
        else
            vtpu=(anetcij+rd)/3.0d0
        endif
      endif
      return
      end subroutine Params_Ci
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine inverse_anet(vcmax,jrubp,vtpu,resistwp,
     &resistch,stargamma,kco,alpha,rd,iminimum,co2i,anet)
      implicit none
!Calculates vcmax, jrubp, or tpu when CO2i and other parameters are known.
!------------------ Inputs -----------------------------------
!iminimum=1, rubisco limitation
!        =2, rubp regeneration limitation
!        =3, tpu limitation
!anet: net co2 assimilation rate (umolm-2s-1)
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!kco (if iminimum=1), Kc(1+O/Ko), (Pa)
!alpha (if iminimum=3), fraction of glycolate carbon not returned to the chloroplast (0-1, dimensionless)
!rd, mitochondrial respiration in the light (umol m-2 s-1).
!------------------ Outputs ----------------------------------
!vcmax (when iminimum=1 only), maximum carboxylation rate limited by Rubisco (umol m-2 s-1) 
!jrubp (when iminimum=2 only), electron transport rate (umol m-2 s-1)
!vtpu (when iminimum=3 only), triose phosphate export rate from chloroplast (umol m-2 s-1)
!
      integer iminimum
      double precision vcmax,jrubp,vtpu,resistwp,resistch,
     &stargamma,kco,co2i,alpha,rd,anet,term1,co2c
!------------------------------------------------------------------
      vcmax=-9999.0d0
      jrubp=-9999.0d0
      vtpu=-9999.0d0
      if(iminimum.eq.3.and.alpha.le.0.0d0)then
        vtpu=(anet+rd)/3.0d0
        return
      endif
      call getco2c(resistwp,resistch,stargamma,rd,co2i,anet,co2c)
      if(co2c.lt.0.0d0)return
      if(iminimum.eq.1)vcmax=(anet+rd)*(co2c+kco)/(co2c-stargamma)
      if(iminimum.eq.2)jrubp=
     &4.0d0*(anet+rd)*(co2c+2.0d0*stargamma)/(co2c-stargamma)
      if(iminimum.eq.3)then
        term1=-(1.0d0+3.0d0*alpha)*stargamma
        vtpu=((anet+rd)*(co2c+term1)/(co2c-stargamma))/3.0d0
      endif
      return
      end subroutine inverse_anet
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine getco2c(resistwp,resistch,stargamma,rd,co2i,anet,
     &co2c)
      implicit none
!Calculates CO2c
!------------------ Inputs -----------------------------------
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!rd, mitochondrial respiration in the light (umol m-2 s-1).
!anet: CO2 assimilation rate (umolm-2s-1)
      double precision resistwp,rwp,resistch,rch,stargamma,co2i,rd,anet,
     &co2c,b,c,b24ac,cy
!------------------------------------------------------------------
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
      cy=co2i-anet*rwp
      if(rch.gt.0.0d0)then
        b=(anet+rd)*rch-cy-stargamma
        c=cy*stargamma
        b24ac=b*b-4.0d0*c
        if(b24ac.ge.0.0d0)then
          if(anet.lt.-rd)then
            co2c=(-b-dsqrt(b24ac))/2.0d0
          else
            co2c=(-b+dsqrt(b24ac))/2.0d0
          endif
        else
          co2c=-9999.0d0
        endif
      else
        co2c=cy
      endif
      return
      end subroutine getco2c
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine getresistmeso(resistwp,resistch,stargamma,rd,co2i,anet,
     &co2c,resistmeso)
      implicit none
!Calculates mesophyll resistance resistmeso (Pa s m2 umol-1) and chloroplastic CO2 co2c (Pa)
!------------------ Inputs -----------------------------------
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!rd, mitochondrial respiration in the light (umol m-2 s-1).
!anet: CO2 assimilation rate (umolm-2s-1)
!co2i: CO2 partial pressure at intercellular air space (Pa)
      double precision resistwp,rwp,resistch,rch,stargamma,co2i,rd,anet,
     &co2c,q,u,q24u,resistmeso
!------------------------------------------------------------------
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
      if(rch.gt.0.0d0)then
        call getco2c(rwp,rch,stargamma,rd,co2i,anet,co2c)
        resistmeso=(co2i-co2c)/anet
!
!        q=-(anet+rd)*rch-co2i+stargamma-anet*rwp
!        u=(anet+rd)*rch*co2i+(co2i-stargamma)*anet*rwp
!        q24u=q*q-4.0d0*u
!        if(q24u.ge.0.0d0)then
!          resistmeso=(-q-dsqrt(q24u))/(2.0d0*anet)
!          co2c=co2i-anet*resistmeso
!          write(*,*)co2c,resistmeso
!          resistmeso=(-q+dsqrt(q24u))/(2.0d0*anet)
!          co2c=co2i-anet*resistmeso
!          write(*,*)co2c,resistmeso
!        else
!          resistmeso=-9999.0d0
!          co2c=-9999.0d0
!        endif
      else
        resistmeso=rwp
        co2c=co2i-anet*resistmeso
      endif
      return
      end subroutine getresistmeso
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine co2recyclingratio(resistwp,resistch,resiststom,
     &stargamma,rd,co2c,anet,recyclingrate)
      implicit none
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!resiststom: resistance to CO2 via stomata (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma: chloraplatic CO2 photocompensation point (Pa)
!rd, mitochondrial respiration in the light (umol m-2 s-1).
!co2c: co2 partial pressure at chloroplast (Pa)
!anet, net assimilation rate (umol m-2 s-1).
      double precision resistwp,resistch,resiststom,stargamma,
     &rd,co2c,anet,recyclingrate,rwp,rch,rst,vc,rcarb
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
      rst=dmax1(0.0d0,resiststom)
      vc=(anet+rd)/(1.0d0-stargamma/co2c)
      rcarb=co2c/vc
      recyclingrate=(rwp+rst)/(rwp+rst+rch+rcarb)
      return
      end
!&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
      subroutine CO2i_Final(vcmax,jrubp,vtpu,resistwp,resistch,
     &stargamma,kco,co2i,alpha,rd,ilimittype,iminimum,anet,co2c,
     &realizedfjelect,co2i_obs,co2c_wp,anet_wp)
      implicit none
!
!Calculates the net assimilation rate once all parameters are given at measurement conditions
!------------------ Inputs -----------------------------------
!ilimittype: limitation types to evaluate
!            1 = Rubisco,RuBp and TPU limitations
!            2 = Rubisco and RuBp limitations only
!            3 = Rubisco and TPU limitations only
!            4 = RuBp and TPU limitations only
!            5 = Rubisco limitation only
!            6 = RuBp limitation only
!            7 = TPU limitation only
!vcmax (if ilimittype=1,2,3,5), maximum carboxylation rate limited by Rubisco (umol m-2 s-1) 
!jrubp (if ilimittype=1,2,4,6), electron transport rate (umol m-2 s-1)
!vtpu (if ilimittype=1,3,4,7), triose phosphate export rate from chloroplast (umol m-2 s-1)
!resistwp: resistance to CO2 via cell walls and plasmalemma (Pa s m2 umol-1). If less than zero, set to zero.
!resistch: resistance to CO2 via chloroplast envelope and stroma (Pa s m2 umol-1). If less than zero, set to zero.
!stargamma, chloraplatic CO2 photocompensation point (Pa)
!kco,(if ilimittype=1,2,3,5), Kc(1+O/Ko), (Pa)
!co2i, intercellular CO2 partial pressure (Pa)
!alpha, (if ilimittype=1,3,4,7), fraction of glycolate carbon not returned to the chloroplast (0-1, dimensionless)
!rd, mitochondrial respiration in the light (umol m-2 s-1). 
!------------------ Outputs ----------------------------------
!anet: the net assimilation rate (umol m-2 s-1)
!iminimum, which limitation type is actually present Rubisco (1), RuBp(2), and TPU (3)
!realizedfjelect: the realized electron transport rate <= jrubp (=when RuBP regeneration limits photosynthesis). 
      integer ilimittype,iminimum,idorubisco,idorubp,idotpu
      double precision vcmax,jrubp,vtpu,stargamma,kco,co2i,
     &alpha,rd,anet,wc,wj,wp,anet_wp,term1,term2,co2c,co2i_wc,co2i_wj,
     &co2i_wp,co2c_wc,co2c_wj,co2c_wp,rwp,resistwp,rch,resistch,
     &realizedfjelect,co2i_obs
      wc=1.0d+10
      wj=1.0d+15
      wp=1.0d+20
      co2i=-9999.0d0
      anet_wp=-9999.0d0
      co2c_wp=-9999.0d0
      co2i_wp=-9999.0d0
      realizedfjelect=-9999.0d0
      rwp=dmax1(0.0d0,resistwp)
      rch=dmax1(0.0d0,resistch)
!This way of initialization is deliberate. If co2c <0, the priority of limitation
!state is Rubisco, RuBP regeneration, TPU
      idorubisco=0
      idorubp=0
      idotpu=0
      iminimum=0
      if(ilimittype.le.3.or.ilimittype.eq.5)then
        idorubisco=1
      endif
      if(ilimittype.le.2.or.ilimittype.eq.4.or.
     &  ilimittype.eq.6)then
        idorubp=1
      endif
      if(ilimittype.eq.1.or.ilimittype.eq.3.or.
     &  ilimittype.eq.4.or.ilimittype.eq.7)then
        idotpu=1
      endif
      if(idorubisco.eq.1)then
!        x=vcmax
!        y=1.0d0
!        z=kco
        call getCO2ibackwards(vcmax,1.0d0,kco,anet,rwp,rch,rd,stargamma,
     &co2i_wc,co2c_wc)
        if(co2c_wc.gt.0.0d0)wc=co2c_wc*vcmax/(co2c_wc+kco)
      endif
      if(idorubp.eq.1)then
!        x=jrubp
!        y=4.0d0
        term1=8.0d0*stargamma
        call getCO2ibackwards(jrubp,4.0d0,term1,anet,rwp,rch,rd,
     &stargamma,co2i_wj,co2c_wj)
        if(co2c_wj.gt.0.0d0)wj=
     &co2c_wj*jrubp/(4.0d0*co2c_wj+8.0d0*stargamma)
      endif
      if(idotpu.eq.1)then
        if(alpha.gt.0.0d0)then
          term1=3.0d0*vtpu
          term2=-(1.0d0+3.0d0*alpha)*stargamma
          call getCO2ibackwards(term1,1.0d0,term2,anet,rwp,rch,rd,
     &stargamma,co2i_wp,co2c_wp)
          if(co2c_wp.gt.(-term2))wp=co2c_wp*term1/(co2c_wp+term2)
        else
!CO2i is undefined for alpha=0 so we use the normal forward mode; in this case, CO2i is an input
!and anet is an output.
          term1=3.0d0*vtpu
          term2=-stargamma
          call findco2c(term1,term2,co2i_obs,rd,stargamma,rwp,rch,
     &co2c_wp)
          co2i_wp=co2i_obs
          if(co2c_wp.gt.stargamma)wp=
     &co2c_wp*3.0d0*vtpu/(co2c_wp-stargamma)
          anet_wp=3.0d0*vtpu-rd
        endif
      endif
      if(ilimittype.ge.5)then
        if(ilimittype.eq.5)then
          iminimum=1
          co2i=co2i_wc
          co2c=co2c_wc
        endif
        if(ilimittype.eq.6)then
          iminimum=2
          co2i=co2i_wj
          co2c=co2c_wj
        endif
        if(ilimittype.eq.7)then
          iminimum=3
          co2i=co2i_wp
          co2c=co2c_wp
        endif
      else
        if(wc.lt.wj)then
          if(wc.le.wp)then
            co2i=co2i_wc
            co2c=co2c_wc
            iminimum=1
          else
            co2i=co2i_wp
            co2c=co2c_wp
            iminimum=3
          endif
        else
          if(wj.le.wp)then
            co2i=co2i_wj
            co2c=co2c_wj
            iminimum=2
          else
            co2i=co2i_wp
            co2c=co2c_wp
            iminimum=3
          endif
        endif
      endif
      if(iminimum.eq.2)then
        realizedfjelect=jrubp
      else
        if(co2c.eq.stargamma)then
          realizedfjelect=0.0d0
        else
          realizedfjelect=
     &(anet+rd)*(4.0d0*co2c+8.0d0*stargamma)/(co2c-stargamma)
        endif
      endif
      return
      end subroutine CO2i_Final
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
      subroutine getCO2ibackwards(x,y,z,anet,rwp,rch,rd,stargamma,
     &co2i,co2c)
      implicit none
!Calculate CO2i and CO2c from anet
!Vc=xCO2c/(yCO2c+z)
!Rubisco: x=Vcmax, y=1, z=kco
!RuBP:    x=jrubp, y=4, z=8*stargamma
!TPU:     x=3*tpu, y=1, z=-(1+3*alpha)*stargamma
!
      double precision x,y,z,anet,rwp,rch,rd,stargamma,co2i,co2c
      co2c=(x*stargamma+z*(anet+rd))/(x-(anet+rd)*y)
      co2i=co2c*(1.0d0+x*rch/(y*co2c+z))+anet*rwp
      return
      end
