<p><b>mhoffman@lanl.gov</b> 2012-06-08 13:00:37 -0600 (Fri, 08 Jun 2012)</p><p>BRANCH COMMIT -- land ice<br>
<br>
Created option for using annual forcing from the input file.  <br>
<br>
See Registry for invocation: config_forcing_frequency = 'Annual'<br>
The forcing is setup in a new module: land_ice_annual_forcing<br>
<br>
* This commit will break any existing grids, because a land ice grid will now need new fields: betaTimeSeries, sfcMassBalTimeSeries, sfcAirTempTimeSeries, basalHeatFluxTimeSeries<br>
* These fields need to be present even if time-series are not supplied (in which case they would have a single time level).<br>
* The scripts in grid_tools and test_cases have been modified to work with the requirements, so any new grids generated with them will work with this revision of the land ice core.<br>
* Using annual forcing with large datasets may create memory problems since the entire forcing time-series is read into memory during init and held for the entire simulation.<br>
[On my laptop with 4 processors/8GB total memory, adding a single 100-yr forcing field for 5km Greenland (346,000 cells) created only a minor performance hit after file input was complete.  However, adding 2 200-yr forcing fields created a large performance hit (the time spent on time integration was 2-4x greater despite not touching that part of the code).]<br>
</p><hr noshade><pre><font color="gray">Modified: branches/land_ice_projects/grid_tools/add_land_ice_variables_to_mpas_grid.py
===================================================================
--- branches/land_ice_projects/grid_tools/add_land_ice_variables_to_mpas_grid.py        2012-06-07 17:25:03 UTC (rev 1973)
+++ branches/land_ice_projects/grid_tools/add_land_ice_variables_to_mpas_grid.py        2012-06-08 19:00:37 UTC (rev 1974)
@@ -65,6 +65,11 @@
 # Create nVertLevelsPlus2 dimension
 # fileout.createDimension('nVertLevelsPlus2', filein.dimensions['nVertLevels'] + 2)
 
+# Create the dimensions needed for time-dependent forcings
+fileout.createDimension('nBetaTimeSlices', 1)
+fileout.createDimension('nSfcMassBalTimeSlices', 1)
+fileout.createDimension('nSfcAirTempTimeSlices', 1)
+fileout.createDimension('nBasalHeatFluxTimeSlices', 1)
 
 
 # Copy over all of the required grid variables to the new file
@@ -102,14 +107,15 @@
 newvar = fileout.createVariable('temperature', datatype, ('Time', 'nCells', 'nVertLevels'))
 #newvar = fileout.createVariable('temperature', 'd', ('Time', 'nCells', 'nVertLevelsPlus2'))
 newvar[:] = numpy.zeros(newvar.shape)
+
 # These boundary conditions are currently part of mesh, and are time independent.  If they change, make sure to adjust the dimensions here and in Registry.
-newvar = fileout.createVariable('beta', datatype, ( 'nCells',))
+newvar = fileout.createVariable('betaTimeSeries', datatype, ( 'nCells', 'nBetaTimeSlices', ))
 newvar[:] = numpy.zeros(newvar.shape)
-newvar = fileout.createVariable('sfcMassBal', datatype, ('nCells',))
+newvar = fileout.createVariable('sfcMassBalTimeSeries', datatype, ( 'nCells', 'nSfcMassBalTimeSlices', ))
 newvar[:] = numpy.zeros(newvar.shape)
-newvar = fileout.createVariable('sfcAirTemp', datatype, ('nCells',))
+newvar = fileout.createVariable('sfcAirTempTimeSeries', datatype, ( 'nCells', 'nSfcAirTempTimeSlices', ))
 newvar[:] = numpy.zeros(newvar.shape)
-newvar = fileout.createVariable('basalHeatFlux', datatype, ('nCells',))
+newvar = fileout.createVariable('basalHeatFluxTimeSeries', datatype, ( 'nCells', 'nBasalHeatFluxTimeSlices',))
 newvar[:] = numpy.zeros(newvar.shape)
 
 # Assign the global attributes

Modified: branches/land_ice_projects/grid_tools/copy_CISM_grid_to_MPAS_grid.py
===================================================================
--- branches/land_ice_projects/grid_tools/copy_CISM_grid_to_MPAS_grid.py        2012-06-07 17:25:03 UTC (rev 1973)
+++ branches/land_ice_projects/grid_tools/copy_CISM_grid_to_MPAS_grid.py        2012-06-08 19:00:37 UTC (rev 1974)
@@ -193,10 +193,11 @@
       sf = 1.0
     if netCDF_module == 'netCDF4':
       sf = 1.0   # netCDF4 should autoscale!
-    beta = outfile.variables['beta']
+    beta = outfile.variables['betaTimeSeries']
     print '</font>
<font color="gray">input beta min/max', inbeta[:].min()*sf, inbeta[:].max()*sf
     #beta[timelevout,:] = BilinearInterp(x0, y0, inbeta[timelev,:,:]*sf, xCell, yCell)
-    beta[:] = BilinearInterp(x0, y0, inbeta[timelev,:,:]*sf, xCell, yCell)
+    beta[:,0] = BilinearInterp(x0, y0, inbeta[timelev,:,:]*sf, xCell, yCell)
+    print 'interim beta min/max', beta[:].min(), beta[:].max()
     # Make all beta be positive values
     b = beta[:]
     b[b&lt;=0.0] = 1.0

Modified: branches/land_ice_projects/implement_core/src/core_land_ice/Makefile
===================================================================
--- branches/land_ice_projects/implement_core/src/core_land_ice/Makefile        2012-06-07 17:25:03 UTC (rev 1973)
+++ branches/land_ice_projects/implement_core/src/core_land_ice/Makefile        2012-06-08 19:00:37 UTC (rev 1974)
@@ -20,6 +20,7 @@
         mpas_land_ice_lifev.o \
         mpas_land_ice_sia.o \
         mpas_land_ice_global_diagnostics.o \
+        mpas_land_ice_annual_forcing.o \
         mpas_ocn_tracer_advection.o \
         mpas_ocn_tracer_advection_std.o \
         mpas_ocn_tracer_advection_std_hadv.o \
@@ -46,13 +47,15 @@
 
 mpas_land_ice_tendency.o: mpas_land_ice_mask.o mpas_ocn_tracer_advection.o
 
+mpas_land_ice_annual_forcing.o:
+
 mpas_land_ice_lifev.o:
 
 mpas_land_ice_sia.o:
 
 mpas_land_ice_global_diagnostics.o:
 
-mpas_land_ice_mpas_core.o: mpas_land_ice_global_diagnostics.o mpas_land_ice_time_integration.o mpas_ocn_advection.o
+mpas_land_ice_mpas_core.o: mpas_land_ice_global_diagnostics.o mpas_land_ice_time_integration.o mpas_ocn_advection.o mpas_land_ice_annual_forcing.o
 
 
 # modules needed for FCT tracer advection from ocean core (eventually to be in operators?)

Modified: branches/land_ice_projects/implement_core/src/core_land_ice/Registry
===================================================================
--- branches/land_ice_projects/implement_core/src/core_land_ice/Registry        2012-06-07 17:25:03 UTC (rev 1973)
+++ branches/land_ice_projects/implement_core/src/core_land_ice/Registry        2012-06-08 19:00:37 UTC (rev 1974)
@@ -27,6 +27,8 @@
 namelist real        land_ice_model  config_sealevel              0.0
 namelist real        land_ice_model  config_dynamic_thickness     100.0
 % Define the ice thickness below which dynamics are not calculated.
+namelist character   land_ice_model  config_forcing_frequency     Static
+% Valid options are Static, Annual
 
 % The following options are used by the ocean core and may be useful in the future
 %namelist logical     land_ice_model  config_h_ScaleWithMesh       false
@@ -80,9 +82,12 @@
 % nvertLevels+2 is only needed if attaching b.c. to a 3-d field.  We are unlikely to use this, but I am retaining it for now. MJH 04/19/12
 % dim nVertLevelsPlus2 nVertLevels+2
 dim nVertLevelsPlus1 nVertLevels+1
+dim nSfcMassBalTimeSlices nSfcMassBalTimeSlices
+dim nBetaTimeSlices nBetaTimeSlices
+dim nSfcAirTempTimeSlices nSfcAirTempTimeSlices
+dim nBasalHeatFluxTimeSlices nBasalHeatFluxTimeSlices
 
 
-
 % VARIABLES =====================
 %
 % var persistence type  name_in_file  ( dims )  time_levs iro-  name_in_code struct super-array array_class
@@ -181,12 +186,18 @@
 % Boundary Conditions (defined as mesh variables because they are read in once and held constant for the simulation - at least for now)
 %
 % Note: beta should be moved to diagnostic fields when a process model comes online
-var persistent real    beta ( nCells ) 0 iro beta mesh - -
-var persistent real    basalHeatFlux ( nCells ) 0 iro basalHeatFlux mesh - -
-var persistent real    sfcAirTemp ( nCells ) 0 iro sfcAirTemp mesh - -
-var persistent real    sfcMassBal ( nCells ) 0 iro sfcMassBal mesh - -
+var persistent real    beta ( nCells ) 0 - beta mesh - -
+var persistent real    basalHeatFlux ( nCells ) 0 - basalHeatFlux mesh - -
+var persistent real    sfcAirTemp ( nCells ) 0 - sfcAirTemp mesh - -
+var persistent real    sfcMassBal ( nCells ) 0 - sfcMassBal mesh - -
 
+% Time-varying forcing for B.C.
+var persistent real    betaTimeSeries ( nBetaTimeSlices nCells ) 0 i betaTimeSeries mesh - -
+var persistent real    basalHeatFluxTimeSeries ( nBasalHeatFluxTimeSlices nCells ) 0 i basalHeatFluxTimeSeries mesh - -
+var persistent real    sfcAirTempTimeSeries ( nSfcAirTempTimeSlices nCells ) 0 i sfcAirTempTimeSeries mesh - -
+var persistent real    sfcMassBalTimeSeries ( nSfcMassBalTimeSlices nCells ) 0 i sfcMassBalTimeSeries mesh - -
 
+
 % STATE VARIABLES =====================
 
 % Prognostic variables: read from input, saved in restart, and written to output

Added: branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_annual_forcing.F
===================================================================
--- branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_annual_forcing.F                                (rev 0)
+++ branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_annual_forcing.F        2012-06-08 19:00:37 UTC (rev 1974)
@@ -0,0 +1,206 @@
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+!
+!  ocn_monthly_forcing
+!
+!&gt; \brief MPAS land ice annual forcing
+!&gt; \author Matt Hoffman
+!&gt; \date   06/07/12
+!&gt; \version SVN:$Id:$
+!&gt; \details
+!&gt;  This module contains routines for building the forcing arrays,
+!&gt;  if annual forcing is used.  Modified from ocn_monthly_forcing.
+!
+!-----------------------------------------------------------------------
+
+module land_ice_annual_forcing
+
+   use mpas_grid_types
+   use mpas_configure
+   use mpas_timekeeping
+
+   implicit none
+   private
+   save
+
+   !--------------------------------------------------------------------
+   !
+   ! Public parameters
+   !
+   !--------------------------------------------------------------------
+
+   !--------------------------------------------------------------------
+   !
+   ! Public member functions
+   !
+   !--------------------------------------------------------------------
+
+   public :: land_ice_assign_annual_forcing
+
+   !--------------------------------------------------------------------
+   !
+   ! Private module variables
+   !
+   !--------------------------------------------------------------------
+
+
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+!  routine land_ice_assign_annual_forcing
+!
+!&gt; \brief   Determines the forcing array used for the annual forcing.
+!&gt; \author  Matt Hoffman
+!&gt; \date    06/07/12
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine computes the forcing arrays used later in MPAS.
+!
+!-----------------------------------------------------------------------
+
+   subroutine land_ice_assign_annual_forcing(timeStamp, grid, err)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      type(MPAS_Time_type), intent(in) :: timeStamp
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+      type (mesh_type), intent(inout) :: &amp;
+         grid          !&lt; Input: grid information
+
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      integer, intent(out) :: err !&lt; Output: Error flag
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+      real (kind=RKIND), dimension(:,:), pointer :: sfcMassBalTimeSeries, sfcAirTempTimeSeries, betaTimeSeries, basalHeatFluxTimeSeries
+      real (kind=RKIND), dimension(:), pointer :: sfcMassBal, sfcAirTemp, beta, basalHeatFlux
+      integer :: iYear, ierr, nCells
+      
+
+      err = 0
+
+      sfcMassBalTimeSeries =&gt; grid % sfcMassBalTimeSeries % array
+      sfcAirTempTimeSeries =&gt; grid % sfcAirTempTimeSeries % array
+      betaTimeSeries =&gt; grid % betaTimeSeries % array
+      basalHeatFluxTimeSeries =&gt; grid % basalHeatFluxTimeSeries % array
+
+      sfcMassBal =&gt; grid % sfcMassBal % array
+      sfcAirTemp =&gt; grid % sfcAirTemp % array
+      beta =&gt; grid % beta % array
+      basalHeatFlux =&gt; grid % basalHeatFlux % array
+
+      nCells = grid % nCells
+      
+      if (config_forcing_frequency .eq. 'Static') then
+         iYear = 1  ! Static forcing uses the first entry in the time series at all time steps of the simulation
+      else
+         ! Get the index to use for the time series.  This assumes that the starting year
+         ! is year 1 and therefore can be used as the index into the time series.
+         call mpas_get_time(timeStamp, YYYY = iYear, ierr = ierr)
+         err = ierr
+      endif
+
+      ! Call this separately for each field - there will be cases where one field is time varying and others are constant, and this routine will deal with that properly. 
+      call assign_annual_forcing_to_1D_array(sfcMassBal, sfcMassBalTimeSeries, iYear, nCells)
+      call assign_annual_forcing_to_1D_array(sfcAirTemp, sfcAirTempTimeSeries, iYear, nCells)
+      call assign_annual_forcing_to_1D_array(beta, betaTimeSeries, iYear, nCells)
+      call assign_annual_forcing_to_1D_array(basalHeatFlux, basalHeatFluxTimeSeries, iYear, nCells)
+
+   end subroutine land_ice_assign_annual_forcing!}}}
+
+   !--------------------------------------------------------------------
+
+
+! Private subroutines=======================
+
+
+!***********************************************************************
+!
+!  routine assign_annual_forcing_to_1D_array
+!
+!&gt; \brief   Assigns the appropriate annual forcing to the array used by MPAS.
+!&gt; \author  Matt Hoffman
+!&gt; \date    06/07/12
+!&gt; \version SVN:$Id$
+!&gt; \details 
+!&gt;  This routine assigns the forcing for a given field to be used later in MPAS.
+!
+!-----------------------------------------------------------------------
+
+   subroutine assign_annual_forcing_to_1D_array(forcing, forcingAnnual, iYear, nCells)!{{{
+
+      !-----------------------------------------------------------------
+      !
+      ! input variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:,:) :: forcingAnnual
+      integer, intent(in) :: iYear, nCells
+
+      !-----------------------------------------------------------------
+      !
+      ! input/output variables
+      !
+      !-----------------------------------------------------------------
+
+
+      !-----------------------------------------------------------------
+      !
+      ! output variables
+      !
+      !-----------------------------------------------------------------
+
+      real (kind=RKIND), dimension(:) :: forcing
+
+      !-----------------------------------------------------------------
+      !
+      ! local variables
+      !
+      !-----------------------------------------------------------------
+      integer :: timeIndex 
+
+      ! Make sure that only valid time levels are used.
+      if (iYear .lt. 1) then
+         timeIndex = 1  
+      elseif (iYear .gt. size(forcingAnnual, 1) ) then
+         timeIndex = size(forcingAnnual, 1)   ! Hold the final value if you run out of time levels - useful if only 1 time level is supplied.
+      else
+         timeIndex = iYear
+      endif
+
+      ! Assign the field
+      forcing(1:nCells) = forcingAnnual( timeIndex, 1:nCells )
+
+   end subroutine assign_annual_forcing_to_1D_array
+
+
+
+!***********************************************************************
+
+end module land_ice_annual_forcing
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker

Modified: branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_mpas_core.F
===================================================================
--- branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_mpas_core.F        2012-06-07 17:25:03 UTC (rev 1973)
+++ branches/land_ice_projects/implement_core/src/core_land_ice/mpas_land_ice_mpas_core.F        2012-06-08 19:00:37 UTC (rev 1974)
@@ -157,12 +157,14 @@
       use land_ice_tendency, only: land_ice_diagnostic_solve
       use mpas_ocn_tracer_advection
       use ocn_advection
+      use land_ice_annual_forcing
 
       implicit none
    
       type (block_type), intent(inout) :: block
       type (mesh_type), intent(inout) :: mesh
       real (kind=RKIND), intent(in) :: dt
+      type (MPAS_Time_Type) :: currTime
    
       type (dm_info) :: dminfo
       integer :: err, err_tmp
@@ -175,6 +177,10 @@
 
       ! Call init routines ====
       call land_ice_setup_vertical_coords(mesh)
+      currTime = mpas_get_clock_time(clock, MPAS_NOW, err_tmp)
+      err = ior(err, err_tmp)
+      call land_ice_assign_annual_forcing(currTime, mesh, err_tmp)
+      err = ior(err, err_tmp)
 
       ! Init for FCT tracer advection
       mesh % maxLevelCell % array = mesh % nVertLevels ! Needed for FCT tracer advection
@@ -221,6 +227,7 @@
       use mpas_grid_types
       use mpas_io_output
       use mpas_timer
+      use land_ice_annual_forcing
    
       implicit none
    
@@ -241,7 +248,9 @@
       write(0,*) 'Initial timestep ', timeStamp
       write(6,*) 'Initial timestep ', timeStamp
 
+      call mpas_timer_start(&quot;write output frame&quot;)
       call write_output_frame(output_obj, output_frame, domain)
+      call mpas_timer_stop(&quot;write output frame&quot;)
 
       ! During integration, time level 1 stores the model state at the beginning of the
       !   time step, and time level 2 stores the state advanced dt in time by timestep(...)
@@ -256,6 +265,14 @@
          write(0,*) 'Doing timestep ', timeStamp
          write(6,*) 'Doing timestep ', timeStamp
 
+         call mpas_timer_start(&quot;assign forcing fields&quot;)
+         block_ptr =&gt; domain % blocklist
+         do while(associated(block_ptr))
+           call land_ice_assign_annual_forcing(currTime, block_ptr % mesh, ierr)
+           block_ptr =&gt; block_ptr % next
+         end do
+         call mpas_timer_stop(&quot;assign forcing fields&quot;)
+
          call mpas_timer_start(&quot;time integration&quot;)
          call mpas_timestep(domain, itimestep, dt, timeStamp)
          call mpas_timer_stop(&quot;time integration&quot;)

Modified: branches/land_ice_projects/test_cases/dome/setup_dome_initial_conditions.py
===================================================================
--- branches/land_ice_projects/test_cases/dome/setup_dome_initial_conditions.py        2012-06-07 17:25:03 UTC (rev 1973)
+++ branches/land_ice_projects/test_cases/dome/setup_dome_initial_conditions.py        2012-06-08 19:00:37 UTC (rev 1974)
@@ -46,10 +46,11 @@
     normalVelocity = gridfile.variables['normalVelocity'][:]
     layerThicknessFractions = gridfile.variables['layerThicknessFractions'][:]
     temperature = gridfile.variables['temperature'][:]
-    beta = gridfile.variables['beta'][:]
-    SMB = gridfile.variables['sfcMassBal'][:]
-    Tsfc = gridfile.variables['sfcAirTemp'][:]
-    G = gridfile.variables['basalHeatFlux'][:]
+    # Get b.c. variables
+    beta = gridfile.variables['betaTimeSeries'][:]
+    SMB = gridfile.variables['sfcMassBalTimeSeries'][:]
+    Tsfc = gridfile.variables['sfcAirTempTimeSeries'][:]
+    G = gridfile.variables['basalHeatFluxTimeSeries'][:]
 except:
     sys.exit('Error: The grid file specified is either missing or lacking needed dimensions/variables.')
 
@@ -78,21 +79,21 @@
 # boundary conditions
 # Sample values to use, or comment these out for them to be 0.
 beta[:] = 10000.
-SMB[:] = 2.0/1000.0 * (thickness[:] + bedTopography[:]) - 1.0  # units: m weq/yr, lapse rate of 1 m/yr with 0 at 500 m
+#SMB[:] = 2.0/1000.0 * (thickness[:] + bedTopography[:]) - 1.0  # units: m/yr, lapse rate of 1 m/yr with 0 at 500 m
 Tsfc[:] = -5.0/1000.0 * (thickness[:] + bedTopography[:]) # lapse rate of 5 deg / km
 G = 0.01
 
 
-# Reassign the modified numpy array values back into netCDF variable objects
+# Reassign the modified numpy array values back into netCDF variable objects 
 gridfile.variables['thickness'][:] = thickness
 gridfile.variables['normalVelocity'][:] = normalVelocity
 gridfile.variables['bedTopography'][:] = bedTopography
 gridfile.variables['temperature'][:] = temperature
 gridfile.variables['layerThicknessFractions'][:] = layerThicknessFractions
-gridfile.variables['beta'][:] = beta
-gridfile.variables['sfcMassBal'][:] = SMB
-gridfile.variables['sfcAirTemp'][:] = Tsfc
-gridfile.variables['basalHeatFlux'][:] = G
+gridfile.variables['betaTimeSeries'][:] = beta
+gridfile.variables['sfcMassBalTimeSeries'][:] = SMB
+gridfile.variables['sfcAirTempTimeSeries'][:] = Tsfc
+gridfile.variables['basalHeatFluxTimeSeries'][:] = G
 
 gridfile.close()
 print 'Successfully added dome initial conditions to ', gridfilename

</font>
</pre>