ROMS
Loading...
Searching...
No Matches
convolve_mod Module Reference

Functions/Subroutines

subroutine, public convolve (driver, rini, rold, rnew)
 
subroutine, public error_covariance (model, driver, outloop, innloop, rbck, rini, rold, rnew, rec1, rec2, lposterior)
 
subroutine, public saddlec (driver, lselect, rini, rold, rnew)
 

Function/Subroutine Documentation

◆ convolve()

subroutine, public convolve_mod::convolve ( character (len=*), intent(in) driver,
integer, intent(in) rini,
integer, dimension(ngrids), intent(in) rold,
integer, dimension(ngrids), intent(in) rnew )

Definition at line 115 of file convolve.F.

116!***********************************************************************
117!
118! Imported variable declarations.
119!
120 integer, intent(in) :: Rini
121 integer, intent(in) :: Rold(Ngrids)
122 integer, intent(in) :: Rnew(Ngrids)
123!
124 character (len=*), intent(in) :: driver
125!
126! Local variable declarations.
127!
128 logical :: Lweak, add
129!
130 integer :: IniRec
131 integer :: ng, tile
132!
133 character (len=*), parameter :: MyFile = &
134 & __FILE__
135!
136 sourcefile=myfile
137!
138!-----------------------------------------------------------------------
139! Specify spatial error covariance on the TLM control vector, at time
140! index "Rold", via convolutions of a pseudo-diffusion operator. The
141! convolved control vector is loaded into time index "Rnew" and index
142! "Rold" is preserved.
143!-----------------------------------------------------------------------
144
145# ifdef BALANCE_OPERATOR
146!
147! Read NLM initial condition in readiness for the balance operator.
148!
149 inirec=rini
150 DO ng=1,ngrids
151 CALL get_state (ng, inlm, 2, ini(ng), inirec, inirec)
152 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
153 nrhs(ng)=rini
154 END DO
155# endif
156!
157! Load "Rold" time index TLM control vector into ADM state arrays.
158! Apply balance operator, if activated. Then, scale control vector
159! with error covariance standard deviations. Next, convolve resulting
160! vector with the squared-root adjoint diffusion operator. Notice
161! that the spatial convolution is only done for half of the diffusion
162! steps (squared-root filter).
163!
164 lweak=.false.
165 add=.false.
166 DO ng=1,ngrids
167# ifdef PROFILE
168 CALL wclock_on (ng, iadm, 82, __line__, myfile)
169# endif
170 DO tile=first_tile(ng),last_tile(ng),+1
171 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
172# ifdef BALANCE_OPERATOR
173 CALL ad_balance (ng, tile, rini, rold(ng))
174# endif
175 CALL ad_variability (ng, tile, rold(ng), lweak)
176 CALL ad_convolution (ng, tile, rold(ng), lweak, 2)
177 END DO
178# ifdef PROFILE
179 CALL wclock_off (ng, iadm, 82, __line__, myfile)
180# endif
181 END DO
182!
183! Since we wish to preserve what is in tl_var(Rold), load resulting
184! filtered solution from above, ad_var(Rold), into tl_var(Rnew).
185! Then, convolve with the squared-root (half of steps) tangent
186! linear diffusion operator. Next, scale results with error
187! covariance standard deviations. Apply balance operator, if
188! activated.
189!
190 add=.false.
191 DO ng=1,ngrids
192# ifdef PROFILE
193 CALL wclock_on (ng, itlm, 82, __line__, myfile)
194# endif
195 DO tile=first_tile(ng),last_tile(ng),+1
196 CALL load_adtotl (ng, tile, rold(ng), rnew(ng), add)
197 CALL tl_convolution (ng, tile, rnew(ng), lweak, 2)
198 CALL tl_variability (ng, tile, rnew(ng), lweak)
199# ifdef BALANCE_OPERATOR
200 CALL tl_balance (ng, tile, rini, rnew(ng))
201# endif
202 END DO
203# ifdef PROFILE
204 CALL wclock_off (ng, itlm, 82, __line__, myfile)
205# endif
206 END DO
207!
208 RETURN
recursive subroutine wclock_off(ng, model, region, line, routine)
Definition timers.F:148
recursive subroutine wclock_on(ng, model, region, line, routine)
Definition timers.F:3

References ad_balance_mod::ad_balance(), ad_convolution_mod::ad_convolution(), ad_variability_mod::ad_variability(), mod_scalars::exit_flag, mod_parallel::first_tile, strings_mod::founderror(), get_state_mod::get_state(), mod_param::iadm, mod_iounits::ini, mod_param::inlm, mod_param::itlm, mod_parallel::last_tile, ini_adjust_mod::load_adtotl(), ini_adjust_mod::load_tltoad(), mod_param::ngrids, mod_scalars::noerror, mod_stepping::nrhs, mod_iounits::sourcefile, tl_balance_mod::tl_balance(), tl_convolution_mod::tl_convolution(), tl_variability_mod::tl_variability(), wclock_off(), and wclock_on().

Referenced by r4dvar_mod::posterior_error(), and rbl4dvar_mod::posterior_error().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ error_covariance()

subroutine, public convolve_mod::error_covariance ( integer, intent(in) model,
character (len=*), intent(in) driver,
integer, intent(in) outloop,
integer, intent(in) innloop,
integer, intent(in) rbck,
integer, intent(in) rini,
integer, dimension(ngrids), intent(in) rold,
integer, dimension(ngrids), intent(in) rnew,
integer, intent(in) rec1,
integer, intent(in) rec2,
logical, intent(in) lposterior )

Definition at line 212 of file convolve.F.

215!***********************************************************************
216!
217! Imported variable declarations.
218!
219 logical, intent(in) :: Lposterior
220!
221 integer, intent(in) :: model, outLoop, innLoop
222 integer, intent(in) :: Rbck, Rini, Rec1, Rec2
223 integer, intent(in) :: Rold(Ngrids)
224 integer, intent(in) :: Rnew(Ngrids)
225!
226 character (len=*), intent(in) :: driver
227!
228! Local variable declarations.
229!
230 logical :: Lweak, add
231!
232 integer :: ADrec, BckRec, Fcount, IniRec
233 integer :: i, irec, ng, tile
234# ifdef RPCG
235 integer :: LTLM1, LTLM2, Rec5, jrec, nADrec
236# endif
237 integer, dimension(Ngrids) :: Nrec
238!
239 character (len=*), parameter :: MyFile = &
240 & __FILE__//", error_covariance"
241!
242 sourcefile=myfile
243!
244!-----------------------------------------------------------------------
245! Convolve adjoint trajectory.
246!-----------------------------------------------------------------------
247!
248 IF (master) THEN
249 IF ((outloop.lt.0).and.(innloop.lt.0)) THEN
250 WRITE (stdout,10)
251 10 FORMAT (/,' Convolving Adjoint Trajectory...')
252 ELSE
253 WRITE (stdout,20) outloop, innloop
254 20 FORMAT (/,' Convolving Adjoint Trajectory: Outer = ',i3.3, &
255 & ' Inner = ',i3.3)
256 END IF
257 END IF
258!
259! Clear adjoint state arrays.
260!
261 DO ng=1,ngrids
262 DO tile=first_tile(ng),last_tile(ng),+1
263 CALL initialize_ocean (ng, tile, iadm)
264 END DO
265 END DO
266!
267! Get number of records in adjoint NetCDF and initialize indices.
268!
269 DO ng=1,ngrids
270 fcount=adm(ng)%Fcount
271 nrec(ng)=adm(ng)%Nrec(fcount)
272 adm(ng)%Nrec(fcount)=0
273 adm(ng)%Rindex=0
274 lwrtstate2d(ng)=.true.
275 lwrttime(ng)=.false.
276 END DO
277!
278! Read in adjoint control vector to convolve from NetCDF file
279! ADM(ng)%name for time record Nrec, which correspond to the
280! initial conditions time. If adjusting open boundaries and/or
281! surface forcing, only record Nrec is read since it is the
282! only record for which adjoint forcing arrays are complete.
283!
284! Notice that since routine "get_state" loads data into the
285! ghost points, the adjoint contol vector is read into the
286! tangent linear state arrays by using iTLM instead of iADM
287! in the calling arguments.
288!
289 DO ng=1,ngrids
290 adrec=nrec(ng)
291 frcrec(ng)=nrec(ng)
292 CALL get_state (ng, itlm, 4, adm(ng), adrec, rold(ng))
293 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
294 END DO
295
296# ifdef BALANCE_OPERATOR
297!
298! Read NLM initial condition in readiness for the balance
299! operator.
300!
301 inirec=rini
302 DO ng=1,ngrids
303 CALL get_state (ng, inlm, 2, ini(ng), inirec, inirec)
304 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
305 nrhs(ng)=rini
306 END DO
307# endif
308!
309! Load ADM control read above from TLM into ADM state arrays.
310! Then, multiply control vector by the error covariance standard
311! deviations. Next, convolve resulting adjoint solution with the
312! squared-root adjoint diffusion operator to impose apriori error
313! hypothesis. Notice that the spatial convolution are only done
314! for half of the diffusion steps (squared-root filter). Clear
315! tangent linear state arrays when done.
316!
317 lweak=.false.
318 add=.false.
319 DO ng=1,ngrids
320# ifdef PROFILE
321 CALL wclock_on (ng, model, 82, __line__, myfile)
322# endif
323 DO tile=first_tile(ng),last_tile(ng),+1
324 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
325# ifdef BALANCE_OPERATOR
326 CALL ad_balance (ng, tile, rini, rold(ng))
327# endif
328 CALL ad_variability (ng, tile, rold(ng), lweak)
329 CALL ad_convolution (ng, tile, rold(ng), lweak, 2)
330 CALL initialize_ocean (ng, tile, itlm)
331 CALL initialize_forces (ng, tile, itlm)
332# ifdef ADJUST_BOUNDARY
333 CALL initialize_boundary (ng, tile, itlm)
334# endif
335 END DO
336# ifdef PROFILE
337 CALL wclock_off (ng, model, 82, __line__, myfile)
338# endif
339 END DO
340!
341! To insure symmetry, convolve resulting filtered adjoint solution
342! from above with the squared-root (half of steps) tangent linear
343! diffusion operator. Then, multiply result with its corresponding
344! error covariance standard deviations. Since the convolved solution
345! is in the adjoint state arrays, first copy to tangent linear state
346! arrays including the ghosts points.
347!
348 lweak=.false.
349 add=.false.
350 DO ng=1,ngrids
351# ifdef PROFILE
352 CALL wclock_on (ng, model, 82, __line__, myfile)
353# endif
354 DO tile=first_tile(ng),last_tile(ng),+1
355 CALL load_adtotl (ng, tile, rold(ng), rold(ng), add)
356 CALL tl_convolution (ng, tile, rold(ng), lweak, 2)
357 CALL tl_variability (ng, tile, rold(ng), lweak)
358# ifdef BALANCE_OPERATOR
359 CALL tl_balance (ng, tile, rini, rold(ng))
360# endif
361 END DO
362
363# ifdef POSTERIOR_ERROR_I
364!
365! If computing the analysis error covariance matrix, copy TLM back
366! into ADM so that it can be written to Hessian NetCDF file.
367!
368 IF (lposterior) THEN
369 DO tile=first_tile(ng),last_tile(ng),+1
370 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
371 END DO
372 END IF
373# endif
374# ifdef PROFILE
375 CALL wclock_off (ng, model, 82, __line__, myfile)
376# endif
377 END DO
378
379# if defined ARRAY_MODES || defined R4DVAR || \
380 defined r4dvar_ana_sensitivity
381!
382! Copy back to adjoint state arrays when done with the convolution.
383! Compute representer model initial conditions by adding convolved
384! adjoint solution to the reference nonlinear state (INI(ng)%name,
385! record Rbck).
386!
387 IF ((model.eq.irpm).and. &
388 & (index(driver,'r4dvar').ne.0)) THEN
389 bckrec=rbck
390 DO ng=1,ngrids
391 CALL get_state (ng, inlm, 9, ini(ng), bckrec, rnew(ng))
392 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
393 END DO
394!
395 add=.false.
396 DO ng=1,ngrids
397 DO tile=first_tile(ng),last_tile(ng),+1
398 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
399 CALL rp_ini_adjust (ng, tile, rnew(ng), rold(ng))
400 END DO
401 END DO
402 END IF
403
404# elif defined RBL4DVAR || defined RBL4DVAR_ANA_SENSITIVITY
405# ifndef RPCG
406!
407! Copy back to adjoint state arrays when done with the convolution.
408! Compute nonlinear model initial conditions by adding convolved
409! adjoint solution to the reference nonlinear state (INI(ng)%name,
410! record Rbck).
411!
412 IF ((model.eq.inlm).and. &
413 & (index(driver,'rbl4dvar').ne.0)) THEN
414 bckrec=rbck
415 DO ng=1,ngrids
416 CALL get_state (ng, inlm, 9, ini(ng), bckrec, rnew(ng))
417 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
418 END DO
419!
420 add=.false.
421 DO ng=1,ngrids
422 DO tile=first_tile(ng),last_tile(ng),+1
423 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
424 CALL ini_adjust (ng, tile, rold(ng), rnew(ng))
425 END DO
426 END DO
427 END IF
428# endif
429# endif
430!
431! Write out tangent linear model initial conditions and tangent
432! linear surface forcing adjustments for next inner loop into
433! ITL(ng)%name (record Rec1). The tangent model initial
434! conditions are set to the convolved adjoint solution.
435!
436 IF (model.eq.itlm) THEN
437 DO ng=1,ngrids
438# ifdef DISTRIBUTE
439 CALL tl_wrt_ini (ng, myrank, rold(ng), rec1)
440# else
441 CALL tl_wrt_ini (ng, -1, rold(ng), rec1)
442# endif
443 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
444 END DO
445# if defined ARRAY_MODES || defined R4DVAR || \
446 defined r4dvar_ana_sensitivity
447 ELSE IF (model.eq.irpm) THEN
448 DO ng=1,ngrids
449# ifdef DISTRIBUTE
450 CALL rp_wrt_ini (ng, myrank, rold(ng), rec2)
451# else
452 CALL rp_wrt_ini (ng, -1, rold(ng), rec2)
453# endif
454 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
455 END DO
456# elif (defined RBL4DVAR || defined RBL4DVAR_ANA_SENSITIVITY) && \
457 !defined RPCG
458 ELSE IF (model.eq.inlm) THEN
459 DO ng=1,ngrids
460# ifdef DISTRIBUTE
461 CALL wrt_ini (ng, myrank, rnew(ng))
462# else
463 CALL wrt_ini (ng, -1, rnew(ng))
464# endif
465 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
466# if defined ADJUST_STFLUX || defined ADJUST_WSTRESS || \
467 defined adjust_boundary
468# ifdef DISTRIBUTE
469 CALL wrt_frc_ad (ng, myrank, rold(ng), ini(ng)%Rindex)
470# else
471 CALL wrt_frc_ad (ng, -1, rold(ng), ini(ng)%Rindex)
472# endif
473 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
474# endif
475 END DO
476# endif
477 END IF
478
479# ifdef RPCG
480!
481! Write out tangent linear model initial conditions and tangent
482! linear surface forcing and obc adjustments for next outer
483! loop into ITLname (record Rec2). The tangent model initial
484! conditions are set to the convolved adjoint solution.
485!
486 IF (model.eq.inlm) THEN
487 DO ng=1,ngrids
488# ifdef DISTRIBUTE
489 CALL tl_wrt_ini (ng, myrank, rold(ng), rec2)
490# else
491 CALL tl_wrt_ini (ng, -1, rold(ng), rec2)
492# endif
493 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
494 END DO
495 END IF
496# endif
497
498# ifdef POSTERIOR_ERROR_I
499!
500! If weak constraint, convolve records 2:Nrec in ADM(ng)%name and
501! Write convolved adjoint solution into Hessian NetCDF file for use
502! later.
503!
504 IF (lposterior.and.(inner.ne.0)) THEN
505 DO ng=1,ngrids
506# ifdef DISTRIBUTE
507 CALL wrt_hessian (ng, myrank, rold(ng), rold(ng))
508# else
509 CALL wrt_hessian (ng, -1, rold(ng), rold(ng))
510# endif
511 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
512 END DO
513 END IF
514# endif
515# ifdef RPCG
516!
517! Now compute the new B^-1(x(k)-x(k-1)) term for the weak constraint
518! forcing terms. Records 6+nADrec/2 to nADrec+5 contain the sums so
519! far. This is ONLY done in the outer-loop not the inner-loops, and
520! is controlled by the flag "LaugWeak".
521!
522 IF (laugweak) THEN
523 ltlm1=1
524 ltlm2=2
525 rec5=5
526 DO ng=1,ngrids
527 IF (nadj(ng).lt.ntimes(ng)) THEN
528 nadrec=2*(1+ntimes(ng)/nadj(ng))
529 ELSE
530 nadrec=0
531 END IF
532 DO irec=1,nadrec/2
533 jrec=rec5+nadrec/2+irec
534!
535! First add the augmented piece which is computed from the previous
536! sum.
537!
538 CALL get_state (ng, itlm, 4, itl(ng), jrec, ltlm1)
539 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
540!
541 DO tile=first_tile(ng),last_tile(ng),+1
542 CALL aug_oper (ng, tile, ltlm1, ltlm2)
543 END DO
544!
545 DO tile=first_tile(ng),last_tile(ng),+1
546 CALL sum_grad (ng, tile, ltlm1, ltlm2)
547 END DO
548!
549! Need to read adjoint netcdf file in reverse.
550!
551 adrec=(nrec(ng)-1)-(irec-1)
552 CALL get_state (ng, itlm, 4, adm(ng), adrec, ltlm1)
553 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
554!
555 DO tile=first_tile(ng),last_tile(ng),+1
556 CALL sum_grad (ng, tile, ltlm1, ltlm2)
557 END DO
558!
559! Write the current sum of adjoint solutions into record jrec of the
560! ITL file.
561!
562# ifdef DISTRIBUTE
563 CALL tl_wrt_ini (ng, myrank, ltlm2, jrec)
564# else
565 CALL tl_wrt_ini (ng, -1, ltlm2, jrec)
566# endif
567 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
568!
569 END DO
570 END DO
571 END IF
572# endif
573# ifdef TIME_CONV
574!
575! Apply the factorized space-time model error covariance
576! matrix of the form ATA' where A is the square-root of the
577! model error covariance matrix, and T is the time-correlation
578! matrix.
579!
580! If weak constraint, convolve records 2-Nrec in ADM(ng)%name
581! and impose model error covariance. NOTE: We will not use the
582! convolved forcing increments generated here since these arrays
583! do not contain the complete solution and are redundant.
584! AMM: We might want to get rid of these unwanted records to
585! avoid any confusion in the future.
586!
587 DO ng=1,ngrids
588 IF (nrec(ng).gt.3) THEN
589# ifdef PROFILE
590 CALL wclock_on (ng, model, 82, __line__, myfile)
591# endif
592 DO irec=1,nrec(ng)-1
593!
594! Read adjoint solution. Since routine "get_state" loads data into the
595! ghost points, the adjoint solution is read in the tangent linear
596! state arrays by using iTLM instead of iADM in the calling arguments.
597!
598 adrec=irec
599 CALL get_state (ng, itlm, 4, adm(ng), adrec, rold(ng))
600 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
601!
602! Load interior solution, read above, into adjoint state arrays.
603! Then, multiply adjoint solution by the background-error standard
604! deviations. Next, convolve resulting adjoint solution with the
605! squared-root adjoint diffusion operator which impose the model-error
606! spatial correlations. Notice that the spatial convolution is only
607! done for half of the diffusion steps (squared-root filter). Clear
608! tangent linear state arrays when done.
609!
610 lweak=.true.
611 add=.false.
612 DO tile=first_tile(ng),last_tile(ng),+1
613 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
614# ifdef BALANCE_OPERATOR
615 CALL ad_balance (ng, tile, rini, rold(ng))
616# endif
617 CALL ad_variability (ng, tile, rold(ng), lweak)
618 CALL ad_convolution (ng, tile, rold(ng), lweak, 2)
619 CALL initialize_ocean (ng, tile, itlm)
620 CALL initialize_forces (ng, tile, itlm)
621# ifdef ADJUST_BOUNDARY
622 CALL initialize_boundary (ng, tile, itlm)
623# endif
624 END DO
625!
626! Overwrite ADM(ng)%name history NetCDF file with convolved adjoint
627! solution.
628!
629 kstp(ng)=rold(ng)
630# ifdef SOLVE3D
631 nstp(ng)=rold(ng)
632# endif
633# ifdef DISTRIBUTE
634 CALL ad_wrt_his (ng, myrank)
635# else
636 CALL ad_wrt_his (ng, -1)
637# endif
638 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
639 END DO
640 lwrtstate2d(ng)=.false.
641 lwrttime(ng)=.true.
642# ifdef PROFILE
643 CALL wclock_off (ng, model, 82, __line__, myfile)
644# endif
645 END IF
646 END DO
647!
648! Apply the time correlation matrix to the newly convolved adjoint
649! fields.
650!
651 DO ng=1,ngrids
652 tlf(ng)%Rindex=0
653 DO tile=first_tile(ng),last_tile(ng),+1
654 CALL time_corr (ng, tile, iadm, adm(ng)%IOtype, adm(ng)%name)
655 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
656 END DO
657 END DO
658!
659 DO ng=1,ngrids
660 IF (nrec(ng).gt.3) THEN
661# ifdef PROFILE
662 CALL wclock_on (ng, model, 82, __line__, myfile)
663# endif
664 adm(ng)%Rindex=0
665 lwrtstate2d(ng)=.true.
666 DO irec=nrec(ng)-1,1,-1
667!
668! Read the latest TLF solution. We need to read the TLF file in reverse
669! order since the final solution is written into the adjoint netcdf
670! file which will be rewritten in ascending order of time in the TLF
671! file by wrt_impulse.
672! NOTE: model=6 here so as to only read the state variables.
673!
674 adrec=irec
675 CALL get_state (ng, 6, 6, tlf(ng), adrec, rold(ng))
676 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
677!
678 lweak=.true.
679 add=.false.
680 DO tile=first_tile(ng),last_tile(ng),+1
681 CALL tl_convolution (ng, tile, rold(ng), lweak, 2)
682 CALL tl_variability (ng, tile, rold(ng), lweak)
683# ifdef BALANCE_OPERATOR
684 CALL tl_balance (ng, tile, rini, rold(ng))
685# endif
686 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
687 END DO
688!
689! Overwrite ADM(ng)%name history NetCDF file with convolved adjoint
690! solution.
691!
692 kstp(ng)=rold(ng)
693# ifdef SOLVE3D
694 nstp(ng)=rold(ng)
695# endif
696# ifdef DISTRIBUTE
697 CALL ad_wrt_his (ng, myrank)
698# else
699 CALL ad_wrt_his (ng, -1)
700# endif
701 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
702 END DO
703 lwrtstate2d(ng)=.false.
704 lwrttime(ng)=.true.
705# ifdef PROFILE
706 CALL wclock_off (ng, model, 82, __line__, myfile)
707# endif
708 END IF
709 END DO
710
711# else
712!
713! If weak constraint, convolve records 2-Nrec in ADM(ng)%name
714! and impose model error covariance. NOTE: We will not use the
715! convolved forcing increments generated here since these arrays
716! do not contain the complete solution and are redundant.
717! AMM: We might want to get rid of these unwanted records to
718! avoid any confusion in the future.
719!
720 DO ng=1,ngrids
721 IF (nrec(ng).gt.3) THEN
722# ifdef PROFILE
723 CALL wclock_on (ng, model, 82, __line__, myfile)
724# endif
725 DO irec=1,nrec(ng)-1
726!
727! Read adjoint solution. Since routine "get_state" loads data into the
728! ghost points, the adjoint solution is read in the tangent linear
729! state arrays by using iTLM instead of iADM in the calling arguments.
730!
731 adrec=irec
732 CALL get_state (ng, itlm, 4, adm(ng), adrec, rold(ng))
733 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
734!
735! Load interior solution, read above, into adjoint state arrays.
736! Then, multiply adjoint solution by the background-error standard
737! deviations. Next, convolve resulting adjoint solution with the
738! squared-root adjoint diffusion operator which impose the model-error
739! spatial correlations. Notice that the spatial convolution is only
740! done for half of the diffusion steps (squared-root filter). Clear
741! tangent linear state arrays when done.
742!
743 lweak=.true.
744 add=.false.
745 DO tile=first_tile(ng),last_tile(ng),+1
746 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
747# ifdef BALANCE_OPERATOR
748 CALL ad_balance (ng, tile, rini, rold(ng))
749# endif
750 CALL ad_variability (ng, tile, rold(ng), lweak)
751 CALL ad_convolution (ng, tile, rold(ng), lweak, 2)
752 CALL initialize_ocean (ng, tile, itlm)
753 CALL initialize_forces (ng, tile, itlm)
754# ifdef ADJUST_BOUNDARY
755 CALL initialize_boundary (ng, tile, itlm)
756# endif
757 END DO
758!
759! To insure symmetry, convolve resulting filtered adjoint solution
760! from above with the squared-root (half of steps) tangent linear
761! diffusion operator. Then, multiply result with its corresponding
762! background-error standard deviations. Since the convolved solution
763! is in the adjoint state arrays, first copy to tangent linear state
764! arrays including the ghosts points. Copy back to adjoint state
765! arrays when done with the convolution for output purposes.
766!
767 lweak=.true.
768 add=.false.
769 DO tile=first_tile(ng),last_tile(ng),+1
770 CALL load_adtotl (ng, tile, rold(ng), rold(ng), add)
771 CALL tl_convolution (ng, tile, rold(ng), lweak, 2)
772 CALL tl_variability (ng, tile, rold(ng), lweak)
773# ifdef BALANCE_OPERATOR
774 CALL tl_balance (ng, tile, rini, rold(ng))
775# endif
776 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
777 END DO
778!
779! Overwrite ADM(ng)%name history NetCDF file with final solution.
780!
781 kstp(ng)=rold(ng)
782# ifdef SOLVE3D
783 nstp(ng)=rold(ng)
784# endif
785# ifdef DISTRIBUTE
786 CALL ad_wrt_his (ng, myrank)
787# else
788 CALL ad_wrt_his (ng, -1)
789# endif
790 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
791 END DO
792 lwrtstate2d(ng)=.false.
793 lwrttime(ng)=.true.
794# ifdef PROFILE
795 CALL wclock_off (ng, model, 82, __line__, myfile)
796# endif
797 END IF
798 END DO
799# endif
800!
801 RETURN

References ad_balance_mod::ad_balance(), ad_convolution_mod::ad_convolution(), ad_variability_mod::ad_variability(), ad_wrt_his_mod::ad_wrt_his(), mod_iounits::adm, comp_jb0_mod::aug_oper(), mod_scalars::exit_flag, mod_parallel::first_tile, strings_mod::founderror(), mod_scalars::frcrec, get_state_mod::get_state(), mod_param::iadm, mod_iounits::ini, ini_adjust_mod::ini_adjust(), mod_boundary::initialize_boundary(), mod_forces::initialize_forces(), mod_ocean::initialize_ocean(), mod_param::inlm, mod_scalars::inner, mod_param::irpm, mod_iounits::itl, mod_param::itlm, mod_stepping::kstp, mod_parallel::last_tile, mod_fourdvar::laugweak, ini_adjust_mod::load_adtotl(), ini_adjust_mod::load_tltoad(), mod_scalars::lwrtstate2d, mod_scalars::lwrttime, mod_parallel::master, mod_parallel::myrank, mod_scalars::nadj, mod_param::ngrids, mod_scalars::noerror, mod_stepping::nrhs, mod_stepping::nstp, mod_scalars::ntimes, ini_adjust_mod::rp_ini_adjust(), rp_wrt_ini_mod::rp_wrt_ini(), mod_iounits::sourcefile, mod_iounits::stdout, sum_grad_mod::sum_grad(), time_corr_mod::time_corr(), tl_balance_mod::tl_balance(), tl_convolution_mod::tl_convolution(), tl_variability_mod::tl_variability(), tl_wrt_ini_mod::tl_wrt_ini(), mod_iounits::tlf, wclock_off(), wclock_on(), wrt_ini_mod::wrt_frc_ad(), wrt_hessian_mod::wrt_hessian(), and wrt_ini_mod::wrt_ini().

Referenced by r4dvar_mod::increment(), rbl4dvar_mod::increment(), and roms_kernel_mod::roms_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ saddlec()

subroutine, public convolve_mod::saddlec ( character (len=*), intent(in) driver,
logical, intent(in) lselect,
integer, intent(in) rini,
integer, dimension(ngrids), intent(in) rold,
integer, dimension(ngrids), intent(in) rnew )

Definition at line 807 of file convolve.F.

808!***********************************************************************
809!
810! Imported variable declarations.
811!
812 integer, intent(in) :: Rini
813 integer, intent(in) :: Rold(Ngrids)
814 integer, intent(in) :: Rnew(Ngrids)
815!
816 logical, intent(in) :: Lselect
817!
818 character (len=*), intent(in) :: driver
819!
820! Local variable declarations.
821!
822 logical :: Lweak, add
823!
824 integer :: IniRec
825 integer :: ng, tile
826!
827 character (len=*), parameter :: MyFile = &
828 & __FILE__//", saddlec"
829!
830 sourcefile=myfile
831!
832!-----------------------------------------------------------------------
833! Specify spatial error covariance on the TLM control vector, at time
834! index "Rold", via convolutions of a pseudo-diffusion operator. The
835! convolved control vector is loaded into time index "Rnew" and index
836! "Rold" is preserved.
837!-----------------------------------------------------------------------
838
839# ifdef BALANCE_OPERATOR
840!
841! Read NLM initial condition in readiness for the balance operator.
842!
843 inirec=rini
844 DO ng=1,ngrids
845 CALL get_state (ng, inlm, 2, ini(ng), inirec, inirec)
846 IF (exit_flag.ne.noerror) RETURN
847 nrhs(ng)=rini
848 END DO
849# endif
850!
851! Load "Rold" time index TLM control vector into ADM state arrays.
852! Apply balance operator, if activated. Then, scale control vector
853! with error covariance standard deviations. Next, convolve resulting
854! vector with the squared-root adjoint diffusion operator. Notice
855! that the spatial convolution is only done for half of the diffusion
856! steps (squared-root filter).
857!
858 lweak=lselect
859 add=.false.
860 DO ng=1,ngrids
861# ifdef PROFILE
862 CALL wclock_on (ng, iadm, 82, __line__, myfile)
863# endif
864 DO tile=first_tile(ng),last_tile(ng),+1
865 CALL load_tltoad (ng, tile, rold(ng), rold(ng), add)
866# ifdef BALANCE_OPERATOR
867 CALL ad_balance (ng, tile, rini, rold(ng))
868# endif
869 CALL ad_variability (ng, tile, rold(ng), lweak)
870 CALL ad_convolution (ng, tile, rold(ng), lweak, 2)
871! AMM Important.
872 CALL initialize_ocean (ng, tile, itlm)
873 CALL initialize_forces (ng, tile, itlm)
874 END DO
875# ifdef PROFILE
876 CALL wclock_off (ng, iadm, 82, __line__, myfile)
877# endif
878 END DO
879!
880! Since we wish to preserve what is in tl_var(Rold), load resulting
881! filtered solution from above, ad_var(Rold), into tl_var(Rnew).
882! Then, convolve with the squared-root (half of steps) tangent
883! linear diffusion operator. Next, scale results with error
884! covariance standard deviations. Apply balance operator, if
885! activated.
886!
887 add=.false.
888 DO ng=1,ngrids
889# ifdef PROFILE
890 CALL wclock_on (ng, itlm, 82, __line__, myfile)
891# endif
892 DO tile=first_tile(ng),last_tile(ng),+1
893 CALL load_adtotl (ng, tile, rold(ng), rnew(ng), add)
894 CALL tl_convolution (ng, tile, rnew(ng), lweak, 2)
895 CALL tl_variability (ng, tile, rnew(ng), lweak)
896# ifdef BALANCE_OPERATOR
897 CALL tl_balance (ng, tile, rini, rnew(ng))
898# endif
899 END DO
900# ifdef PROFILE
901 CALL wclock_off (ng, itlm, 82, __line__, myfile)
902# endif
903 END DO
904!
905 RETURN

References ad_balance_mod::ad_balance(), ad_convolution_mod::ad_convolution(), ad_variability_mod::ad_variability(), mod_scalars::exit_flag, mod_parallel::first_tile, get_state_mod::get_state(), mod_param::iadm, mod_iounits::ini, mod_forces::initialize_forces(), mod_ocean::initialize_ocean(), mod_param::inlm, mod_param::itlm, mod_parallel::last_tile, ini_adjust_mod::load_adtotl(), ini_adjust_mod::load_tltoad(), mod_param::ngrids, mod_scalars::noerror, mod_stepping::nrhs, mod_iounits::sourcefile, tl_balance_mod::tl_balance(), tl_convolution_mod::tl_convolution(), tl_variability_mod::tl_variability(), wclock_off(), and wclock_on().

Here is the call graph for this function: