Line data Source code
1 : !=======================================================================
2 :
3 : ! Read and write ice model restart files
4 : !
5 : ! authors Elizabeth C. Hunke, LANL
6 :
7 : module icedrv_restart
8 :
9 : use icedrv_kinds
10 : use icedrv_constants, only: nu_diag, nu_restart, nu_dump
11 : use icedrv_constants, only: c0, c1, p5
12 : use icedrv_restart_shared, only: restart, restart_dir, restart_file, lenstr
13 : use icedrv_restart_shared, only: restart_format
14 : use icepack_intfc, only: icepack_warnings_flush, icepack_warnings_aborted
15 : use icepack_intfc, only: icepack_query_tracer_flags, icepack_query_tracer_indices
16 : use icepack_intfc, only: icepack_query_parameters, icepack_query_tracer_sizes
17 : use icedrv_system, only: icedrv_system_abort
18 : #ifdef USE_NETCDF
19 : use netcdf
20 : #endif
21 :
22 : implicit none
23 : private :: &
24 : write_restart_age, read_restart_age, &
25 : write_restart_FY, read_restart_FY, &
26 : write_restart_lvl, read_restart_lvl, &
27 : write_restart_pond_lvl, read_restart_pond_lvl, &
28 : write_restart_pond_topo, read_restart_pond_topo, &
29 : write_restart_snow, read_restart_snow, &
30 : write_restart_fsd, read_restart_fsd, &
31 : write_restart_iso, read_restart_iso, &
32 : write_restart_aero, read_restart_aero
33 :
34 : character (len=3), private :: nchar !
35 :
36 : logical (kind=log_kind), private :: diag ! netCDF diagnostics flag
37 :
38 : #ifdef USE_NETCDF
39 : private :: &
40 : define_rest_field, write_restart_field_nc2D, &
41 : write_restart_field_nc1D, ice_write_nc2D, &
42 : ice_write_nc1D, read_restart_field_net2D, &
43 : read_restart_field_net1D, ice_read_nc2D, &
44 : ice_read_nc1D
45 :
46 : integer (kind=int_kind), private :: &
47 : ncid ! ID for NetCDF file
48 : #endif
49 :
50 : public :: dumpfile, restartfile, final_restart, &
51 : write_restart_field, read_restart_field
52 :
53 : !=======================================================================
54 :
55 : contains
56 :
57 : !=======================================================================
58 :
59 : !=======================================================================
60 : !---! these subroutines write/read restart data files ..
61 : ! Which can either be in unformatted Fortran format
62 : ! (restart_format = 'bin') or NetCDF (restart_format = 'nc')
63 : !=======================================================================
64 :
65 : ! Dumps all values needed for a restart
66 : ! authors Elizabeth C. Hunke, LANL
67 : ! David Clemens-Sewall, NCAR
68 :
69 2462 : subroutine dumpfile
70 :
71 : use icedrv_calendar, only: sec, month, mday, nyr, istep1
72 : use icedrv_calendar, only: time, time_forc, year_init
73 : use icedrv_domain_size, only: nilyr, nslyr, ncat, n_aero, nfsd, nx, n_iso
74 : use icedrv_forcing, only: oceanmixed_ice
75 : use icedrv_flux, only: scale_factor, swvdr, swvdf, swidr, swidf
76 : use icedrv_flux, only: sst, frzmlt, frz_onset, fsnow
77 : use icedrv_state, only: aicen, vicen, vsnon, trcrn
78 : use icedrv_arrays_column, only: dhsn, ffracn
79 : use icedrv_arrays_column, only: first_ice, first_ice_real
80 :
81 : ! local variables
82 :
83 : integer (kind=int_kind) :: &
84 : k, & ! counting indices
85 : iyear
86 :
87 : integer (kind=int_kind) :: &
88 : nt_Tsfc, nt_sice, nt_qice, nt_qsno
89 :
90 : logical (kind=log_kind) :: &
91 : tr_iage, tr_FY, tr_lvl, tr_iso, tr_aero, tr_brine, &
92 : tr_pond_topo, tr_pond_lvl, tr_snow, tr_fsd
93 : ! skl_bgc, z_tracers
94 :
95 : integer (kind=int_kind) :: dims(2)
96 :
97 : character(len=char_len_long) :: filename
98 : character(len=*), parameter :: subname='(dumpfile)'
99 :
100 : #ifdef USE_NETCDF
101 : ! local variables if we're writing in NetCDF
102 : integer (kind=int_kind) :: &
103 : dimid_ni, & ! netCDF identifiers
104 : dimid_ncat, & !
105 : iflag, & ! netCDF creation flag
106 : status ! status variable from netCDF routine
107 : #endif
108 :
109 : ! get year
110 1231 : iyear = nyr + year_init - 1
111 :
112 : ! query which tracers are active and their indices
113 : call icepack_query_tracer_indices(nt_Tsfc_out=nt_Tsfc, nt_sice_out=nt_sice, &
114 1231 : nt_qice_out=nt_qice, nt_qsno_out=nt_qsno)
115 :
116 : call icepack_query_tracer_flags(tr_iage_out=tr_iage, tr_FY_out=tr_FY, &
117 : tr_lvl_out=tr_lvl, tr_aero_out=tr_aero, tr_iso_out=tr_iso, &
118 : tr_brine_out=tr_brine, &
119 : tr_pond_topo_out=tr_pond_topo, &
120 1231 : tr_pond_lvl_out=tr_pond_lvl,tr_snow_out=tr_snow,tr_fsd_out=tr_fsd)
121 : ! call icepack_query_parameters(skl_bgc_out=skl_bgc, z_tracers_out=z_tracers)
122 1231 : call icepack_warnings_flush(nu_diag)
123 1231 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
124 0 : file=__FILE__,line= __LINE__)
125 :
126 1231 : dims(:) = 0
127 1231 : if (restart_format == 'bin') then
128 : write(filename,'(a,a,a,i4.4,a,i2.2,a,i2.2,a,i5.5)') &
129 1165 : restart_dir(1:lenstr(restart_dir)), &
130 1165 : restart_file(1:lenstr(restart_file)),'.', &
131 2330 : iyear,'-',month,'-',mday,'-',sec
132 :
133 1165 : open(nu_dump,file=filename,form='unformatted')
134 1165 : write(nu_dump) istep1,time,time_forc
135 66 : else if (restart_format == 'nc') then
136 : #ifdef USE_NETCDF
137 : ! Change this if you want diagnostic output
138 66 : diag = .false.
139 :
140 : write(filename,'(a,a,a,i4.4,a,i2.2,a,i2.2,a,i5.5)') &
141 66 : restart_dir(1:lenstr(restart_dir)), &
142 66 : restart_file(1:lenstr(restart_file)),'.', &
143 132 : iyear,'-',month,'-',mday,'-',sec
144 66 : filename = trim(filename) // '.nc'
145 :
146 : ! Open NetCDF restart file in define mode
147 66 : iflag = nf90_clobber
148 66 : status = nf90_create(trim(filename), iflag, ncid)
149 66 : if (status /= nf90_noerr) call icedrv_system_abort(string=subname, &
150 0 : file=__FILE__,line= __LINE__)
151 : ! Set time attributes for restart file
152 66 : status = nf90_put_att(ncid,nf90_global,'istep1',istep1)
153 66 : status = nf90_put_att(ncid,nf90_global,'time',time)
154 66 : status = nf90_put_att(ncid,nf90_global,'time_forc',time_forc)
155 66 : status = nf90_put_att(ncid,nf90_global,'nyr',iyear)
156 66 : status = nf90_put_att(ncid,nf90_global,'month',month)
157 66 : status = nf90_put_att(ncid,nf90_global,'mday',mday)
158 66 : status = nf90_put_att(ncid,nf90_global,'sec',sec)
159 : ! Set dimensions for restart file
160 66 : status = nf90_def_dim(ncid,'ni',nx,dimid_ni)
161 66 : status = nf90_def_dim(ncid,'ncat',ncat,dimid_ncat)
162 :
163 : ! Get dimension IDs
164 66 : dims(1) = dimid_ni
165 66 : dims(2) = dimid_ncat
166 : #else
167 0 : call icedrv_system_abort(string=subname//' ERROR: restart_format = "nc" requires USE_NETCDF',file=__FILE__,line=__LINE__)
168 : #endif
169 : endif
170 :
171 1231 : write(nu_diag,*) 'Writing ',filename(1:lenstr(filename))
172 :
173 : !-----------------------------------------------------------------
174 : ! state variables
175 : ! Tsfc is the only tracer written to binary files. All other
176 : ! tracers are written to their own dump/restart binary files.
177 : !-----------------------------------------------------------------
178 :
179 1231 : call write_restart_field(nu_dump,aicen(:,:),ncat,'aicen',dims)
180 1231 : call write_restart_field(nu_dump,vicen(:,:),ncat,'vicen',dims)
181 1231 : call write_restart_field(nu_dump,vsnon(:,:),ncat,'vsnon',dims)
182 1231 : call write_restart_field(nu_dump,trcrn(:,nt_Tsfc,:),ncat,'Tsfcn',dims)
183 9452 : do k=1,nilyr
184 8221 : write(nchar,'(i3.3)') k
185 : call write_restart_field(nu_dump,trcrn(:,nt_sice+k-1,:),ncat,&
186 9452 : 'sice'//trim(nchar),dims)
187 : enddo
188 9452 : do k=1,nilyr
189 8221 : write(nchar,'(i3.3)') k
190 : call write_restart_field(nu_dump,trcrn(:,nt_qice+k-1,:),ncat,&
191 9452 : 'qice'//trim(nchar),dims)
192 : enddo
193 3038 : do k=1,nslyr
194 1807 : write(nchar,'(i3.3)') k
195 : call write_restart_field(nu_dump,trcrn(:,nt_qsno+k-1,:),ncat,&
196 3038 : 'qsno'//trim(nchar),dims)
197 : enddo
198 :
199 : !-----------------------------------------------------------------
200 : ! radiation fields
201 : !-----------------------------------------------------------------
202 1231 : call write_restart_field(nu_dump,scale_factor,1,'scale_factor',dims)
203 1231 : call write_restart_field(nu_dump,swvdr,1,'swvdr',dims)
204 1231 : call write_restart_field(nu_dump,swvdf,1,'swvdf',dims)
205 1231 : call write_restart_field(nu_dump,swidr,1,'swidr',dims)
206 1231 : call write_restart_field(nu_dump,swidf,1,'swidf',dims)
207 :
208 : !-----------------------------------------------------------------
209 : ! for mixed layer model
210 : !-----------------------------------------------------------------
211 1231 : if (oceanmixed_ice) then
212 1231 : call write_restart_field(nu_dump,sst,1,'sst',dims)
213 1231 : call write_restart_field(nu_dump,frzmlt,1,'frzmlt',dims)
214 : endif
215 :
216 : ! tracers
217 1231 : if (tr_iage) call write_restart_age(dims) ! ice age tracer
218 1231 : if (tr_FY) call write_restart_FY(dims) ! first-year area tracer
219 1231 : if (tr_lvl) call write_restart_lvl(dims) ! level ice tracer
220 1231 : if (tr_pond_lvl) call write_restart_pond_lvl(dims) ! level-ice melt ponds
221 1231 : if (tr_pond_topo) call write_restart_pond_topo(dims) ! topographic melt ponds
222 1231 : if (tr_snow) call write_restart_snow(dims) ! snow metamorphosis tracers
223 1231 : if (tr_iso) call write_restart_iso(dims) ! ice isotopes
224 1231 : if (tr_aero) call write_restart_aero(dims) ! ice aerosols
225 1231 : if (tr_brine) call write_restart_hbrine(dims) ! brine height
226 1231 : if (tr_fsd) call write_restart_fsd(dims) ! floe size distribution
227 : ! called in icedrv_RunMod.F90 to prevent circular dependencies
228 : ! if (skl_bgc .or. z_tracers) &
229 : ! call write_restart_bgc ! biogeochemistry
230 :
231 : ! Close netcdf file
232 132 : if (restart_format == 'nc') then
233 : #ifdef USE_NETCDF
234 66 : status = nf90_close(ncid)
235 66 : if (status /= nf90_noerr) call icedrv_system_abort(string=subname, &
236 0 : file=__FILE__,line= __LINE__)
237 : #endif
238 : endif
239 :
240 1231 : end subroutine dumpfile
241 :
242 : !=======================================================================
243 :
244 : ! Restarts from a dump
245 : ! author Elizabeth C. Hunke, LANL
246 :
247 81 : subroutine restartfile (ice_ic)
248 :
249 : use icedrv_calendar, only: istep0, istep1, time, time_forc
250 : use icepack_intfc, only: icepack_aggregate
251 : use icedrv_domain_size, only: nilyr, nslyr, ncat, nfsd, nblyr
252 : use icedrv_domain_size, only: max_ntrcr, nx, n_iso, n_aero
253 : use icedrv_flux, only: swvdr, swvdf, swidr, swidf, Tf
254 : use icedrv_flux, only: sst, frzmlt, scale_factor
255 : use icedrv_flux, only: frz_onset,fsnow
256 : use icedrv_forcing, only: oceanmixed_ice
257 : use icedrv_init, only: tmask
258 : use icedrv_state, only: trcr_depend, aice, vice, vsno, trcr
259 : use icedrv_state, only: aice0, aicen, vicen, vsnon, trcrn, aice_init
260 : use icedrv_state, only: trcr_base, nt_strata, n_trcr_strata
261 : use icedrv_restart_shared, only: restart_format
262 : use icedrv_arrays_column, only: dhsn, ffracn, hin_max
263 : use icedrv_arrays_column, only: first_ice, first_ice_real
264 :
265 : character (*), optional :: ice_ic
266 :
267 : ! local variables
268 :
269 : integer (kind=int_kind) :: &
270 : i, k ! counting indices
271 :
272 : integer (kind=int_kind) :: &
273 : ntrcr
274 :
275 : integer (kind=int_kind) :: &
276 : nt_Tsfc, nt_sice, nt_qice, nt_qsno
277 :
278 : logical (kind=log_kind) :: &
279 : tr_iage, tr_FY, tr_lvl, tr_iso, tr_aero, tr_brine, &
280 : tr_pond_topo, tr_pond_lvl, tr_snow, tr_fsd
281 :
282 : character(len=char_len_long) :: filename
283 : character(len=*), parameter :: subname='(restartfile)'
284 :
285 : ! local variable for reading from a netcdf file
286 : integer (kind=int_kind) :: &
287 : status
288 :
289 : ! Query tracers
290 : call icepack_query_tracer_indices(nt_Tsfc_out=nt_Tsfc, nt_sice_out=nt_sice, &
291 27 : nt_qice_out=nt_qice, nt_qsno_out=nt_qsno)
292 27 : call icepack_query_tracer_sizes(ntrcr_out=ntrcr)
293 : call icepack_query_tracer_flags(tr_iage_out=tr_iage, tr_FY_out=tr_FY, &
294 : tr_lvl_out=tr_lvl, tr_aero_out=tr_aero, tr_iso_out=tr_iso, &
295 : tr_brine_out=tr_brine, &
296 : tr_pond_topo_out=tr_pond_topo, &
297 27 : tr_pond_lvl_out=tr_pond_lvl,tr_snow_out=tr_snow,tr_fsd_out=tr_fsd)
298 27 : call icepack_warnings_flush(nu_diag)
299 27 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
300 0 : file=__FILE__,line= __LINE__)
301 :
302 27 : if (present(ice_ic)) then
303 27 : filename = trim(ice_ic)
304 : else
305 : call icedrv_system_abort(string=subname//'no ice_ic present', &
306 0 : file=__FILE__,line=__LINE__)
307 : endif
308 :
309 27 : write(nu_diag,*) 'Using restart dump=', trim(filename)
310 :
311 27 : if (restart_format == 'bin') then
312 25 : open(nu_restart,file=filename,form='unformatted')
313 25 : read (nu_restart) istep0,time,time_forc
314 2 : else if (restart_format == 'nc') then
315 : #ifdef USE_NETCDF
316 : ! set this to .true. for netcdf diagnostic output
317 2 : diag = .false.
318 : ! Open restart files
319 2 : status = nf90_open(trim(filename), nf90_nowrite, ncid)
320 2 : if (status /= nf90_noerr) call icedrv_system_abort(string=subname//'Couldnt open netcdf file', &
321 0 : file=__FILE__,line=__LINE__)
322 :
323 2 : status = nf90_get_att(ncid, nf90_global, 'istep1', istep0)
324 2 : status = nf90_get_att(ncid, nf90_global, 'time', time)
325 2 : status = nf90_get_att(ncid, nf90_global, 'time_forc', time_forc)
326 : #else
327 0 : call icedrv_system_abort(string=subname//' ERROR: restart_format = "nc" requires USE_NETCDF',file=__FILE__,line=__LINE__)
328 : #endif
329 : else
330 : call icedrv_system_abort(string=subname//'unrecognized restart format', &
331 0 : file=__FILE__,line=__LINE__)
332 : endif
333 :
334 27 : write(nu_diag,*) 'Restart read at istep=',istep0,time,time_forc
335 :
336 27 : istep1 = istep0
337 :
338 : !-----------------------------------------------------------------
339 : ! state variables
340 : ! Tsfc is the only tracer read in this file. All other
341 : ! tracers are in their own dump/restart files.
342 : !-----------------------------------------------------------------
343 27 : write(nu_diag,*) 'min/max area, vol ice, vol snow, Tsfc'
344 :
345 27 : call read_restart_field(nu_restart,aicen,ncat,'aicen')
346 27 : call read_restart_field(nu_restart,vicen,ncat,'vicen')
347 27 : call read_restart_field(nu_restart,vsnon,ncat,'vsnon')
348 27 : call read_restart_field(nu_restart,trcrn(:,nt_Tsfc,:),ncat,'Tsfcn')
349 :
350 27 : write(nu_diag,*) 'min/max sice for each layer'
351 204 : do k=1,nilyr
352 177 : write(nchar,'(i3.3)') k
353 : call read_restart_field(nu_restart,trcrn(:,nt_sice+k-1,:),ncat, &
354 204 : 'sice'//trim(nchar))
355 : enddo
356 :
357 27 : write(nu_diag,*) 'min/max qice for each layer'
358 204 : do k=1,nilyr
359 177 : write(nchar,'(i3.3)') k
360 : call read_restart_field(nu_restart,trcrn(:,nt_qice+k-1,:),ncat, &
361 204 : 'qice'//trim(nchar))
362 : enddo
363 :
364 27 : write(nu_diag,*) 'min/max qsno for each layer'
365 74 : do k=1,nslyr
366 47 : write(nchar,'(i3.3)') k
367 : call read_restart_field(nu_restart,trcrn(:,nt_qsno+k-1,:),ncat, &
368 74 : 'qsno'//trim(nchar))
369 : enddo
370 :
371 : !-----------------------------------------------------------------
372 : ! radiation fields
373 : !-----------------------------------------------------------------
374 :
375 27 : write(nu_diag,*) 'min/max radiation fields'
376 :
377 27 : call read_restart_field(nu_restart,scale_factor,1,'scale_factor')
378 27 : call read_restart_field(nu_restart,swvdr,1,'swvdr')
379 27 : call read_restart_field(nu_restart,swvdf,1,'swvdf')
380 27 : call read_restart_field(nu_restart,swidr,1,'swidr')
381 27 : call read_restart_field(nu_restart,swidf,1,'swidf')
382 :
383 : !-----------------------------------------------------------------
384 : ! for mixed layer model
385 : !-----------------------------------------------------------------
386 :
387 27 : if (oceanmixed_ice) then
388 27 : write(nu_diag,*) 'min/max sst, frzmlt'
389 27 : call read_restart_field(nu_restart,sst,1,'sst')
390 27 : call read_restart_field(nu_restart,frzmlt,1,'frzmlt')
391 : endif
392 :
393 : ! tracers
394 27 : if (tr_iage) call read_restart_age() ! ice age tracer
395 27 : if (tr_FY) call read_restart_FY() ! first-year area tracer
396 27 : if (tr_lvl) call read_restart_lvl() ! level ice tracer
397 27 : if (tr_pond_lvl) call read_restart_pond_lvl() ! level-ice melt ponds
398 27 : if (tr_pond_topo) call read_restart_pond_topo() ! topographic melt ponds
399 27 : if (tr_snow) call read_restart_snow() ! snow metamorphosis tracers
400 27 : if (tr_iso) call read_restart_iso() ! ice isotopes
401 27 : if (tr_aero) call read_restart_aero() ! ice aerosols
402 27 : if (tr_brine) call read_restart_hbrine ! brine height
403 27 : if (tr_fsd) call read_restart_fsd() ! floe size distribution
404 :
405 : !-----------------------------------------------------------------
406 : ! Ensure ice is binned in correct categories
407 : ! (should not be necessary unless restarting from a run with
408 : ! different category boundaries).
409 : !
410 : ! If called, this subroutine does not give exact restart.
411 : !-----------------------------------------------------------------
412 : !!! call cleanup_itd
413 :
414 : !-----------------------------------------------------------------
415 : ! compute aggregate ice state and open water area
416 : !-----------------------------------------------------------------
417 :
418 135 : do i = 1, nx
419 108 : if (tmask(i)) &
420 : call icepack_aggregate(trcrn=trcrn(i,1:ntrcr,:), &
421 : aicen=aicen(i,:), &
422 : vicen=vicen(i,:), &
423 : vsnon=vsnon(i,:), &
424 : trcr=trcr (i,1:ntrcr), &
425 : aice=aice (i), &
426 : vice=vice (i), &
427 : vsno=vsno (i), &
428 : aice0=aice0(i), &
429 : trcr_depend=trcr_depend(1:ntrcr), &
430 : trcr_base=trcr_base (1:ntrcr,:), &
431 : n_trcr_strata=n_trcr_strata(1:ntrcr), &
432 : nt_strata=nt_strata (1:ntrcr,:), &
433 81 : Tf = Tf(i))
434 :
435 135 : aice_init(i) = aice(i)
436 : enddo
437 27 : call icepack_warnings_flush(nu_diag)
438 27 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
439 0 : file=__FILE__, line=__LINE__)
440 :
441 27 : end subroutine restartfile
442 :
443 : !=======================================================================
444 :
445 : ! Reads a single restart field
446 : ! author Chris Newman, LANL
447 :
448 1551 : subroutine read_restart_field(nu,work,ndim,name)
449 :
450 : use icedrv_domain_size, only: nx
451 :
452 : integer (kind=int_kind), intent(in) :: &
453 : nu , & ! unit number (not used for netcdf)
454 : ndim ! number of dimensions
455 :
456 : real (kind=dbl_kind), dimension(nx,ndim), intent(inout) :: &
457 : work ! input array (real, 8-byte)
458 :
459 : character (len=*), intent(in), optional :: &
460 : name
461 :
462 : ! local variables
463 :
464 : integer (kind=int_kind) :: &
465 : n, i ! loop indices
466 :
467 : real (kind=dbl_kind), dimension(nx) :: &
468 : work2 ! input array (real, 8-byte)
469 :
470 : real (kind=dbl_kind) :: &
471 : minw, maxw, sumw ! diagnostics
472 :
473 : character(len=*), parameter :: subname='(read_restart_field)'
474 :
475 1551 : if (restart_format == 'bin') then
476 7902 : do n = 1, ndim
477 32095 : read(nu) (work2(i), i=1,nx)
478 33578 : work(:,n) = work2(:)
479 : enddo
480 68 : else if (restart_format == 'nc') then
481 : #ifdef USE_NETCDF
482 68 : if (ndim == 1) then
483 16 : call read_restart_field_net1D(ncid,1,work,name,1,diag)
484 : else
485 52 : call read_restart_field_net2D(ncid,1,work,name,ndim,diag)
486 : endif
487 : #else
488 0 : call icedrv_system_abort(string=subname//' ERROR: restart_format = "nc" requires USE_NETCDF',file=__FILE__,line=__LINE__)
489 : #endif
490 : else
491 : call icedrv_system_abort(string=subname//'unrecognized restart format', &
492 0 : file=__FILE__,line=__LINE__)
493 : endif
494 :
495 35026 : minw = minval(work)
496 35026 : maxw = maxval(work)
497 35026 : sumw = sum(work)
498 1551 : write(nu_diag,*) subname, minw, maxw, sumw
499 :
500 1551 : end subroutine read_restart_field
501 :
502 : !=======================================================================
503 :
504 : ! Writes a single restart field.
505 : ! author Chris Newman, LANL
506 :
507 56343 : subroutine write_restart_field(nu,work,ndim,vname,dims)
508 :
509 : use icedrv_domain_size, only: nx
510 :
511 : integer (kind=int_kind), intent(in) :: &
512 : nu , & ! unit number
513 : ndim ! number of dimensions
514 :
515 : real (kind=dbl_kind), dimension(nx,ndim), intent(in) :: &
516 : work ! input array (real, 8-byte)
517 :
518 : character (len=*), intent(in), optional :: &
519 : vname ! variable name for netcdf output
520 :
521 : integer (kind=int_kind), intent(in), optional :: &
522 : dims(:) ! netcdf dimension IDs
523 :
524 : ! local variables
525 :
526 : integer (kind=int_kind) :: &
527 : n, i ! loop indices
528 :
529 : real (kind=dbl_kind), dimension(nx) :: &
530 : work2 ! input array (real, 8-byte)
531 :
532 : real (kind=dbl_kind) :: &
533 : minw, maxw, sumw ! diagnostics
534 :
535 : character(len=*), parameter :: subname='(write_restart_field)'
536 :
537 : #ifdef USE_NETCDF
538 : ! local variables if we're writing in NetCDF
539 : integer (kind=int_kind) :: &
540 : status, & ! Status variable from netCDF routine
541 : varid ! Variable ID
542 : #endif
543 :
544 56343 : if (restart_format == 'bin') then
545 282694 : do n = 1, ndim
546 1142975 : work2(:) = work(:,n)
547 1197074 : write(nu) (work2(i), i=1,nx)
548 : enddo
549 2244 : else if (restart_format == 'nc') then
550 : #ifdef USE_NETCDF
551 : ! Check whether the variable already exists in the netcdf file
552 2244 : status = nf90_inq_varid(ncid,trim(vname),varid)
553 2244 : if (status == nf90_enotvar) then ! if not add it to the file
554 2244 : status = nf90_redef(ncid) ! Put file into define mode
555 2244 : if (ndim == 1) then
556 : ! Handle 1D cases
557 528 : status = nf90_def_var(ncid,trim(vname),nf90_double,dims(1:1),varid)
558 : else
559 1716 : status = nf90_def_var(ncid,trim(vname),nf90_double,dims,varid)
560 : endif
561 : endif
562 2244 : status = nf90_enddef(ncid) ! put file into data mode
563 2244 : if (ndim == 1) then
564 528 : call write_restart_field_nc1D(ncid,0,work,'ruf8',vname,1,diag)
565 : else
566 1716 : call write_restart_field_nc2D(ncid,0,work,'ruf8',vname,ndim,diag)
567 : endif
568 : #else
569 0 : call icedrv_system_abort(string=subname//' ERROR: restart_format = "nc" requires USE_NETCDF',file=__FILE__,line=__LINE__)
570 : #endif
571 : else
572 0 : write (nu_diag,*) 'WARNING: Restart format must be either "bin" or "nc", no restart file written'
573 : endif
574 :
575 1244858 : minw = minval(work)
576 1244858 : maxw = maxval(work)
577 1244858 : sumw = sum(work)
578 56343 : write(nu_diag,*) subname, minw, maxw, sumw
579 :
580 56343 : end subroutine write_restart_field
581 :
582 : !=======================================================================
583 :
584 : ! Finalize the restart file.
585 : ! author David A. Bailey, NCAR
586 :
587 1231 : subroutine final_restart()
588 :
589 : use icedrv_calendar, only: istep1, time, time_forc
590 :
591 : character(len=*), parameter :: subname='(final_restart)'
592 :
593 1231 : close(nu_dump)
594 1231 : write(nu_diag,*) 'Restart read/written ',istep1,time,time_forc
595 :
596 1231 : end subroutine final_restart
597 :
598 : !=======================================================================
599 :
600 : ! Dumps all values needed for restarting
601 : !
602 : ! authors Elizabeth C. Hunke, LANL
603 : ! David A. Bailey, NCAR
604 :
605 54 : subroutine write_restart_pond_topo(dims)
606 :
607 : use icedrv_state, only: trcrn
608 : use icedrv_domain_size, only: ncat
609 :
610 : integer (kind=int_kind), intent(in), optional :: &
611 : dims(:) ! netcdf dimension IDs
612 :
613 : integer (kind=int_kind) :: nt_apnd, nt_hpnd, nt_ipnd
614 : character(len=*), parameter :: subname='(write_restart_pond_topo)'
615 :
616 : call icepack_query_tracer_indices(nt_apnd_out=nt_apnd, nt_hpnd_out=nt_hpnd, &
617 54 : nt_ipnd_out=nt_ipnd)
618 54 : call icepack_warnings_flush(nu_diag)
619 54 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
620 0 : file=__FILE__,line= __LINE__)
621 :
622 54 : call write_restart_field(nu_dump,trcrn(:,nt_apnd,:),ncat,'apnd',dims)
623 54 : call write_restart_field(nu_dump,trcrn(:,nt_hpnd,:),ncat,'hpnd',dims)
624 54 : call write_restart_field(nu_dump,trcrn(:,nt_ipnd,:),ncat,'ipnd',dims)
625 :
626 54 : end subroutine write_restart_pond_topo
627 :
628 : !=======================================================================
629 :
630 : ! Reads all values needed for a meltpond volume restart
631 : !
632 : ! authors Elizabeth C. Hunke, LANL
633 : ! David A. Bailey, NCAR
634 :
635 2 : subroutine read_restart_pond_topo()
636 :
637 : use icedrv_state, only: trcrn
638 : use icedrv_domain_size, only: ncat
639 : integer (kind=int_kind) :: nt_apnd, nt_hpnd, nt_ipnd
640 : character(len=*), parameter :: subname='(read_restart_pond_topo)'
641 :
642 : call icepack_query_tracer_indices(nt_apnd_out=nt_apnd, nt_hpnd_out=nt_hpnd, &
643 2 : nt_ipnd_out=nt_ipnd)
644 2 : call icepack_warnings_flush(nu_diag)
645 2 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
646 0 : file=__FILE__,line= __LINE__)
647 :
648 2 : write(nu_diag,*) 'min/max topo ponds'
649 :
650 2 : call read_restart_field(nu_restart,trcrn(:,nt_apnd,:),ncat,'apnd')
651 2 : call read_restart_field(nu_restart,trcrn(:,nt_hpnd,:),ncat,'hpnd')
652 2 : call read_restart_field(nu_restart,trcrn(:,nt_ipnd,:),ncat,'ipnd')
653 :
654 2 : end subroutine read_restart_pond_topo
655 :
656 : !=======================================================================
657 :
658 : ! Dumps values needed to restart snow redistribution/metamorphism tracers
659 : !
660 : ! authors Elizabeth C. Hunke, LANL
661 :
662 111 : subroutine write_restart_snow(dims)
663 :
664 : use icedrv_state, only: trcrn
665 : use icedrv_domain_size, only: nslyr, ncat
666 :
667 : integer (kind=int_kind), intent(in), optional :: &
668 : dims(:) ! netcdf dimension IDs
669 :
670 : integer (kind=int_kind) :: nt_smice, nt_smliq, nt_rhos, nt_rsnw, k
671 : character(len=*), parameter :: subname='(write_restart_snow)'
672 :
673 : call icepack_query_tracer_indices(nt_smice_out=nt_smice, &
674 111 : nt_smliq_out=nt_smliq, nt_rhos_out=nt_rhos, nt_rsnw_out=nt_rsnw)
675 111 : call icepack_warnings_flush(nu_diag)
676 111 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
677 0 : file=__FILE__,line= __LINE__)
678 :
679 666 : do k=1,nslyr
680 555 : write(nchar,'(i3.3)') k
681 555 : call write_restart_field(nu_dump,trcrn(:,nt_smice+k-1,:),ncat,'smice'//trim(nchar),dims)
682 555 : call write_restart_field(nu_dump,trcrn(:,nt_smliq+k-1,:),ncat,'smliq'//trim(nchar),dims)
683 555 : call write_restart_field(nu_dump,trcrn(:,nt_rhos +k-1,:),ncat,'rhos'//trim(nchar),dims)
684 666 : call write_restart_field(nu_dump,trcrn(:,nt_rsnw +k-1,:),ncat,'rsnw'//trim(nchar),dims)
685 : enddo
686 :
687 111 : end subroutine write_restart_snow
688 :
689 : !=======================================================================
690 :
691 : ! Reads all values needed to restart snow redistribution/metamorphism
692 : !
693 : ! authors Elizabeth C. Hunke, LANL
694 :
695 4 : subroutine read_restart_snow()
696 :
697 : use icedrv_state, only: trcrn
698 : use icedrv_domain_size, only: nslyr, ncat
699 :
700 : integer (kind=int_kind) :: nt_smice, nt_smliq, nt_rhos, nt_rsnw, k
701 : character(len=*), parameter :: subname='(read_restart_snow)'
702 :
703 : call icepack_query_tracer_indices(nt_smice_out=nt_smice, &
704 4 : nt_smliq_out=nt_smliq, nt_rhos_out=nt_rhos, nt_rsnw_out=nt_rsnw)
705 4 : call icepack_warnings_flush(nu_diag)
706 4 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
707 0 : file=__FILE__,line= __LINE__)
708 :
709 4 : write(nu_diag,*) 'min/max snow metamorphosis tracers'
710 :
711 24 : do k=1,nslyr
712 20 : write(nchar,'(i3.3)') k
713 20 : call read_restart_field(nu_restart,trcrn(:,nt_smice+k-1,:),ncat,'smice'//trim(nchar))
714 20 : call read_restart_field(nu_restart,trcrn(:,nt_smliq+k-1,:),ncat,'smliq'//trim(nchar))
715 20 : call read_restart_field(nu_restart,trcrn(:,nt_rhos +k-1,:),ncat,'rhos'//trim(nchar))
716 24 : call read_restart_field(nu_restart,trcrn(:,nt_rsnw +k-1,:),ncat,'rsnw'//trim(nchar))
717 : enddo
718 :
719 4 : end subroutine read_restart_snow
720 :
721 : !=======================================================================
722 :
723 : ! Dumps all values needed for restarting
724 : ! author Elizabeth C. Hunke, LANL
725 :
726 21 : subroutine write_restart_age(dims)
727 :
728 : use icedrv_state, only: trcrn
729 : use icedrv_domain_size, only: ncat
730 :
731 : integer (kind=int_kind), intent(in), optional :: &
732 : dims(:) ! netcdf dimension IDs
733 :
734 : integer (kind=int_kind) :: nt_iage
735 : character(len=*), parameter :: subname='(write_restart_age)'
736 :
737 21 : call icepack_query_tracer_indices(nt_iage_out=nt_iage)
738 21 : call icepack_warnings_flush(nu_diag)
739 21 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
740 0 : file=__FILE__,line= __LINE__)
741 :
742 21 : call write_restart_field(nu_dump,trcrn(:,nt_iage,:),ncat,'iage',dims)
743 :
744 21 : end subroutine write_restart_age
745 :
746 : !=======================================================================
747 :
748 : ! Reads all values needed for an ice age restart
749 : ! author Elizabeth C. Hunke, LANL
750 :
751 2 : subroutine read_restart_age()
752 :
753 : use icedrv_state, only: trcrn
754 : use icedrv_domain_size, only: ncat
755 : integer (kind=int_kind) :: nt_iage
756 : character(len=*), parameter :: subname='(read_restart_age)'
757 :
758 1 : write(nu_diag,*) 'min/max age (s)'
759 :
760 1 : call icepack_query_tracer_indices(nt_iage_out=nt_iage)
761 1 : call icepack_warnings_flush(nu_diag)
762 1 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
763 0 : file=__FILE__,line= __LINE__)
764 :
765 1 : call read_restart_field(nu_restart,trcrn(:,nt_iage,:),ncat,'iage')
766 :
767 1 : end subroutine read_restart_age
768 :
769 : !=======================================================================
770 :
771 : ! Dumps all values needed for restarting
772 : ! author Elizabeth C. Hunke, LANL
773 :
774 45 : subroutine write_restart_fsd(dims)
775 :
776 : use icedrv_state, only: trcrn
777 : use icedrv_domain_size, only: ncat, nfsd
778 :
779 : integer (kind=int_kind), intent(in), optional :: &
780 : dims(:) ! netcdf dimension IDs
781 :
782 : integer (kind=int_kind) :: nt_fsd, k
783 : character(len=*), parameter :: subname='(write_restart_fsd)'
784 :
785 45 : call icepack_query_tracer_indices(nt_fsd_out=nt_fsd)
786 45 : call icepack_warnings_flush(nu_diag)
787 45 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
788 0 : file=__FILE__,line= __LINE__)
789 :
790 453 : do k = 1, nfsd
791 408 : write(nchar,'(i3.3)') k
792 : call write_restart_field(nu_dump,trcrn(:,nt_fsd+k-1,:),ncat,&
793 453 : 'fsd'//trim(nchar),dims)
794 : end do
795 :
796 45 : end subroutine write_restart_fsd
797 :
798 : !=======================================================================
799 :
800 : ! Reads all values needed for a FSD restart
801 : ! author Elizabeth C. Hunke, LANL
802 :
803 2 : subroutine read_restart_fsd()
804 :
805 : use icedrv_state, only: trcrn
806 : use icedrv_domain_size, only: ncat, nfsd
807 : integer (kind=int_kind) :: nt_fsd, k
808 : character(len=*), parameter :: subname='(read_restart_fsd)'
809 :
810 1 : write(nu_diag,*) 'min/max fsd'
811 :
812 1 : call icepack_query_tracer_indices(nt_fsd_out=nt_fsd)
813 1 : call icepack_warnings_flush(nu_diag)
814 1 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
815 0 : file=__FILE__,line= __LINE__)
816 :
817 13 : do k =1, nfsd
818 12 : write(nchar,'(i3.3)') k
819 13 : call read_restart_field(nu_restart,trcrn(:,nt_fsd+k-1,:),ncat,'fsd'//trim(nchar))
820 : end do
821 :
822 1 : end subroutine read_restart_fsd
823 :
824 : !=======================================================================
825 :
826 : ! Dumps all values needed for restarting
827 : ! author Elizabeth C. Hunke, LANL
828 :
829 66 : subroutine write_restart_FY(dims)
830 :
831 : use icedrv_flux, only: frz_onset
832 : use icedrv_state, only: trcrn
833 : use icedrv_domain_size, only: ncat
834 :
835 : integer (kind=int_kind), intent(in), optional :: &
836 : dims(:) ! netcdf dimension IDs
837 :
838 : integer (kind=int_kind) :: nt_FY
839 : character(len=*), parameter :: subname='(write_restart_FY)'
840 :
841 66 : call icepack_query_tracer_indices(nt_FY_out=nt_FY)
842 66 : call icepack_warnings_flush(nu_diag)
843 66 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
844 0 : file=__FILE__,line= __LINE__)
845 :
846 66 : call write_restart_field(nu_dump,trcrn(:,nt_FY,:),ncat,'FY',dims)
847 66 : call write_restart_field(nu_dump,frz_onset,1,'frz_onset',dims)
848 :
849 66 : end subroutine write_restart_FY
850 :
851 : !=======================================================================
852 :
853 : ! Reads all values needed for an ice FY restart
854 : ! author Elizabeth C. Hunke, LANL
855 :
856 3 : subroutine read_restart_FY()
857 :
858 : use icedrv_flux, only: frz_onset
859 : use icedrv_state, only: trcrn
860 : use icedrv_domain_size, only: ncat
861 : integer (kind=int_kind) :: nt_FY
862 : character(len=*), parameter :: subname='(read_restart_FY)'
863 :
864 3 : call icepack_query_tracer_indices(nt_FY_out=nt_FY)
865 3 : call icepack_warnings_flush(nu_diag)
866 3 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
867 0 : file=__FILE__,line= __LINE__)
868 :
869 3 : write(nu_diag,*) 'min/max first-year ice area'
870 :
871 3 : call read_restart_field(nu_restart,trcrn(:,nt_FY,:),ncat,'FY')
872 :
873 3 : write(nu_diag,*) 'min/max frz_onset'
874 :
875 3 : call read_restart_field(nu_restart,frz_onset,1,'frz_onset')
876 :
877 3 : end subroutine read_restart_FY
878 :
879 : !=======================================================================
880 :
881 : ! Dumps all values needed for restarting
882 : !
883 : ! author Elizabeth C. Hunke, LANL
884 :
885 1210 : subroutine write_restart_lvl(dims)
886 :
887 : use icedrv_state, only: trcrn
888 : use icedrv_domain_size, only: ncat
889 :
890 : integer (kind=int_kind), intent(in), optional :: &
891 : dims(:) ! netcdf dimension IDs
892 :
893 : integer (kind=int_kind) :: nt_alvl, nt_vlvl
894 : character(len=*), parameter :: subname='(write_restart_lvl)'
895 :
896 1210 : call icepack_query_tracer_indices(nt_alvl_out=nt_alvl, nt_vlvl_out=nt_vlvl)
897 1210 : call icepack_warnings_flush(nu_diag)
898 1210 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
899 0 : file=__FILE__,line= __LINE__)
900 :
901 1210 : call write_restart_field(nu_dump,trcrn(:,nt_alvl,:),ncat,'alvl',dims)
902 1210 : call write_restart_field(nu_dump,trcrn(:,nt_vlvl,:),ncat,'vlvl',dims)
903 :
904 1210 : end subroutine write_restart_lvl
905 :
906 : !=======================================================================
907 :
908 : ! Reads all values needed for an ice lvl restart
909 : !
910 : ! author Elizabeth C. Hunke, LANL
911 :
912 26 : subroutine read_restart_lvl()
913 :
914 : use icedrv_state, only: trcrn
915 : use icedrv_domain_size, only: ncat
916 : integer (kind=int_kind) :: nt_alvl, nt_vlvl
917 : character(len=*), parameter :: subname='(read_restart_lvl)'
918 :
919 26 : call icepack_query_tracer_indices(nt_alvl_out=nt_alvl, nt_vlvl_out=nt_vlvl)
920 26 : call icepack_warnings_flush(nu_diag)
921 26 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
922 0 : file=__FILE__,line= __LINE__)
923 :
924 26 : write(nu_diag,*) 'min/max level ice area, volume'
925 :
926 26 : call read_restart_field(nu_restart,trcrn(:,nt_alvl,:),ncat,'alvl')
927 26 : call read_restart_field(nu_restart,trcrn(:,nt_vlvl,:),ncat,'vlvl')
928 :
929 26 : end subroutine read_restart_lvl
930 :
931 : !=======================================================================
932 : !
933 : ! Dumps all values needed for restarting
934 : !
935 : ! authors Elizabeth C. Hunke, LANL
936 :
937 1078 : subroutine write_restart_pond_lvl(dims)
938 :
939 : use icedrv_arrays_column, only: dhsn, ffracn
940 : use icedrv_flux, only: fsnow
941 : use icedrv_state, only: trcrn
942 : use icedrv_domain_size, only: ncat
943 :
944 : integer (kind=int_kind), intent(in), optional :: &
945 : dims(:) ! netcdf dimension IDs
946 :
947 : integer (kind=int_kind) :: nt_apnd, nt_hpnd, nt_ipnd
948 : character(len=*), parameter :: subname='(write_restart_pond_lvl)'
949 :
950 : call icepack_query_tracer_indices(nt_apnd_out=nt_apnd, nt_hpnd_out=nt_hpnd, &
951 1078 : nt_ipnd_out=nt_ipnd)
952 1078 : call icepack_warnings_flush(nu_diag)
953 1078 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
954 0 : file=__FILE__,line= __LINE__)
955 :
956 1078 : call write_restart_field(nu_dump,trcrn(:,nt_apnd,:),ncat,'apnd',dims)
957 1078 : call write_restart_field(nu_dump,trcrn(:,nt_hpnd,:),ncat,'hpnd',dims)
958 1078 : call write_restart_field(nu_dump,trcrn(:,nt_ipnd,:),ncat,'ipnd',dims)
959 1078 : call write_restart_field(nu_dump,fsnow(:),1,'fsnow',dims)
960 1078 : call write_restart_field(nu_dump,dhsn(:,:),ncat,'dhsn',dims)
961 1078 : call write_restart_field(nu_dump,ffracn(:,:),ncat,'ffracn',dims)
962 :
963 1078 : end subroutine write_restart_pond_lvl
964 :
965 : !=======================================================================
966 :
967 : ! Reads all values needed for a meltpond volume restart
968 : !
969 : ! authors Elizabeth C. Hunke, LANL
970 :
971 22 : subroutine read_restart_pond_lvl()
972 :
973 : use icedrv_arrays_column, only: dhsn, ffracn
974 : use icedrv_flux, only: fsnow
975 : use icedrv_state, only: trcrn
976 : use icedrv_domain_size, only: ncat
977 : integer (kind=int_kind) :: nt_apnd, nt_hpnd, nt_ipnd
978 : character(len=*), parameter :: subname='(write_restart_pond_lvl)'
979 :
980 : call icepack_query_tracer_indices(nt_apnd_out=nt_apnd, nt_hpnd_out=nt_hpnd, &
981 22 : nt_ipnd_out=nt_ipnd)
982 22 : call icepack_warnings_flush(nu_diag)
983 22 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
984 0 : file=__FILE__,line= __LINE__)
985 :
986 22 : write(nu_diag,*) 'min/max level-ice ponds'
987 :
988 22 : call read_restart_field(nu_restart,trcrn(:,nt_apnd,:),ncat,'apnd')
989 22 : call read_restart_field(nu_restart,trcrn(:,nt_hpnd,:),ncat,'hpnd')
990 22 : call read_restart_field(nu_restart,trcrn(:,nt_ipnd,:),ncat,'ipnd')
991 22 : call read_restart_field(nu_restart,fsnow(:),1,'fsnow')
992 22 : call read_restart_field(nu_restart,dhsn(:,:),ncat,'dhsn')
993 22 : call read_restart_field(nu_restart,ffracn(:,:),ncat,'ffracn')
994 :
995 22 : end subroutine read_restart_pond_lvl
996 :
997 : !=======================================================================
998 :
999 : ! Dumps all values needed for restarting
1000 : !
1001 : ! authors Elizabeth Hunke, LANL
1002 : ! David Bailey, NCAR
1003 : ! Marika Holland, NCAR
1004 :
1005 33 : subroutine write_restart_aero(dims)
1006 :
1007 : use icedrv_domain_size, only: n_aero
1008 : use icedrv_state, only: trcrn
1009 : use icedrv_domain_size, only: ncat
1010 :
1011 : integer (kind=int_kind), intent(in), optional :: &
1012 : dims(:) ! netcdf dimension IDs
1013 :
1014 : ! local variables
1015 :
1016 : integer (kind=int_kind) :: &
1017 : k ! loop indices
1018 : integer (kind=int_kind) :: nt_aero
1019 : character(len=*), parameter :: subname='(write_restart_aero)'
1020 :
1021 33 : call icepack_query_tracer_indices(nt_aero_out=nt_aero)
1022 33 : call icepack_warnings_flush(nu_diag)
1023 33 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
1024 0 : file=__FILE__,line= __LINE__)
1025 :
1026 33 : write(nu_diag,*) 'write_restart_aero (aerosols)'
1027 :
1028 66 : do k = 1, n_aero
1029 33 : write(nchar,'(i3.3)') k
1030 : call write_restart_field(nu_dump, trcrn(:,nt_aero +(k-1)*4,:),ncat,&
1031 33 : 'aerosnossl'//trim(nchar),dims)
1032 : call write_restart_field(nu_dump, trcrn(:,nt_aero+1+(k-1)*4,:),ncat,&
1033 33 : 'aerosnoint'//trim(nchar),dims)
1034 : call write_restart_field(nu_dump, trcrn(:,nt_aero+2+(k-1)*4,:),ncat,&
1035 33 : 'aeroicessl'//trim(nchar),dims)
1036 : call write_restart_field(nu_dump, trcrn(:,nt_aero+3+(k-1)*4,:),ncat,&
1037 66 : 'aeroiceint'//trim(nchar),dims)
1038 : enddo
1039 :
1040 33 : end subroutine write_restart_aero
1041 :
1042 : !=======================================================================
1043 :
1044 : ! Reads all values needed for an ice aerosol restart
1045 : !
1046 : ! authors Elizabeth Hunke, LANL
1047 : ! David Bailey, NCAR
1048 : ! Marika Holland, NCAR
1049 :
1050 1 : subroutine read_restart_aero()
1051 :
1052 : use icedrv_domain_size, only: n_aero
1053 : use icedrv_state, only: trcrn
1054 : use icedrv_domain_size, only: ncat
1055 :
1056 : ! local variables
1057 :
1058 : integer (kind=int_kind) :: &
1059 : k ! loop indices
1060 : integer (kind=int_kind) :: nt_aero
1061 : character(len=*), parameter :: subname='(read_restart_aero)'
1062 :
1063 : !-----------------------------------------------------------------
1064 :
1065 1 : call icepack_query_tracer_indices(nt_aero_out=nt_aero)
1066 1 : call icepack_warnings_flush(nu_diag)
1067 1 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
1068 0 : file=__FILE__,line= __LINE__)
1069 :
1070 1 : write(nu_diag,*) 'read_restart_aero (aerosols)'
1071 :
1072 2 : do k = 1, n_aero
1073 1 : write(nchar,'(i3.3)') k
1074 1 : call read_restart_field(nu_restart, trcrn(:,nt_aero +(k-1)*4,:),ncat,'aerosnossl'//trim(nchar))
1075 1 : call read_restart_field(nu_restart, trcrn(:,nt_aero+1+(k-1)*4,:),ncat,'aerosnoint'//trim(nchar))
1076 1 : call read_restart_field(nu_restart, trcrn(:,nt_aero+2+(k-1)*4,:),ncat,'aeroicessl'//trim(nchar))
1077 2 : call read_restart_field(nu_restart, trcrn(:,nt_aero+3+(k-1)*4,:),ncat,'aeroiceint'//trim(nchar))
1078 : enddo
1079 :
1080 1 : end subroutine read_restart_aero
1081 :
1082 : !=======================================================================
1083 :
1084 : ! Dumps all values needed for restarting
1085 : !
1086 : ! authors Elizabeth Hunke, LANL
1087 : ! David Bailey, NCAR
1088 : ! Marika Holland, NCAR
1089 :
1090 21 : subroutine write_restart_iso(dims)
1091 :
1092 : use icedrv_domain_size, only: n_iso
1093 : use icedrv_state, only: trcrn
1094 : use icedrv_domain_size, only: ncat
1095 :
1096 : integer (kind=int_kind), intent(in), optional :: &
1097 : dims(:) ! netcdf dimension IDs
1098 :
1099 : ! local variables
1100 :
1101 : integer (kind=int_kind) :: &
1102 : k ! loop indices
1103 : integer (kind=int_kind) :: nt_isosno, nt_isoice
1104 : character(len=*), parameter :: subname='(write_restart_iso)'
1105 :
1106 21 : call icepack_query_tracer_indices(nt_isosno_out=nt_isosno)
1107 21 : call icepack_query_tracer_indices(nt_isoice_out=nt_isoice)
1108 21 : call icepack_warnings_flush(nu_diag)
1109 21 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
1110 0 : file=__FILE__,line= __LINE__)
1111 :
1112 21 : write(nu_diag,*) 'write_restart_iso (isotopes)'
1113 :
1114 84 : do k = 1, n_iso
1115 63 : write(nchar,'(i3.3)') k
1116 : call write_restart_field(nu_dump, trcrn(:,nt_isosno+(k-1),:),ncat,&
1117 63 : 'isosno'//trim(nchar),dims)
1118 : call write_restart_field(nu_dump, trcrn(:,nt_isoice+(k-1),:),ncat,&
1119 84 : 'isoice'//trim(nchar),dims)
1120 : enddo
1121 :
1122 21 : end subroutine write_restart_iso
1123 :
1124 : !=======================================================================
1125 :
1126 : ! Reads all values needed for an ice isotope restart
1127 : !
1128 : ! authors Elizabeth Hunke, LANL
1129 : ! David Bailey, NCAR
1130 : ! Marika Holland, NCAR
1131 :
1132 2 : subroutine read_restart_iso()
1133 :
1134 : use icedrv_domain_size, only: n_iso
1135 : use icedrv_state, only: trcrn
1136 : use icedrv_domain_size, only: ncat
1137 :
1138 : ! local variables
1139 :
1140 : integer (kind=int_kind) :: &
1141 : k ! loop indices
1142 : integer (kind=int_kind) :: nt_isosno, nt_isoice
1143 : character(len=*), parameter :: subname='(read_restart_iso)'
1144 :
1145 : !-----------------------------------------------------------------
1146 :
1147 1 : call icepack_query_tracer_indices(nt_isosno_out=nt_isosno)
1148 1 : call icepack_query_tracer_indices(nt_isoice_out=nt_isoice)
1149 1 : call icepack_warnings_flush(nu_diag)
1150 1 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
1151 0 : file=__FILE__,line= __LINE__)
1152 :
1153 1 : write(nu_diag,*) 'read_restart_iso (isotopes)'
1154 :
1155 4 : do k = 1, n_iso
1156 3 : write(nchar,'(i3.3)') k
1157 3 : call read_restart_field(nu_restart, trcrn(:,nt_isosno+(k-1),:),ncat,'isosno'//trim(nchar))
1158 4 : call read_restart_field(nu_restart, trcrn(:,nt_isoice+(k-1),:),ncat,'isoice'//trim(nchar))
1159 : enddo
1160 :
1161 1 : end subroutine read_restart_iso
1162 :
1163 : !=======================================================================
1164 :
1165 67 : subroutine write_restart_hbrine(dims)
1166 :
1167 : ! Dumps all values needed for a hbrine restart
1168 : ! author Elizabeth C. Hunke, LANL
1169 :
1170 : use icedrv_arrays_column, only: first_ice, first_ice_real
1171 : use icedrv_state, only: trcrn
1172 : use icedrv_domain_size, only: ncat, nx
1173 :
1174 : integer (kind=int_kind), intent(in), optional :: &
1175 : dims(:) ! netcdf dimension IDs
1176 :
1177 : ! local variables
1178 :
1179 : integer (kind=int_kind) :: &
1180 : i, n ! horizontal indices
1181 : integer (kind=int_kind) :: nt_fbri
1182 : character(len=*), parameter :: subname='(write_restart_hbrine)'
1183 :
1184 67 : call icepack_query_tracer_indices(nt_fbri_out=nt_fbri)
1185 67 : call icepack_warnings_flush(nu_diag)
1186 67 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
1187 0 : file=__FILE__,line= __LINE__)
1188 :
1189 335 : do i = 1, nx
1190 1675 : do n = 1, ncat
1191 1608 : if (first_ice (i,n)) then
1192 633 : first_ice_real(i,n) = c1
1193 : else
1194 707 : first_ice_real(i,n) = c0
1195 : endif
1196 : enddo ! n
1197 : enddo ! i
1198 :
1199 67 : call write_restart_field(nu_dump,trcrn(:,nt_fbri,:),ncat,'fbri',dims)
1200 67 : call write_restart_field(nu_dump,first_ice_real(:,:),ncat,'first_ice',dims)
1201 :
1202 67 : end subroutine write_restart_hbrine
1203 :
1204 : !=======================================================================
1205 :
1206 3 : subroutine read_restart_hbrine()
1207 :
1208 : ! Reads all values needed for hbrine
1209 : ! author Elizabeth C. Hunke, LANL
1210 :
1211 : use icedrv_arrays_column, only: first_ice_real, first_ice
1212 : use icedrv_state, only: trcrn
1213 : use icedrv_domain_size, only: ncat, nx
1214 :
1215 : ! local variables
1216 :
1217 : integer (kind=int_kind) :: &
1218 : i, n ! horizontal indices
1219 : integer (kind=int_kind) :: nt_fbri
1220 : character(len=*), parameter :: subname='(read_restart_hbrine)'
1221 :
1222 3 : call icepack_query_tracer_indices(nt_fbri_out=nt_fbri)
1223 3 : call icepack_warnings_flush(nu_diag)
1224 3 : if (icepack_warnings_aborted()) call icedrv_system_abort(string=subname, &
1225 0 : file=__FILE__,line= __LINE__)
1226 :
1227 3 : write(nu_diag,*) 'read brine restart'
1228 :
1229 3 : call read_restart_field(nu_restart,trcrn(:,nt_fbri,:),ncat,'fbri')
1230 3 : call read_restart_field(nu_restart,first_ice_real(:,:),ncat,'first_ice')
1231 :
1232 15 : do i = 1, nx
1233 75 : do n = 1, ncat
1234 72 : if (first_ice_real(i,n) >= p5) then
1235 31 : first_ice (i,n) = .true.
1236 : else
1237 29 : first_ice (i,n) = .false.
1238 : endif
1239 : enddo ! ncat
1240 : enddo ! i
1241 :
1242 3 : end subroutine read_restart_hbrine
1243 :
1244 : !=======================================================================
1245 : #ifdef USE_NETCDF
1246 0 : subroutine define_rest_field(ncid, vname, dims)
1247 :
1248 : ! Defines a field in NetCDF restart file
1249 : ! author Chris Riedel, NCAR
1250 :
1251 : character (len=*) , intent(in) :: vname
1252 : integer (kind=int_kind), intent(in) :: dims(:)
1253 : integer (kind=int_kind), intent(in) :: ncid
1254 :
1255 : integer (kind=int_kind) :: varid
1256 :
1257 : integer (kind=int_kind) :: &
1258 : status ! status variable from netCDF routine
1259 :
1260 0 : status = nf90_def_var(ncid,trim(vname),nf90_double,dims,varid)
1261 :
1262 0 : end subroutine define_rest_field
1263 : !=======================================================================
1264 1716 : subroutine write_restart_field_nc2D(ncid,nrec,work,atype,vname,ndim3,diag)
1265 :
1266 : ! Write a 2D field (nx, ncat) in NetCDF restart
1267 : ! author Chris Riedel, NCAR
1268 :
1269 : use icedrv_domain_size, only: ncat,nx
1270 : !use ice_fileunits, only: nu_diag
1271 : !use ice_read_write, only: ice_write, ice_write_nc
1272 :
1273 : integer (kind=int_kind), intent(in) :: &
1274 : ncid , & ! unit number
1275 : ndim3 , & ! third dimension
1276 : nrec ! record number (0 for sequential access)
1277 : real (kind=dbl_kind), intent(in), dimension(nx,ncat) :: &
1278 : work ! input array (real, 8-byte)
1279 : character (len=4), intent(in) :: &
1280 : atype ! format for output array
1281 : ! (real/integer, 4-byte/8-byte)
1282 :
1283 : logical (kind=log_kind), intent(in) :: &
1284 : diag ! if true, write diagnostic output
1285 :
1286 : character (len=*), intent(in) :: vname
1287 :
1288 : ! local variables
1289 :
1290 : integer (kind=int_kind) :: &
1291 : n, & ! dimension counter
1292 : varid, & ! variable id
1293 : status ! status variable from netCDF routine
1294 :
1295 :
1296 1716 : status = nf90_inq_varid(ncid,trim(vname),varid)
1297 1716 : write(nu_diag,*) 'Writing out ',trim(vname)
1298 1716 : call ice_write_nc2D(ncid, 1, varid, work, diag)
1299 :
1300 1716 : end subroutine write_restart_field_nc2D
1301 : !=======================================================================
1302 528 : subroutine write_restart_field_nc1D(ncid,nrec,work,atype,vname,ndim3,diag)
1303 :
1304 : ! Write a 1D field (nx) in NetCDF restart
1305 : ! author Chris Riedel, NCAR
1306 :
1307 : use icedrv_domain_size, only: ncat,nx
1308 :
1309 : integer (kind=int_kind), intent(in) :: &
1310 : ncid , & ! unit number
1311 : ndim3 , & ! third dimension
1312 : nrec ! record number (0 for sequential access)
1313 : real (kind=dbl_kind), intent(in), dimension(nx) :: &
1314 : work ! input array (real, 8-byte)
1315 : character (len=4), intent(in) :: &
1316 : atype ! format for output array
1317 : ! (real/integer, 4-byte/8-byte)
1318 :
1319 : logical (kind=log_kind), intent(in) :: &
1320 : diag ! if true, write diagnostic output
1321 :
1322 : character (len=*), intent(in) :: vname
1323 :
1324 : ! local variables
1325 :
1326 : integer (kind=int_kind) :: &
1327 : n, & ! dimension counter
1328 : varid, & ! variable id
1329 : status ! status variable from netCDF routine
1330 :
1331 :
1332 528 : status = nf90_inq_varid(ncid,trim(vname),varid)
1333 528 : if (status /= 0) then
1334 0 : write(nu_diag,*) 'Writing out ',trim(vname)
1335 0 : write(nu_diag,*) 'Erros Status ',status
1336 : call icedrv_system_abort(string='Write out restart', &
1337 0 : file=__FILE__,line= __LINE__)
1338 : else
1339 528 : write(nu_diag,*) 'Writing out ',trim(vname)
1340 : endif
1341 528 : call ice_write_nc1D(ncid, 1, varid, work, diag)
1342 :
1343 528 : end subroutine write_restart_field_nc1D
1344 : !=======================================================================
1345 1716 : subroutine ice_write_nc2D(fid, nrec, varid, work, diag)
1346 :
1347 : ! Write a 2D field (nx, ncat) in NetCDF restart
1348 : ! author Chris Riedel, NCAR
1349 :
1350 : use icedrv_domain_size, only: ncat,nx
1351 :
1352 : integer (kind=int_kind), intent(in) :: &
1353 : fid , & ! file id
1354 : varid , & ! variable id
1355 : nrec ! record number
1356 :
1357 : logical (kind=log_kind), intent(in) :: &
1358 : diag ! if true, write diagnostic output
1359 :
1360 : real (kind=dbl_kind), intent(in), dimension(nx,ncat) :: &
1361 : work ! output array (real, 8-byte)
1362 :
1363 : ! local variables
1364 :
1365 : integer (kind=int_kind) :: &
1366 : status, & ! status output from netcdf routines
1367 : ndim, nvar, & ! sizes of netcdf file
1368 : id, & ! dimension index
1369 : dimlen ! size of dimension
1370 : integer (kind=int_kind) :: start2(2),count2(2)
1371 :
1372 : real (kind=dbl_kind) :: &
1373 : amin, amax, asum ! min, max values and sum of input array
1374 :
1375 : character (char_len) :: &
1376 : dimname ! dimension name
1377 :
1378 : integer (kind=int_kind) :: ny,numDims
1379 :
1380 1716 : ny = ncat
1381 1716 : start2(1) = 1
1382 1716 : count2(1) = nx
1383 1716 : start2(2) = 1
1384 1716 : count2(2) = ncat
1385 :
1386 : status = nf90_put_var( fid, varid, work, &
1387 : start=start2, &
1388 1716 : count=count2)
1389 :
1390 : !-------------------------------------------------------------------
1391 : ! optional diagnostics
1392 : !-------------------------------------------------------------------
1393 :
1394 1716 : if (diag) then
1395 0 : amin = minval(work)
1396 0 : amax = maxval(work)
1397 : !asum = sum (work)
1398 0 : write(nu_diag,*) ' min, max =', amin, amax
1399 : endif
1400 :
1401 : !deallocate(work)
1402 :
1403 1716 : end subroutine ice_write_nc2D
1404 : !=======================================================================
1405 528 : subroutine ice_write_nc1D(fid, nrec, varid, work, diag)
1406 :
1407 : ! Write a 1D field (nx) in NetCDF restart
1408 : ! author Chris Riedel, NCAR
1409 :
1410 : use icedrv_domain_size, only: ncat,nx
1411 :
1412 : integer (kind=int_kind), intent(in) :: &
1413 : fid , & ! file id
1414 : varid , & ! variable id
1415 : nrec ! record number
1416 :
1417 : logical (kind=log_kind), intent(in) :: &
1418 : diag ! if true, write diagnostic output
1419 :
1420 : real (kind=dbl_kind), intent(in), dimension(nx) :: &
1421 : work ! output array (real, 8-byte)
1422 :
1423 : ! local variables
1424 :
1425 : integer (kind=int_kind) :: &
1426 : status, & ! status output from netcdf routines
1427 : ndim, nvar, & ! sizes of netcdf file
1428 : id, & ! dimension index
1429 : dimlen ! size of dimension
1430 : integer (kind=int_kind) :: start2(1),count2(1)
1431 :
1432 : real (kind=dbl_kind) :: &
1433 : amin, amax, asum ! min, max values and sum of input array
1434 :
1435 : character (char_len) :: &
1436 : dimname ! dimension name
1437 :
1438 : integer (kind=int_kind) :: ny,numDims
1439 :
1440 528 : ny = ncat
1441 528 : start2(1) = 1
1442 528 : count2(1) = nx
1443 :
1444 : status = nf90_put_var( fid, varid, work, &
1445 : start=start2, &
1446 528 : count=count2)
1447 :
1448 : !-------------------------------------------------------------------
1449 : ! optional diagnostics
1450 : !-------------------------------------------------------------------
1451 :
1452 528 : if (diag) then
1453 0 : amin = minval(work)
1454 0 : amax = maxval(work)
1455 : !asum = sum (work)
1456 0 : write(nu_diag,*) ' min, max =', amin, amax
1457 : endif
1458 :
1459 : !deallocate(work)
1460 :
1461 528 : end subroutine ice_write_nc1D
1462 : !=======================================================================
1463 52 : subroutine read_restart_field_net2D(nu,nrec,work,vname,ndim3, &
1464 : diag)
1465 :
1466 : ! author Chris Riedel, NCAR
1467 :
1468 : use icedrv_domain_size, only: ncat,nx
1469 :
1470 : integer (kind=int_kind), intent(in) :: &
1471 : nu , & ! unit number (not used for netcdf)
1472 : ndim3 , & ! third dimension
1473 : nrec ! record number (0 for sequential access)
1474 :
1475 : real (kind=dbl_kind), intent(inout), dimension(nx,ncat) :: &
1476 : work ! input array (real, 8-byte)
1477 :
1478 : logical (kind=log_kind), intent(in) :: &
1479 : diag ! if true, write diagnostic output
1480 :
1481 : character (len=*), intent(in) :: vname
1482 :
1483 : ! local variables
1484 :
1485 : integer (kind=int_kind) :: &
1486 : n, & ! number of dimensions for variable
1487 : varid, & ! variable id
1488 : status ! status variable from netCDF routine
1489 :
1490 52 : call ice_read_nc2D(ncid, 1, vname, work, diag)
1491 :
1492 52 : end subroutine read_restart_field_net2D
1493 : !=======================================================================
1494 16 : subroutine read_restart_field_net1D(nu,nrec,work,vname,ndim3, &
1495 : diag)
1496 :
1497 : ! author Chris Riedel, NCAR
1498 :
1499 : use icedrv_domain_size, only: ncat,nx
1500 :
1501 : integer (kind=int_kind), intent(in) :: &
1502 : nu , & ! unit number (not used for netcdf)
1503 : ndim3 , & ! third dimension
1504 : nrec ! record number (0 for sequential access)
1505 :
1506 : real (kind=dbl_kind), intent(inout), dimension(nx) :: &
1507 : work ! input array (real, 8-byte)
1508 :
1509 : logical (kind=log_kind), intent(in) :: &
1510 : diag ! if true, write diagnostic output
1511 :
1512 : character (len=*), intent(in) :: vname
1513 :
1514 : ! local variables
1515 :
1516 : integer (kind=int_kind) :: &
1517 : n, & ! number of dimensions for variable
1518 : varid, & ! variable id
1519 : status ! status variable from netCDF routine
1520 :
1521 16 : call ice_read_nc1D(ncid, 1, vname, work, diag)
1522 :
1523 16 : end subroutine read_restart_field_net1D
1524 : !=======================================================================
1525 52 : subroutine ice_read_nc2D(fid, nrec, varname, work, diag)
1526 :
1527 : ! author Chris Riedel, NCAR
1528 :
1529 : use icedrv_domain_size, only: ncat,nx
1530 :
1531 : integer (kind=int_kind), intent(in) :: &
1532 : fid , & ! file id
1533 : nrec ! record number
1534 :
1535 : logical (kind=log_kind), intent(in) :: &
1536 : diag ! if true, write diagnostic output
1537 :
1538 : character (len=*), intent(in) :: &
1539 : varname ! field name in netcdf file
1540 :
1541 : real (kind=dbl_kind), intent(out), dimension(nx,ncat) :: &
1542 : work ! output array (real, 8-byte)
1543 :
1544 : integer (kind=int_kind) :: &
1545 : varid , & ! variable id
1546 : status, & ! status output from netcdf routines
1547 : ndim, nvar, & ! sizes of netcdf file
1548 : id, & ! dimension index
1549 : dimlen ! size of dimension
1550 :
1551 : real (kind=dbl_kind) :: &
1552 : amin, amax, asum ! min, max values and sum of input array
1553 :
1554 : character (char_len) :: &
1555 : dimname ! dimension name
1556 :
1557 : integer (kind=int_kind) :: start2(2),count2(2)
1558 :
1559 : integer (kind=int_kind) :: ny,numDims
1560 :
1561 52 : ny = ncat
1562 52 : start2(1) = 1
1563 52 : count2(1) = nx
1564 52 : start2(2) = 1
1565 52 : count2(2) = ncat
1566 :
1567 52 : status = nf90_inq_varid(fid, trim(varname), varid)
1568 :
1569 52 : if (status /= nf90_noerr) then
1570 : call icedrv_system_abort(string='ice_read_nc2D:Var not found '//trim(varname), &
1571 0 : file=__FILE__,line=__LINE__)
1572 : endif
1573 :
1574 : status = nf90_get_var( fid, varid, work, &
1575 : start=start2, &
1576 52 : count=count2 )
1577 :
1578 :
1579 52 : if (diag) then
1580 0 : amin = minval(work)
1581 0 : amax = maxval(work)
1582 0 : asum = sum (work)
1583 0 : write(nu_diag,*) ' min, max, sum =', amin, amax, asum
1584 : endif
1585 :
1586 52 : end subroutine ice_read_nc2D
1587 : !=======================================================================
1588 16 : subroutine ice_read_nc1D(fid, nrec, varname, work, diag)
1589 :
1590 : ! author Chris Riedel, NCAR
1591 :
1592 : use icedrv_domain_size, only: ncat,nx
1593 :
1594 : integer (kind=int_kind), intent(in) :: &
1595 : fid , & ! file id
1596 : nrec ! record number
1597 :
1598 : logical (kind=log_kind), intent(in) :: &
1599 : diag ! if true, write diagnostic output
1600 :
1601 : character (len=*), intent(in) :: &
1602 : varname ! field name in netcdf file
1603 :
1604 : real (kind=dbl_kind), intent(out), dimension(nx) :: &
1605 : work ! output array (real, 8-byte)
1606 :
1607 : integer (kind=int_kind) :: &
1608 : varid , & ! variable id
1609 : status, & ! status output from netcdf routines
1610 : ndim, nvar, & ! sizes of netcdf file
1611 : id, & ! dimension index
1612 : dimlen ! size of dimension
1613 :
1614 : real (kind=dbl_kind) :: &
1615 : amin, amax, asum ! min, max values and sum of input array
1616 :
1617 : character (char_len) :: &
1618 : dimname ! dimension name
1619 :
1620 : integer (kind=int_kind) :: start2(1),count2(1)
1621 :
1622 : integer (kind=int_kind) :: ny,numDims
1623 :
1624 16 : ny = ncat
1625 16 : start2(1) = 1
1626 16 : count2(1) = nx
1627 :
1628 16 : status = nf90_inq_varid(fid, trim(varname), varid)
1629 :
1630 16 : if (status /= nf90_noerr) then
1631 : call icedrv_system_abort(string='ice_read_nc2D:Var not found'//trim(varname), &
1632 0 : file=__FILE__,line=__LINE__)
1633 : endif
1634 :
1635 : status = nf90_get_var( fid, varid, work, &
1636 : start=start2, &
1637 16 : count=count2 )
1638 :
1639 16 : if (diag) then
1640 0 : amin = minval(work)
1641 0 : amax = maxval(work)
1642 0 : asum = sum (work)
1643 0 : write(nu_diag,*) ' min, max, sum =', amin, amax, asum
1644 : endif
1645 :
1646 16 : end subroutine ice_read_nc1D
1647 : #endif
1648 : !=======================================================================
1649 : end module icedrv_restart
1650 :
1651 : !=======================================================================
|