[Dart-dev] DART/branches Revision: 12175

dart at ucar.edu dart at ucar.edu
Tue Dec 5 10:05:40 MST 2017


nancy at ucar.edu
2017-12-05 10:05:39 -0700 (Tue, 05 Dec 2017)
222
i think i have a slick way to handle obs which are
in different vertical levels in different ensemble
members.  the goal is to minimize the number of calls
to get_state() since it has to communicate with other
MPI tasks.




Modified: DART/branches/recam/models/cam-fv/model_mod.f90
===================================================================
--- DART/branches/recam/models/cam-fv/model_mod.f90	2017-12-05 02:25:46 UTC (rev 12174)
+++ DART/branches/recam/models/cam-fv/model_mod.f90	2017-12-05 17:05:39 UTC (rev 12175)
@@ -318,6 +318,9 @@
 end subroutine get_state_meta_data
 
 !-----------------------------------------------------------------------
+!> given the (i,j,k) indices into a field in the state vector,
+!> and the quantity, and the dimensionality of the field (2d, 3d),
+!> compute the location of that item.  
 
 function get_location_from_index(i, j, k, q, nd)
 integer, intent(in) :: i
@@ -331,14 +334,28 @@
 real(r8) :: use_vert_val
 integer  :: use_vert_type
 
-if (nd == 2) then
-   use_vert_type = VERTISSURFACE
-   use_vert_val  = MISSING_R8  ! could also be surface elevation
-else
+! full 3d fields are returned with lon/lat/level.
+! 2d fields are either surface fields, or if they
+! are column integrated values then they are 'undefined'
+! in the vertical.
+
+if (nd == 3) then
    use_vert_type = VERTISLEVEL
    use_vert_val  = real(k,r8)
+else
+   if (q == QTY_SURFACE_ELEVATION .or. q == QTY_SURFACE_PRESSURE) then
+      use_vert_type = VERTISSURFACE
+      use_vert_val  = MISSING_R8  ! could also be surface elevation:
+      !use_vert_val  = phis(lon_index, lat_index) / gravity
+   else
+      use_vert_type = VERTISUNDEF
+      use_vert_val  = MISSING_R8
+   endif
 endif
 
+! the horizontal location depends on whether this quantity is on the
+! mass point grid or staggered in either lat or lon.  
+
 select case (grid_stagger%qty_stagger(q))
   case (STAGGER_U)
    get_location_from_index = set_location(grid_data%lon%vals(i), &
@@ -346,9 +363,10 @@
                                           use_vert_val, use_vert_type)
 
   case (STAGGER_V)
+   ! the first staggered longitude is negative.  dart requires lons
+   ! be between 0 and 360.
    slon_val = grid_data%slon%vals(i)
-   if (slon_val <   0) slon_val = slon_val + 360.0_r8
-   if (slon_val > 360) slon_val = slon_val - 360.0_r8
+   if (slon_val < 0) slon_val = slon_val + 360.0_r8
    get_location_from_index = set_location(slon_val, &
                                           grid_data%lat%vals(j), &
                                           use_vert_val, use_vert_type)
@@ -450,7 +468,14 @@
 
 
 !-----------------------------------------------------------------------
+!> this routine takes care of getting the actual state values.  get_state()
+!> communicates with other MPI tasks and can be expensive.
 !>
+!> all ensemble members have the same horizontal location, but different 
+!> ensemble members could have different vertical locations and
+!> so be between different vertical layers.  this code tries to do the fewest
+!> calls to get_state by only calling it for levels that are actually needed
+!> and setting all members with those same levels in a single pass.
 !> 
 
 subroutine get_values_from_varid(ens_handle, ens_size, lon_index, lat_index, lev_index, &
@@ -465,16 +490,49 @@
 integer,  intent(out) :: my_status(ens_size)
 
 integer(i8) :: state_indx
+integer  :: i, j
+real(r8) :: temp_vals(ens_size)
+logical  :: member_done(ens_size)
 
-!>@todo FIXME add error checking?  is state_indx < 0 how it indicates error?
+! as we get the values for each ensemble member, we set the 'done' flag
+! and a good return code. 
+my_status(:) = 16
+member_done(:) = .false.
 
-!>@todo FIXME find unique level indices here (see new wrf code)
+! start with lev_index(1).  get the vals into a temp var.  
+! run through 2-N. any other member that has the same level 
+! set the outgoing values.  keep a separate flag for which 
+! member(s) have been done.  skip to the next undone member 
+! and get the state for that level.  repeat until all
+! levels done.
 
-state_indx = get_dart_vector_index(lon_index, lat_index, lev_index(1), domain_id, varid)
-vals       = get_state(state_indx, ens_handle)
+do i=1, ens_size
 


More information about the Dart-dev mailing list