module aqm_model_mod use aqm_rc_mod use aqm_types_mod use aqm_config_mod use aqm_domain_mod, only : aqm_domain_type use aqm_state_mod, only : aqm_state_type implicit none type aqm_model_type type(aqm_config_type), pointer :: config => null() type(aqm_domain_type) :: domain type(aqm_state_type) :: stateIn, stateOut end type aqm_model_type type(aqm_model_type), dimension(:), allocatable, target :: aqm_model private public :: aqm_model_type ! -- also provide subtypes public :: aqm_config_type public :: aqm_domain_type public :: aqm_state_type public :: aqm_model_create public :: aqm_model_destroy public :: aqm_model_get public :: aqm_model_set public :: aqm_model_config_create public :: aqm_model_domain_get public :: aqm_model_domain_set public :: aqm_model_domain_coord_set contains subroutine aqm_model_create(deCount, rc) integer, intent(in), optional :: deCount integer, intent(out), optional :: rc !-- local variables integer :: localDeCount, localrc !-- begin if (present(rc)) rc = AQM_RC_SUCCESS localDeCount = 1 if (present(deCount)) localDeCount = deCount ! -- AQM can only support up to 1 DE/PET if (localDeCount > 1) then call aqm_rc_set(AQM_RC_FAILURE, & msg="AQM only supports up to 1 DE/PET.", & file=__FILE__, line=__LINE__, rc=rc) return end if if (localDeCount > 0) then allocate(aqm_model(0:localDeCount-1), stat=localrc) if (aqm_rc_test((localrc /= 0), msg="Failure to create model", & file=__FILE__, line=__LINE__, rc=rc)) return end if end subroutine aqm_model_create subroutine aqm_model_destroy(rc) integer, intent(out), optional :: rc !-- local variables integer :: localrc integer :: de !-- begin if (present(rc)) rc = AQM_RC_SUCCESS if (allocated(aqm_model)) then do de = 1, size(aqm_model)-1 nullify(aqm_model(de) % config) end do de = 0 if (associated(aqm_model(de) % config)) then if (associated(aqm_model(de) % config % species)) then deallocate(aqm_model(de) % config % species, stat=localrc) if (aqm_rc_test((localrc /= 0), & msg="Failure to deallocate model species memory", & file=__FILE__, line=__LINE__, rc=rc)) return nullify(aqm_model(de) % config % species) end if deallocate(aqm_model(de) % config, stat=localrc) if (aqm_rc_test((localrc /= 0), & msg="Failure to deallocate model config memory", & file=__FILE__, line=__LINE__, rc=rc)) return nullify(aqm_model(de) % config) if (associated(aqm_model(de) % domain % lon)) then deallocate(aqm_model(de) % domain % lon, stat=localrc) if (aqm_rc_test((localrc /= 0), & msg="Failure to deallocate model domain longitudes memory", & file=__FILE__, line=__LINE__, rc=rc)) return nullify(aqm_model(de) % domain % lon) end if if (associated(aqm_model(de) % domain % lat)) then deallocate(aqm_model(de) % domain % lat, stat=localrc) if (aqm_rc_test((localrc /= 0), & msg="Failure to deallocate model domain latitudes memory", & file=__FILE__, line=__LINE__, rc=rc)) return nullify(aqm_model(de) % domain % lat) end if end if deallocate(aqm_model, stat=localrc) if (aqm_rc_test((localrc /= 0), msg="Failure to allocate model memory", & file=__FILE__, line=__LINE__, rc=rc)) return end if end subroutine aqm_model_destroy subroutine aqm_model_config_create(rc) integer, optional, intent(out) :: rc ! -- local variables integer :: localrc integer :: de, deCount type(aqm_model_type), pointer :: model ! -- begin if (present(rc)) rc = AQM_RC_SUCCESS ! -- NOTE: config is allocated only on DE 0 on each PET ! -- config points to DE 0 on other DEs on the same PET deCount = 0 call aqm_model_local_get(de=0, deCount=deCount, model=model, rc=localrc) if (aqm_rc_check(localrc, msg="Failure to retrieve model on local DE", & file=__FILE__, line=__LINE__, rc=rc)) return if (deCount > 0) then if (.not.associated(model % config)) then allocate(model % config, stat=localrc) if (aqm_rc_test((localrc /= 0), msg="Failure to allocate model configuration", & file=__FILE__, line=__LINE__, rc=rc)) return end if ! -- populate pointers on other local DEs do de = 1, deCount-1 call aqm_model_set(de=de, config=model % config, rc=localrc) if (aqm_rc_check(localrc, file=__FILE__, line=__LINE__, rc=rc)) return end do end if end subroutine aqm_model_config_create subroutine aqm_model_domain_set(minIndexPDe, maxIndexPDe, minIndexPTile, maxIndexPTile, & minIndexLocal, maxIndexLocal, tile, tileCount, de, rc) integer, dimension(2), optional, intent(in) :: minIndexPDe, maxIndexPDe integer, dimension(2), optional, intent(in) :: minIndexPTile, maxIndexPTile integer, dimension(2), optional, intent(in) :: minIndexLocal, maxIndexLocal integer, optional, intent(in) :: tile, tileCount integer, optional, intent(in) :: de integer, optional, intent(out) :: rc !-- local variables integer :: deCount, localrc type(aqm_model_type), pointer :: model !-- begin if (present(rc)) rc = AQM_RC_SUCCESS call aqm_model_local_get(de=de, deCount=deCount, model=model, rc=localrc) if (aqm_rc_check(localrc, msg="Failure to retrieve model", & file=__FILE__, line=__LINE__, rc=rc)) return if (deCount < 1) return model % domain % tile = 0 if (present(tile)) model % domain % tile = tile model % domain % tileCount = 0 if (present(tileCount)) model % domain % tileCount = tileCount if (present(minIndexPDe)) then model % domain % ids = minIndexPDe(1) model % domain % jds = minIndexPDe(2) end if if (present(maxIndexPDe)) then model % domain % ide = maxIndexPDe(1) model % domain % jde = maxIndexPDe(2) end if if (present(minIndexPTile)) then model % domain % its = minIndexPTile(1) model % domain % jts = minIndexPTile(2) end if if (present(maxIndexPTile)) then model % domain % ite = maxIndexPTile(1) model % domain % jte = maxIndexPTile(2) end if if (present(minIndexLocal)) then model % domain % ims = minIndexLocal(1) model % domain % jms = minIndexLocal(2) end if if (present(maxIndexLocal)) then model % domain % ime = maxIndexLocal(1) model % domain % jme = maxIndexLocal(2) end if end subroutine aqm_model_domain_set subroutine aqm_model_domain_coord_set(coordDim, coord, scale, de, rc) integer, intent(in) :: coordDim real(AQM_KIND_R8), intent(in) :: coord(:,:) real(AQM_KIND_R8), optional, intent(in) :: scale integer, optional, intent(in) :: de integer, optional, intent(out) :: rc !-- local variables integer :: deCount, localrc real(AQM_KIND_R8) :: fscale type(aqm_model_type), pointer :: model !-- begin if (present(rc)) rc = AQM_RC_SUCCESS call aqm_model_local_get(de=de, deCount=deCount, model=model, rc=localrc) if (aqm_rc_check(localrc, msg="Failure to retrieve model on local DE", & file=__FILE__, line=__LINE__, rc=rc)) return if (deCount < 1) return fscale = 1._AQM_KIND_R8 if (present(scale)) fscale = scale select case (coordDim) case(1) allocate(model % domain % lon, source=fscale * coord, stat=localrc) if (aqm_rc_test((localrc /= 0), & msg="Failure to allocate model config memory", & file=__FILE__, line=__LINE__, rc=rc)) return case(2) allocate(model % domain % lat, source=fscale * coord, stat=localrc) if (aqm_rc_test((localrc /= 0), & msg="Failure to allocate model config memory", & file=__FILE__, line=__LINE__, rc=rc)) return case default call aqm_rc_set(AQM_RC_FAILURE, & msg="coordDim can only be 1 or 2.", & file=__FILE__, line=__LINE__, rc=rc) return end select end subroutine aqm_model_domain_coord_set subroutine aqm_model_domain_get(de, & ids, ide, jds, jde, & its, ite, jts, jte, & ims, ime, jms, jme, & ni, nl, nt, tile, & lon, lat, rc) integer, optional, intent(in) :: de integer, optional, intent(out) :: ids, ide, jds, jde integer, optional, intent(out) :: its, ite, jts, jte integer, optional, intent(out) :: ims, ime, jms, jme integer, optional, intent(out) :: ni, nl, nt integer, optional, intent(out) :: tile real(AQM_KIND_R8), optional, pointer :: lon(:,:) real(AQM_KIND_R8), optional, pointer :: lat(:,:) integer, optional, intent(out) :: rc ! -- local variables integer :: localrc type(aqm_model_type), pointer :: model ! -- begin if (present(rc)) rc = AQM_RC_SUCCESS call aqm_model_local_get(de=de, model=model, rc=localrc) if (aqm_rc_check(localrc, msg="Failure to retrieve model on local DE", & file=__FILE__, line=__LINE__, rc=rc)) return if (present(ids)) ids = model % domain % ids if (present(ide)) ide = model % domain % ide if (present(jds)) jds = model % domain % jds if (present(jde)) jde = model % domain % jde if (present(its)) its = model % domain % its if (present(ite)) ite = model % domain % ite if (present(jts)) jts = model % domain % jts if (present(jte)) jte = model % domain % jte if (present(ims)) ims = model % domain % ims if (present(ime)) ime = model % domain % ime if (present(jms)) jms = model % domain % jms if (present(jme)) jme = model % domain % jme if (present(ni)) ni = model % domain % ni if (present(nl)) nl = model % domain % nl if (present(nt)) nt = model % domain % nt if (present(tile)) tile = model % domain % tile if (present(lon)) lon => model % domain % lon if (present(lat)) lat => model % domain % lat end subroutine aqm_model_domain_get subroutine aqm_model_set(de, numIntLayers, numModLayers, numSoilLayers, numTracers, & config, rc) integer, optional, intent(in) :: de integer, optional, intent(in) :: numIntLayers integer, optional, intent(in) :: numModLayers integer, optional, intent(in) :: numSoilLayers integer, optional, intent(in) :: numTracers type(aqm_config_type), optional, pointer :: config integer, optional, intent(out) :: rc ! -- local variables integer :: deCount, localrc type(aqm_model_type), pointer :: model ! -- begin if (present(rc)) rc = AQM_RC_SUCCESS call aqm_model_local_get(de=de, deCount=deCount, model=model, rc=localrc) if (aqm_rc_check(localrc, msg="Failure to retrieve model on local DE", & file=__FILE__, line=__LINE__, rc=rc)) return if (deCount > 0) then if (present(numIntLayers)) model % domain % ni = numIntLayers if (present(numModLayers)) model % domain % nl = numModLayers if (present(numSoilLayers)) model % domain % ns = numSoilLayers if (present(numTracers)) model % domain % nt = numTracers if (present(config)) model % config => config end if end subroutine aqm_model_set subroutine aqm_model_get(de, deCount, stateIn, stateOut, config, & domain, tile, tileCount, rc) integer, optional, intent(in) :: de integer, optional, intent(out) :: deCount type(aqm_state_type), optional, pointer :: stateIn, stateOut type(aqm_config_type), optional, pointer :: config type(aqm_domain_type), optional, pointer :: domain integer, optional, intent(out) :: tile integer, optional, intent(out) :: tileCount integer, optional, intent(out) :: rc !-- local variables integer :: localrc, localDeCount type(aqm_model_type), pointer :: model ! -- begin if (present(rc)) rc = AQM_RC_SUCCESS localDeCount = 0 call aqm_model_local_get(de=de, deCount=localDeCount, model=model, rc=localrc) if (aqm_rc_check(localrc, msg="Failure to retrieve model on local DE", & file=__FILE__, line=__LINE__, rc=rc)) return if (present(deCount)) deCount = localDeCount if (localDeCount > 0) then if (present(stateIn)) stateIn => model % stateIn if (present(stateOut)) stateOut => model % stateOut if (present(config)) config => model % config if (present(domain)) domain => model % domain if (present(tile)) tile = model % domain % tile if (present(tileCount)) tileCount = model % domain % tileCount end if end subroutine aqm_model_get subroutine aqm_model_local_get(de, deCount, model, rc) integer, optional, intent(in) :: de integer, optional, intent(out) :: deCount type(aqm_model_type), optional, pointer :: model integer, optional, intent(out) :: rc !-- local variables integer :: localDe !-- begin if (present(rc)) rc = AQM_RC_SUCCESS if (present(model)) nullify(model) localDe = 0 if (present(de)) localDe = de if (aqm_rc_test((localDe < 0), & msg="DE must be >= 0", & file=__FILE__, line=__LINE__, rc=rc)) return if (allocated(aqm_model)) then if (present(deCount)) deCount = size(aqm_model) if (present(model)) then if (localDe <= ubound(aqm_model, dim=1)) then model => aqm_model(localDe) else call aqm_rc_set(AQM_RC_FAILURE, msg="Model undefined on local DE", & file=__FILE__, line=__LINE__, rc=rc) return end if end if else if (present(deCount)) deCount = 0 end if end subroutine aqm_model_local_get end module aqm_model_mod