#include "./ESMFVersionDefine.h" #ifdef WITH_NUOPC module module_MEDIATOR !----------------------------------------------------------------------------- ! NEMS Mediator Component. ! ! The Mediator has two Run() phases: ! ! * Run(phase=1) covers the more frequent interaction with the ATM ! component. The ATM exports some fields as time averages over the ! integration period. Other fields are exported as instantaneous. For ! the time averaged fields the Mediator is responsible to continue ! the averaging. ! ! * Run(phase=2) is invoked for the less frequent interaction with the OCN ! component. Here the averaged and instantanous ATM fields are passed on ! to the OCN component, and OCN export fields are received by the ! Mediator and forwarded to the ATM component. ! ! The two phases are operating on different time scales, and hence require ! two separate internal Component Clocks. The NUOPC layer accesses a ! Component's Clock through the ESMF CompGet() interface, regardless of the ! phase. Phase specific Clocks are implemented by swapping Clocks during the ! phase specific "label_SetRunClock" specialization method. These Clock ! objects are stored in the Component instance's own internal state. ! ! Current implementation (March 2014) assumes the atm and ice are running ! at the same coupling period which is shorter than the ocean coupling period. ! Accumulation of atm and ice fields are done for the ocean model. No ! accumulation is done for the atm or ice models from any model. The ! atm, ice, and ocean pass their latest data directly to the atm and ice models. !----------------------------------------------------------------------------- use ESMF use NUOPC use NUOPC_Mediator, & mediator_routine_SS => routine_SetServices, & mediator_routine_Run => routine_Run, & mediator_type_IS => type_InternalState, & mediator_label_IS => label_InternalState, & mediator_label_DataInitialize => label_DataInitialize, & mediator_label_Advance => label_Advance, & mediator_label_CheckImport => label_CheckImport, & mediator_label_TimestampExport => label_TimestampExport, & mediator_label_SetRunClock => label_SetRunClock implicit none private ! private internal state to keep instance data type InternalStateStruct type(ESMF_Clock) :: clockAtm ! clock for atm type(ESMF_Clock) :: clockOcn ! clock for ocn type(ESMF_Clock) :: clockIce ! clock for ice integer :: fastcntr ! slice counter for writing to NetCDF file integer :: slowcntr ! slice counter for writing to NetCDF file integer :: accumcntAtm ! accumulator counter integer :: accumcntOcn ! accumulator counter integer :: accumcntIce ! accumulator counter type(ESMF_FieldBundle):: FBaccumAtm ! accumulator of atm export data type(ESMF_FieldBundle):: FBaccumOcn ! accumulator of ocn export data type(ESMF_FieldBundle):: FBaccumIce ! accumulator of ice export data type(ESMF_FieldBundle):: FBforOcn ! data storage for ocn import type(ESMF_FieldBundle):: FBforAtm ! data storage for atm import type(ESMF_FieldBundle):: FBforIce ! data storage for ice import type(ESMF_RouteHandle):: rh !gjt: temporary solution ! tcx Xgrid ! type(ESMF_RouteHandle):: RHa2x ! atm to xgrid RH ! type(ESMF_RouteHandle):: RHo2x ! ocn to xgrid RH ! type(ESMF_RouteHandle):: RHx2a ! xgrid to atm RH ! type(ESMF_RouteHandle):: RHx2o ! xgrid to ocn RH end type type InternalState type(InternalStateStruct), pointer :: wrap end type interface fieldBundle_accum ; module procedure & fieldBundle_accumFB2FB, & fieldBundle_accumFB2ST, & fieldBundle_accumST2FB end interface interface fieldBundle_copy ; module procedure & fieldBundle_copyFB2FB, & fieldBundle_copyFB2ST, & fieldBundle_copyST2FB end interface ! tcraig some temporary debug variables integer, parameter :: nx_atm=400, ny_atm=200 integer, parameter :: nx_ocn=400, ny_ocn=200 integer, parameter :: nx_ice=400, ny_ice=200 integer, parameter :: dbug_flag = 5 integer :: dbrc character(len=256) :: tmpstr real(ESMF_KIND_R8), parameter :: const_lhvap = 2.501e6_ESMF_KIND_R8 ! latent heat of evaporation ~ J/kg integer, parameter :: med_phase_max = 3 !--- These also appear in module_EARTH_GENERIC_COMP.F90 integer, parameter :: medPhase_slow = 1 integer, parameter :: medPhase_fast_before = 2 integer, parameter :: medPhase_fast_after = 3 type fld_list_type integer :: num = -1 character(len=64), pointer :: stdname(:) character(len=64), pointer :: shortname(:) character(len=64), pointer :: longname(:) character(len=64), pointer :: units(:) character(len=64), pointer :: transferOffer(:) end type fld_list_type type (fld_list_type) :: fldsToAtm type (fld_list_type) :: fldsFrAtm type (fld_list_type) :: fldsToOcn type (fld_list_type) :: fldsFrOcn type (fld_list_type) :: fldsToIce type (fld_list_type) :: fldsFrIce public SetServices !----------------------------------------------------------------------------- contains !----------------------------------------------------------------------------- subroutine SetServices(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! local variables integer :: nphase character(len=*),parameter :: subname='(module_MEDIATOR:SetServices)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! the NUOPC mediator component will register the generic methods call NUOPC_CompDerive(gcomp, mediator_routine_SS, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Provide InitP0 to overwrite the default IPD00 call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & InitializeP0, phase=0, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! InitP1, where Fields should be advertised call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & userRoutine=InitializeP1, phase=1, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! InitP2, where Fields should be realized, call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & userRoutine=InitializeP2, phase=2, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! InitP6, where ... call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & userRoutine=InitializeP6, phase=6, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! InitP7, where ... call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_INITIALIZE, & userRoutine=InitializeP7, phase=7, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! attach specializing method(s) call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_DataInitialize, & specRoutine=DataInitialize, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out do nphase = 2,med_phase_max call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_RUN, & userRoutine=mediator_routine_Run, phase=nphase, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo ! overwrite Finalize call ESMF_GridCompSetEntryPoint(gcomp, ESMF_METHOD_FINALIZE, & userRoutine=Finalize, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! attach specializing methods for Run ( phase = slow) "ocn" call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_SetRunClock, & specIndex=MedPhase_slow, specRoutine=SetRunClock_ocn, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_Advance, & specIndex=MedPhase_slow, specRoutine=Advance_slow, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! attach specializing methods for Run( phase = fast_before ) call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_SetRunClock, & specIndex=MedPhase_fast_before, specRoutine=SetRunClock_atm_before, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_CheckImport, & specIndex=MedPhase_fast_before, specRoutine=CheckImport_atm_before, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_TimestampExport, & specIndex=MedPhase_fast_before, specRoutine=TimestampExport_atm_before, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_Advance, & specIndex=MedPhase_fast_before, specRoutine=Advance_fast_before, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! attach specializing methods for Run( phase = fast_after ) call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_SetRunClock, & specIndex=MedPhase_fast_after, specRoutine=SetRunClock_atm_after, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_CheckImport, & specIndex=MedPhase_fast_after, specRoutine=CheckImport_atm_after, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_TimestampExport, & specIndex=MedPhase_fast_after, specRoutine=TimestampExport_atm_after, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_CompSpecialize(gcomp, specLabel=mediator_label_Advance, & specIndex=MedPhase_fast_after, specRoutine=Advance_fast_after, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out #if (1 == 0) !----- Ocn-Atm call fld_list_add(fldsFrOcn,"sea_surface_temperature", "sst", "sea surface temperature on t-cell","K", "will provide") call fld_list_add(fldsToAtm,"sea_surface_temperature", "sst", "sea surface temperature on t-cell","K", "will provide") !----- Atm-Ocn, Atm-Ice ! shortwave call fld_list_add(fldsFrAtm,"mean_down_sw_ir_dir_flx" , "sw_flux_nir_dir" , "Mean infrared direct downward shortwave flux" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_ir_dif_flx" , "sw_flux_nir_dif" , "Mean infrared diffuse downward shortwave flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_vis_dir_flx", "sw_flux_vis_dir" , "Mean visible direct downward shortwave flux" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_vis_dif_flx", "sw_flux_vis_dif" , "Mean visible diffuse downward shortwave flux" , "W m-2", "will provide") ! other heat fluxes call fld_list_add(fldsFrAtm,"mean_down_lw_flx" , "mdlwfx" , "Mean Downward Long Wave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_down_lw_flx" , "mdlwfx" , "Mean Downward Long Wave Radiation Flux", "W m-2", "will provide") ! water call fld_list_add(fldsFrAtm,"mean_prec_rate" , "lprec" , "Mean Liquid Precipitation Rate", "kg/m^2/s", "will provide") call fld_list_add(fldsFrAtm,"mean_fprec_rate" , "fprec" , "Mean Frozen Precipitation Rate", "kg/m^2/s", "will provide") call fld_list_add(fldsToOcn,"mean_prec_rate" , "lprec" , "Mean Liquid Precipitation Rate", "kg/m^2/s", "will provide") ! call fld_list_add(fldsToOcn,"mean_fprec_rate" , "fprec" , "Mean Frozen Precipitation Rate", "kg/m^2/s", "will provide") ! states call fld_list_add(fldsFrAtm,"inst_pres_height_surface", "ips" , "Pressure at surface defined by inst_surface_height","Pa", "will provide") call fld_list_add(fldsToOcn,"inst_pres_height_surface", "ips" , "Pressure at surface defined by inst_surface_height","Pa", "will provide") call fld_list_add(fldsFrAtm,"inst_spec_humid_height2m", "ishh2m" , "Instantaneous Specific Humidity 2m Above Ground","kg kg-1", "will provide") call fld_list_add(fldsToOcn,"mean_laten_heat_flx" , "mlhfx" , "Mean Latent Heat Flux" ,"W m-2" , "will provide") call fld_list_add(fldsToOcn,"mean_evap_rate" , "mevap" , "Mean Evaporation Rate" ,"kg m-2 s-1" , "will provide") !----- Ice-Atm ! momentum stress call fld_list_add(fldsFrIce,"stress_on_air_ice_zonal", "strairxT", "stress on air by ice x component", "N m-2", "will provide") call fld_list_add(fldsFrIce,"stress_on_air_ice_merid", "strairyT", "stress on air by ice y component", "N m-2", "will provide") call fld_list_add(fldsToAtm,"stress_on_air_ice_zonal", "strairxT", "stress on air by ice x component", "N m-2", "will provide") call fld_list_add(fldsToAtm,"stress_on_air_ice_merid", "strairyT", "stress on air by ice y component", "N m-2", "will provide") !----- Ice-Ocn ! momentum stress call fld_list_add(fldsFrIce,"stress_on_ocn_ice_zonal", "strocnxT", "stress on ocn by ice x component", "N m-2", "will provide") call fld_list_add(fldsFrIce,"stress_on_ocn_ice_merid", "strocnyT", "stress on ocn by ice y component", "N m-2", "will provide") call fld_list_add(fldsToOcn,"stress_on_ocn_ice_zonal", "strocnxT", "stress on ocn by ice x component", "N m-2", "will provide") call fld_list_add(fldsToOcn,"stress_on_ocn_ice_merid", "strocnyT", "stress on ocn by ice y component", "N m-2", "will provide") ! ----- Ocn-Ice ! states call fld_list_add(fldsFrOcn,"ocn_current_zonal", "ocncx", "ocean current x component", "m s-1", "will provide") call fld_list_add(fldsFrOcn,"ocn_current_merid", "ocncy", "ocean current y component", "m s-1", "will provide") call fld_list_add(fldsToIce,"ocn_current_zonal", "ocncx", "ocean current x component", "m s-1", "will provide") call fld_list_add(fldsToIce,"ocn_current_merid", "ocncy", "ocean current y component", "m s-1", "will provide") call fld_list_add(fldsFrOcn,"s_surf", "sss", "sea surface salinity on t-cell", "psu", "will provide") call fld_list_add(fldsToIce,"s_surf", "sss", "sea surface salinity on t-cell", "psu", "will provide") #endif ! Fields to ATM call fld_list_add(fldsToAtm,"sea_surface_temperature", "sst" , "sea surface temperature on t-cell","K" , "will provide") call fld_list_add(fldsToAtm,"stress_on_air_ice_zonal" , "strairxT", "stress on air by ice x component" ,"N m-2", "will provide") call fld_list_add(fldsToAtm,"stress_on_air_ice_merid" , "strairyT", "stress on air by ice y component" ,"N m-2", "will provide") ! Fields from ATM call fld_list_add(fldsFrAtm,"mean_zonal_moment_flx" , "mzmfx" , "Mean Zonal Component of Momentum Flux", "Pa", "will provide") call fld_list_add(fldsFrAtm,"mean_merid_moment_flx" , "mmmfx" , "Mean Merid Component of Momentum Flux", "Pa", "will provide") call fld_list_add(fldsFrAtm,"mean_sensi_heat_flx" , "mshfx" , "Mean Sensible Heat Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_laten_heat_flx" , "mlhfx" , "Mean Latent Heat Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_lw_flx" , "mdlwfx" , "Mean Downward Long Wave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_flx" , "mdswfx" , "Mean Downward Shortwave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_prec_rate" , "lprec" , "Mean Liquid Precipitation Rate", "kg/m^2/s", "will provide") call fld_list_add(fldsFrAtm,"mean_fprec_rate" , "fprec" , "Mean Frozen Precipitation Rate", "kg/m^2/s", "will provide") call fld_list_add(fldsFrAtm,"inst_zonal_moment_flx" , "izmfx" , "Instantaneous Zonal Component of Momentum Flux", "Pa", "will provide") call fld_list_add(fldsFrAtm,"inst_merid_moment_flx" , "immfx" , "Instantaneous Merid Component of Momentum Flux", "Pa", "will provide") call fld_list_add(fldsFrAtm,"inst_sensi_heat_flx" , "ishfx" , "Instantaneous Sensible Heat Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_laten_heat_flx" , "ilhfx" , "Instantaneous Latent Heat Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_down_lw_flx" , "idlwfx" , "Instantaneous Downward Long Wave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_down_sw_flx" , "idswfx" , "Instantaneous Downward Shortwave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_temp_height2m" , "ith2m" , "Instantaneous Temperature 2m Above Ground", "K", "will provide") call fld_list_add(fldsFrAtm,"inst_spec_humid_height2m", "ishh2m" , "Instantaneous Specific Humidity 2m Above Ground","kg kg-1", "will provide") call fld_list_add(fldsFrAtm,"inst_u_wind_height10m" , "iuwh10m", "Instantaneous u Wind 10m Above Ground", "m s-1", "will provide") call fld_list_add(fldsFrAtm,"inst_v_wind_height10m" , "ivwh10m", "Instantaneous v Wind 10m Above Ground", "m s-1", "will provide") call fld_list_add(fldsFrAtm,"inst_temp_height_surface", "its" , "Instantaneous Temperature Surface", "K", "will provide") call fld_list_add(fldsFrAtm,"inst_pres_height_surface", "ips" , "Instantaneous Pressure Surface", "Pa", "will provide") call fld_list_add(fldsFrAtm,"inst_surface_height" , "ish" , "Instantaneous Surface Height", "m", "will provide") ! new imports from GSM added 04/23/14: call fld_list_add(fldsFrAtm,"mean_net_lw_flx" , "mnlwfx" , "Mean Net Long Wave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_net_sw_flx" , "mnswfx" , "Mean Net Short Wave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_net_lw_flx" , "inlwfx" , "Instantaneous Net Long Wave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_net_sw_flx" , "inswfx" , "Instantaneous Net Short Wave Radiation Flux", "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_ir_dir_flx" , "sw_flux_nir_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_ir_dif_flx" , "sw_flux_nir_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_vis_dir_flx", "sw_flux_vis_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_down_sw_vis_dif_flx", "sw_flux_vis_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_down_sw_ir_dir_flx" , "inst_sw_flux_nir_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_down_sw_ir_dif_flx" , "inst_sw_flux_nir_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_down_sw_vis_dir_flx", "inst_sw_flux_vis_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_down_sw_vis_dif_flx", "inst_sw_flux_vis_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_net_sw_ir_dir_flx" , "sw_net_flux_nir_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_net_sw_ir_dif_flx" , "sw_net_flux_nir_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_net_sw_vis_dir_flx" , "sw_net_flux_vis_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"mean_net_sw_vis_dif_flx" , "sw_net_flux_vis_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_net_sw_ir_dir_flx" , "inst_net_sw_flux_nir_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_net_sw_ir_dif_flx" , "inst_net_sw_flux_nir_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_net_sw_vis_dir_flx" , "inst_net_sw_flux_vis_dir" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_net_sw_vis_dif_flx" , "inst_net_sw_flux_vis_dif" , "" , "W m-2", "will provide") call fld_list_add(fldsFrAtm,"inst_ir_dir_albedo" , "iirdira" , "" , "1", "will provide") call fld_list_add(fldsFrAtm,"inst_ir_dif_albedo" , "iirdifa" , "" , "1", "will provide") call fld_list_add(fldsFrAtm,"inst_vis_dir_albedo" , "ivisdira", "" , "1", "will provide") call fld_list_add(fldsFrAtm,"inst_vis_dif_albedo" , "ivisdifa", "" , "1", "will provide") call fld_list_add(fldsFrAtm,"inst_ocn_ir_dir_albedo" , "ioirdira" , "Ocean infrared band direct albedo" , "1", "will provide") call fld_list_add(fldsFrAtm,"inst_ocn_ir_dif_albedo" , "ioirdifa" , "Ocean infrared band diffuse albedo" , "1", "will provide") call fld_list_add(fldsFrAtm,"inst_ocn_vis_dir_albedo" , "iovisdira", "Ocean visible band direct albedo" , "1", "will provide") call fld_list_add(fldsFrAtm,"inst_ocn_vis_dif_albedo" , "iovisdifa", "Ocean visible band diffuse albedo" , "1", "will provide") ! Fields to OCN call fld_list_add(fldsToOcn,"mean_zonal_moment_flx" , "mzmfx" , "Mean Zonal Component of Momentum Flux" ,"Pa", "will provide") call fld_list_add(fldsToOcn,"mean_merid_moment_flx" , "mmmfx" , "Mean Merid Component of Momentum Flux" ,"Pa", "will provide") call fld_list_add(fldsToOcn,"mean_sensi_heat_flx" , "mshfx" , "Mean Sensible Heat Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_laten_heat_flx" , "mlhfx" , "Mean Latent Heat Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_down_lw_flx" , "mdlwfx" , "Mean Downward Long Wave Radiation Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_down_sw_vis_dir_flx", "mdvrsfx" , "Mean Downward visible direct Shortwave Radiation Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_down_sw_vis_dif_flx", "mdvfsfx" , "Mean Downward visible diffuse Shortwave Radiation Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_down_sw_ir_dir_flx" , "mdirsfx" , "Mean Downward nearinfrared direct Shortwave Radiation Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_down_sw_ir_dif_flx" , "mdifsfx" , "Mean Downward nearinfrared diffuse Shortwave Radiation Flux","W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_net_sw_vis_dir_flx" , "mndvrsfx" , "Mean Downward visible direct Shortwave Radiation Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_net_sw_vis_dif_flx" , "mndvfsfx" , "Mean Downward visible diffuse Shortwave Radiation Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_net_sw_ir_dir_flx" , "mndirsfx" , "Mean Downward nearinfrared direct Shortwave Radiation Flux" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"mean_net_sw_ir_dif_flx" , "mndifsfx" , "Mean Downward nearinfrared diffuse Shortwave Radiation Flux","W m-2", "will provide") ! call fld_list_add(fldsToOcn,"mean_salt_flx" , "saltflx" , "salt flux into ocean" ,"kg/m^2/s", "will provide") call fld_list_add(fldsToOcn,"mean_prec_rate" , "lprec" , "Mean Liquid Precipitation Rate" ,"kg/m^2/s", "will provide") ! call fld_list_add(fldsToOcn,"mean_fprec_rate" , "fprec" , "Mean Frozen Precipitation Rate" ,"kg/m^2/s", "will provide") call fld_list_add(fldsToOcn,"mean_evap_rate" , "mevap" , "Mean Evaporation Rate" ,"kg/m^2/s", "will provide") ! call fld_list_add(fldsToOcn,"mean_runoff_rate" , "runoff" , "mass flux of liquid runoff" ,"kg/m^2/s", "will provide") ! call fld_list_add(fldsToOcn,"mean_calving_rate" , "calving" , "mass flux of frozen runoff" ,"kg/m^2/s", "will provide") ! call fld_list_add(fldsToOcn,"mean_runoff_flx" , "rofhfx" , "heat flux, relative to 0C, of liquid land water into ocean" ,"W m-2", "will provide") ! call fld_list_add(fldsToOcn,"mean_calving_flx" , "cahflx" , "heat flux, relative to 0C, of frozen land water into ocean" ,"W m-2", "will provide") call fld_list_add(fldsToOcn,"inst_pres_height_surface", "ips" , "pressure of overlying sea ice and atmosphere" ,"Pa", "will provide") ! call fld_list_add(fldsToOcn,"mass_of_overlying_sea_ice, "massice" , "mass of overlying sea ice" ,"kg", "will provide") call fld_list_add(fldsToOcn,"stress_on_ocn_ice_zonal" , "strocnxT", "stress on ocn by ice x component" ,"N m-2", "will provide") call fld_list_add(fldsToOcn,"stress_on_ocn_ice_merid" , "strocnyT", "stress on ocn by ice y component" ,"N m-2", "will provide") ! Fields from OCN call fld_list_add(fldsFrOcn,"sea_surface_temperature" , "sst" , "sea surface temperature on t-cell","K", "will provide") call fld_list_add(fldsFrOcn,"s_surf" , "sss" , "sea surface salinity on t-cell" ,"psu", "will provide") call fld_list_add(fldsFrOcn,"u_surf" , "uocn", "ocean current x component" ,"m s-1", "will provide") call fld_list_add(fldsFrOcn,"v_surf" , "vocn", "ocean current y component" ,"m s-1", "will provide") call fld_list_add(fldsFrOcn,"sea_lev" , "ssh" , "Sea Level Height" ,"m", "will provide") ! Fields to ICE call fld_list_add(fldsToIce,"sss_zonal" , "ss_tltx", "sea surface slope x component" ,"m m-1", "will provide") call fld_list_add(fldsToIce,"sss_merid" , "ss_tlty", "sea surface slope y component" ,"m m-1", "will provide") call fld_list_add(fldsToIce,"wind_stress_zonal", "strax" , "wind stress x component" ,"N m-2", "will provide") call fld_list_add(fldsToIce,"wind_stress_merid", "stray" , "wind stress y component" ,"N m-2", "will provide") call fld_list_add(fldsToIce,"ocn_current_zonal", "uocn" , "ocean current x component" ,"m s-1", "will provide") call fld_list_add(fldsToIce,"ocn_current_merid", "vocn" , "ocean current y component" ,"m s-1", "will provide") ! Fields from ICE call fld_list_add(fldsFrIce,"stress_on_air_ice_zonal", "strairxT", "stress on air by ice x component","N m-2", "will provide") call fld_list_add(fldsFrIce,"stress_on_air_ice_merid", "strairyT", "stress on air by ice y component","N m-2", "will provide") call fld_list_add(fldsFrIce,"stress_on_ocn_ice_zonal", "strocnxT", "stress on ocn by ice x component","N m-2", "will provide") call fld_list_add(fldsFrIce,"stress_on_ocn_ice_merid", "strocnyT", "stress on ocn by ice y component","N m-2", "will provide") if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine SetServices !----------------------------------------------------------------------------- subroutine InitializeP0(gcomp, importState, exportState, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables character(len=NUOPC_PhaseMapStringLength) :: initPhases(6) character(len=*),parameter :: subname='(module_MEDIATOR:InitializeP0)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS !gjt initPhases(1) = "IPDv02p1=1" !gjt initPhases(2) = "IPDv02p3=2" !gjt initPhases(3) = "IPDv02p4=3" !gjt initPhases(4) = "IPDv02p5=5" initPhases(1) = "IPDv03p1=1" initPhases(2) = "IPDv03p3=2" initPhases(3) = "IPDv03p4=6" initPhases(4) = "IPDv03p5=7" initPhases(5) = "IPDv03p6=3" initPhases(6) = "IPDv03p7=5" call ESMF_AttributeSet(gcomp, & name="InitializePhaseMap", valueList=initPhases, & convention="NUOPC", purpose="General", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine InitializeP0 !----------------------------------------------------------------------- subroutine InitializeP1(gcomp, importState, exportState, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables integer :: n character(len=*),parameter :: subname='(module_MEDIATOR:InitializeP1)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! importable fields: do n = 1,fldsFrAtm%num if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": Advertise "//trim(fldsFrAtm%stdname(n))//":"// & trim(fldsFrAtm%shortname(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_StateAdvertiseField(importState, & StandardName = trim(fldsFrAtm%stdname(n)), & name=fldsFrAtm%shortname(n), & TransferOfferGeomObject=fldsFrAtm%transferOffer(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo do n = 1,fldsFrOcn%num if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": Advertise "//trim(fldsFrOcn%stdname(n))//":"// & trim(fldsFrOcn%shortname(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_StateAdvertiseField(importState, & StandardName = fldsFrOcn%stdname(n), & name = fldsFrOcn%shortname(n), & TransferOfferGeomObject=fldsFrOcn%transferOffer(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo do n = 1,fldsFrIce%num if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": Advertise "//trim(fldsFrIce%stdname(n))//":"// & trim(fldsFrIce%shortname(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_StateAdvertiseField(importState, & StandardName = fldsFrIce%stdname(n), & name = fldsFrIce%shortname(n), & TransferOfferGeomObject=fldsFrIce%transferOffer(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo ! exportable fields: do n = 1,fldsToAtm%num if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": Advertise "//trim(fldsToAtm%stdname(n))//":"// & trim(fldsToAtm%shortname(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_StateAdvertiseField(exportState, & StandardName = fldsToAtm%stdname(n), & name = fldsToAtm%shortname(n), & TransferOfferGeomObject=fldsToAtm%transferOffer(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo do n = 1,fldsToOcn%num if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": Advertise "//trim(fldsToOcn%stdname(n))//":"// & trim(fldsToOcn%shortname(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_StateAdvertiseField(exportState, & StandardName = fldsToOcn%stdname(n), & name = fldsToOcn%shortname(n), & TransferOfferGeomObject=fldsToOcn%transferOffer(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo do n = 1,fldsToIce%num if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": Advertise "//trim(fldsToIce%stdname(n))//":"// & trim(fldsToIce%shortname(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_StateAdvertiseField(exportState, & StandardName = fldsToIce%stdname(n), & name = fldsToIce%shortname(n), & TransferOfferGeomObject=fldsToIce%transferOffer(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine InitializeP1 !----------------------------------------------------------------------------- subroutine InitializeP2(gcomp, importState, exportState, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables type(ESMF_Grid) :: gridAtm, gridOcn, gridIce type(ESMF_Array) :: array integer :: i, j real(kind=ESMF_KIND_R8),pointer :: lonPtr(:,:), latPtr(:,:) type(InternalState) :: is integer :: stat type(ESMF_Config) :: config real(ESMF_KIND_R8) :: intervalSec type(ESMF_TimeInterval) :: timeStep ! tcx XGrid ! type(ESMF_Field) :: fieldX, fieldA, fieldO ! type(ESMF_XGrid) :: xgrid character(len=*),parameter :: subname='(module_MEDIATOR:InitializeP2)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! Allocate memory for the internal state and set it in the Component. allocate(is%wrap, stat=stat) if (ESMF_LogFoundAllocError(statusToCheck=stat, & msg="Allocation of the internal state memory failed.", & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_GridCompSetInternalState(gcomp, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Initialize the internal state members is%wrap%fastcntr = 1 is%wrap%slowcntr = 1 gridAtm = NUOPC_GridCreateSimpleSph(0._ESMF_KIND_R8, -85._ESMF_KIND_R8, & 360._ESMF_KIND_R8, 85._ESMF_KIND_R8, nx_atm, ny_atm, & scheme=ESMF_REGRID_SCHEME_FULL3D, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out gridOcn = NUOPC_GridCreateSimpleSph(0._ESMF_KIND_R8, -85._ESMF_KIND_R8, & 360._ESMF_KIND_R8, 85._ESMF_KIND_R8, nx_ocn, ny_ocn, & scheme=ESMF_REGRID_SCHEME_FULL3D, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out gridIce = NUOPC_GridCreateSimpleSph(0._ESMF_KIND_R8, -85._ESMF_KIND_R8, & 360._ESMF_KIND_R8, 85._ESMF_KIND_R8, nx_ice, ny_ice, & scheme=ESMF_REGRID_SCHEME_FULL3D, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out #if 1 ! dump the ATM Grid coordinate arrays for reference call ESMF_GridGetCoord(gridAtm, coordDim=1, array=array, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_ArrayWrite(array, file="array_med_atm_grid_coord1.nc", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_GridGetCoord(gridAtm, coordDim=2, array=array, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_ArrayWrite(array, file="array_med_atm_grid_coord2.nc", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! dump the OCN Grid coordinate arrays for reference call ESMF_GridGetCoord(gridOcn, coordDim=1, array=array, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_ArrayWrite(array, file="array_med_ocn_grid_coord1.nc", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_GridGetCoord(gridOcn, coordDim=2, array=array, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_ArrayWrite(array, file="array_med_ocn_grid_coord2.nc", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) ! dump the ICE Grid coordinate arrays for reference call ESMF_GridGetCoord(gridIce, coordDim=1, array=array, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_ArrayWrite(array, file="array_med_ice_grid_coord1.nc", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) call ESMF_GridGetCoord(gridIce, coordDim=2, array=array, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_ArrayWrite(array, file="array_med_ice_grid_coord2.nc", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & call ESMF_Finalize(endflag=ESMF_END_ABORT) #endif !--- Generate RouteHandles ! tcx Xgrid ! what needs to be in the grids to create an XGrid (corners?) ! add error checking code ! xgrid = ESMF_XGridCreate(sideAGrid=(/gridatm/), sideBGrid=(/gridocn/), rc=rc) ! if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & ! line=__LINE__, & ! file=__FILE__)) & ! return ! bail out ! fieldX = ESMF_FieldCreate(xgrid , typekind=ESMF_TYPEKIND_R8, rc=rc) ! fieldA = ESMF_FieldCreate(gridAtm, typekind=ESMF_TYPEKIND_R8, rc=rc) ! fieldO = ESMF_FieldCreate(gridAtm, typekind=ESMF_TYPEKIND_R8, rc=rc) ! call ESMF_FieldRegridStore(xgrid, fieldA, fieldX, routehandle=is%wrap%RHa2x, rc=rc) ! call ESMF_FieldRegridStore(xgrid, fieldO, fieldX, routehandle=is%wrap%RHo2x, rc=rc) ! call ESMF_FieldRegridStore(xgrid, fieldX, fieldA, routehandle=is%wrap%RHx2a, rc=rc) ! call ESMF_FieldRegridStore(xgrid, fieldX, fieldO, routehandle=is%wrap%RHx2o, rc=rc) ! call ESMF_FieldDestroy(fieldX, rc=rc) ! call ESMF_FieldDestroy(fieldA, rc=rc) ! call ESMF_FieldDestroy(fieldO, rc=rc) ! call ESMF_XGridDestroy(xgrid, rc=rc) !--- Importable fields from atm: !gjt: import fields from ATM are now marked as "cannot provide" thus accept Grid !gjt: -> eventually comment out the following lines... call realizeConnectedFields(importState, fieldNameList=fldsFrAtm%shortname(1:fldsFrAtm%num), & grid=gridAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--- Exportable fields to atm: call realizeConnectedFields(exportState, fieldNameList=fldsToAtm%shortname(1:fldsToAtm%num), & grid=gridAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--- Importable fields from ocn: call realizeConnectedFields(importState, fieldNameList=fldsFrOcn%shortname(1:fldsFrOcn%num), & grid=gridOcn, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--- Exportable fields to ocn: call realizeConnectedFields(exportState, fieldNameList=fldsToOcn%shortname(1:fldsToOcn%num), & grid=gridOcn, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--- Importable fields from ice: call realizeConnectedFields(importState, fieldNameList=fldsFrIce%shortname(1:fldsFrIce%num), & grid=gridIce, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--- Exportable fields to ice: call realizeConnectedFields(exportState, fieldNameList=fldsToIce%shortname(1:fldsToIce%num), & grid=gridIce, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Accumulators call fieldBundle_init(is%wrap%FBaccumAtm, fieldNameList=fldsFrAtm%shortname(1:fldsFrAtm%num), & grid=gridAtm, state=importState, name='FBaccumAtm', rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_init(is%wrap%FBaccumOcn, fieldNameList=fldsFrOcn%shortname(1:fldsFrOcn%num), & grid=gridOcn, state=importState, name='FBaccumOcn', rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_init(is%wrap%FBaccumIce, fieldNameList=fldsFrIce%shortname(1:fldsFrIce%num), & grid=gridIce, state=importState, name='FBaccumIce', rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Data ready for export to models call fieldBundle_init(is%wrap%FBforAtm, fieldNameList=fldsToAtm%shortname(1:fldsToAtm%num), & grid=gridAtm, state=exportState, name='FBforAtm', rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_init(is%wrap%FBforOcn, fieldNameList=fldsToOcn%shortname(1:fldsToOcn%num), & grid=gridOcn, state=exportState, name='FBforOcn', rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_init(is%wrap%FBforIce, fieldNameList=fldsToIce%shortname(1:fldsToIce%num), & grid=gridIce, state=exportState, name='FBforIce', rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Initialize the internal clocks ! both atm and ocn clocks start out as copies of the incoming clock if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": clockcreate", ESMF_LOGMSG_INFO, rc=dbrc) endif is%wrap%clockAtm = ESMF_ClockCreate(clock, rc=rc) ESMF_ERR_RETURN(rc,rc) is%wrap%clockOcn = ESMF_ClockCreate(clock, rc=rc) ESMF_ERR_RETURN(rc,rc) is%wrap%clockIce = ESMF_ClockCreate(clock, rc=rc) ESMF_ERR_RETURN(rc,rc) config = ESMF_ConfigCreate(rc=rc) ESMF_ERR_RETURN(rc,rc) call ESMF_ConfigLoadFile(config, "nems.configure", rc=rc) ESMF_ERR_RETURN(rc,rc) ! ATM coupling interval -> atm time step call ESMF_ConfigGetAttribute(config, intervalSec, & label="med_atm_coupling_interval_sec:", default=-1.0_ESMF_KIND_R8, & rc=rc) ESMF_ERR_RETURN(rc,rc) if (dbug_flag > 1) then write(tmpstr,'(A,f12.3)') trim(subname)//': atm intervalSec = ',intervalSec call ESMF_LogWrite(trim(tmpstr), ESMF_LOGMSG_INFO, rc=dbrc) endif if (intervalSec>0._ESMF_KIND_R8) then ! The coupling time step was provided call ESMF_TimeIntervalSet(timeStep, s_r8=intervalSec, rc=rc) ESMF_ERR_RETURN(rc,rc) call ESMF_ClockSet(is%wrap%clockAtm, timestep=timeStep, rc=rc) ESMF_ERR_RETURN(rc,rc) endif ! OCN coupling interval -> ocn time step call ESMF_ConfigGetAttribute(config, intervalSec, & label="med_ocn_coupling_interval_sec:", default=-1.0_ESMF_KIND_R8, & rc=rc) ESMF_ERR_RETURN(rc,rc) if (dbug_flag > 1) then write(tmpstr,'(A,f12.3)') trim(subname)//': ocn intervalSec = ',intervalSec call ESMF_LogWrite(trim(tmpstr), ESMF_LOGMSG_INFO, rc=dbrc) endif if (intervalSec>0._ESMF_KIND_R8) then ! The coupling time step was provided call ESMF_TimeIntervalSet(timeStep, s_r8=intervalSec, rc=rc) ESMF_ERR_RETURN(rc,rc) call ESMF_ClockSet(is%wrap%clockOcn, timestep=timeStep, rc=rc) ESMF_ERR_RETURN(rc,rc) endif ! ICE coupling interval -> ice time step call ESMF_ConfigGetAttribute(config, intervalSec, & label="med_ice_coupling_interval_sec:", default=-1.0_ESMF_KIND_R8, & rc=rc) ESMF_ERR_RETURN(rc,rc) if (dbug_flag > 1) then write(tmpstr,'(A,f12.3)') trim(subname)//': ice intervalSec = ',intervalSec call ESMF_LogWrite(trim(tmpstr), ESMF_LOGMSG_INFO, rc=dbrc) endif if (intervalSec>0._ESMF_KIND_R8) then ! The coupling time step was provided call ESMF_TimeIntervalSet(timeStep, s_r8=intervalSec, rc=rc) ESMF_ERR_RETURN(rc,rc) call ESMF_ClockSet(is%wrap%clockIce, timestep=timeStep, rc=rc) ESMF_ERR_RETURN(rc,rc) endif ! Clean Up ! call ESMF_GridDestroy(gridAtm, rc=rc) ! if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & ! line=__LINE__, & ! file=__FILE__)) & ! return ! bail out ! call ESMF_GridDestroy(gridOcn, rc=rc) ! if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & ! line=__LINE__, & ! file=__FILE__)) & ! return ! bail out call ESMF_ConfigDestroy(config, rc=rc) ESMF_ERR_RETURN(rc,rc) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif contains !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - subroutine realizeConnectedFields(state, fieldNameList, grid, rc) type(ESMF_State) :: state character(len=*) :: fieldNameList(:) type(ESMF_Grid) :: grid integer, intent(out), optional :: rc integer :: n type(ESMF_Field) :: field character(len=*),parameter :: subname='(module_MEDIATOR:realizeConnectedFields)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS do n=1, size(fieldNameList) if (NUOPC_StateIsFieldConnected(state, fieldName=fieldNameList(n))) then ! realize the connected Field using the internal coupling Field field = ESMF_FieldCreate(grid, ESMF_TYPEKIND_R8, name=fieldNameList(n),rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call NUOPC_StateRealizeField(state, field=field, rc=rc) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": create "//trim(fieldNameList(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out else ! remove a not connected Field from State call ESMF_StateRemove(state, (/fieldNameList(n)/), rc=rc) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": exclude "//trim(fieldNameList(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out endif enddo if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine realizeConnectedFields end subroutine InitializeP2 !----------------------------------------------------------------------------- !----------------------------------------------------------------------------- subroutine InitializeP6(gcomp, importState, exportState, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables type(ESMF_Field) :: field type(ESMF_Grid) :: grid integer :: localDeCount character(160) :: msgString type(ESMF_DistGrid) :: distgrid integer :: dimCount, tileCount, petCount integer :: deCountPTile, extraDEs integer, allocatable :: minIndexPTile(:,:), maxIndexPTile(:,:) integer, allocatable :: regDecompPTile(:,:) integer :: i, j, n character(len=*),parameter :: subname='(module_MEDIATOR:InitializeP6)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS #if 0 !NOTE: All fo the Fields that set their TransferOfferGeomObject Attribute !NOTE: to "cannot provide" should now have the accepted Grid available. !NOTE: Go and pull out this Grid for one of a representative Field and !NOTE: modify the decomposition and distribution of the Grid to match the !NOTE: Mediator PETs. !gjt: for now I am only doing this on the ATM side, but it should eventually !gjt: be done on OCN side, too. !TODO: quick implementation, assume that there is at least one field !TODO: and assume that all fields in fldsFrAtm are going to accept Grids ! access the first Field that is in fldsFrAtm and access in importState call ESMF_StateGet(exportState, field=field, & itemName=fldsFrAtm%shortname(1), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! while this is still an empty field, it does now hold a Grid with DistGrid call ESMF_FieldGet(field, grid=grid, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! access localDeCount to show this is a real Grid call ESMF_GridGet(grid, localDeCount=localDeCount, distgrid=distgrid, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out write (msgString,*) "MED - InitializeP6: localDeCount = ", localDeCount call ESMF_LogWrite(msgString, ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Create a custom DistGrid, based on the minIndex, maxIndex of the ! accepted DistGrid, but with a default regDecomp for the current VM ! that leads to 1DE/PET. ! get dimCount and tileCount call ESMF_DistGridGet(distgrid, dimCount=dimCount, tileCount=tileCount, & rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! allocate minIndexPTile and maxIndexPTile accord. to dimCount and tileCount allocate(minIndexPTile(dimCount, tileCount), & maxIndexPTile(dimCount, tileCount)) ! get minIndex and maxIndex arrays call ESMF_DistGridGet(distgrid, minIndexPTile=minIndexPTile, & maxIndexPTile=maxIndexPTile, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! construct a default regDecompPTile -> TODO: move this into ESMF as default call ESMF_GridCompGet(gcomp, petCount=petCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out allocate(regDecompPTile(dimCount, tileCount)) deCountPTile = petCount/tileCount extraDEs = max(0, petCount-deCountPTile) do i=1, tileCount if (i<=extraDEs) then regDecompPTile(1, i) = deCountPTile + 1 else regDecompPTile(1, i) = deCountPTile endif do j=2, dimCount regDecompPTile(j, i) = 1 enddo enddo ! create the new DistGrid with the same minIndexPTile and maxIndexPTile, ! but with a default regDecompPTile distgrid = ESMF_DistGridCreate(minIndexPTile=minIndexPTile, & maxIndexPTile=maxIndexPTile, regDecompPTile=regDecompPTile, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Create a new Grid on the new DistGrid and swap it in the Field grid = ESMF_GridCreate(distgrid, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_FieldEmptySet(field, grid=grid, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! local clean-up deallocate(minIndexPTile, maxIndexPTile, regDecompPTile) ! access localDeCount of the final Grid call ESMF_GridGet(grid, localDeCount=localDeCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out write (msgString,*) "MED - InitializeP6: final Grid localDeCount = ", & localDeCount call ESMF_LogWrite(msgString, ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Also must swap the Grid for all the other fldsFrAtm Fields in the ! importState do n=2, fldsFrAtm%num ! access a field in the importState and set the Grid call ESMF_StateGet(importState, field=field, & itemName=fldsFrAtm%shortname(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call ESMF_FieldEmptySet(field, grid=grid, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif #endif end subroutine InitializeP6 !----------------------------------------------------------------------------- subroutine InitializeP7(gcomp, importState, exportState, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables type(ESMF_Field) :: field integer :: n character(len=*),parameter :: subname='(module_MEDIATOR:InitializeP6)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS #if 0 do n=1, fldsFrAtm%num ! access a field in the importState and complete it with data allocation call ESMF_StateGet(importState, field=field, & itemName=fldsFrAtm%shortname(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! the transferred Grid is already set, allocate field data memory call ESMF_FieldEmptyComplete(field, typekind=ESMF_TYPEKIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out enddo #endif end subroutine InitializeP7 !----------------------------------------------------------------------------- subroutine DataInitialize(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! local variables type(ESMF_Clock) :: clock type(ESMF_State) :: importState, exportState type(ESMF_Time) :: time type(ESMF_Field) :: field type(ESMF_StateItem_Flag) :: itemType logical :: neededCurrent logical :: allDone type(InternalState) :: is real(ESMF_KIND_R8), pointer :: dataPtr(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:DataInitialize)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! the MED needs valid ATM export Fields to initialize its internal state ! query the Component for its clock, importState and exportState call ESMF_GridCompGet(gcomp, clock=clock, importState=importState, & exportState=exportState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Get the internal state from Component. nullify(is%wrap) call ESMF_GridCompGetInternalState(gcomp, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! get the current time out of the clock call ESMF_ClockGet(clock, currTime=time, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out allDone = .true. ! flag that can be reset if anything is not found done ! check that required Fields in the importState show correct timestamp ! -> really should check _all_ of the fields from the ATM ! -> check for "mzmfx" call ESMF_StateGet(importState, itemName="mzmfx", itemType=itemType, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (itemType /= ESMF_STATEITEM_NOTFOUND) then call ESMF_StateGet(importState, field=field, itemName="mzmfx", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out neededCurrent = NUOPC_FieldIsAtTime(field, time, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (.not.neededCurrent) then call ESMF_LogWrite("MED - Initialize-Data-Dependency NOT YET SATISFIED!!!", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out allDone = .false. else call ESMF_LogWrite("MED - Initialize-Data-Dependency SATISFIED!!!", & ESMF_LOGMSG_INFO, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out endif endif ! TODO - tcraig ?? what's above here? ! For the real case this should probably use the "mzmfx" field from the ! importState and do something with it as a sensible starting point ! for the accumulation field so that the OCN receives a meaningful ! "mzmfx" field during its first time step. However, here for testing ! I simply initialize to zero. call fieldBundle_reset(is%wrap%FBaccumAtm, value=0._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out is%wrap%accumcntAtm = 0 call fieldBundle_reset(is%wrap%FBaccumOcn, value=0._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out is%wrap%accumcntOcn = 0 call fieldBundle_reset(is%wrap%FBaccumIce, value=0._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out is%wrap%accumcntIce = 0 #if 0 !gjt: with different Grids on each side, need to precompute a Regrid call ESMF_FieldBundleRegridStore(srcFieldBundle=is%wrap%FBaccumAtm, & dstFieldBundle=is%wrap%FBforOcn, & unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & routehandle=is%wrap%rh, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out #endif if (allDone) then ! -> set InitializeDataComplete Component Attribute to "true", indicating ! to the driver that this Component has fully initialized its data call ESMF_AttributeSet(gcomp, & name="InitializeDataComplete", value="true", & convention="NUOPC", purpose="General", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine DataInitialize !----------------------------------------------------------------------------- subroutine SetRunClock_atm_before(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! local variables type(InternalState) :: is_local type(mediator_type_IS) :: is character(len=*),parameter :: subname='(module_MEDIATOR:SetRunClock_atm_before)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query component for its internal state nullify(is_local%wrap) call ESMF_GridCompGetInternalState(gcomp, is_local, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! set clockAtm to be the component clock call ESMF_GridCompSet(gcomp, clock=is_local%wrap%clockAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! query component for its inherited internal state nullify(is%wrap) call ESMF_UserCompGetInternalState(gcomp, mediator_label_IS, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! check and set the component clock against the driver clock call NUOPC_GridCompCheckSetClock(gcomp, is%wrap%driverClock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, & msg="NUOPC INCOMPATIBILITY DETECTED: between model and driver clocks", & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine SetRunClock_atm_before !----------------------------------------------------------------------------- subroutine SetRunClock_atm_after(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! local variables type(InternalState) :: is_local type(mediator_type_IS) :: is character(len=*),parameter :: subname='(module_MEDIATOR:SetRunClock_atm_after)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query component for its internal state nullify(is_local%wrap) call ESMF_GridCompGetInternalState(gcomp, is_local, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! set clockAtm to be the component clock call ESMF_GridCompSet(gcomp, clock=is_local%wrap%clockAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! query component for its inherited internal state nullify(is%wrap) call ESMF_UserCompGetInternalState(gcomp, mediator_label_IS, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! check and set the component clock against the driver clock call NUOPC_GridCompCheckSetClock(gcomp, is%wrap%driverClock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, & msg="NUOPC INCOMPATIBILITY DETECTED: between model and driver clocks", & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine SetRunClock_atm_after !----------------------------------------------------------------------------- subroutine SetRunClock_ocn(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! local variables type(InternalState) :: is_local type(mediator_type_IS) :: is character(len=*),parameter :: subname='(module_MEDIATOR:SetRunClock_ocn)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query component for its internal state nullify(is_local%wrap) call ESMF_GridCompGetInternalState(gcomp, is_local, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! set clockOcn to be the component clock call ESMF_GridCompSet(gcomp, clock=is_local%wrap%clockOcn, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! query component for its inherited internal state nullify(is%wrap) call ESMF_UserCompGetInternalState(gcomp, mediator_label_IS, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! check and set the component clock against the driver clock call NUOPC_GridCompCheckSetClock(gcomp, is%wrap%driverClock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, & msg="NUOPC INCOMPATIBILITY DETECTED: between model and driver clocks", & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine SetRunClock_ocn !----------------------------------------------------------------------------- subroutine CheckImport_atm_before(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! This is the routine that ensures that the import Fields come in with ! the correct time stamps during the "fast" cycle: ! -> Fields from the ATM are not used by the "before" phase and need not ! be checked. ! -> Fields from the OCN must be at the startTime of the parent driver ! Clock ! local variables type(ESMF_Clock) :: clock type(ESMF_Time) :: startTime type(ESMF_State) :: importState type(ESMF_Field) :: field logical :: atCorrectTime character(len=*),parameter :: subname='(module_MEDIATOR:CheckImport_atm_before)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query the Component for its importState call ESMF_GridCompGet(gcomp, importState=importState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! query the Component for its driverClock call NUOPC_MediatorGet(gcomp, driverClock=clock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! get the start time out of the driver Clock call ESMF_ClockGet(clock, startTime=startTime, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! check fields from OCN to be at startTime of the driver Clock if (NUOPC_StateIsFieldConnected(importState, fieldName="sst")) then call ESMF_StateGet(importState, itemName="sst", field=field, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out atCorrectTime = NUOPC_FieldIsAtTime(field, startTime, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (.not.atCorrectTime) then !TODO: introduce and use INCOMPATIBILITY return codes!!!! call ESMF_LogSetError(ESMF_RC_ARG_BAD, & msg="NUOPC INCOMPATIBILITY DETECTED: Import Fields not at correct time", & line=__LINE__, & file=__FILE__, & rcToReturn=rc) return ! bail out endif endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine CheckImport_atm_before !----------------------------------------------------------------------------- subroutine CheckImport_atm_after(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! This is the routine that ensures that the import Fields come in with ! the correct time stamps during the "fast" cycle: ! -> Fields from the ATM must be at stopTime because this mediator phase ! runs _after_ the ATM runs. ! -> Fields from the OCN are not used by the "after" phase and need not ! be checked. ! local variables type(ESMF_Clock) :: clock type(ESMF_Time) :: stopTime type(ESMF_State) :: importState type(ESMF_Field) :: field logical :: atCorrectTime character(len=*),parameter :: subname='(module_MEDIATOR:CheckImport_atm_after)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query the Component for its Clock and importState call ESMF_GridCompGet(gcomp, clock=clock, importState=importState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! get the stop time out of the Clock call ESMF_ClockGet(clock, stopTime=stopTime, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! check fields from ATM to be at stopTime if (NUOPC_StateIsFieldConnected(importState, fieldName="pmsl")) then call ESMF_StateGet(importState, itemName="pmsl", field=field, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out atCorrectTime = NUOPC_FieldIsAtTime(field, stopTime, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (.not.atCorrectTime) then !TODO: introduce and use INCOMPATIBILITY return codes!!!! call ESMF_LogSetError(ESMF_RC_ARG_BAD, & msg="NUOPC INCOMPATIBILITY DETECTED: Import Fields not at correct time", & line=__LINE__, & file=__FILE__, & rcToReturn=rc) return ! bail out endif endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine CheckImport_atm_after !----------------------------------------------------------------------------- subroutine TimestampExport_atm_before(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! This is the routine that executes _after_ the "fast_before" mediator ! phase has been run. Timestamping does not need to be adjusted here, ! but the Clock needs to be stepped back because the "fast_after" phase ! will be updating the same Clock during the same driver cylce. ! local variables type(ESMF_Clock) :: clock type(ESMF_TimeInterval) :: timeStep character(len=*),parameter :: subname='(module_MEDIATOR:TimestampExport_atm_before)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query the Component for info call ESMF_GridCompGet(gcomp, clock=clock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! get the timeStep out of Clock call ESMF_ClockGet(clock, timeStep=timeStep, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! step the Clock back one timestep call ESMF_ClockAdvance(clock, timeStep= -timeStep, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine TimestampExport_atm_before !----------------------------------------------------------------------------- subroutine TimestampExport_atm_after(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! This is the routine that applies the time stamp on the export Fields ! during the "atm" cycle: ! -> By default the MED Run method time stamps the export Fields with the ! current time at the beginning of the advance step, however here, ! because the "atm" cycle runs after the ATM model, the correct time ! stamp is the currTime _after_ the MED advance step. ! local variables type(ESMF_Clock) :: clock type(ESMF_State) :: exportState character(len=*),parameter :: subname='(module_MEDIATOR:TimestampExport_atm_after)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query the Component for info call ESMF_GridCompGet(gcomp, clock=clock, exportState=exportState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! update timestamp on export Fields call NUOPC_StateSetTimestamp(exportState, clock, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine TimestampExport_atm_after !----------------------------------------------------------------------------- subroutine Advance_fast_before(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! This Mediator phase runs before ATM and ICE are being called and ! prepares the ATM and ICE import Fields. ! local variables type(ESMF_Clock) :: clock type(ESMF_Time) :: time character(len=64) :: timestr type(ESMF_State) :: importState, exportState type(InternalState) :: is integer :: i,j character(len=*),parameter :: subname='(module_MEDIATOR:Advance_fast_before)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query the Component for its clock, importState and exportState call ESMF_GridCompGet(gcomp, clock=clock, importState=importState, & exportState=exportState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Get the internal state from Component. nullify(is%wrap) call ESMF_GridCompGetInternalState(gcomp, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! HERE THE MEDIATOR does the mediation of Fields that come in on the ! importState with a timestamp consistent to the currTime of the ! mediators Clock. ! The Mediator uses the data on the import Fields to update the data ! held by Fields in the exportState. ! After this routine returns the generic Mediator will correctly ! timestamp the export Fields to the currTime. call ESMF_ClockGet(clock,currtime=time,rc=rc) call ESMF_TimeGet(time,timestring=timestr) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": time = "//trim(timestr), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_ClockPrintCurrTime(clock, & "-------->MED Advance() mediating for: ", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--------------------------------------- !--- this is fast, so just copy latest values from import state to atm/ice FB !--- no accumulator needed !--------------------------------------- call fieldBundle_copy(is%wrap%FBforAtm, importState, rc=rc) call fieldBundle_copy(is%wrap%FBforIce, importState, rc=rc) if (dbug_flag > 1) then call FieldBundle_diagnose(is%wrap%FBforAtm, trim(subname)//' FBforA_AFcopy ', rc=rc) call FieldBundle_diagnose(is%wrap%FBforIce, trim(subname)//' FBforI_AFcopy ', rc=rc) endif !--------------------------------------- !--- custom calculations to atm and ice !--------------------------------------- ! None yet !--------------------------------------- !--- set export State to special value for testing !--------------------------------------- call state_reset(exportState, value=-99._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call State_diagnose(exportState, trim(subname)//' es_AF99 ', rc=rc) endif !--------------------------------------- !--- copy into export state !--------------------------------------- call fieldBundle_copy(exportState, is%wrap%FBforAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_copy(exportState, is%wrap%FBforIce, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call state_diagnose(exportState, trim(subname)//' es_endfast ', rc=rc) endif ! write the fields exported to atm to file call NUOPC_StateWrite(exportState, fieldNameList=fldsToAtm%shortname, & filePrefix="field_med_to_atm_", timeslice=is%wrap%fastcntr, & relaxedFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! write the fields exported to ice to file call NUOPC_StateWrite(exportState, fieldNameList=fldsToIce%shortname, & filePrefix="field_med_to_ice_", timeslice=is%wrap%fastcntr, & relaxedFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--------------------------------------- !--- clean up !--------------------------------------- if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine Advance_fast_before !----------------------------------------------------------------------------- subroutine Advance_fast_after(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! local variables type(ESMF_Clock) :: clock type(ESMF_Time) :: time character(len=64) :: timestr type(ESMF_State) :: importState, exportState type(InternalState) :: is integer :: i,j character(len=*),parameter :: subname='(module_MEDIATOR:Advance_fast_after)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query the Component for its clock, importState and exportState call ESMF_GridCompGet(gcomp, clock=clock, importState=importState, & exportState=exportState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Get the internal state from Component. nullify(is%wrap) call ESMF_GridCompGetInternalState(gcomp, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! HERE THE MEDIATOR does the mediation of Fields that come in on the ! importState with a timestamp consistent to the stopTime of the ! mediators Clock. ! The Mediator uses the data on the import Fields to update the data ! held by Fields in the exportState. ! After this routine returns the generic Mediator will correctly ! timestamp the export Fields to the stopTime, and then update ! the Mediator Clock to: ! ! currTime -> currTime + timeStep ! ! Where the timeStep is equal to the parent timeStep. call ESMF_ClockGet(clock,currtime=time,rc=rc) call ESMF_TimeGet(time,timestring=timestr) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": time = "//trim(timestr), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_ClockPrintCurrTime(clock, & "-------->MED Advance() mediating for: ", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! write the fields imported from atm to file call NUOPC_StateWrite(importState, fieldNameList=fldsFrAtm%shortname, & filePrefix="field_med_from_atm_", timeslice=is%wrap%fastcntr, & relaxedFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! write the fields imported from ice to file call NUOPC_StateWrite(importState, fieldNameList=fldsFrIce%shortname, & filePrefix="field_med_from_ice_", timeslice=is%wrap%fastcntr, & relaxedFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--------------------------------------- !--- atm, ice accumulator for ocean !--------------------------------------- if (dbug_flag > 1) then call State_diagnose(importState, trim(subname)//' is_beginfast ', rc=rc) call FieldBundle_diagnose(is%wrap%FBaccumAtm, trim(subname)//' FBaccA_B4accum ', rc=rc) call FieldBundle_diagnose(is%wrap%FBaccumIce, trim(subname)//' FBaccI_B4accum ', rc=rc) endif call fieldBundle_accum(is%wrap%FBaccumAtm, importState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out is%wrap%accumcntAtm = is%wrap%accumcntAtm + 1 call fieldBundle_accum(is%wrap%FBaccumIce, importState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out is%wrap%accumcntIce = is%wrap%accumcntIce + 1 if (dbug_flag > 1) then call FieldBundle_diagnose(is%wrap%FBaccumAtm, trim(subname)//' FBaccA_AFaccum ', rc=rc) call FieldBundle_diagnose(is%wrap%FBaccumIce, trim(subname)//' FBaccI_AFaccum ', rc=rc) endif if (dbug_flag > 1) then call State_diagnose(exportState, trim(subname)//' es_AF99 ', rc=rc) endif if (dbug_flag > 1) then call state_diagnose(exportState, trim(subname)//' es_endfast ', rc=rc) endif !--------------------------------------- !--- clean up !--------------------------------------- !--------------------------------------- is%wrap%fastcntr = is%wrap%fastcntr + 1 !--------------------------------------- if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine Advance_fast_after !----------------------------------------------------------------------------- subroutine Advance_slow(gcomp, rc) type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc ! local variables type(ESMF_Clock) :: clock type(ESMF_Time) :: time character(len=64) :: timestr type(ESMF_State) :: importState, exportState type(ESMF_StateItem_Flag) :: itemType type(InternalState) :: is integer :: i,j,n character(len=64) :: fieldname1(10),fieldname2(10),fieldname3(10) real(ESMF_KIND_R8), pointer :: dataPtr1(:,:),dataPtr2(:,:),dataPtr3(:,:) logical :: isPresent, checkOK, checkOK1, checkOK2 character(len=*),parameter :: subname='(module_MEDIATOR:Advance_slow)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! query the Component for its clock, importState and exportState call ESMF_GridCompGet(gcomp, clock=clock, importState=importState, & exportState=exportState, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Get the internal state from Component. nullify(is%wrap) call ESMF_GridCompGetInternalState(gcomp, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! HERE THE MEDIATOR does the mediation of Fields that come in on the ! importState with a timestamp consistent to the currTime of the ! mediators Clock. ! The Mediator uses the data on the import Fields to update the data ! held by Fields in the exportState. ! After this routine returns the generic Mediator will correctly ! timestamp the export Fields to the currentTime, and then update ! the Mediator Clock to: ! ! currTime -> currTime + timeStep ! ! Where the timeStep is equal to the parent timeStep. call ESMF_ClockGet(clock,currtime=time,rc=rc) call ESMF_TimeGet(time,timestring=timestr) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": time = "//trim(timestr), ESMF_LOGMSG_INFO, rc=dbrc) endif call NUOPC_ClockPrintCurrTime(clock, & "-------->MED Advance() mediating for: ", rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! write the fields imported from ocn to file call NUOPC_StateWrite(importState, fieldNameList=fldsFrOcn%shortname, & filePrefix="field_med_from_ocn_", timeslice=is%wrap%slowcntr, & overwrite=.true., relaxedFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--------------------------------------- !--- average atm accumulator !--------------------------------------- if (dbug_flag > 1) then call FieldBundle_diagnose(is%wrap%FBaccumAtm, trim(subname)//' FBaccA_B4avg ', rc=rc) call FieldBundle_diagnose(is%wrap%FBaccumIce, trim(subname)//' FBaccI_B4avg ', rc=rc) endif call FieldBundle_average(is%wrap%FBaccumAtm, is%wrap%accumcntAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call FieldBundle_average(is%wrap%FBaccumIce, is%wrap%accumcntIce, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--------------------------------------- !--- regrid average atm fields to ocean grid !--------------------------------------- if (dbug_flag > 1) then call FieldBundle_diagnose(is%wrap%FBaccumAtm, trim(subname)//' FBaccA_B4regrid ', rc=rc) call FieldBundle_diagnose(is%wrap%FBaccumIce, trim(subname)//' FBaccI_B4regrid ', rc=rc) endif ! tcx Xgrid ! XGrid intermediary required? instantiate FBXgrid FieldBundle? ! call ESMF_FieldBundleRegrid(is%wrap%FBaccumAtm, FBXgrid, is%wrap%RHa2x, rc=rc) ! call ESMF_FieldBundleRegrid(FBXgrid, is%wrap%FBforOcn , is%wrap%RHx2o, rc=rc) ! tcraig temporarily copy #if 0 !gjt: with different grids on each side we need at least a regrid here !gjt call fieldBundle_copy(is%wrap%FBforOcn, is%wrap%FBaccumAtm, rc=rc) call ESMF_FieldBundleRegrid(srcFieldBundle=is%wrap%FBaccumAtm, & dstFieldBundle=is%wrap%FBforOcn, routehandle=is%wrap%rh, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out #else call fieldBundle_copy(is%wrap%FBforOcn, is%wrap%FBaccumAtm, rc=rc) call fieldBundle_copy(is%wrap%FBforOcn, is%wrap%FBaccumIce, rc=rc) #endif if (dbug_flag > 1) then call FieldBundle_diagnose(is%wrap%FBforOcn, trim(subname)//' FB4ocn_AFregrid ', rc=rc) endif !--------------------------------------- !--- custom calculations to ocn !--------------------------------------- !--- split total solar into 4 terms and compute net shortwave !--- atm downward sw fieldname1(1) = 'sw_flux_vis_dir' fieldname1(2) = 'sw_flux_vis_dif' fieldname1(3) = 'sw_flux_nir_dir' fieldname1(4) = 'sw_flux_nir_dif' ! check fields exist checkOK = .true. do n = 1,4 checkOK = checkOK .and. FieldBundle_FldChk(is%wrap%FBaccumAtm, trim(fieldname1(n)), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return enddo if (dbug_flag > 1) then if (checkOK) then call ESMF_LogWrite(trim(subname)//' swd:found 4 sw down terms from atm', ESMF_LOGMSG_INFO, rc=dbrc) else call ESMF_LogWrite(trim(subname)//' swd:did not find 4 sw down terms from atm', ESMF_LOGMSG_INFO, rc=dbrc) endif endif ! tcraig old single downward sw field ! if (.not. checkOK) then ! fieldname1(1) = 'mdswfx' ! ! check field exists ! checkOK = FieldBundle_FldChk(is%wrap%FBaccumAtm, trim(fieldname1(1)), rc=rc) ! if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! if (dbug_flag > 1) then ! if (checkOK) then ! call ESMF_LogWrite(trim(subname)//' swd:found mdswfx from atm', ESMF_LOGMSG_INFO, rc=dbrc) ! else ! call ESMF_LogWrite(trim(subname)//' swd:did not find mdswfx from atm', ESMF_LOGMSG_INFO, rc=dbrc) ! endif ! endif ! endif if (checkOK) then !--- ocn net sw fieldname2(1) = 'mndvrsfx' fieldname2(2) = 'mndvfsfx' fieldname2(3) = 'mndirsfx' fieldname2(4) = 'mndifsfx' ! check fields exist checkOK1 = .true. do n = 1,4 checkOK1 = checkOK1 .and. FieldBundle_FldChk(is%wrap%FBforOcn, trim(fieldname2(n)), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return enddo if (dbug_flag > 1) then if (checkOK1) then call ESMF_LogWrite(trim(subname)//' swd:found 4 net sw for ocn', ESMF_LOGMSG_INFO, rc=dbrc) else call ESMF_LogWrite(trim(subname)//' swd:did not find 4 net sw for ocn', ESMF_LOGMSG_INFO, rc=dbrc) endif endif !--- ocn down sw if (.not. checkOK1) then fieldname2(1) = 'mdvrsfx' fieldname2(2) = 'mdvfsfx' fieldname2(3) = 'mdirsfx' fieldname2(4) = 'mdifsfx' checkOK1 = .true. do n = 1,4 checkOK1 = checkOK1 .and. FieldBundle_FldChk(is%wrap%FBforOcn, trim(fieldname2(n)), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return enddo if (dbug_flag > 1) then if (checkOK1) then call ESMF_LogWrite(trim(subname)//' swd:found 4 down sw for ocn', ESMF_LOGMSG_INFO, rc=dbrc) else call ESMF_LogWrite(trim(subname)//' swd:did not find 4 down sw for ocn', ESMF_LOGMSG_INFO, rc=dbrc) endif endif endif endif if (checkOK .and. checkOK1) then !--- ocean albedo from atm fieldname3(1) = 'iovisdira' fieldname3(2) = 'iovisdifa' fieldname3(3) = 'ioirdira' fieldname3(4) = 'ioirdifa' checkOK2 = .true. do n = 1,4 checkOK2 = checkOK2 .and. FieldBundle_FldChk(is%wrap%FBaccumAtm, trim(fieldname3(n)), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return enddo if (dbug_flag > 1) then if (checkOK2) then call ESMF_LogWrite(trim(subname)//' swd:found 4 ocn albedos from atm', ESMF_LOGMSG_INFO, rc=dbrc) else call ESMF_LogWrite(trim(subname)//' swd:did not find 4 ocn albedos from atm', ESMF_LOGMSG_INFO, rc=dbrc) endif endif if (.not.checkOK2) then !--- use merged albedo from atm fieldname3(1) = 'ivisdira' fieldname3(2) = 'ivisdifa' fieldname3(3) = 'iirdira' fieldname3(4) = 'iirdifa' checkOK2 = .true. do n = 1,4 checkOK2 = checkOK2 .and. FieldBundle_FldChk(is%wrap%FBaccumAtm, trim(fieldname3(n)), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return enddo if (dbug_flag > 1) then if (checkOK2) then call ESMF_LogWrite(trim(subname)//' swd:found 4 avg albedos from atm', ESMF_LOGMSG_INFO, rc=dbrc) else call ESMF_LogWrite(trim(subname)//' swd:did not find 4 avg albedos from atm', ESMF_LOGMSG_INFO, rc=dbrc) call ESMF_LogWrite(trim(subname)//' swd:use ocean albedo 0.06', ESMF_LOGMSG_INFO, rc=dbrc) endif endif endif endif if (checkOK .and. checkOK1) then ! tcraig old single downward sw field ! call FieldBundle_GetFldPtr(is%wrap%FBaccumAtm, trim(fieldname1(1)), dataPtr1, rc=rc) ! if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1,4 call FieldBundle_GetFldPtr(is%wrap%FBaccumAtm, trim(fieldname1(n)), dataPtr1, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call FieldBundle_GetFldPtr(is%wrap%FBforOcn, trim(fieldname2(n)), dataPtr2, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (.not.FldPtr_SameCheck(dataPtr1, dataPtr2, 'swnet', rc)) then call ESMF_LogWrite(trim(subname)//": ERROR in dataPtr size ", ESMF_LOGMSG_ERROR, line=__LINE__, file=__FILE__, rc=rc) return endif if (checkOK2) then call FieldBundle_GetFldPtr(is%wrap%FBaccumAtm, trim(fieldname3(n)), dataPtr3, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (.not.FldPtr_SameCheck(dataPtr1, dataPtr3, 'swnet-albedo', rc)) then call ESMF_LogWrite(trim(subname)//": ERROR in dataPtr size ", ESMF_LOGMSG_ERROR, line=__LINE__, file=__FILE__, rc=rc) return endif endif do j=lbound(dataPtr2,2),ubound(dataPtr2,2) do i=lbound(dataPtr2,1),ubound(dataPtr2,1) if (checkOK2) then ! tcraig old single downward sw field ! dataPtr2(i,j) = dataPtr1(i,j) * (1.0 - dataPtr3(i,j)) * 0.25_ESMF_KIND_R8 dataPtr2(i,j) = dataPtr1(i,j) * (1.0 - dataPtr3(i,j)) else !--- hardwire 0.06 ocean albedo ! tcraig old single downward sw field ! dataPtr2(i,j) = dataPtr1(i,j) * (1.0 - 0.06) * 0.25_ESMF_KIND_R8 dataPtr2(i,j) = dataPtr1(i,j) * (1.0 - 0.06) endif enddo enddo enddo else if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//' swd:failed', ESMF_LOGMSG_INFO, rc=dbrc) endif endif !--- compute specific humidity flux from latent heat flux fieldname1(1) = 'mlhfx' fieldname2(1) = 'mevap' ! check fields exist checkOK = FieldBundle_FldChk(is%wrap%FBaccumAtm, trim(fieldname1(1)), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return checkOK = checkOK .and. FieldBundle_FldChk(is%wrap%FBforOcn, trim(fieldname2(1)), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (checkOK) then if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//' evap:compute mevap from mlhfx', ESMF_LOGMSG_INFO, rc=dbrc) endif call FieldBundle_GetFldPtr(is%wrap%FBaccumAtm, trim(fieldname1(1)), dataPtr1, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call FieldBundle_GetFldPtr(is%wrap%FBforOcn, trim(fieldname2(1)), dataPtr2, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (.not.FldPtr_SameCheck(dataPtr1, dataPtr2, 'evap_from_mlhfx', rc)) then call ESMF_LogWrite(trim(subname)//": ERROR in dataPtr size ", ESMF_LOGMSG_ERROR, line=__LINE__, file=__FILE__, rc=rc) return endif do j=lbound(dataPtr2,2),ubound(dataPtr2,2) do i=lbound(dataPtr2,1),ubound(dataPtr2,1) dataPtr2(i,j) = dataPtr1(i,j) / const_lhvap !Lw is temperature dependent so more accurate calc can be done here. enddo enddo else if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//' evap:failed', ESMF_LOGMSG_INFO, rc=dbrc) endif endif if (dbug_flag > 1) then call FieldBundle_diagnose(is%wrap%FBforOcn, trim(subname)//' FB4ocn_AFcc ', rc=rc) endif !--------------------------------------- !--- zero accumulator !--------------------------------------- is%wrap%accumcntAtm = 0 call fieldBundle_reset(is%wrap%FBaccumAtm, value=0._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out is%wrap%accumcntIce = 0 call fieldBundle_reset(is%wrap%FBaccumIce, value=0._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then !tcx call FieldBundle_diagnose(is%wrap%FBaccumAtm, trim(subname)//' FBacc_AFzero ', rc=rc) !tcx call FieldBundle_diagnose(is%wrap%FBaccumIce, trim(subname)//' FBacc_AFzero ', rc=rc) endif !--- set export State to special value for testing call state_reset(exportState, value=-99._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call State_diagnose(exportState, trim(subname)//' es_AF99 ', rc=rc) endif !--------------------------------------- !--- copy into export state !--------------------------------------- call fieldBundle_copy(exportState, is%wrap%FBforOcn, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call State_diagnose(exportState, trim(subname)//' es_AFcp ', rc=rc) endif ! write the fields exported to ocn to file call NUOPC_StateWrite(exportState, fieldNameList=fldsToOcn%shortname, & filePrefix="field_med_to_ocn_", timeslice=is%wrap%slowcntr, & relaxedFlag=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out !--------------------------------------- is%wrap%slowcntr = is%wrap%slowcntr + 1 !--------------------------------------- !--- clean up !--------------------------------------- if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine Advance_slow !----------------------------------------------------------------------------- subroutine Finalize(gcomp, importState, exportState, clock, rc) type(ESMF_GridComp) :: gcomp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock integer, intent(out) :: rc ! local variables type(InternalState) :: is integer :: stat character(len=*),parameter :: subname='(module_MEDIATOR:Finalize)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif rc = ESMF_SUCCESS ! Get the internal state from Component. nullify(is%wrap) call ESMF_GridCompGetInternalState(gcomp, is, rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Destroy objects inside of internal state. ! TODO: destroy objects inside objects call fieldBundle_clean(is%wrap%FBaccumAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! tcraig - generates errors ! call fieldBundle_clean(is%wrap%FBaccumOcn, rc=rc) ! if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & ! line=__LINE__, & ! file=__FILE__)) & ! return ! bail out call fieldBundle_clean(is%wrap%FBaccumIce, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_clean(is%wrap%FBforAtm, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_clean(is%wrap%FBforOcn, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out call fieldBundle_clean(is%wrap%FBforIce, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & line=__LINE__, & file=__FILE__)) & return ! bail out ! Deallocate the internal state memory. deallocate(is%wrap, stat=stat) if (ESMF_LogFoundDeallocError(statusToCheck=stat, & msg="Deallocation of internal state memory failed.", & line=__LINE__, & file=__FILE__)) & return ! bail out if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine Finalize !----------------------------------------------------------------------------- !----------------------------------------------------------------------------- subroutine fieldBundle_initFromFB(FBout, FBin, grid, name, rc) ! ---------------------------------------------- ! Create FieldBundle from another FieldBundle. ! Zero out new FieldBundle ! If grid is not passed, use grid from FBin ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FBout type(ESMF_FieldBundle), intent(in) :: FBin type(ESMF_Grid) , intent(in), optional :: grid character(len=*) , intent(in), optional :: name integer , intent(out),optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) type(ESMF_Field) :: field type(ESMF_Grid) :: lgrid character(len=64) :: lname character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_initFromFB)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lname = 'undefined' if (present(name)) then lname = trim(name) endif call ESMF_FieldBundleGet(FBin, fieldCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FBin, fieldNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (present(grid)) then call fieldBundle_init(FBout, fieldNameList=fieldNameList, grid=grid, name=trim(lname), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return else call ESMF_FieldBundleGet(FBin, grid=lgrid, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call fieldBundle_init(FBout, fieldNameList=fieldNameList, grid=lgrid, name=trim(lname), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return endif deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldbundle_initFromFB !----------------------------------------------------------------------------- subroutine fieldBundle_init(FieldBundle, fieldNameList, grid, State, name, rc) ! ---------------------------------------------- ! Create FieldBundle from fieldNameList and grid ! If State if present, only include fields that are ! in both fieldNameList and State ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FieldBundle character(len=*) , intent(in) :: fieldNameList(:) type(ESMF_Grid) , intent(in) :: grid type(ESMF_State) , intent(in), optional :: State ! check if fieldnames are there character(len=*) , intent(in), optional :: name integer , intent(out),optional :: rc ! local variables integer :: i,j,n logical :: doadd character(len=64) :: lname type(ESMF_Field) :: field type(ESMF_StateItem_Flag) :: itemType character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_init)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lname = 'undefined' if (present(name)) then lname = trim(name) endif FieldBundle = ESMF_FieldBundleCreate(name=trim(lname), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n=1, size(fieldNameList) doadd = .true. if (present(State)) then call ESMF_StateGet(State, itemName=fieldNameList(n), itemType=itemType, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return doadd = (itemType /= ESMF_STATEITEM_NOTFOUND) endif if (doadd) then field = ESMF_FieldCreate(grid, ESMF_TYPEKIND_R8, name=fieldNameList(n), rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_FieldBundleAdd(FieldBundle, (/field/), rc=rc) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//":"//trim(lname)//":add "//trim(fieldNameList(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif else if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//":"//trim(lname)//":skip "//trim(fieldNameList(n)), ESMF_LOGMSG_INFO, rc=dbrc) endif endif ! doadd enddo ! fieldNameList call fieldBundle_reset(FieldBundle, value=0._ESMF_KIND_R8, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_init !----------------------------------------------------------------------------- subroutine fieldBundle_clean(FieldBundle, rc) ! ---------------------------------------------- ! Destroy fields in FieldBundle and FieldBundle ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FieldBundle integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) type(ESMF_Field) :: field character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_clean)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS call ESMF_FieldBundleGet(FieldBundle, fieldCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FieldBundle, fieldNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1, fieldCount call ESMF_FieldBundleGet(FieldBundle, fieldName=fieldNameList(n), field=field, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_FieldDestroy(field, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return enddo call ESMF_FieldBundleDestroy(FieldBundle, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_clean !----------------------------------------------------------------------------- subroutine fieldBundle_reset(FieldBundle, value, rc) ! ---------------------------------------------- ! Set all fields to value in FieldBundle ! If value is not provided, reset to 0.0 ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FieldBundle real(ESMF_KIND_R8), intent(in), optional :: value integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) real(ESMF_KIND_R8) :: lvalue real(ESMF_KIND_R8), pointer :: dataPtr(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_reset)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lvalue = 0._ESMF_KIND_R8 if (present(value)) then lvalue = value endif call ESMF_FieldBundleGet(FieldBundle, fieldCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FieldBundle, fieldNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1, fieldCount call FieldBundle_GetFldPtr(FieldBundle, fieldNameList(n), dataPtr, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do j=lbound(dataPtr,2),ubound(dataPtr,2) do i=lbound(dataPtr,1),ubound(dataPtr,1) dataPtr(i,j) = lvalue enddo enddo enddo deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_reset !----------------------------------------------------------------------------- subroutine state_reset(State, value, rc) ! ---------------------------------------------- ! Set all fields to value in State ! If value is not provided, reset to 0.0 ! ---------------------------------------------- type(ESMF_State), intent(inout) :: State real(ESMF_KIND_R8), intent(in), optional :: value integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) real(ESMF_KIND_R8) :: lvalue real(ESMF_KIND_R8), pointer :: dataPtr(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:state_reset)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lvalue = 0._ESMF_KIND_R8 if (present(value)) then lvalue = value endif call ESMF_StateGet(State, itemCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_StateGet(State, itemNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1, fieldCount call State_GetFldPtr(State, fieldNameList(n), dataPtr, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do j=lbound(dataPtr,2),ubound(dataPtr,2) do i=lbound(dataPtr,1),ubound(dataPtr,1) dataPtr(i,j) = lvalue enddo enddo enddo deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine state_reset !----------------------------------------------------------------------------- subroutine fieldBundle_average(FieldBundle, count, rc) ! ---------------------------------------------- ! Set all fields to zero in FieldBundle ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FieldBundle integer , intent(in) :: count integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) real(ESMF_KIND_R8), pointer :: dataPtr(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_average)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS if (count == 0) then call ESMF_LogWrite(trim(subname)//": WARNING count is 0", ESMF_LOGMSG_INFO, rc=dbrc) else call ESMF_FieldBundleGet(FieldBundle, fieldCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FieldBundle, fieldNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1, fieldCount call FieldBundle_GetFldPtr(FieldBundle, fieldNameList(n), dataPtr, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do j=lbound(dataPtr,2),ubound(dataPtr,2) do i=lbound(dataPtr,1),ubound(dataPtr,1) dataPtr(i,j) = dataPtr(i,j) / real(count, ESMF_KIND_R8) enddo enddo enddo deallocate(fieldNameList) endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_average !----------------------------------------------------------------------------- subroutine fieldBundle_diagnose(FieldBundle, string, rc) ! ---------------------------------------------- ! Diagnose status of fieldBundle ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FieldBundle character(len=*), intent(in), optional :: string integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) character(len=64) :: lstring real(ESMF_KIND_R8), pointer :: dataPtr(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_diagnose)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lstring = '' if (present(string)) then lstring = trim(string) endif call ESMF_FieldBundleGet(FieldBundle, fieldCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FieldBundle, fieldNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1, fieldCount call FieldBundle_GetFldPtr(FieldBundle, fieldNameList(n), dataPtr, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return write(tmpstr,'(A,3g14.7)') trim(subname)//' '//trim(lstring)//':'//trim(fieldNameList(n)), & minval(dataPtr),maxval(dataPtr),sum(dataPtr) call ESMF_LogWrite(trim(tmpstr), ESMF_LOGMSG_INFO, rc=dbrc) enddo deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_diagnose !----------------------------------------------------------------------------- subroutine state_diagnose(State, string, rc) ! ---------------------------------------------- ! Diagnose status of fieldBundle ! ---------------------------------------------- type(ESMF_State), intent(inout) :: State character(len=*), intent(in), optional :: string integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) character(len=64) :: lstring real(ESMF_KIND_R8), pointer :: dataPtr(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:state_diagnose)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lstring = '' if (present(string)) then lstring = trim(string) endif call ESMF_StateGet(State, itemCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_StateGet(State, itemNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1, fieldCount call State_GetFldPtr(State, fieldNameList(n), dataPtr, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return write(tmpstr,'(A,3g14.7)') trim(subname)//' '//trim(lstring)//':'//trim(fieldNameList(n)), & minval(dataPtr),maxval(dataPtr),sum(dataPtr) call ESMF_LogWrite(trim(tmpstr), ESMF_LOGMSG_INFO, rc=dbrc) enddo deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine state_diagnose !----------------------------------------------------------------------------- subroutine fieldBundle_copyFB2FB(FBout, FBin, rc) ! ---------------------------------------------- ! Copy common field names from FBin to FBout ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FBout type(ESMF_FieldBundle), intent(in) :: FBin integer, intent(out), optional :: rc character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_copyFB2FB)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS call fieldBundle_accum(FBout, FBin, copy=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_copyFB2FB !----------------------------------------------------------------------------- subroutine fieldBundle_copyFB2ST(STout, FBin, rc) ! ---------------------------------------------- ! Copy common field names from FBin to STout ! ---------------------------------------------- type(ESMF_State) , intent(inout) :: STout type(ESMF_FieldBundle), intent(in) :: FBin integer, intent(out), optional :: rc character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_copyFB2ST)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS call fieldBundle_accum(STout, FBin, copy=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_copyFB2ST !----------------------------------------------------------------------------- subroutine fieldBundle_copyST2FB(FBout, STin, rc) ! ---------------------------------------------- ! Copy common field names from STin to FBout ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FBout type(ESMF_State) , intent(in) :: STin integer, intent(out), optional :: rc character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_copyST2FB)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS call fieldBundle_accum(FBout, STin, copy=.true., rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_copyST2FB !----------------------------------------------------------------------------- subroutine fieldBundle_accumFB2FB(FBout, FBin, copy, rc) ! ---------------------------------------------- ! Accumulate common field names from FBin to FBout ! If copy is passed in and true, the this is a copy ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FBout type(ESMF_FieldBundle), intent(in) :: FBin logical, intent(in) , optional :: copy integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount character(len=64) ,pointer :: fieldNameList(:) logical :: exists logical :: lcopy type(ESMF_StateItem_Flag) :: itemType real(ESMF_KIND_R8), pointer :: dataPtri(:,:), dataPtro(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_accumFB2FB)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lcopy = .false. ! accumulate by default if (present(copy)) then lcopy = copy endif call ESMF_FieldBundleGet(FBout, fieldCount=fieldCount, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FBout, fieldNameList=fieldNameList, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return do n = 1, fieldCount call ESMF_FieldBundleGet(FBin, fieldName=fieldNameList(n), isPresent=exists, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (exists) then call FieldBundle_GetFldPtr(FBin, fieldNameList(n), dataPtri, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call FieldBundle_GetFldPtr(FBout, fieldNameList(n), dataPtro, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (.not.FldPtr_SameCheck(dataPtro, dataPtri, subname, rc)) then call ESMF_LogWrite(trim(subname)//": ERROR in dataPtr size ", ESMF_LOGMSG_ERROR, line=__LINE__, file=__FILE__, rc=rc) return endif if (lcopy) then do j=lbound(dataPtri,2),ubound(dataPtri,2) do i=lbound(dataPtri,1),ubound(dataPtri,1) dataPtro(i,j) = dataPtri(i,j) enddo enddo else do j=lbound(dataPtri,2),ubound(dataPtri,2) do i=lbound(dataPtri,1),ubound(dataPtri,1) dataPtro(i,j) = dataPtro(i,j) + dataPtri(i,j) enddo enddo endif endif enddo deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_accumFB2FB !----------------------------------------------------------------------------- subroutine fieldBundle_accumST2FB(FBout, STin, copy, rc) ! ---------------------------------------------- ! Accumulate common field names from State to FieldBundle ! If copy is passed in and true, the this is a copy ! ---------------------------------------------- type(ESMF_FieldBundle), intent(inout) :: FBout type(ESMF_State) , intent(in) :: STin logical, intent(in) , optional :: copy integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount logical :: lcopy character(len=64) ,pointer :: fieldNameList(:) type(ESMF_StateItem_Flag) :: itemType real(ESMF_KIND_R8), pointer :: dataPtrS(:,:), dataPtrB(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_accumST2FB)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lcopy = .false. if (present(copy)) then lcopy = copy endif call ESMF_FieldBundleGet(FBout, fieldCount=fieldCount, rc=rc) allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FBout, fieldNameList=fieldNameList, rc=rc) do n = 1, fieldCount call ESMF_StateGet(STin, itemName=fieldNameList(n), itemType=itemType, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (itemType /= ESMF_STATEITEM_NOTFOUND) then call State_GetFldPtr(STin, fieldNameList(n), dataPtrS, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call FieldBundle_GetFldPtr(FBout, fieldNameList(n), dataPtrB, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (.not.FldPtr_SameCheck(dataPtrS, dataPtrB, subname, rc)) then call ESMF_LogWrite(trim(subname)//": ERROR in dataPtr size ", ESMF_LOGMSG_ERROR, line=__LINE__, file=__FILE__, rc=rc) return endif if (lcopy) then do j=lbound(dataPtrB,2),ubound(dataPtrB,2) do i=lbound(dataPtrB,1),ubound(dataPtrB,1) dataPtrB(i,j) = dataPtrS(i,j) enddo enddo else do j=lbound(dataPtrB,2),ubound(dataPtrB,2) do i=lbound(dataPtrB,1),ubound(dataPtrB,1) dataPtrB(i,j) = dataPtrB(i,j) + dataPtrS(i,j) enddo enddo endif endif ! statefound enddo ! fieldCount deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_accumST2FB !----------------------------------------------------------------------------- subroutine fieldBundle_accumFB2ST(STout, FBin, copy, rc) ! ---------------------------------------------- ! Accumulate common field names from FieldBundle to State ! If copy is passed in and true, the this is a copy ! ---------------------------------------------- type(ESMF_State) , intent(inout) :: STout type(ESMF_FieldBundle), intent(in) :: FBin logical, intent(in) , optional :: copy integer, intent(out), optional :: rc ! local variables integer :: i,j,n integer :: fieldCount logical :: lcopy character(len=64) ,pointer :: fieldNameList(:) type(ESMF_StateItem_Flag) :: itemType real(ESMF_KIND_R8), pointer :: dataPtrS(:,:), dataPtrB(:,:) character(len=*),parameter :: subname='(module_MEDIATOR:fieldBundle_accumFB2ST)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS lcopy = .false. if (present(copy)) then lcopy = copy endif call ESMF_FieldBundleGet(FBin, fieldCount=fieldCount, rc=rc) allocate(fieldNameList(fieldCount)) call ESMF_FieldBundleGet(FBin, fieldNameList=fieldNameList, rc=rc) do n = 1, fieldCount call ESMF_StateGet(STout, itemName=fieldNameList(n), itemType=itemType, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (itemType /= ESMF_STATEITEM_NOTFOUND) then call FieldBundle_GetFldPtr(FBin, fieldNameList(n), dataPtrB, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call State_GetFldPtr(STout, fieldNameList(n), dataPtrS, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (.not.FldPtr_SameCheck(dataPtrS, dataPtrB, subname, rc)) then call ESMF_LogWrite(trim(subname)//": ERROR in dataPtr size ", ESMF_LOGMSG_ERROR, line=__LINE__, file=__FILE__, rc=rc) return endif if (lcopy) then do j=lbound(dataPtrB,2),ubound(dataPtrB,2) do i=lbound(dataPtrB,1),ubound(dataPtrB,1) dataPtrS(i,j) = dataPtrB(i,j) enddo enddo else do j=lbound(dataPtrB,2),ubound(dataPtrB,2) do i=lbound(dataPtrB,1),ubound(dataPtrB,1) dataPtrS(i,j) = dataPtrS(i,j) + dataPtrB(i,j) enddo enddo endif endif ! statefound enddo ! fieldCount deallocate(fieldNameList) if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fieldBundle_accumFB2ST !----------------------------------------------------------------------------- logical function FieldBundle_FldChk(FB, fldname, rc) type(ESMF_FieldBundle), intent(in) :: FB character(len=*) ,intent(in) :: fldname integer, intent(out), optional :: rc ! local variables logical :: isPresent integer :: lrc character(len=*),parameter :: subname='(module_MEDIATOR:FieldBundle_FldChk)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS FieldBundle_FldChk = .false. call ESMF_FieldBundleGet(FB, fieldName=trim(fldname), isPresent=isPresent, rc=lrc) if (present(rc)) rc = lrc if (ESMF_LogFoundError(rcToCheck=lrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (isPresent) then FieldBundle_FldChk = .true. endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end function FieldBundle_FldChk !----------------------------------------------------------------------------- subroutine FieldBundle_GetFldPtr(FB, fldname, fldptr, rc) type(ESMF_FieldBundle), intent(in) :: FB character(len=*) , intent(in) :: fldname real(ESMF_KIND_R8), pointer, intent(in) :: fldptr(:,:) integer, intent(out), optional :: rc ! local variables type(ESMF_Field) :: lfield integer :: lrc character(len=*),parameter :: subname='(module_MEDIATOR:FieldBundle_GetFldPtr)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS call ESMF_FieldBundleGet(FB, fieldName=trim(fldname), field=lfield, rc=lrc) if (ESMF_LogFoundError(rcToCheck=lrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_FieldGet(lfield, farrayPtr=fldptr, rc=lrc) if (ESMF_LogFoundError(rcToCheck=lrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (present(rc)) rc = lrc if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine FieldBundle_GetFldPtr !----------------------------------------------------------------------------- !----------------------------------------------------------------------------- subroutine State_GetFldPtr(ST, fldname, fldptr, rc) type(ESMF_State), intent(in) :: ST character(len=*), intent(in) :: fldname real(ESMF_KIND_R8), pointer, intent(in) :: fldptr(:,:) integer, intent(out), optional :: rc ! local variables type(ESMF_Field) :: lfield integer :: lrc character(len=*),parameter :: subname='(module_MEDIATOR:State_GetFldPtr)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS call ESMF_StateGet(ST, itemName=trim(fldname), field=lfield, rc=lrc) if (ESMF_LogFoundError(rcToCheck=lrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return call ESMF_FieldGet(lfield, farrayPtr=fldptr, rc=lrc) if (ESMF_LogFoundError(rcToCheck=lrc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return if (present(rc)) rc = lrc if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine State_GetFldPtr !----------------------------------------------------------------------------- logical function FldPtr_SameCheck(fldptr1, fldptr2, cstring, rc) real(ESMF_KIND_R8), pointer, intent(in) :: fldptr1(:,:) real(ESMF_KIND_R8), pointer, intent(in) :: fldptr2(:,:) character(len=*), intent(in) :: cstring integer, intent(out), optional :: rc ! local variables integer :: lrc character(len=*),parameter :: subname='(module_MEDIATOR:FldPtr_SameCheck)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (present(rc)) rc = ESMF_SUCCESS FldPtr_SameCheck = .false. if (lbound(fldptr2,2) /= lbound(fldptr1,2) .or. & lbound(fldptr2,1) /= lbound(fldptr1,1) .or. & ubound(fldptr2,2) /= ubound(fldptr1,2) .or. & ubound(fldptr2,1) /= ubound(fldptr1,1)) then call ESMF_LogWrite(trim(subname)//": ERROR in data size "//trim(cstring), ESMF_LOGMSG_ERROR, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return write(tmpstr,*) trim(subname)//': fldptr2 ',lbound(fldptr2),ubound(fldptr2) call ESMF_LogWrite(trim(tmpstr), ESMF_LOGMSG_INFO, rc=dbrc) write(tmpstr,*) trim(subname)//': fldptr1 ',lbound(fldptr1),ubound(fldptr1) call ESMF_LogWrite(trim(tmpstr), ESMF_LOGMSG_INFO, rc=dbrc) else FldPtr_SameCheck = .true. endif if (present(rc)) rc = lrc if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end function FldPtr_SameCheck !----------------------------------------------------------------------------- subroutine fld_list_add(fldlist, stdname, shortname, longname, units, & transferOffer) ! ---------------------------------------------- ! Accumulate common field names from FieldBundle to State ! If copy is passed in and true, the this is a copy ! ---------------------------------------------- type(fld_list_type),intent(inout) :: fldlist character(len=*), intent(in) :: stdname character(len=*), intent(in) :: shortname character(len=*), intent(in) :: longname character(len=*), intent(in) :: units character(len=*), intent(in) :: transferOffer ! local variables integer :: cnum ! current size of array integer :: nnum ! new size of array integer :: rc character(len=256), pointer :: tmpstr(:) character(len=*),parameter :: subname='(module_MEDIATOR:fld_list_add)' if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": called", ESMF_LOGMSG_INFO, rc=dbrc) endif if (fldlist%num < 0) then nnum = 10 fldlist%num = 0 allocate(fldlist%stdname(nnum)) allocate(fldlist%shortname(nnum)) allocate(fldlist%longname(nnum)) allocate(fldlist%units(nnum)) allocate(fldlist%transferOffer(nnum)) endif cnum = size(fldlist%stdname) if (fldlist%num > cnum) then call ESMF_LogWrite(trim(subname)//": ERROR in num for fld "//trim(stdname), ESMF_LOGMSG_ERROR, rc=rc) return endif if (fldlist%num == cnum) then nnum = cnum + 10 allocate(tmpstr(cnum)) tmpstr(1:cnum) = fldlist%stdname(1:cnum) deallocate(fldlist%stdname) allocate(fldlist%stdname(nnum)) fldlist%stdname(1:cnum) = tmpstr(1:cnum) tmpstr(1:cnum) = fldlist%shortname(1:cnum) deallocate(fldlist%shortname) allocate(fldlist%shortname(nnum)) fldlist%shortname(1:cnum) = tmpstr(1:cnum) tmpstr(1:cnum) = fldlist%longname(1:cnum) deallocate(fldlist%longname) allocate(fldlist%longname(nnum)) fldlist%longname(1:cnum) = tmpstr(1:cnum) tmpstr(1:cnum) = fldlist%units(1:cnum) deallocate(fldlist%units) allocate(fldlist%units(nnum)) fldlist%units(1:cnum) = tmpstr(1:cnum) tmpstr(1:cnum) = fldlist%transferOffer(1:cnum) deallocate(fldlist%transferOffer) allocate(fldlist%transferOffer(nnum)) fldlist%transferOffer(1:cnum) = tmpstr(1:cnum) deallocate(tmpstr) endif fldlist%num = fldlist%num + 1 fldlist%stdname (fldlist%num) = trim(stdname) fldlist%shortname (fldlist%num) = trim(shortname) fldlist%longname (fldlist%num) = trim(longname) fldlist%units (fldlist%num) = trim(units) fldlist%transferOffer (fldlist%num) = trim(transferOffer) !-------------------------------------------------- ! This automatically adds dictionary entries ! Want fields to be defined in the global dictionary !-------------------------------------------------- ! if (.not.NUOPC_FieldDictionaryHasEntry(trim(stdname))) then ! call NUOPC_FieldDictionaryAddEntry( & ! standardName = trim(stdname) , & ! canonicalUnits = trim(units) , & ! defaultLongName = trim(longname) , & ! defaultShortName = trim(shortname) , rc=rc); ! if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, & ! line=__LINE__, & ! file=__FILE__)) & ! return ! bail out ! endif if (dbug_flag > 1) then call ESMF_LogWrite(trim(subname)//": done", ESMF_LOGMSG_INFO, rc=dbrc) endif end subroutine fld_list_add !----------------------------------------------------------------------------- end module #endif