!------------------------------------------------------------------------------ ! ! MODULE: Model (for GFS/NAM/RAP model) ! ! DESCRIPTION: !> Read in model data, convert to pressure levels for RAP and derive fields !> Write icing products ! ! REVISION HISTORY: ! September 2010, modified November 2011 ! March 2014 - modified ! !------------------------------------------------------------------------------ module Model use Kinds use Config use Grib1 use Grib2 use Hybrid2Pressure ! For RAP use Derived_Fields IMPLICIT NONE private public runModel, writeIcing !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! Parameters !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! integer, parameter :: INTERPOLATION_TYPE = 1 ! RAP only !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! private members (configration related) !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! character(len=3) :: CFG_CMODEl ! RAP/NAM/GFS integer :: CFG_GRIB ! 1/2, input model file in grib 1 or 2 integer :: CFG_NUM_HYBRID != 50 ! RAP only integer :: CFG_NUM_PRESSURE != 37 real :: CFG_MAX_PRESSURE != 1000.0 ! in hPa real :: CFG_PRESSURE_STEP != -25.0 ! in hPa contains !------------------------------------------------------------------------------ ! DESCRIPTION: !> Read in all model fields (dispatching to grib 1 or 2), !> convert to pressure levels for RAP and derive fields ! !> @param[in] filename - input model file !> @param[in] cfg - configurations !> @param[out] kpds - model PDS ! for Grib1 !> @param[out] kgds - model GDS ! for Grib1, Grib2 !> @param[out] gfld - model gfld ! for Grib2 !> @param[out] modelData - type of model_inputs_t, including derived fields !> @param[out] iret - status (0 is successful) ! !------------------------------------------------------------------------------ subroutine runModel(filename, cfg, kpds, kgds, gfld, modelData, iret) IMPLICIT NONE character(len=*), intent(in):: filename type(config_t), intent(in) :: cfg integer, intent(out) :: kpds(:) ! for Grib1 integer, intent(out) :: kgds(:) ! for Grib1, Grib2 type(gribfield), intent(out) :: gfld ! for Grib2 type(model_inputs_t), intent(out) :: modelData integer, intent(out) :: iret integer :: nx, ny, nz integer :: np, k real, allocatable :: pressures(:) integer, allocatable :: pds7(:) ! vertical information type(model_fields3D_t) :: fields ! For RAP 3D fields, they will go through Hybrid2Pressure, ! So temporary variable is needed. type(model_fields3D_t) :: fields_H ! for RAP character(len=*), parameter :: myself = "Model::runModel() " ! configuration fields CFG_CMODEL = cfg% model% name CFG_GRIB = cfg% model% grib CFG_NUM_HYBRID = cfg% levels% num_hybrid CFG_NUM_PRESSURE = cfg% levels% num_pressure CFG_MAX_PRESSURE = cfg% levels% max_pressure CFG_PRESSURE_STEP = cfg% levels% pressure_step iret = -1 np = CFG_NUM_PRESSURE select case(CFG_CMODEL) case('RAP') nz = CFG_NUM_HYBRID allocate(pds7(nz)) do k = 1, nz pds7(k) = k end do !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! read in RAP data. 3D data in fields3D_H, 2D data in modelData !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! if(CFG_GRIB == 1) then call readModelGB1(filename,CFG_CMODEL,pds7,fields_H,modelData,kpds,kgds,iret) else if(CFG_GRIB == 2) then call readModelGB2(filename,CFG_CMODEL,pds7,fields_H,modelData,gfld,kgds,iret) end if nx = kgds(2) ny = kgds(3) if(iret /= 0) then write(*,*) myself, "unable to read in ", CFG_cmodel, " grib file" return end if !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! hybrid level => pressure level !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! allocate(pressures(np)) do k = 1, np pressures(k) = CFG_MAX_PRESSURE + (k-1) * CFG_PRESSURE_STEP pressures(k) = pressures(k) * 100 ! from millibar to pascal end do ! Pressure on Hybrid/Sigma level is needed for initialization. ! When initialization, pressure of pressure-level is set and ! memories of fields on pressure-level are allocated. call initHybrid2Pressure(nx, ny, nz, np, pressures, fields_H%p, fields) ! All fields need interpolation except for pressure. call processHybrid2Pressure(INTERPOLATION_TYPE, fields_H, fields, iret) if(iret /= 0) then write(*,*) myself, "unable to process Hybrid2Pressure" return end if deallocate(pressures) !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! release the memory of 3D fields on Hybrid levels !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! call m_doneModel(fields_H) ! change value of nz after Hybrid2Pressure nz = CFG_NUM_PRESSURE case('GFS', 'NAM', 'FV3') nz = CFG_NUM_PRESSURE allocate(pds7(nz)) ! in hPa do k = 1, nz pds7(k) = int(CFG_MAX_PRESSURE) + (k-1) * int(CFG_PRESSURE_STEP) end do !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! read in GFS/NAM data. 3D data in fields3D, 2D data in modelData. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! if(CFG_GRIB == 1) then call readModelGB1(filename,CFG_CMODEL,pds7,fields,modelData,kpds,kgds,iret) else if(CFG_GRIB == 2) then call readModelGB2(filename,CFG_CMODEL,pds7,fields,modelData,gfld,kgds,iret) end if nx = kgds(2) ny = kgds(3) if(iret /= 0) then write(*,*) myself, "unable to read in ", CFG_CMODEL, " grib file" return end if end select deallocate(pds7) !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! calculate derived fields for all models !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! call calculateDerived_Fields(nx, ny, nz, CFG_CMODEL, fields, modelData, iret) if(iret /= 0) then write(*,*) myself, "unable to derive fields" return end if !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! ! release the memory of native 3D model fields !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~! call m_doneModel(fields) return end subroutine runModel !------------------------------------------------------------------------------ ! DESCRIPTION: !> write out icing products interface, dispatch to output in grib 1 or grib 2 ! !> @param[in] filename - output file name !> @param[in] grib - 1/2, write out icing products in grib 1 or 2 !> @param[in] icingData - type of icing_output_t, including all icing products !> @param[out] iret - status (0 is successful) !> @param[in] kpds - PDS ! for Grib 1 !> @param[in] kgds - GDS ! for Grib 1 !> @param[in] gfld - gribfield ! for Grib 2 ! !------------------------------------------------------------------------------ subroutine writeIcing(filename, icingData, iret, kpds, kgds, gfld ) IMPLICIT NONE character(*), intent(in) :: filename type(icing_output_t), intent(in) :: icingData integer, intent(out) :: iret integer, intent(in), optional :: kpds(:), kgds(:) ! for Grib 1 type(gribfield), intent(in), optional :: gfld ! for Grib 2 if(present(kpds) .and. present(kgds)) then call writeIcingGB1(filename, kpds, kgds, icingData, iret) else if(present(gfld)) then call writeIcingGB2(filename, gfld, icingData, iret) end if return end subroutine writeIcing !------------------------------------------------------------------------------ ! DESCRIPTION: !> release the memory allocated for model native 3D input fields ! !> @param[in] fields - type of model_fields3D_t ! !------------------------------------------------------------------------------ subroutine m_doneModel(fields) type(model_fields3D_t), intent(inout) :: fields if(allocated(fields%p)) deallocate(fields%p) if(allocated(fields%h)) deallocate(fields%h) if(allocated(fields%pvv)) deallocate(fields%pvv) if(allocated(fields%cwm)) deallocate(fields%cwm) if(allocated(fields%t)) deallocate(fields%t) if(allocated(fields%wvm)) deallocate(fields%wvm) if(allocated(fields%rwm)) deallocate(fields%rwm) if(allocated(fields%snm)) deallocate(fields%snm) if(allocated(fields%icm)) deallocate(fields%icm) if(allocated(fields%gpm)) deallocate(fields%gpm) if(allocated(fields%rh)) deallocate(fields%rh) return end subroutine m_doneModel end module Model