Scheduled Downtime
On Tuesday 24 October 2023 @ 5pm MT the forums will be in read only mode in preparation for the downtime. On Wednesday 25 October 2023 @ 5am MT, this website will be down for maintenance and expected to return online later in the morning.
Normal Operations
The forums are back online with normal operations. If you notice any issues or errors related to the forums, please reach out to help@ucar.edu

Questions on physics_buffer

Dear all:

In CAM5, there are a lot of physics buffers in modle physics. These buffers are added by pbuf_add('xxx'.....)

Since they can only be inquired by pointers, so how are they initiated?

Is there a uniform initialization of phys_buf that are added? Or they are initiated respectively in different schemes?
 

eaton

CSEG and Liaisons
The default initialization of the physics buffer (pbuf) fields is to set
them to the nan value accessed from the infnan module (this is done in the
pbuf_allocate subroutine in phys_buffer.F90).

Below is sample code that illustrates the basics of how physics buffer
fields are set. The sample shows how to initialize a pbuf field, although
this is unnecessary if the parameterization that sets the values is called
before any parameterization that accesses the values.



Code:
module mod1

use shr_kind_mod,  only: r8=>shr_kind_r8
use ppgrid,        only: pcols, pver, begchunk, endchunk
use phys_buffer,   only: pbuf_add, pbuf_fld
use physics_types, only: physics_state, physics_ptend
use time_manager,  only: is_first_step

implicit none
private
save

public :: mod1_register, mod1_init, mod1_tend

integer :: fld1_idx   ! save the index into the pbuf

contains

subroutine mod1_register

   ! Add 3D pbuf field with global scope.  This field will
   ! persist across timesteps, and automatically be written
   ! to the restart file.
   
   call pbuf_add('FLD1', 'global', 1, pver, 1, fld1_idx)

end subroutine mod1_register

subroutine mod1_init(pbuf)

   ! Example of initializing a field in the physics buffer.  Note that this
   ! is not necessary if the 'run' subroutine which computes the field values
   ! is called before any other subroutines which need to access the values.
   !
   ! Note that init routines are called outside the loop over chunks (the
   ! data structure used by the physics grid decompostion), and so all the
   ! chunks, begchunk:endchunk, need to be dealt with.

   type(pbuf_fld) :: pbuf(:)

   real(r8), pointer :: fld1(:,:,:)  ! all the chunks

   ! associate the pointer with the physics buffer field
   fld1 => pbuf(fld1_idx)%fld_ptr(1,1:pcols,1:pver,begchunk:endchunk,1)

   ! Initialize field values 
   ! Note -- init subroutines are typically called on the first step of a
   !         restart as well as during the first step of an initial run.
   !         For 'global' fields, to avoid having the values that are
   !         restored from the restart file from being overwritten, an
   !         initialization done in an init method needs to happen inside
   !         an is_first_step conditional.

   if (is_first_step) then
      fld1 = 0._r8
   end if

   ......

end subroutine mod1_init

subroutine mod1_tend(state, ptend, pbuf)

   ! Example of setting a field in the physics buffer.
   !
   ! Note that 'tend' routines are called inside the loop over chunks (the
   ! data structure used by the physics grid decompostion), and so only
   ! the chunk corresponding to the state variables, state%lchnk, is set.

   type(physics_state), intent(in)  :: state   ! State variables
   type(physics_ptend), intent(out) :: ptend   ! physics tendencies
   type(pbuf_fld)                   :: pbuf(:)

   real(r8), pointer :: fld1(:,:)  ! just one chunk
   integer :: i, k, lchnk, ncol

   lchnk = state%lchnk
   ncol  = state%ncol    ! number of active columns in this chunk

   ! associate the pointer with the physics buffer field
   fld1 => pbuf(fld1_idx)%fld_ptr(1,1:pcols,1:pver,lchnk,1)

   ! set the field
   do k = 1, plev
      do i = 1, ncol
         fld1(i,k) = ...
      end do
   end do

   ......

end subroutine mod1_tend

end module mod1
 
cesm1_2_2I am running pure mpi, state_save and tend_save are defined at the module levelthen in one routine I have:nstep = get_nstep()
write(0, *) 'crm_save_state_tend: nstep: ', nstep
if(is_first_step())then
write(0, *) 'crm_save_state_tend: allocating tend_save'
call physics_tend_alloc(tend_save, pcols)
end if
call physics_tend_init(tend_save)
tend_save = tend

The output is:crm_save_state_tend: nstep: 0
crm_save_state_tend: allocating tend_save
(shr_sys_abort) ERROR: physics_tend_alloc error: allocation error for tend%dtdt I am suspecting the problem is when the second time it passes by to do another chunck of grid (and it still is the first step)it complains that tend_save is already allocated ...  
 

eaton

CSEG and Liaisons
In the physics_types module there are subroutines physics_state_copy and physics_ptend_copy to make local copies of state and ptend objects.You probably want to be working with a physics_ptend object and not a physics_tend object.  The ptend objects are what the individual parameterizations return to the driver layer.  The tend objects are updated with the information from a ptend object by physics_update.  There is no physics_tend_copy subroutine because we've not yet come across a need for one. 
 
Hello:Thanks for the answer.1, How about the subroutines named: pbuf_add_field, pbuf_get_field ?It seems both two are used in a easy way in crm_physics.f90 (SPCAM) as following: call pbuf_add_field('CRM_U',     'global', dtype_r8, (/pcols,crm_nx, crm_ny, crm_nz/),                crm_u_idx)
call pbuf_get_field (pbuf, crm_u_idx,         crm_u).It seems these variables are not assigned to all the chunks but still working.2, And whats the different between "global" and "physpkg"? Is there any limitation about the size of fields put into the physics puffer?
 
Top