From 18ca5e49d917938e82fbdf46a581648e8fa5ebc0 Mon Sep 17 00:00:00 2001 From: Steven Brus Date: Mon, 4 Feb 2019 14:06:00 -0700 Subject: [PATCH 1/3] Add time varying atmospheric forcing - Forcing includes u,v wind velocities, and atmospheric pressure - A tanh ramp has been applied to these variables for spin-up purposes - Wind stress computed with drag law from: J.R. Garratt MWR 1977 - Design document included in docs/ocean/design_docs - The logic used to decide when to write restart information for all other previously added time varying forcing inputs (i.e. salinity restoring, shortwave, and ecosys) has been unified since the MPAS_forcing_write_restart_times should only be called once. --- docs/ocean/design_docs/time-varying-wind.rst | 100 ++++ src/core_ocean/Registry.xml | 64 +++ .../driver/mpas_ocn_core_interface.F | 13 + .../mode_forward/mpas_ocn_forward_mode.F | 24 +- src/core_ocean/shared/Makefile | 5 +- .../shared/mpas_ocn_time_varying_forcing.F | 461 ++++++++++++++++++ 6 files changed, 660 insertions(+), 7 deletions(-) create mode 100644 docs/ocean/design_docs/time-varying-wind.rst create mode 100644 src/core_ocean/shared/mpas_ocn_time_varying_forcing.F diff --git a/docs/ocean/design_docs/time-varying-wind.rst b/docs/ocean/design_docs/time-varying-wind.rst new file mode 100644 index 000000000000..2d2326a97cc2 --- /dev/null +++ b/docs/ocean/design_docs/time-varying-wind.rst @@ -0,0 +1,100 @@ +Setting up time-varying forcing for MPAS-O +========================================== +Implementation +--------------- + https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F + +API +--- + https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/framework/mpas_forcing.F + +Example datasets +---------------- + https://zenodo.org/record/1219191#.W9jWCKlRcUF with example from this dataset:: + + > pwd + /Users/pwolfram/Downloads/MPAS-Seaice_test_dataset_V1/domain_QU240km + + > ncdump -h LYq_six_hourly.2000.nc + netcdf LYq_six_hourly.2000 { + dimensions: + nCells = 1794 ; + StrLen = 64 ; + Time = UNLIMITED ; // (1460 currently) + variables: + char xtime(Time, StrLen) ; + double airTemperature(Time, nCells) ; + double airSpecificHumidity(Time, nCells) ; + double uAirVelocity(Time, nCells) ; + double vAirVelocity(Time, nCells) ; + } + + > ncdump -v xtime LYq_six_hourly.2000.nc | tail + "2000-12-29_24:00:00 ", + "2000-12-30_06:00:00 ", + "2000-12-30_12:00:00 ", + "2000-12-30_18:00:00 ", + "2000-12-30_24:00:00 ", + "2000-12-31_06:00:00 ", + "2000-12-31_12:00:00 ", + "2000-12-31_18:00:00 ", + "2000-12-31_24:00:00 " ; + } + +Data structure +-------------- +1. Global variables needed: `type (MPAS_forcing_group_type), pointer :: seaiceForcingGroups` + +2. Register against the `ForcingGroups` using the following initialization steps. `ForcingGroups` is a pointer to a list of forcings, e.g., see initialized group in https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L167 and members of the group https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L180 and https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L193 + +3. Streams file defines these source inputs, use example list of steps to get the data into a registry defined variable field / array. + +Initialization +-------------- +Example of init steps (https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L232) + + +1. Create forcing group via `MPAS_forcing_init_group` https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L167 + +2. Initialize fields via `MPAS_forcing_init_field` https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L180 + +3. Initialize the data via reading the file with `MPAS_forcing_init_field_data`: https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L232 + +In time-step usage +------------------ +Example of usage steps: + +1. `MPAS_forcing_get_forcing` Loop over all the individual forcing fields in the forcing group and get the data and perform the time interpolation. https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L389 + +2. `MPAS_forcing_get_forcing_time` Return the current forcing clock time for a forcing group. https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L517 + +3. `MPAS_forcing_write_restart_times` Loop over the forcing groups in the forcing group object and write out the forcing clock times to registry variables that are included in the restart stream. 'forcingGroupHead' is the forcing group object https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/shared/mpas_seaice_forcing.F#L2080 + +Registry changes needed (for restarts to work) +---------------------------------------------- +Registry variables needed for restart: + +1. `nForcingGroupMax` https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/Registry.xml#L287 + +2. `nForcingGroupCounter` https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/Registry.xml#L3295 + +3. `forcingGroupNames` https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/Registry.xml#L3297 + +4. `forcingGroupRestartTimes` https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/Registry.xml#L3298 + +Register to restart streams: + +1. https://github.com/MPAS-Dev/MPAS-Model/blob/seaice/develop/src/core_seaice/Registry.xml#L1798 + + | `` + | `` + +Additional resources +-------------------- +M Maltrud PRs using this information: https://github.com/MPAS-Dev/MPAS/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aclosed+author%3Amaltrud +Old (depricated-- recommended to NOT USE) design doc: https://docs.google.com/document/d/1QtjmVCxLKS-S9Z_X8-WiHqXGn_yDu_VFHLA93ZZHg88/edit + +Time estimate (MPAS / MPAS-O novice) +From start (this document) to merged PR: +2 solid weeks +4 weeks half-time diff --git a/src/core_ocean/Registry.xml b/src/core_ocean/Registry.xml index c30facd08db8..84826e8ae80c 100644 --- a/src/core_ocean/Registry.xml +++ b/src/core_ocean/Registry.xml @@ -713,6 +713,40 @@ possible_values="Any positive real number." /> + + + + + + + + + + + @@ -1602,6 +1637,17 @@ + + + + + + + + + + + \brief Module to handle time-varying forcing for the ocean core +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> Manages the wind and pressure forcing for the ocean. +!> Based very closely on the seaice forcing module and +!> framework written by Adrian Turner. +! +!----------------------------------------------------------------------- + +module ocn_time_varying_forcing + + use mpas_derived_types + use mpas_pool_routines + use mpas_timekeeping + use mpas_forcing + use mpas_stream_manager + use ocn_framework_forcing + use mpas_log, only: mpas_log_write + + implicit none + + private + public :: & + ocn_time_varying_forcing_init, & + ocn_time_varying_forcing_get, & + ocn_time_varying_forcing_write_restart_times + +contains + +!----------------------------------------------------------------------- +! initialization +!----------------------------------------------------------------------- + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! ocn_time_varying_forcing_init +! +!> \brief Driver for ocean core forcing initialization +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_time_varying_forcing_init(domain)!{{{ + + type (domain_type) :: domain + + logical, pointer :: & + config_use_atmospheric_forcing + + call MPAS_pool_get_config(domain % configs, "config_use_time_varying_atmospheric_forcing", config_use_atmospheric_forcing) + + ! init the atmospheric forcing + if (config_use_atmospheric_forcing) then + call init_atmospheric_forcing(domain) + endif + + ! init other forcings, to be added later as needed + !if (config_use_time_varying_****_forcing) then + ! call init_****_forcing(domain) + !endif + + end subroutine ocn_time_varying_forcing_init!}}} + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! init_atmospheric_forcing +! +!> \brief +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> +! +!----------------------------------------------------------------------- + + subroutine init_atmospheric_forcing(domain)!{{{ + + type (domain_type) :: domain + + character(len=strKIND), pointer :: & + config_atmospheric_forcing_type + + call MPAS_pool_get_config(domain % configs, "config_time_varying_atmospheric_forcing_type", config_atmospheric_forcing_type) + + select case (trim(config_atmospheric_forcing_type)) + case ("WINDPRES") + call init_atmospheric_forcing_WINDPRES(domain) + case default + call mpas_log_write("Atmospheric forcing type unknown: "//trim(config_atmospheric_forcing_type), MPAS_LOG_CRIT) + end select + + end subroutine init_atmospheric_forcing!}}} + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! init_atmospheric_forcing_WINDPRES +! +!> \brief Initialize the forcing objects for wind and pressure +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> This routine calls the MPAS_forcing module subroutines that initializes +!> the forcings type +! +!----------------------------------------------------------------------- + + subroutine init_atmospheric_forcing_WINDPRES(domain)!{{{ + + type(domain_type) :: domain + + character(len=strKIND), pointer :: & + config_forcing_start_time, & + config_forcing_cycle_start, & + config_forcing_cycle_duration, & + forcingInterval, & + forcingReferenceTime + + logical, pointer :: & + config_do_restart + + ! get atmospheric forcing configuration options + call MPAS_pool_get_config(& + domain % configs, & + "config_time_varying_atmospheric_forcing_start_time", & + config_forcing_start_time) + + call MPAS_pool_get_config(& + domain % configs, & + "config_time_varying_atmospheric_forcing_cycle_start", & + config_forcing_cycle_start) + + call MPAS_pool_get_config(& + domain % configs, & + "config_time_varying_atmospheric_forcing_cycle_duration", & + config_forcing_cycle_duration) + + call MPAS_pool_get_config(& + domain % configs, & + "config_time_varying_atmospheric_forcing_interval", & + forcingInterval) + + call MPAS_pool_get_config(& + domain % configs, & + "config_time_varying_atmospheric_forcing_reference_time", & + forcingReferenceTime) + + call MPAS_pool_get_config(& + domain % configs, & + "config_do_restart", & + config_do_restart) + + ! create the atmospheric forcing group + call MPAS_forcing_init_group(& + forcingGroupHead, & ! forcingGroupHead + "ocn_atmospheric_forcing", & ! forcingGroupName + domain, & ! domain + config_forcing_start_time, & ! startTimeStr + config_forcing_cycle_start, & ! forcingCycleStart + config_forcing_cycle_duration, & ! forcingCycleDuration + config_do_restart)!, & ! restart + !.false.) ! forcingCycleStartInclusive + + ! windSpeedU init + call MPAS_forcing_init_field(& + domain % streamManager, & ! streamManager + forcingGroupHead, & ! forcingGroupHead + "ocn_atmospheric_forcing", & ! forcingGroupName + "windSpeedU", & ! forcingName + "atmospheric_forcing", & ! forcingStreamID + "timeVaryingForcing", & ! poolname + "windSpeedU", & ! fieldname + "linear", & ! interpolationType + forcingReferenceTime, & ! forcingReferenceTimeStr + forcingInterval)!, ! forcingIntervalStr + !"next") ! forcingInitializationType + + ! windSpeedV init + call MPAS_forcing_init_field(& + domain % streamManager, & + forcingGroupHead, & + "ocn_atmospheric_forcing", & + "windSpeedV", & + "atmospheric_forcing", & + "timeVaryingForcing", & + "windSpeedV", & + "linear", & + forcingReferenceTime, & + forcingInterval)!, & + !"next") + + ! atmosphericPressure init + call MPAS_forcing_init_field(& + domain % streamManager, & + forcingGroupHead, & + "ocn_atmospheric_forcing", & + "atmosPressure", & + "atmospheric_forcing", & + "timeVaryingForcing", & + "atmosPressure", & + "linear", & + forcingReferenceTime, & + forcingInterval)!, & + !"next") + + call MPAS_forcing_init_field_data(& + forcingGroupHead, & ! forcingGroupHead + "ocn_atmospheric_forcing", & ! forcingGroupName + domain % streamManager, & ! streamManager + config_do_restart, & ! restart + .false.) ! interpolateAtInit + + end subroutine init_atmospheric_forcing_WINDPRES!}}} + +!----------------------------------------------------------------------- +! runtime +!----------------------------------------------------------------------- + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! ocn_time_varying_forcing_get +! +!> \brief Retrieve forcing data during time stepping +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> This routine calls the MPAS_forcing routine that will perform the +!> forcing data aquisition and interpolation during timestepping +! +!----------------------------------------------------------------------- + + subroutine ocn_time_varying_forcing_get(streamManager, domain, simulationClock)!{{{ + + type (MPAS_streamManager_type), intent(inout) :: streamManager + + type (domain_type) :: domain + + type (MPAS_clock_type) :: simulationClock + + logical, pointer :: & + config_use_atmospheric_forcing + + call MPAS_pool_get_config(domain % configs, "config_use_time_varying_atmospheric_forcing", config_use_atmospheric_forcing) + + if (config_use_atmospheric_forcing) then + + call atmospheric_forcing(& + streamManager, & + domain, & + simulationClock) + + endif + + ! call other forcings, to be added if needed + ! if (config_use_****_forcing) then + ! call ****_forcing(& + ! streamManager, & + ! domain, & + ! simulationClock) + ! endif + + + end subroutine ocn_time_varying_forcing_get!}}} + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! atmospheric_forcing +! +!> \brief +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> +! +!----------------------------------------------------------------------- + + subroutine atmospheric_forcing(streamManager, domain, simulationClock)!{{{ + + type (MPAS_streamManager_type), intent(inout) :: streamManager + + type (domain_type) :: domain + + type (MPAS_clock_type) :: simulationClock + + type (MPAS_time_type) :: currentForcingTime + + type (block_type), pointer :: block + + character(len=StrKIND), pointer :: config_dt + + character(len=strKIND), pointer :: config_atmospheric_forcing_type + + type (MPAS_timeInterval_type) :: timeStepESMF + + character(len=StrKIND) :: timeStamp + + real (kind=RKIND) :: dtSim + + integer :: err + + ! configurations + call mpas_pool_get_config(domain % configs, 'config_dt', config_dt) + call mpas_pool_get_config(domain % configs, 'config_time_varying_atmospheric_forcing_type', config_atmospheric_forcing_type) + + ! convert config_dt to real + call mpas_set_timeInterval(timeStepESMF, timeString=config_dt,ierr=err) + call mpas_get_timeInterval(timeStepESMF, dt=dtSim) + + ! use the forcing layer to get data + call MPAS_forcing_get_forcing(& + forcingGroupHead, & ! forcingGroupHead + "ocn_atmospheric_forcing", & ! forcingGroupName + streamManager, & ! streamManager + dtSim) ! dt + + call MPAS_forcing_get_forcing_time(& + forcingGroupHead, & ! forcingGroupHead + "ocn_atmospheric_forcing", & ! forcingGroupName + currentForcingTime) ! forcingTime + !call mpas_get_time(curr_time=currentForcingTime, dateTimeString=timeStamp, ierr=err) + !call mpas_log_write('Forcing time ' // trim(timeStamp)) + + ! perform post forcing + block => domain % blocklist + do while (associated(block)) + + ! apply drag law to compute wind stress from wind speed + if (trim(config_atmospheric_forcing_type) == "WINDPRES") then + call post_atmospheric_forcing(block) + endif + + block => block % next + end do + + end subroutine atmospheric_forcing!}}} + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! post_atmospheric_forcing +! +!> \brief Calculate wind stress from wind speed and apply ramp +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> Uses drag law from Garratt, J.R., 1977. Review of drag coefficients +!> over oceans and continents. Monthly weather review, 105(7), pp.915-929. +!> +! +!----------------------------------------------------------------------- + + subroutine post_atmospheric_forcing(block)!{{{ + + type (block_type), pointer :: block + + type (MPAS_time_type) :: currentForcingTime + + type (mpas_pool_type), pointer :: & + mesh, & + forcingPool, & + timeVaryingForcingPool, & + diagnosticsPool + + real(kind=RKIND), dimension(:), pointer :: & + windSpeedU, & + windSpeedV, & + windSpeedMagnitude, & + windStressZonal, & + windStressMeridional, & + atmosPressure, & + atmosphericPressure + + real(kind=RKIND) :: & + windStressCoefficient, & + rhoAir, & + ramp, & + currentTime + + real(kind=RKIND), pointer:: & + config_forcing_ramp, & + daysSinceStartOfSim + + integer, pointer :: & + nCells + + integer :: & + iCell + + call MPAS_pool_get_config(block % configs, "config_time_varying_atmospheric_forcing_ramp", config_forcing_ramp) + + call MPAS_pool_get_subpool(block % structs, "mesh", mesh) + call MPAS_pool_get_subpool(block % structs, "forcing", forcingPool) + call MPAS_pool_get_subpool(block % structs, "timeVaryingForcing", timeVaryingForcingPool) + call MPAS_pool_get_subpool(block % structs, "diagnostics", diagnosticsPool) + + call MPAS_pool_get_dimension(mesh, "nCells", nCells) + + call MPAS_pool_get_array(diagnosticsPool, "daysSinceStartOfSim", daysSinceStartOfSim) + call MPAS_pool_get_array(timeVaryingForcingPool, "windSpeedU", windSpeedU) + call MPAS_pool_get_array(timeVaryingForcingPool, "windSpeedV", windSpeedV) + call MPAS_pool_get_array(timeVaryingForcingPool, "windSpeedMagnitude", windSpeedMagnitude) + call MPAS_pool_get_array(forcingPool, "windStressZonal", windStressZonal) + call MPAS_pool_get_array(forcingPool, "windStressMeridional", windStressMeridional) + + call MPAS_pool_get_array(timeVaryingForcingPool, "atmosPressure", atmosPressure) + call MPAS_pool_get_array(forcingPool, "atmosphericPressure", atmosphericPressure) + + rhoAir = 1.225_RKIND + + ramp = tanh((2.0_RKIND*daysSinceStartOfSim)/config_forcing_ramp) + + do iCell = 1, nCells + + windSpeedU(iCell) = ramp*windSpeedU(iCell) + windSpeedV(iCell) = ramp*windSpeedV(iCell) + windSpeedMagnitude(iCell) = sqrt(windSpeedU(iCell)**2 + windSpeedV(iCell)**2) + windStressCoefficient = (0.75_RKIND + 0.067_RKIND * windSpeedMagnitude(iCell)) * 0.001_RKIND * rhoAir ! Garratt 1977 + + windStressZonal(iCell) = windSpeedU(iCell) * windSpeedMagnitude(iCell) * windStressCoefficient + windStressMeridional(iCell) = windSpeedV(iCell) * windSpeedMagnitude(iCell) * windStressCoefficient + + atmosphericPressure(iCell) = ((1.0_RKIND-ramp)*101325.0_RKIND + ramp*atmosPressure(iCell)) - 101325.0_RKIND + + enddo + + end subroutine post_atmospheric_forcing!}}} + + +!----------------------------------------------------------------------- +! restart +!----------------------------------------------------------------------- +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! ocn_time_varying_forcing_write_restart_times +! +!> \brief +!> \author Steven Brus, LANL +!> \date 1/8/2019 +!> \details +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_time_varying_forcing_write_restart_times(domain)!{{{ + + type(domain_type) :: domain + + call MPAS_forcing_write_restart_times(forcingGroupHead) + + end subroutine ocn_time_varying_forcing_write_restart_times!}}} + +!----------------------------------------------------------------------- + +end module ocn_time_varying_forcing +! vim: foldmethod=marker From c9d4c6b4d49a02c5b9d2f1e78b5f3c200af6cd51 Mon Sep 17 00:00:00 2001 From: Steven Brus Date: Mon, 4 Feb 2019 14:19:10 -0700 Subject: [PATCH 2/3] Add SOMA test case in compass for time varying atmospheric forcing --- .../32km/time_varying_wind/compute_forcing.py | 51 +++++++++++++ .../32km/time_varying_wind/config_driver.xml | 28 ++++++++ .../32km/time_varying_wind/config_forward.xml | 64 +++++++++++++++++ .../32km/time_varying_wind/config_init1.xml | 66 +++++++++++++++++ .../32km/time_varying_wind/config_init2.xml | 71 +++++++++++++++++++ 5 files changed, 280 insertions(+) create mode 100755 testing_and_setup/compass/ocean/soma/32km/time_varying_wind/compute_forcing.py create mode 100644 testing_and_setup/compass/ocean/soma/32km/time_varying_wind/config_driver.xml create mode 100644 testing_and_setup/compass/ocean/soma/32km/time_varying_wind/config_forward.xml create mode 100644 testing_and_setup/compass/ocean/soma/32km/time_varying_wind/config_init1.xml create mode 100644 testing_and_setup/compass/ocean/soma/32km/time_varying_wind/config_init2.xml diff --git a/testing_and_setup/compass/ocean/soma/32km/time_varying_wind/compute_forcing.py b/testing_and_setup/compass/ocean/soma/32km/time_varying_wind/compute_forcing.py new file mode 100755 index 000000000000..854f69ed89c7 --- /dev/null +++ b/testing_and_setup/compass/ocean/soma/32km/time_varying_wind/compute_forcing.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +import numpy as np +import scipy as sp +import xarray as xr +import netCDF4 +import datetime + +forcing = xr.open_dataset('forcing.nc') + +# build xtime +time = np.arange(26) +ref_date = datetime.datetime.strptime('1901-01-01_00:00:00','%Y-%m-%d_%H:%M:%S') +xtime = [] +for t in time: + date = ref_date + datetime.timedelta(hours=np.float64(t)) + xdate = date.strftime('%Y-%m-%d_%H:%M:%S')+45*' ' + xdate = '0001'+xdate[4:] # Change year because strftime has issues with years <1900 + xtime.append(xdate) + +scaling = np.linspace(0,1.0,len(xtime)).T + +# build fields +def make_data_array(values, scaling, forcing): + #adjusted = np.sign(values)*np.sqrt(scaling[np.newaxis,:].T*1e3*abs(values)) + adjusted = np.repeat(100.0*values,len(xtime),axis=0)*scaling[:,np.newaxis] + return adjusted + +windSpeedU = make_data_array(forcing.windStressZonal.values, scaling, forcing) +windSpeedV = make_data_array(forcing.windStressMeridional.values, scaling, forcing) +atmosphericPressure = windSpeedU*0.0 + 101325.0 + +ncds = netCDF4.Dataset('atmospheric_forcing.nc', 'w', format='NETCDF3_64BIT_OFFSET') + +ncds.createDimension('nCells', len(forcing.nCells)) +ncds.createDimension('StrLen', 64) +ncds.createDimension('Time', None) + +time = ncds.createVariable('xtime','S1', ('Time', 'StrLen')) +time[:] = netCDF4.stringtochar(np.asarray(xtime)) + +time = ncds.dimensions['Time'].name +ncells = ncds.dimensions['nCells'].name +ncds.createVariable('windSpeedU', np.float64,(time, ncells)) +ncds.createVariable('windSpeedV', np.float64,(time, ncells)) +ncds.createVariable('atmosPressure', np.float64,(time, ncells)) + +ncds.variables['windSpeedU'][:,:] = windSpeedU[:,:] +ncds.variables['windSpeedV'][:,:] = windSpeedV[:,:] +ncds.variables['atmosPressure'][:,:] = atmosphericPressure[:,:] + +ncds.close() diff --git a/testing_and_setup/compass/ocean/soma/32km/time_varying_wind/config_driver.xml b/testing_and_setup/compass/ocean/soma/32km/time_varying_wind/config_driver.xml new file mode 100644 index 000000000000..046265dd2ba3 --- /dev/null +++ b/testing_and_setup/compass/ocean/soma/32km/time_varying_wind/config_driver.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + +