ROMS
Loading...
Searching...
No Matches
ad_main2d.F
Go to the documentation of this file.
1#include "cppdefs.h"
2#if defined ADJOINT && !defined SOLVE3D
3 SUBROUTINE ad_main2d (RunInterval)
4!
5!git $Id$
6!================================================== Hernan G. Arango ===
7! Copyright (c) 2002-2025 The ROMS Group Andrew M. Moore !
8! Licensed under a MIT/X style license !
9! See License_ROMS.md !
10!=======================================================================
11! !
12! This subroutine is the main driver for adjoint ROMS when !
13! configurated as shallow water (barotropic) ocean model only. It !
14! advances backward the adjoint model for all nested grids, if !
15! any, by the specified time interval (seconds), RunInterval. !
16! !
17!=======================================================================
18!
19 USE mod_param
20 USE mod_parallel
21# if defined MODEL_COUPLING && defined MCT_LIB
22 USE mod_coupler
23# endif
24# ifdef FOUR_DVAR
25 USE mod_fourdvar
26# endif
27 USE mod_iounits
28 USE mod_scalars
29 USE mod_stepping
30# ifdef SO_SEMI
31 USE mod_storage
32# endif
33!
34# if defined AD_SENSITIVITY || defined I4DVAR_ANA_SENSITIVITY || \
35 defined opt_observations || defined sensitivity_4dvar
37# endif
38 USE ad_diag_mod, ONLY : ad_diag
39# if defined WEAK_CONSTRAINT || defined FORCING_SV
40 USE ad_forcing_mod, ONLY : ad_forcing
41# endif
42# ifdef ADJUST_WSTRESS
44# endif
46# ifdef AD_OUTPUT_STATE
48# endif
49# if defined FOUR_DVAR && defined OBSERVATIONS
50# ifdef WEAK_CONSTRAINT
51 USE ad_htobs_mod, ONLY : ad_htobs
52# else
53 USE ad_misfit_mod, ONLY : ad_misfit
54# endif
55# endif
56# ifdef ADJUST_BOUNDARY
58# endif
59# ifdef NEARSHORE_MELLOR_NOT_YET
60!! USE ad_radiation_stress_mod, ONLY : ad_radiation_stress
61# endif
62# ifdef AD_AVERAGES
63 USE ad_set_avg_mod, ONLY : ad_set_avg
64# endif
65# if defined SSH_TIDES_NOT_YET || defined UV_TIDES_NOT_YET
66!! USE ad_set_tides_mod, ONLY : ad_set_tides
67# endif
68 USE ad_set_vbc_mod, ONLY : ad_set_vbc
69 USE ad_step2d_mod, ONLY : ad_step2d
70# ifdef FLOATS_NOT_YET
71!! USE ad_step_floats_mod, ONLY : tl_step_floats
72# endif
73 USE dateclock_mod, ONLY : time_string
74# ifdef TIDE_GENERATING_FORCES
75 USE equilibrium_tide_mod, ONLY : equilibrium_tide
76# endif
77# ifdef WEAK_CONSTRAINT
79# endif
80# ifdef AIR_OCEAN_NOT_YET && defined MCT_LIB
81 USE mct_coupler_mod, ONLY : ocn2atm_coupling
82# endif
83# if defined WAV_COUPLING_NOT_YET && defined MCT_LIB
84 USE mct_coupler_mod, ONLY : ocn2wav_coupling
85# endif
86# if (defined FOUR_DVAR && !defined I4DVAR_ANA_SENSITIVITY) && \
87 defined observations
88 USE obs_read_mod, ONLY : obs_read
89# endif
90# ifdef SO_SEMI
91 USE packing_mod, ONLY : ad_pack
92# endif
93 USE strings_mod, ONLY : founderror
94!
95 implicit none
96!
97! Imported variable declarations.
98!
99 real(dp), intent(in) :: RunInterval
100!
101! Local variable declarations.
102!
103 logical:: backward = .true.
104!
105 integer :: ng, tile
106 integer :: next_indx1
107# ifdef FLOATS_NOT_YET
108 integer :: Lend, Lstr, chunk_size
109# endif
110 integer :: ksav, ktmp
111!
112 real(r8) :: HalfDT, MaxDT, my_StepTime
113!
114 character (len=*), parameter :: MyFile = &
115 & __FILE__
116!
117!=======================================================================
118! Time-step adjoint vertically integrated equations.
119!=======================================================================
120!
121 my_steptime=0.0_r8
122 maxdt=maxval(dt)
123
124 step_loop : DO WHILE (my_steptime.le.(runinterval+0.5_r8*maxdt))
125
126 my_steptime=my_steptime+maxdt
127!
128! Set time clock.
129!
130 DO ng=1,ngrids
131 iic(ng)=iic(ng)-1
132 time(ng)=time(ng)-dt(ng)
133 tdays(ng)=time(ng)*sec2day
134 CALL time_string (time(ng), time_code(ng))
135 END DO
136!
137!-----------------------------------------------------------------------
138! Read in required data, if any, from input NetCDF files.
139!-----------------------------------------------------------------------
140!
141 DO ng=1,ngrids
142 CALL ad_get_data (ng)
143 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
144 END DO
145!
146!-----------------------------------------------------------------------
147! Process input data, if any: time interpolate between snapshots.
148! If appropriate, compute and report diagnostics.
149!-----------------------------------------------------------------------
150!
151 DO ng=1,ngrids
152 DO tile=first_tile(ng),last_tile(ng),+1 ! irreversible
153 CALL ad_set_data (ng, tile)
154# ifdef AD_AVERAGES
155 CALL ad_set_avg (ng, tile)
156# endif
157# ifdef TIDE_GENERATING_FORCES
158 CALL equilibrium_tide (ng, tile, iadm)
159# endif
160# ifdef DIAGNOSTICS
161!! CALL ad_set_diags (ng, tile)
162# endif
163 CALL ad_diag (ng, tile)
164 END DO
165 END DO
166 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
167
168# if (defined FOUR_DVAR && !defined I4DVAR_ANA_SENSITIVITY) && \
169 defined observations
170!
171!-----------------------------------------------------------------------
172! If appropriate, read observation and model state at observation
173! locations. Then, compute adjoint misfit forcing terms.
174!-----------------------------------------------------------------------
175!
176 DO ng=1,ngrids
177# ifdef SENSITIVITY_4DVAR
178 IF (.not.lsen4dvar(ng)) THEN
179# endif
180 halfdt=0.5_r8*dt(ng)
181 IF (((time(ng)-halfdt).le.obstime(ng)).and. &
182 & (obstime(ng).lt.(time(ng)+halfdt))) THEN
183 processobs(ng)=.true.
184 CALL obs_read (ng, iadm, backward)
186 & __line__, myfile)) RETURN
187 ELSE
188 processobs(ng)=.false.
189 END IF
190!
191# ifdef SP4DVAR
192!
193! Skip assimilation of obs on first timestep unless inter=Nsaddle.
194!
195 IF ((iic(ng).ne.ntstart(ng)).or.lsadd(ng)) THEN
196# endif
197 DO tile=first_tile(ng),last_tile(ng),+1
198# ifdef WEAK_CONSTRAINT
199 CALL ad_htobs (ng, tile, iadm)
200# else
201 CALL ad_misfit (ng, tile, iadm)
202# endif
203 END DO
204 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
205# ifdef SENSITIVITY_4DVAR
206 END IF
207# endif
208# ifdef SP4DVAR
209 END IF
210# endif
211 END DO
212# endif
213
214# ifdef WEAK_CONSTRAINT
215!
216!-----------------------------------------------------------------------
217! If appropriate, add representer coefficients (Beta hat) impulse
218! forcing to adjoint solution. Read next impulse record, if available.
219!-----------------------------------------------------------------------
220!
221 DO ng=1,ngrids
222 IF (processobs(ng)) THEN
223 DO tile=first_tile(ng),last_tile(ng),+1
224 CALL ad_forcing (ng, tile, knew(ng), nnew(ng))
225 END DO
226 END IF
227 END DO
228# endif
229!
230! Avoid time-stepping if additional delayed IO time-step.
231!
232 time_step: IF (minval(iic).ne.minval(ntstart)) THEN
233
234# ifdef FLOATS_NOT_YET
235!
236!-----------------------------------------------------------------------
237! Compute Lagrangian drifters trajectories.
238!-----------------------------------------------------------------------
239!
240! Shift floats time indices.
241!
242 DO ng=1,ngrids
243 IF (lfloats(ng)) THEN
244 nfp1(ng)=mod(nfp1(ng)+1,nft+1)
245 nf(ng)=mod(nf(ng)+1,nft+1)
246 nfm1(ng)=mod(nfm1(ng)+1,nft+1)
247 nfm2(ng)=mod(nfm2(ng)+1,nft+1)
248 nfm3(ng)=mod(nfm3(ng)+1,nft+1)
249!
250# ifdef _OPENMP
251 chunk_size=(nfloats(ng)+numthreads-1)/numthreads
252 lstr=1+mythread*chunk_size
253 lend=min(nfloats(ng),lstr+chunk_size-1)
254# else
255 lstr=1
256 lend=nfloats(ng)
257# endif
258 CALL ad_step_floats (ng, lstr, lend)
259 END IF
260 END DO
261# endif
262!
263!-----------------------------------------------------------------------
264! Solve the vertically integrated primitive equations for the
265! free-surface and momentum components.
266!-----------------------------------------------------------------------
267!
268! Corrector step - Apply 2D time-step corrector scheme. Notice that
269! ============== there is not need for a corrector step during the
270! auxiliary (nfast+1) time-step.
271!
272 DO ng=1,ngrids
273 iif(ng)=1
274 nfast(ng)=1
275 IF (iif(ng).lt.(nfast(ng)+1)) THEN
276 DO tile=first_tile(ng),last_tile(ng),+1
277 CALL ad_step2d (ng, tile)
278 END DO
279 END IF
280!
281! Set time indices for corrector step.
282!
283 next_indx1=3-indx1(ng)
284 IF (.not.predictor_2d_step(ng)) THEN
285 predictor_2d_step(ng)=.true.
286 ktmp=knew(ng)
287 ksav=kstp(ng)
288 knew(ng)=krhs(ng)
289 kstp(ng)=ktmp
290 krhs(ng)=ksav
291 END IF
292 END DO
293!
294! Predictor step - Advance barotropic equations using 2D time-step
295! ============== predictor scheme.
296!
297 DO ng=1,ngrids
298 DO tile=last_tile(ng),first_tile(ng),-1
299 CALL ad_step2d (ng, tile)
300 END DO
301!
302! Set time indices for predictor step. The PREDICTOR_2D_STEP switch
303! it is assumed to be false before the first time-step.
304!
305 IF (predictor_2d_step(ng).and. &
306 & (iic(ng).ne.ntend(ng))) THEN
307 predictor_2d_step(ng)=.false.
308 ksav=knew(ng)
309 knew(ng)=krhs(ng)
310 krhs(ng)=ksav
311 END IF
312 END DO
313
314 END IF time_step
315
316# ifdef SO_SEMI
317!
318!-----------------------------------------------------------------------
319! If stochastic optimals with respect the seminorm of chosen
320! functional, pack adjoint state surface forcing needed by the
321! dynamical propagator.
322!-----------------------------------------------------------------------
323!
324 DO ng=1,ngrids
325 IF (mod(iic(ng)-1,nadj(ng)).eq.0) THEN
326 sorec(ng)=sorec(ng)+1
327 DO tile=first_tile(ng),last_tile(ng),+1
328 CALL ad_pack (ng, tile, nstr(ng), nend(ng), &
329 & storage(ng)%so_state(:,sorec(ng)))
330 END DO
331 END IF
332 END DO
333# endif
334!
335!-----------------------------------------------------------------------
336! Set vertical boundary conditions. Process tidal forcing.
337!-----------------------------------------------------------------------
338!
339 DO ng=1,ngrids
340 DO tile=first_tile(ng),last_tile(ng),+1
341# if defined SSH_TIDES_NOT_YET || defined UV_TIDES_NOT_YET
342 CALL ad_set_tides (ng, tile)
343# endif
344 CALL ad_set_vbc (ng, tile)
345 END DO
346 END DO
347
348# ifdef NEARSHORE_MELLOR_NOT_YET
349!
350!-----------------------------------------------------------------------
351! Compute radiation stress terms.
352!-----------------------------------------------------------------------
353!
354 DO ng=1,ngrids
355 DO tile=last_tile(ng),first_tile(ng),-1
356 CALL ad_radiation_stress (ng, tile)
357 END DO
358 END DO
359# endif
360
361# if defined WAV_COUPLING_NOT_YET && defined MCT_LIB
362!
363!-----------------------------------------------------------------------
364! Couple to waves model every CoupleSteps(Iwaves,ng) timesteps: get
365! waves/sea fluxes.
366!-----------------------------------------------------------------------
367!
368 DO ng=1,ngrids
369 IF ((iic(ng).ne.ntstart(ng)).and. &
370 & mod(iic(ng)-1,couplesteps(iwaves,ng)).eq.0) THEN
371 DO tile=first_tile(ng),last_tile(ng),+1
372 CALL ocn2wav_coupling (ng, tile)
373 END DO
374 END IF
375 END DO
376# endif
377
378# if defined ATM_COUPLING_NOT_YET && defined MCT_LIB
379!
380!-----------------------------------------------------------------------
381! Couple to atmospheric model every CoupleSteps(Iatmos) timesteps: get
382! air/sea fluxes.
383!-----------------------------------------------------------------------
384!
385 DO ng=1,ngrids
386 IF ((iic(ng).ne.ntstart(ng)).and. &
387 & mod(iic(ng)-1,couplesteps(iatmos,ng)).eq.0) THEN
388 DO tile=last_tile(ng),first_tile(ng),-1
389 CALL ocn2atm_coupling (ng, tile)
390 END DO
391 END IF
392 END DO
393# endif
394# ifdef AD_OUTPUT_STATE
395!
396!-----------------------------------------------------------------------
397! Set full adjoint output arrays. Due to the predictor/corrector and
398! multiple time level schemes, pieces of the adjoint solution are in
399! two-time levels and need to be added in the "_sol" arrays for output
400! purposes.
401!-----------------------------------------------------------------------
402!
403 DO ng=1,ngrids
404 IF (iic(ng).ne.ntend(ng)) THEN
405 DO tile=last_tile(ng),first_tile(ng),-1
406 CALL ad_out_fields (ng, tile, iadm)
407 END DO
408 DO tile=first_tile(ng),last_tile(ng),+1
409 CALL ad_out_zeta (ng, tile, iadm)
410 END DO
411 END IF
412 END DO
413# endif
414!
415!-----------------------------------------------------------------------
416! If not a restart, initialize all time levels and compute other
417! initial fields.
418!-----------------------------------------------------------------------
419!
420 DO ng=1,ngrids
421 IF (iic(ng).eq.ntend(ng)) THEN
422!
423! Initialize other state variables.
424!
425 DO tile=last_tile(ng),first_tile(ng),-1
426 CALL ad_ini_fields (ng, tile, iadm)
427 END DO
428!
429! Initialize free-surface.
430!
431 DO tile=first_tile(ng),last_tile(ng),+1
432 CALL ad_ini_zeta (ng, tile, iadm)
433 END DO
434 END IF
435 END DO
436
437# ifdef FORCING_SV
438!
439!-----------------------------------------------------------------------
440! Compute adjoint forcing for forcing singular vectors.
441!-----------------------------------------------------------------------
442!
443 IF (iic(ng).ne.ntend(ng)) THEN
444 DO ng=1,ngrids
445 DO tile=first_tile(ng),last_tile(ng),+1
446 CALL ad_forcing (ng, tile, kstp(ng), knew(ng), nstp(ng))
447 END DO
448 END DO
449 ELSE
450 DO ng=1,ngrids
451 DO tile=first_tile(ng),last_tile(ng),+1
452 CALL ad_forcing (ng, tile, kstp(ng), krhs(ng), nstp(ng))
453 END DO
454 END DO
455 END IF
456# endif
457
458# ifdef ADJUST_WSTRESS
459!
460!-----------------------------------------------------------------------
461! Interpolate surface forcing increments and adjust surface forcing.
462! Skip first timestep.
463!-----------------------------------------------------------------------
464!
465# ifdef RBL4DVAR_FCT_SENSITIVITY
466 DO ng=1,ngrids
467 IF (.not.lsen4dvar(ng)) THEN ! ignore in forecast interval
468 IF (iic(ng).ne.ntstart(ng)) THEN
469 DO tile=first_tile(ng),last_tile(ng),+1
470 CALL ad_frc_adjust (ng, tile, lfout(ng))
471 END DO
472 END IF
473 END IF
474 END DO
475# else
476 DO ng=1,ngrids
477 IF (iic(ng).ne.ntstart(ng)) THEN
478 DO tile=first_tile(ng),last_tile(ng),+1
479 CALL ad_frc_adjust (ng, tile, lfout(ng))
480 END DO
481 END IF
482 END DO
483# endif
484# endif
485
486# ifdef ADJUST_BOUNDARY
487!
488!-----------------------------------------------------------------------
489! Interpolate open boundary increments and adjust open boundaries.
490! Skip first timestep.
491!-----------------------------------------------------------------------
492!
493# ifdef RBL4DVAR_FCT_SENSITIVITY
494 DO ng=1,ngrids
495 IF (.not.lsen4dvar(ng)) THEN ! ignore in forecast interval
496 IF (iic(ng).ne.ntstart(ng)) THEN
497 DO tile=first_tile(ng),last_tile(ng),+1
498 CALL ad_obc_adjust (ng, tile, lbout(ng))
499 END DO
500 END IF
501 END IF
502 END DO
503# else
504 DO ng=1,ngrids
505 IF (iic(ng).ne.ntstart(ng)) THEN
506 DO tile=first_tile(ng),last_tile(ng),+1
507 CALL ad_obc_adjust (ng, tile, lbout(ng))
508 END DO
509 END IF
510 END DO
511# endif
512# endif
513
514# if defined WEAK_CONSTRAINT && !defined SP4DVAR
515!
516!-----------------------------------------------------------------------
517! Gather weak constraint forcing to storage arrays.
518!-----------------------------------------------------------------------
519!
520 DO ng=1,ngrids
521 IF (iic(ng).ne.ntstart(ng)) THEN
522 DO tile=first_tile(ng),last_tile(ng),+1
523 CALL frc_adgather (ng, tile)
524 END DO
525 END IF
526 END DO
527# endif
528!
529!-----------------------------------------------------------------------
530! If appropriate, write out fields into output NetCDF files.
531!-----------------------------------------------------------------------
532!
533 DO ng=1,ngrids
534 CALL ad_output (ng)
535 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
536 END DO
537
538# if defined WEAK_CONSTRAINT && !defined SP4DVAR
539!
540!-----------------------------------------------------------------------
541! Copy storage arrays index 1 into index 2, and clear index 1.
542!-----------------------------------------------------------------------
543!
544 DO ng=1,ngrids
545 IF (mod(iic(ng)-1,nadj(ng)).eq.0) THEN
546 DO tile=first_tile(ng),last_tile(ng),+1
547 CALL frc_clear (ng, tile)
548 END DO
549 END IF
550 END DO
551# endif
552
553# if defined AD_SENSITIVITY || defined I4DVAR_ANA_SENSITIVITY || \
554 defined opt_observations || defined sensitivity_4dvar
555!
556!-----------------------------------------------------------------------
557! Add appropriate forcing terms to the adjoint model. The form of the
558! forcing depends on the functional whose sensitivity is required.
559!-----------------------------------------------------------------------
560!
561 DO ng=1,ngrids
562# ifdef SENSITIVITY_4DVAR
563 IF (lsen4dvar(ng)) THEN
564# endif
565# if !defined AD_IMPULSE
566 IF ((dends(ng).ge.tdays(ng)).and. &
567 & (tdays(ng).ge.dstrs(ng))) THEN
568# endif
569 DO tile=first_tile(ng),last_tile(ng),+1
570 CALL adsen_force (ng, tile)
571 END DO
572# if !defined AD_IMPULSE
573 END IF
574# endif
575# ifdef SENSITIVITY_4DVAR
576 END IF
577# endif
578 END DO
579# endif
580 END DO step_loop
581!
582 RETURN
583 END SUBROUTINE ad_main2d
584#else
585 SUBROUTINE ad_main2d
586 RETURN
587 END SUBROUTINE ad_main2d
588#endif
subroutine ad_get_data(ng)
Definition ad_get_data.F:4
subroutine ad_main2d
Definition ad_main2d.F:586
subroutine ad_output(ng)
Definition ad_output.F:4
subroutine ad_set_data(ng, tile)
Definition ad_set_data.F:4
subroutine, public ad_diag(ng, tile)
Definition ad_diag.F:25
subroutine, public ad_forcing(ng, tile, kfrc, nfrc)
Definition ad_forcing.F:26
subroutine, public ad_frc_adjust(ng, tile, linp)
subroutine ad_htobs(ng, tile, model)
Definition ad_htobs.F:30
subroutine, public ad_ini_fields(ng, tile, model)
subroutine, public ad_out_zeta(ng, tile, model)
subroutine, public ad_ini_zeta(ng, tile, model)
subroutine, public ad_out_fields(ng, tile, model)
subroutine ad_misfit(ng, tile, model)
Definition ad_misfit.F:29
subroutine, public ad_obc_adjust(ng, tile, linp)
subroutine, public ad_set_avg(ng, tile)
Definition ad_set_avg.F:26
subroutine, public ad_set_vbc(ng, tile)
Definition ad_set_vbc.F:32
subroutine, public ad_step2d(ng, tile)
subroutine, public adsen_force(ng, tile)
Definition adsen_force.F:29
subroutine, public time_string(mytime, date_string)
Definition dateclock.F:1272
subroutine, public frc_clear(ng, tile)
Definition frc_weak.F:406
subroutine, public frc_adgather(ng, tile)
Definition frc_weak.F:27
integer, dimension(:,:), allocatable couplesteps
integer iatmos
integer iwaves
logical, dimension(:), allocatable lsadd
logical, dimension(:), allocatable lsen4dvar
logical, dimension(:), allocatable processobs
integer numthreads
integer, dimension(:), allocatable first_tile
integer mythread
integer, dimension(:), allocatable last_tile
integer, dimension(:), allocatable nfloats
Definition mod_param.F:543
integer, dimension(:), allocatable nstr
Definition mod_param.F:646
integer, parameter iadm
Definition mod_param.F:665
integer, parameter nft
Definition mod_param.F:539
integer ngrids
Definition mod_param.F:113
integer, dimension(:), allocatable nend
Definition mod_param.F:647
logical, dimension(:), allocatable lfloats
real(dp), dimension(:), allocatable obstime
integer, dimension(:), allocatable iic
real(dp), dimension(:), allocatable dt
integer, dimension(:), allocatable sorec
logical, dimension(:), allocatable predictor_2d_step
real(dp), dimension(:), allocatable tdays
real(r8), dimension(:), allocatable dends
integer, dimension(:), allocatable nfast
real(dp), parameter sec2day
integer, dimension(:), allocatable ntend
character(len=22), dimension(:), allocatable time_code
integer exit_flag
integer, dimension(:), allocatable indx1
real(r8), dimension(:), allocatable dstrs
real(dp), dimension(:), allocatable time
integer, dimension(:), allocatable ntstart
integer, dimension(:), allocatable nadj
integer, dimension(:), allocatable iif
integer noerror
integer, dimension(:), allocatable nfm2
integer, dimension(:), allocatable lbout
integer, dimension(:), allocatable kstp
integer, dimension(:), allocatable knew
integer, dimension(:), allocatable nfm1
integer, dimension(:), allocatable nf
integer, dimension(:), allocatable nfm3
integer, dimension(:), allocatable nnew
integer, dimension(:), allocatable nfp1
integer, dimension(:), allocatable krhs
integer, dimension(:), allocatable lfout
integer, dimension(:), allocatable nstp
type(t_storage), dimension(:), allocatable storage
Definition mod_storage.F:91
subroutine, public obs_read(ng, model, backward)
Definition obs_read.F:42
logical function, public founderror(flag, noerr, line, routine)
Definition strings.F:52
subroutine ad_pack(ng, tile, mstr, mend, ad_state)
Definition packing.F:341