Skip to content
Snippets Groups Projects
Forked from Méso-NH / Méso-NH code
2806 commits behind the upstream repository.
budget.f90 10.90 KiB
!MNH_LIC Copyright 1994-2020 CNRS, Meteo-France and Universite Paul Sabatier
!MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence
!MNH_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
!MNH_LIC for details. version 1.
!-----------------------------------------------------------------
! Modifications
!  P. Wautelet 28/01/2020: new subroutines: Budget_store_init, Budget_store_end and Budget_source_id_find in new module mode_budget
!  P. Wautelet 17/08/2020: treat LES budgets correctly
!-----------------------------------------------------------------

!#################
module mode_budget
!#################

use modd_budget, only: cbutype, nbutime, tbudgetdata

use modi_cart_compress, only: Cart_compress
use modi_mask_compress, only: Mask_compress

use mode_msg

implicit none

private

public :: Budget_store_init
public :: Budget_store_end
public :: Budget_store_add


contains

subroutine Budget_store_init( tpbudget, hsource, pvars )
  use modd_les, only: lles_call

  type(tbudgetdata),      intent(inout) :: tpbudget ! Budget datastructure
  character(len=*),       intent(in)    :: hsource  ! Name of the source term
  real, dimension(:,:,:), intent(in)    :: pvars    ! Current value to be stored

  integer :: iid ! Reference number of the current source term

  call Print_msg( NVERB_DEBUG, 'BUD', 'Budget_store_init', trim( tpbudget%cname )//':'//trim( hsource ) )

  if ( lles_call ) then
    if ( allocated( tpbudget%xtmplesstore ) ) then
      call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_init', 'xtmplesstore already allocated' )
    else
      allocate( tpbudget%xtmplesstore( Size( pvars, 1 ), Size( pvars, 2 ), Size ( pvars, 3 )  ) )
    end if
    tpbudget%xtmplesstore(:, :, :) = pvars(:, :, :)

    tpbudget%clessource = hsource
  end if

  ! Nothing else to do if budgets are not enabled
  if ( .not. tpbudget%lenabled ) return

  call Budget_source_id_find( tpbudget, hsource, iid )

  if ( tpbudget%ntmpstoresource /= 0 ) then
    call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_init', 'ntmpstoresource already set (previous call to ' &
                    //'Budget_store_end missing?) for '//trim( tpbudget%cname )//':'//trim( hsource ) )
  end if

  if ( tpbudget%tsources(iid)%ldonotinit ) then
    ! If ldonotinit is set, this subroutine should not be called
    call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_init', 'should not be called for ' &
                    //trim( tpbudget%cname )//':'//trim( hsource ) )
    return
  end if

  if ( tpbudget%tsources(iid)%lenabled ) then
    if ( tpbudget%ntmpstoresource /= 0 ) then
      call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_init', 'xtmpstore already used by ' &
                      //trim( tpbudget%tsources(tpbudget%ntmpstoresource)%cmnhname ) )
      return
    end if

    tpbudget%ntmpstoresource = iid

    !Store data into the budget temporary array
    !This value will be subtracted from the next one (in Budget_store_end) to get the evolution of the array between the 2 calls
    if ( cbutype == 'CART' ) then
      tpbudget%xtmpstore(:, :, :) = Cart_compress( pvars(:, :, :) )
    else if ( cbutype == 'MASK' ) then
      tpbudget%xtmpstore(:, nbutime, :) = Mask_compress( pvars(:, :, :) )
    else
      call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_init', 'unknown cbutype: '//trim( cbutype ) )
    end if
  end if

end subroutine Budget_store_init


subroutine Budget_store_end( tpbudget, hsource, pvars )
  use modd_les, only: lles_call

  use modi_les_budget, only: Les_budget

  type(tbudgetdata),      intent(inout) :: tpbudget ! Budget datastructure
  character(len=*),       intent(in) :: hsource     ! Name of the source term
  real, dimension(:,:,:), intent(in) :: pvars       ! Current value to be stored

  integer :: iid    ! Reference number of the current source term
  integer :: igroup ! Number of the group where to store the source term
  real, dimension(:,:,:), allocatable :: zvars_add

  call Print_msg( NVERB_DEBUG, 'BUD', 'Budget_store_end', trim( tpbudget%cname )//':'//trim( hsource ) )

  if ( lles_call ) then
    if ( hsource /= tpbudget%clessource ) &
      call Print_msg( NVERB_FATAL, 'BUD', 'Budget_store_end', 'hsource not the same as in Budget_store_init (' &
                      // Trim( hsource ) // ' / ' // Trim( tpbudget%clessource ) // ')' )

    tpbudget%clessource = 'reset'

    if ( allocated( tpbudget%xtmplesstore ) ) then
      ! Do the call to Les_budget with oadd=.true.
      ! This is necessary when the call to Budget_store_init was done with pvars not strictly
      ! equal to the source term
      Allocate( zvars_add( Size( pvars, 1 ), Size( pvars, 2 ), Size ( pvars, 3 ) ) )
      zvars_add(:, :, :) = pvars(:, :, :) - tpbudget%xtmplesstore(:, :, :)
      call Les_budget( zvars_add, tpbudget%nid, hsource, oadd = .true. )
      Deallocate( zvars_add )
      Deallocate( tpbudget%xtmplesstore )
    else
      call Les_budget( pvars, tpbudget%nid, hsource, oadd = .false. )
    end if
  end if

  ! Nothing to do if budgets are not enabled
  if ( .not. tpbudget%lenabled ) return

  call Budget_source_id_find( tpbudget, hsource, iid )

  if ( tpbudget%tsources(iid)%lenabled ) then
    if ( iid /= tpbudget%ntmpstoresource .and. .not.tpbudget%tsources(iid)%ldonotinit ) then
      if ( tpbudget%ntmpstoresource == 0 ) then
        call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_end', 'ntmpstoresource not set for ' &
                        //trim( tpbudget%tsources(iid)%cmnhname ) )
      else
        call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_end', 'xtmpstore used by an other source: '    &
                        //trim( tpbudget%tsources(tpbudget%ntmpstoresource)%cmnhname )//', expected: '   &
                        //trim( tpbudget%tsources(iid)%cmnhname ) )
      end if
    end if

    !Store data into the budget array
    !The values are computed by the difference between the values stored in the temporary array (filled in Budget_store_init)
    !and the current values added to the already stored ones.
    !Except if ldonotinit is true. In that case, overwrite the array.
    igroup = tpbudget%tsources(iid)%ngroup
    if ( cbutype == 'CART' ) then
      if ( tpbudget%tsources(iid)%ldonotinit ) then
        if ( tpbudget%tsources(iid)%loverwrite ) then
          tpbudget%tgroups(igroup)%xdata(:, :, :) =   Cart_compress( pvars(:, :, :) )
        else
          tpbudget%tgroups(igroup)%xdata(:, :, :) =   tpbudget%tgroups(igroup)%xdata(:, :, :) &
                                                    + Cart_compress( pvars(:, :, :) )
        end if
      else
        if ( tpbudget%tsources(iid)%loverwrite ) then
          tpbudget%tgroups(igroup)%xdata(:, :, :) =   Cart_compress( pvars(:, :, :) )          &
                                                    - tpbudget%xtmpstore(:, :, :)
        else
          tpbudget%tgroups(igroup)%xdata(:, :, :) =   tpbudget%tgroups(igroup)%xdata(:, :, :) &
                                                     + Cart_compress( pvars(:, :, :) )          &
                                                     - tpbudget%xtmpstore(:, :, :)
        end if
      end if
    else if ( cbutype == 'MASK' ) then
      if ( tpbudget%tsources(iid)%ldonotinit ) then
        if ( tpbudget%tsources(iid)%loverwrite ) then
          tpbudget%tgroups(igroup)%xdata(:, nbutime, :) =   Mask_compress( pvars(:, :, :) )
        else
          tpbudget%tgroups(igroup)%xdata(:, nbutime, :) =   tpbudget%tgroups(igroup)%xdata(:, nbutime, :) &
                                                           + Mask_compress( pvars(:, :, :) )
        end if
      else
        if ( tpbudget%tsources(iid)%loverwrite ) then
          tpbudget%tgroups(igroup)%xdata(:, nbutime, :) =   Mask_compress( pvars(:, :, :) )   &
                                                          - tpbudget%xtmpstore(:, nbutime, :)
        else
          tpbudget%tgroups(igroup)%xdata(:, nbutime, :) =   tpbudget%tgroups(igroup)%xdata(:, nbutime, :) &
                                                          + Mask_compress( pvars(:, :, :) )                &
                                                          - tpbudget%xtmpstore(:, nbutime, :)
        end if
      end if
    else
      call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_end', 'unknown cbutype: '//trim( cbutype ) )
    end if

    ! Release the budget temporary array
    tpbudget%ntmpstoresource = 0
  end if

end subroutine Budget_store_end


subroutine Budget_store_add( tpbudget, hsource, pvars )
  use modd_les, only: lles_call

  use modi_les_budget, only: Les_budget

  type(tbudgetdata),      intent(inout) :: tpbudget ! Budget datastructure
  character(len=*),       intent(in) :: hsource     ! Name of the source term
  real, dimension(:,:,:), intent(in) :: pvars       ! Current value to be stored

  integer :: iid    ! Reference number of the current source term
  integer :: igroup ! Number of the group where to store the source term

  call Print_msg( NVERB_DEBUG, 'BUD', 'Budget_store_add', trim( tpbudget%cname )//':'//trim( hsource ) )

  if ( lles_call ) call Les_budget( pvars, tpbudget%nid, hsource, oadd = .true. )

  ! Nothing to do if budgets are not enabled
  if ( .not. tpbudget%lenabled ) return

  call Budget_source_id_find( tpbudget, hsource, iid )

  if ( tpbudget%tsources(iid)%lenabled ) then
    if ( tpbudget%tsources(iid)%loverwrite ) &
      call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_add', 'loverwrite=.true. is not allowed' )

    !Store data into the budget array
    igroup = tpbudget%tsources(iid)%ngroup
    if ( cbutype == 'CART' ) then
      tpbudget%tgroups(igroup)%xdata(:, :, :) =   tpbudget%tgroups(igroup)%xdata(:, :, :) &
                                                + Cart_compress( pvars(:, :, :) )
    else if ( cbutype == 'MASK' ) then
      tpbudget%tgroups(igroup)%xdata(:, nbutime, :) =   tpbudget%tgroups(igroup)%xdata(:, nbutime, :) &
                                                      + Mask_compress( pvars(:, :, :) )
    else
      call Print_msg( NVERB_ERROR, 'BUD', 'Budget_store_add', 'unknown cbutype: '//trim( cbutype ) )
    end if
  end if

end subroutine Budget_store_add


subroutine Budget_source_id_find( tpbudget, hsource, kid )
  type(tbudgetdata), intent(in)  :: tpbudget ! Budget datastructure
  character(len=*),  intent(in)  :: hsource  ! Name of the source term
  integer,           intent(out) :: kid      ! Reference number of the current source term

  integer :: iid
  integer :: ji

  call Print_msg( NVERB_DEBUG, 'BUD', 'Budget_source_id_find', trim( tpbudget%cname )//':'//trim( hsource ) )

  iid = 0
  do ji = 1, tpbudget%nsources
    if ( trim( hsource ) == trim( tpbudget%tsources(ji)%cmnhname ) ) then
      iid = ji
      exit
    end if
  end do

  if ( iid > 0 ) then
    call Print_msg( NVERB_DEBUG, 'BUD', 'Budget_source_id_find', trim( tpbudget%cname )//':'//trim( hsource )//' found' )
  else
    call Print_msg( NVERB_ERROR, 'BUD', 'Budget_source_id_find', trim( tpbudget%cname )//':'//trim( hsource )//' not found' )
  end if

  kid = iid
end subroutine Budget_source_id_find

end module mode_budget