EB Subroutine

public subroutine EB()

Uses

  • proc~~eb~~UsesGraph proc~eb EB module~initfac initfac proc~eb->module~initfac module~modglobal modglobal proc~eb->module~modglobal module~modmpi modmpi proc~eb->module~modmpi module~modstat_nc modstat_nc proc~eb->module~modstat_nc module~initfac->module~modglobal module~initfac->module~modmpi mpi mpi module~initfac->mpi netcdf netcdf module~initfac->netcdf module~modmpi->mpi module~modstat_nc->module~modmpi module~modstat_nc->netcdf

Arguments

None

Calls

proc~~eb~~CallsGraph proc~eb EB interface~writestat_nc writestat_nc proc~eb->interface~writestat_nc mpi_bcast mpi_bcast proc~eb->mpi_bcast proc~calclw calclw proc~eb->proc~calclw proc~gaussji gaussji proc~eb->proc~gaussji proc~intqh intqH proc~eb->proc~intqh proc~matinv4 matinv4 proc~eb->proc~matinv4 proc~updategr updateGR proc~eb->proc~updategr proc~writestat_1d_nc writestat_1D_nc proc~eb->proc~writestat_1d_nc proc~writestat_2d_nc writestat_2D_nc proc~eb->proc~writestat_2d_nc interface~writestat_nc->proc~writestat_1d_nc interface~writestat_nc->proc~writestat_2d_nc proc~writestat_3d_nc writestat_3D_nc interface~writestat_nc->proc~writestat_3d_nc proc~writestat_3d_short_nc writestat_3D_short_nc interface~writestat_nc->proc~writestat_3d_short_nc proc~writestat_time_nc writestat_time_nc interface~writestat_nc->proc~writestat_time_nc mpi_allreduce mpi_allreduce proc~intqh->mpi_allreduce proc~qsat qsat proc~updategr->proc~qsat nf90_inq_varid nf90_inq_varid proc~writestat_1d_nc->nf90_inq_varid nf90_put_var nf90_put_var proc~writestat_1d_nc->nf90_put_var nf90_sync nf90_sync proc~writestat_1d_nc->nf90_sync proc~writestat_2d_nc->nf90_inq_varid proc~writestat_2d_nc->nf90_put_var proc~writestat_2d_nc->nf90_sync proc~writestat_3d_nc->nf90_inq_varid proc~writestat_3d_nc->nf90_put_var proc~writestat_3d_nc->nf90_sync proc~writestat_3d_short_nc->nf90_inq_varid proc~writestat_3d_short_nc->nf90_put_var proc~writestat_3d_short_nc->nf90_sync proc~writestat_time_nc->nf90_inq_varid proc~writestat_time_nc->nf90_put_var proc~writestat_time_nc->nf90_sync

Called by

proc~~eb~~CalledByGraph proc~eb EB program~dalesurban DALESURBAN program~dalesurban->proc~eb

Source Code

  subroutine EB
    !calculates the energy balance for every facet
    use modglobal, only: nfcts, boltz, tEB, AM, BM,CM,DM,EM,FM,GM,HM, inAM, bb,w, dumv,Tdash, timee, dtEB, tnextEB, rk3step, rhoa, cp, lEB, ntrun, lwriteEBfiles,nfaclyrs
    use initfac, only: faclam, faccp, netsw, facem, fachf, facef, fachfi, facT, facLWin, faca,facefi,facf,facets,facTdash,facqsat,facwsoil,facf,fachurel,facd,fackappa
    use modmpi, only: myid, comm3d, mpierr, MY_REAL, nprocs, cmyid
    use modstat_nc, only : writestat_nc, writestat_1D_nc, writestat_2D_nc
    real  :: ca = 0., cb = 0., cc = 0., cd = 0., ce = 0., cf = 0.
    real  :: ab = 0.
    integer :: l, n, m,i,j
    character(19) name

    if (.not. (lEB)) return
    !calculate latent heat flux from vegetation and soil
    call intqH
    !calculate energy balance, update facet temperature and soil moisture
    if ((rk3step .eq. 3) .and. (timee .ge. tnextEB)) then

      if (myid .eq. 0) then
        tEB = timee - tEB !time since last calculation of energy balance
        !write (*, *) "doing EB, time since last EB:", tEB

        !calculate time mean, facet area mean latent heat flux and update green roof
        !ILS13 02.05.18 ABOUT updateGR: convert latent heatflux E properly should be done before temperature calculatation. BUT the rest of updateGR should be done after!
        !update green roof
        call updateGR

        !get longwave fluxes for all facets
        call calclw

        !get time mean, facet area mean sensible heat flux
        do n = 1, nfcts
          fachfi(n) = fachfi(n)/tEB/faca(n)*rhoa*cp !mean heat flux since last EB calculation (time average)
          !since fachf is the sum over all cells making up a facet we need to divide by the number of cells, assuming a given density to convert to W/m2
        end do

        !solve the system:
        !see Suter 2018
        !A * T'= bb + B * T,   where T' = dT/dz
        !C * d/dtT + D d/dtT'= e * T'
        !
        !-> T(n+1)=(F-G*dt)^-1*(F*T+w*dt)
        !where F=(C + D*A^-1*B), G=(E*A^-1*B), w=(E*A^-1*bb)


        do n = 1, nfcts
          if (facets(n) < -100) cycle

          !calculate wallflux and update surface temperature
          !! define time dependent fluxes
          ab = boltz*facem(n)*(facT(n, 1)**3)/faclam(n, 1) ! ab*T is the Stefan-Boltzman law
          bb(1) = -(netsw(n) + facLWin(n) + fachfi(n) + facefi(n))/faclam(n, 1) !net surface flux

          !!define the matrices to solve wall heat flux
          !! CREATE MATRICES BASED ON WALL PROPERTIES
          i=1;m=0; !position along columns, placeholder for layerindex since only 3 layers implemented (initfac.f90)
          do j=1,nfaclyrs
            m=j  !!CARE!!! ONLY 3 LAYERS ARE CURRENTLY BEING READ FROM INPUT FILES. PROPERTIES OF LAYER 3 ARE USED FOR SUBSEQUENT LAYERS!!!
            ca=1./facd(n,m)
            BM(j+1,i)=-ca
            BM(j+1,i+1)=ca
            EM(j,i)=-faclam(n,m)
            EM(j,i+1)=faclam(n,m+1)
            cb=faccp(n,m)*facd(n,m)/2.
            CM(j,i)=cb
            CM(j,i+1)=cb
            ca=faccp(n,m)*facd(n,m)**2/12.
            DM(j,i)=ca
            DM(j,i+1)=-ca
            i=i+1
          end do
          CM(nfaclyrs+1,nfaclyrs+1)=1.
          BM(1,1)=ab


          w = matmul(EM, matmul(inAM,bb))*tEB !easier than loop and sum
          HM = matmul(inAM,BM)
          FM = CM + matmul(DM,HM)
          GM = matmul(EM,HM)
          HM = FM-GM*tEB
          if (nfaclyrs == 3) then
            GM = matinv4(HM)
          else
            GM = gaussji(HM,IDM,nfaclyrs+1)
          end if
          !instead of inverting matrix HM and multiplying by GM (=HM^-1) it would be waster to do a  left matrix division HM\x is faster than (HM^-1)*x
          dumv = matmul(GM, (matmul(FM,facT(n,:))+w))

          facT(n, :) = dumv
          !calculate Temperature gradient dT/dz=>Tdash so we can output it
          !ground heat flux = lambda dT/dz
          w = matmul(BM, dumv)
          facTdash(n, :) = matmul(inAM, (bb + w))

          !end if
        end do

        if (lwriteEBfiles) then
          if (myid == 0) then
            allocate(varsT(nfcts,nfaclyrs+1,nstatT))
            varsT(:,:,1) = facT(1:nfcts,1:nfaclyrs+1)
            varsT(:,:,2) = facTdash(1:nfcts,1:nfaclyrs+1)
            call writestat_nc(ncidT,1,tncstatT,(/timee/),nrecT,.true.)
            call writestat_2D_nc(ncidT,nstatT,ncstatT,varsT,nrecT,nfcts,nfaclyrs+1)
            deallocate(varsT)

            allocate(varsEB(nfcts,nstatEB))
            varsEB(:,1) = netsw(1:nfcts)
            varsEB(:,2) = facLWin(1:nfcts)
            varsEB(:,3) = boltz*facem(1:nfcts)*facT(1:nfcts,1)**4
            varsEB(:,4) = fachfi(1:nfcts)
            varsEB(:,5) = facefi(1:nfcts)
            varsEB(:,6) = facwsoil(1:nfcts)
            ! add longwave out
            call writestat_nc(ncidEB,1,tncstatEB,(/timee/),nrecEB,.true.)
            call writestat_1D_nc(ncidEB,nstatEB,ncstatEB,varsEB,nrecEB,nfcts)
            deallocate(varsEB)

          end if !myid
        end if

        tEB = timee !set time of last calculation of energy balance to current time
        tnextEB = NINT((timee + dtEB))*1.0  !rounded to nearest integer  (e.g. if current time is 10.013s and dtEb=10s, then the next energy balance will be calculated at t>=20s)
        !write (*, *) "time, time next EB", timee, tnextEB

        do n = 1, nfcts
          fachfi(n) = 0.
          facefi(n) = 0.
        end do
      end if !myid==0

      !write (*, *) "bcasting facT"
      call MPI_BCAST(facT(0:nfcts, 1:nfaclyrs+1), (nfaclyrs+1)*(nfcts + 1), MY_REAL, 0, comm3d, mpierr)
      call MPI_BCAST(tnextEB, 1, MY_REAL, 0, comm3d, mpierr)
      call MPI_BCAST(facqsat(0:nfcts), nfcts + 1, MY_REAL, 0, comm3d, mpierr)
      call MPI_BCAST(facf(0:nfcts, 1:5), (nfcts + 1)*5, MY_REAL, 0, comm3d, mpierr)
      call MPI_BCAST(fachurel(0:nfcts), nfcts + 1, MY_REAL, 0, comm3d, mpierr)
      !call MPI_BCAST(facwsoil(0:nfcts), nfcts + 1, MY_REAL, 0, comm3d, mpierr)
    end if !time>tnextEB

  end subroutine EB