@@ -113,7 +113,7 @@ module model_mod
113
113
get_num_variables, get_domain_size, get_varid_from_varname, &
114
114
get_variable_name, get_num_dims, get_dim_lengths, &
115
115
get_dart_vector_index, get_num_varids_from_kind, &
116
- get_dim_name, get_varid_from_kind
116
+ get_dim_name, get_varid_from_kind, get_num_domains
117
117
118
118
use get_reconstruct_mod, only : get_reconstruct_init, get_reconstruct
119
119
use get_geometry_mod, only : get_geometry
@@ -165,16 +165,12 @@ module model_mod
165
165
is_global_grid, &
166
166
uv_cell_to_edges
167
167
168
- ! try adjusting what static_init_model does, before it is called.
169
- ! the main update_bc program, for example, can call these before
170
- ! calling static_init_model() and that will modify what it does.
171
168
public :: set_lbc_variables, &
172
169
force_u_into_state
173
170
174
171
! set_lbc_variables sets the lbc_variables string array
175
172
! force_u_into_state sets a logical add_u_to_state_list that forces u to be in state
176
173
177
- ! version controlled file description for error handling, do not edit
178
174
character (len=* ), parameter :: source = ' models/mpas_atm/model_mod.f90'
179
175
180
176
! error codes:
@@ -198,8 +194,6 @@ module model_mod
198
194
integer , parameter :: PRESSURE_NOT_MONOTONIC = 988 ! Pressure is not monotonically descreased with level
199
195
200
196
201
- ! module global storage; maintains values between calls, accessible by
202
- ! any subroutine
203
197
character (len= 512 ) :: string1, string2, string3
204
198
logical , save :: module_initialized = .false.
205
199
@@ -224,7 +218,6 @@ module model_mod
224
218
! set in static_init_model() to 1e-5 or 1e-12 depending on compiled precision
225
219
real (r8 ) :: roundoff
226
220
227
- ! Storage for a random sequence for perturbing a single initial state
228
221
type (random_seq_type) :: random_seq
229
222
230
223
! Structure for computing distances to cell centers, and assorted arrays
@@ -233,12 +226,8 @@ module model_mod
233
226
type (xyz_location_type), allocatable :: cell_locs(:)
234
227
logical :: search_initialized = .false.
235
228
236
- ! compile-time control over whether grid information is written to the
237
- ! diagnostic files or not. if it is, the files are self-contained (e.g. for
238
- ! ease of plotting), but are also much larger than they would be otherwise.
239
- ! change this private variable to control whether the grid information is
240
- ! written or not.
241
- logical :: add_static_data_to_diags = .false.
229
+ integer :: anl_domid = - 1
230
+ integer :: lbc_domid = - 1
242
231
243
232
! variables which are in the module namelist
244
233
character (len= 256 ) :: init_template_filename = ' mpas_init.nc'
@@ -257,9 +246,6 @@ module model_mod
257
246
! test for elevation and surface pressure.)
258
247
logical :: always_assim_surf_altimeters = .false.
259
248
260
- integer :: anl_domid = - 1 ! For state_structure_mod access
261
- integer :: lbc_domid = - 1
262
-
263
249
! if .false. use U/V reconstructed winds tri interp at centers for wind forward ops
264
250
! if .true. use edge normal winds (u) with RBF functs for wind forward ops
265
251
logical :: use_u_for_wind = .false.
@@ -337,7 +323,6 @@ module model_mod
337
323
write_grid_to_diag_files, &
338
324
no_normalization_of_scale_heights
339
325
340
- ! DART state vector contents are specified in the input.nml:&mpas_vars_nml namelist.
341
326
integer , parameter :: MAX_STATE_VARIABLES = 80
342
327
integer , parameter :: NUM_STATE_TABLE_COLUMNS = 2
343
328
integer , parameter :: NUM_BOUNDS_TABLE_COLUMNS = 4 ! HK @todo get rid of clamp or fail
@@ -351,10 +336,7 @@ module model_mod
351
336
352
337
namelist / mpas_vars_nml/ mpas_state_variables, mpas_state_bounds
353
338
354
- integer :: nfields
355
-
356
339
! Grid parameters - the values will be read from an mpas analysis file.
357
-
358
340
integer :: nCells = - 1 ! Total number of cells making up the grid
359
341
integer :: nVertices = - 1 ! Unique points in grid that are corners of cells
360
342
integer :: nEdges = - 1 ! Straight lines between vertices making up cells
@@ -366,18 +348,6 @@ module model_mod
366
348
367
349
! scalar grid positions
368
350
369
- ! FIXME: we read in a lot of metadata about the grids. if space becomes an
370
- ! issue we could consider reading in only the x,y,z arrays for all the items
371
- ! plus the radius, and then compute the lat/lon for locations needed by
372
- ! get_state_meta_data() on demand. most of the computations we need to do
373
- ! are actually easier in xyz coords (no issue with poles).
374
-
375
- ! FIXME: it may be desirable to read in xCell(:), yCell(:), zCell(:)
376
- ! to keep from having to compute them on demand, especially since we
377
- ! have converted the radian lat/lon of the cell centers into degrees.
378
- ! we have to convert back, then take a few sin and cos to get xyz.
379
- ! time/space/accuracy tradeoff here.
380
-
381
351
real (r8 ), allocatable :: xVertex(:), yVertex(:), zVertex(:)
382
352
real (r8 ), allocatable :: xEdge(:), yEdge(:), zEdge(:)
383
353
real (r8 ), allocatable :: lonEdge(:) ! edge longitudes (degrees, original radians in file)
@@ -411,7 +381,7 @@ module model_mod
411
381
412
382
integer , allocatable :: surftype(:) ! ! surface type (land=0, water=1, seaice = 2) - for rttov
413
383
414
- integer :: model_size ! the state vector length
384
+ integer (i8) :: model_size
415
385
type (time_type) :: model_timestep ! smallest time to adv model
416
386
417
387
! useful flags in making decisions when searching for points, etc
@@ -421,23 +391,8 @@ module model_mod
421
391
logical :: has_uvreconstruct = .false. ! true = has reconstructed at centers
422
392
423
393
! Do we have any state vector items located on the cell edges?
424
- ! If not, avoid reading in or using the edge arrays to save space.
425
- ! FIXME: this should be set after looking at the fields listed in the
426
- ! namelist which are to be read into the state vector - if any of them
427
- ! are located on the edges then this flag should be changed to .true.
428
- ! however, the way the code is structured these arrays are allocated
429
- ! before the details of field list is examined. since right now the
430
- ! only possible field array that is on the edges is the 'u' edge normal
431
- ! winds, search specifically for that in the state field list and set
432
- ! this based on that. if any other data might be on edges, this routine
433
- ! will need to be updated: is_edgedata_in_state_vector()
434
394
logical :: data_on_edges = .false.
435
395
436
- ! currently unused; for a regional model it is going to be necessary to know
437
- ! if the grid is continuous around longitudes (wraps in east-west) or not,
438
- ! and if it covers either of the poles.
439
- character (len= 64 ) :: ew_boundary_type, ns_boundary_type
440
-
441
396
442
397
INTERFACE get_analysis_time
443
398
MODULE PROCEDURE get_analysis_time_ncid
@@ -479,8 +434,6 @@ module model_mod
479
434
!- -----------------------------------------------------------------
480
435
481
436
subroutine static_init_model ()
482
- ! >@todo FIXME - can we add an optional arg here for update_bc use? !HK No.
483
-
484
437
! Called to do one time initialization of the model.
485
438
486
439
integer , dimension (NF90_MAX_VAR_DIMS) :: dimIDs
@@ -490,16 +443,14 @@ subroutine static_init_model()
490
443
integer :: iunit, io, ivar, i
491
444
integer :: ss, dd, z1, m1
492
445
integer :: nDimensions, nVariables, nAttributes, unlimitedDimID, TimeDimID
493
- integer :: lbc_nfields
446
+ integer :: nfields, lbc_nfields
494
447
logical :: both
495
448
real (r8 ) :: variable_bounds(MAX_STATE_VARIABLES, 2 )
496
449
integer :: variable_qtys(MAX_STATE_VARIABLES)
497
450
character (len=* ), parameter :: routine = ' static_init_model'
498
451
499
- if ( module_initialized ) return ! only need to do this once.
452
+ if ( module_initialized ) return
500
453
501
- ! Since this routine calls other routines that could call this routine
502
- ! we'll say we've been initialized pretty dang early.
503
454
module_initialized = .true.
504
455
505
456
! Read the DART namelist for this model
@@ -512,18 +463,10 @@ subroutine static_init_model()
512
463
if (do_nml_term()) write ( * , nml= model_nml)
513
464
514
465
! Read the MPAS variable list to populate DART state vector
515
- ! Intentionally do not try to dump them to the nml unit because
516
- ! they include large character arrays which output pages of white space.
517
- ! The routine that reads and parses this namelist will output what
518
- ! values it found into the log.
519
466
call find_namelist_in_file(' input.nml' , ' mpas_vars_nml' , iunit)
520
467
read (iunit, nml = mpas_vars_nml, iostat = io)
521
468
call check_namelist_read(iunit, io, ' mpas_vars_nml' )
522
469
523
- !- --------------------------------------------------------------
524
- ! Set the time step ... causes mpas namelists to be read - HK does it?
525
- ! Ensures model_timestep is multiple of 'dynamics_timestep'
526
-
527
470
call set_calendar_type( calendar )
528
471
529
472
model_timestep = set_model_time_step()
@@ -537,24 +480,22 @@ subroutine static_init_model()
537
480
538
481
call verify_state_variables(ncid, init_template_filename, &
539
482
nfields, variable_qtys, variable_bounds)
540
- call read_grid()
541
-
542
- call nc_close_file(ncid, routine)
543
483
544
484
anl_domid = add_domain(init_template_filename, nfields, &
545
485
var_names = variable_table (1 :nfields,1 ), &
546
486
kind_list = variable_qtys(1 :nfields), &
547
487
clamp_vals = variable_bounds(1 :nfields,:) )
548
488
489
+ call read_grid()
490
+
491
+ call nc_close_file(ncid, routine)
492
+
549
493
model_size = get_domain_size(anl_domid)
550
494
551
495
lbc_nfields = 0
552
496
553
497
! if we have a lateral boundary file, add it to the domain
554
498
! so we have access to the corresponding lbc_xxx fields.
555
- ! >@todo FIXME: if we want to do increments, we could also add a
556
- ! third domain which is the original forecast fields before
557
- ! the assimilation (so we can compute increments) !HK why would you need to add a third domain?
558
499
if (.not. global_grid .and. lbc_variables(1 ) /= ' ' ) then
559
500
! regional: count number of lbc fields to read in
560
501
COUNTUP: do i= 1 , MAX_STATE_VARIABLES
@@ -568,12 +509,8 @@ subroutine static_init_model()
568
509
var_names = lbc_variables)
569
510
! FIXME clamp_vals = variable_bounds(1:nfields,:) )
570
511
model_size = model_size + get_domain_size(lbc_domid)
571
- else
572
- lbc_domid = - 1
573
512
endif
574
513
575
- ! do some sanity checking here:
576
-
577
514
! if you have at least one of these wind components in the state vector,
578
515
! you have to have them both. the subroutine will error out if only one
579
516
! is found and not both.
@@ -622,9 +559,7 @@ subroutine static_init_model()
622
559
text2= string2, text3= string3)
623
560
endif
624
561
625
- ! basically we cannot do much without having at least these
626
- ! three fields in the state vector. refuse to go further
627
- ! if these are not present:
562
+ ! Required state vector fields
628
563
if ((get_num_varids_from_kind(anl_domid, QTY_POTENTIAL_TEMPERATURE) < 0 ) .or. &
629
564
(get_num_varids_from_kind(anl_domid, QTY_DENSITY) < 0 ) .or. &
630
565
(get_num_varids_from_kind(anl_domid, QTY_VAPOR_MIXING_RATIO) < 0 )) then
@@ -635,15 +570,11 @@ subroutine static_init_model()
635
570
text2= string2, text3= string3)
636
571
endif
637
572
638
- ! tell the location module how we want to localize in the vertical
639
573
call set_vertical_localization_coord(vert_localization_coord)
640
574
641
- ! set an appropriate value for roundoff tests based
642
- ! on this code being compiled single or double precision.
643
- ! set to 1e-5 (for single) or 1e-12 (for double precision).
644
- if (r8 == digits12) then
575
+ if (r8 == digits12) then ! double precision
645
576
roundoff = 1.0e-12_r8
646
- else
577
+ else ! single precision
647
578
roundoff = 1.0e-5_r8
648
579
endif
649
580
@@ -685,9 +616,9 @@ subroutine read_grid()
685
616
allocate (edgeNormalVectors(3 , nEdges))
686
617
allocate (xVertex(nVertices), yVertex(nVertices), zVertex(nVertices))
687
618
688
- ! see if U is in the state vector list . if not, don't read in or
619
+ ! see if and variables on Edges are in the state vector. If not, do not read in or
689
620
! use any of the Edge arrays to save space.
690
- data_on_edges = is_edgedata_in_state_vector(variable_table, lbc_variables )
621
+ data_on_edges = is_edgedata_in_state_vector()
691
622
692
623
if (data_on_edges) then
693
624
allocate (zGridEdge(nVertLevels, nEdges))
@@ -1858,13 +1789,10 @@ end function string_to_time
1858
1789
1859
1790
function set_model_time_step ()
1860
1791
1861
- ! the static_init_model ensures that the model namelists are read.
1862
-
1863
1792
type (time_type) :: set_model_time_step
1864
1793
1865
1794
if ( .not. module_initialized ) call static_init_model
1866
1795
1867
- ! these are from the namelist
1868
1796
set_model_time_step = set_time(assimilation_period_seconds, assimilation_period_days)
1869
1797
1870
1798
end function set_model_time_step
@@ -2166,58 +2094,29 @@ subroutine verify_state_variables(ncid, filename, ngood, qty_list, variable_boun
2166
2094
variable_table(ngood,2 ) = " QTY_EDGE_NORMAL_SPEED"
2167
2095
endif
2168
2096
2169
- ! state bounds
2170
-
2171
-
2172
2097
end subroutine verify_state_variables
2173
2098
2174
2099
2175
2100
!- -----------------------------------------------------------------
2101
+ function is_edgedata_in_state_vector ()
2176
2102
2177
- ! > @todo FIXME if you can call this *after* add_domain() has been
2178
- ! > called, then we could use state structure calls for this.
2179
- ! >
2180
- ! > but right now, it's called first. so pass in the namelist
2181
- ! > and boundary lists and base the decision on those.
2182
- ! >
2183
- ! > this routine can only be called after the namelist is read.
2184
- ! > also, it's called BY static_init_model() so it can't call
2185
- ! > back into it.
2186
- ! >
2187
-
2188
- function is_edgedata_in_state_vector (state_list , bdy_list )
2189
- character (len=* ), intent (in ) :: state_list(MAX_STATE_VARIABLES, NUM_STATE_TABLE_COLUMNS)
2190
- character (len=* ), intent (in ) :: bdy_list(MAX_STATE_VARIABLES)
2191
- logical :: is_edgedata_in_state_vector
2192
-
2193
- integer :: i
2194
-
2195
- StateLoop : do i = 1 , MAX_STATE_VARIABLES
2196
-
2197
- if (state_list(i, 1 ) == ' ' ) exit StateLoop ! Found end of list.
2198
-
2199
- if (state_list(i, 1 ) == ' u' ) then
2200
- is_edgedata_in_state_vector = .true.
2201
- return
2202
- endif
2103
+ logical :: is_edgedata_in_state_vector
2203
2104
2204
- enddo StateLoop
2205
-
2206
- ! if U is not in the state, does it matter if U is
2207
- ! in the boundary file? yes, return true if so.
2208
- BdyLoop : do i = 1 , MAX_STATE_VARIABLES
2209
-
2210
- if (bdy_list(i) == ' ' ) exit BdyLoop ! Found end of list.
2211
-
2212
- if (bdy_list(i) == ' lbc_u' ) then
2213
- is_edgedata_in_state_vector = .true.
2214
- return
2215
- endif
2216
-
2217
- enddo BdyLoop
2105
+ integer :: dom, var, dim
2218
2106
2219
2107
is_edgedata_in_state_vector = .false.
2220
2108
2109
+ do dom = 1 , get_num_domains()
2110
+ do var = 1 , get_num_variables(dom)
2111
+ do dim = 1 , get_num_dims(dom, var)
2112
+ if (get_dim_name(dom, var, dim) == ' nEdges' ) then
2113
+ is_edgedata_in_state_vector = .true.
2114
+ return
2115
+ endif
2116
+ enddo
2117
+ enddo
2118
+ enddo
2119
+
2221
2120
end function is_edgedata_in_state_vector
2222
2121
2223
2122
0 commit comments