ROMS
Loading...
Searching...
No Matches
afte_roms.h
Go to the documentation of this file.
1 MODULE roms_kernel_mod
2!
3!git $Id$
4!================================================== Hernan G. Arango ===
5! Copyright (c) 2002-2025 The ROMS Group Andrew M. Moore !
6! Licensed under a MIT/X style license !
7! See License_ROMS.md !
8!=======================================================================
9! !
10! ROMS Adjoint Finite Time Eigenmodes (AFTE) Driver: !
11! !
12! This driver computes the adjoint finite time eigenmodes of the !
13! propagator transpose[R(t,0)] linearized about a time evolving !
14! circulation. They represent the optimal excitations of the !
15! eigenvectors of R(0,t) and are used to compute the projection !
16! of any perturbation on the eigenvectors of R(0,t). They also !
17! used to quantify the non-normality of a dynamical system. !
18! !
19! These routines control the initialization, time-stepping, and !
20! finalization of ROMS model following ESMF conventions: !
21! !
22! ROMS_initialize !
23! ROMS_run !
24! ROMS_finalize !
25! !
26! WARNING: This driver cannot be run from the ESMF super-structure. !
27! ======= Therefore, ESMF coupling is not possible. !
28! !
29! Reference: !
30! !
31! Moore, A.M. et al., 2004: A comprehensive ocean prediction and !
32! analysis system based on the tangent linear and adjoint of a !
33! regional ocean model, Ocean Modelling, 7, 227-258. !
34! !
35!=======================================================================
36!
37 USE mod_param
38 USE mod_parallel
39 USE mod_arrays
40 USE mod_iounits
41 USE mod_ncparam
42 USE mod_netcdf
43#if defined PIO_LIB && defined DISTRIBUTE
45#endif
46 USE mod_scalars
47 USE mod_stepping
48 USE mod_storage
49!
51!
53#ifdef CHECKPOINTING
54 USE def_gst_mod, ONLY : def_gst
55 USE get_gst_mod, ONLY : get_gst
56#endif
57 USE inp_par_mod, ONLY : inp_par
58#ifdef MCT_LIB
59# ifdef ATM_COUPLING
60 USE mct_coupler_mod, ONLY : initialize_ocn2atm_coupling
61# endif
62# ifdef WAV_COUPLING
63 USE mct_coupler_mod, ONLY : initialize_ocn2wav_coupling
64# endif
65#endif
66 USE packing_mod, ONLY : c_norm2
67 USE packing_mod, ONLY : r_norm2
69 USE strings_mod, ONLY : founderror
70#ifdef CHECKPOINTING
71 USE wrt_gst_mod, ONLY : wrt_gst
72#endif
73 USE wrt_rst_mod, ONLY : wrt_rst
74!
75 implicit none
76!
77 PRIVATE :: iram_error
78 PUBLIC :: roms_initialize
79 PUBLIC :: roms_run
80 PUBLIC :: roms_finalize
81!
82 CONTAINS
83!
84 SUBROUTINE roms_initialize (first, mpiCOMM)
85!
86!=======================================================================
87! !
88! This routine allocates and initializes ROMS state variables !
89! and internal and external parameters. !
90! !
91!=======================================================================
92!
93! Imported variable declarations.
94!
95 logical, intent(inout) :: first
96!
97 integer, intent(in), optional :: mpiCOMM
98!
99! Local variable declarations.
100!
101 logical :: allocate_vars = .true.
102!
103#ifdef DISTRIBUTE
104 integer :: MyError, MySize
105#endif
106 integer :: chunk_size, ng, thread
107#ifdef _OPENMP
108 integer :: my_threadnum
109#endif
110!
111 character (len=*), parameter :: MyFile = &
112 & __FILE__//", ROMS_initialize"
113
114#ifdef DISTRIBUTE
115!
116!-----------------------------------------------------------------------
117! Set distribute-memory (mpi) world communictor.
118!-----------------------------------------------------------------------
119!
120 IF (PRESENT(mpicomm)) THEN
121 ocn_comm_world=mpicomm
122 ELSE
123 ocn_comm_world=mpi_comm_world
124 END IF
125 CALL mpi_comm_rank (ocn_comm_world, myrank, myerror)
126 CALL mpi_comm_size (ocn_comm_world, mysize, myerror)
127#endif
128!
129!-----------------------------------------------------------------------
130! On first pass, initialize model parameters a variables for all
131! nested/composed grids. Notice that the logical switch "first"
132! is used to allow multiple calls to this routine during ensemble
133! configurations.
134!-----------------------------------------------------------------------
135!
136 IF (first) THEN
137 first=.false.
138!
139! Initialize parallel control switches. These scalars switches are
140! independent from standard input parameters.
141!
143!
144! Set the ROMS standard output unit to write verbose execution info.
145! Notice that the default standard out unit in Fortran is 6.
146!
147! In some applications like coupling or disjointed mpi-communications,
148! it is advantageous to write standard output to a specific filename
149! instead of the default Fortran standard output unit 6. If that is
150! the case, it opens such formatted file for writing.
151!
152 IF (set_stdoutunit) THEN
154 set_stdoutunit=.false.
155 END IF
156!
157! Read in model tunable parameters from standard input. Allocate and
158! initialize variables in several modules after the number of nested
159! grids and dimension parameters are known.
160!
161 CALL inp_par (iadm)
162 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
163!
164! Set domain decomposition tile partition range. This range is
165! computed only once since the "first_tile" and "last_tile" values
166! are private for each parallel thread/node.
167!
168#if defined _OPENMP
169 mythread=my_threadnum()
170#elif defined DISTRIBUTE
172#else
173 mythread=0
174#endif
175 DO ng=1,ngrids
176 chunk_size=(ntilex(ng)*ntilee(ng)+numthreads-1)/numthreads
177 first_tile(ng)=mythread*chunk_size
178 last_tile(ng)=first_tile(ng)+chunk_size-1
179 END DO
180!
181! Initialize internal wall clocks. Notice that the timings does not
182! includes processing standard input because several parameters are
183! needed to allocate clock variables.
184!
185 IF (master) THEN
186 WRITE (stdout,10)
187 10 FORMAT (/,' Process Information:',/)
188 END IF
189!
190 DO ng=1,ngrids
191 DO thread=thread_range
192 CALL wclock_on (ng, iadm, 0, __line__, myfile)
193 END DO
194 END DO
195!
196! Allocate and initialize modules variables.
197!
198 CALL roms_allocate_arrays (allocate_vars)
200 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
201
202 END IF
203
204#if defined MCT_LIB && (defined ATM_COUPLING || defined WAV_COUPLING)
205!
206!-----------------------------------------------------------------------
207! Initialize coupling streams between model(s).
208!-----------------------------------------------------------------------
209!
210 DO ng=1,ngrids
211# ifdef ATM_COUPLING
212 CALL initialize_ocn2atm_coupling (ng, myrank)
213# endif
214# ifdef WAV_COUPLING
215 CALL initialize_ocn2wav_coupling (ng, myrank)
216# endif
217 END DO
218#endif
219!
220!-----------------------------------------------------------------------
221! Initialize adjoint model for all grids first in order to compute
222! the size of the state vector, Nstate. This size is computed in
223! routine "wpoints".
224!-----------------------------------------------------------------------
225
226#ifdef FORWARD_FLUXES
227!
228! Set the BLK structure to contain the nonlinear model surface fluxes
229! needed by the tangent linear and adjoint models. Also, set switches
230! to process that structure in routine "check_multifile". Notice that
231! it is possible to split the solution into multiple NetCDF files to
232! reduce their size.
233!
234! The switch LreadFRC is deactivated because all the atmospheric
235! forcing, including shortwave radiation, is read from the NLM
236! surface fluxes or is assigned during ESM coupling. Such fluxes
237! are available from the QCK structure. There is no need for reading
238! and processing from the FRC structure input forcing-files.
239!
240 CALL edit_multifile ('QCK2BLK')
241 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
242 DO ng=1,ngrids
243 lreadblk(ng)=.true.
244 lreadfrc(ng)=.false.
245 END DO
246#endif
247!
248! Initialize adjoint model.
249!
250 DO ng=1,ngrids
251 lreadfwd(ng)=.true.
252 CALL ad_initial (ng)
253 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
254 END DO
255!
256! Allocate arrays associated with Generalized Stability Theory (GST)
257! analysis.
258!
260!
261! Initialize various IO flags.
262!
263 nrun=0
264 DO ng=1,ngrids
265 ldefadj(ng)=.true.
266 lwrtadj(ng)=.true.
267 lwrtper(ng)=.false.
268 lcycleadj(ng)=.false.
269 nadj(ng)=ntimes(ng)
270 END DO
271!
272! Initialize ARPACK parameters.
273!
274 lrvec=.true. ! Compute Ritz vectors
275 bmat='I' ! standard eigenvalue problem
276 which='LM' ! compute NEV largest eigenvalues
277 howmany='A' ! compute NEV Ritz vectors
278 DO ng=1,ngrids
279 ido(ng)=0 ! reverse communication flag
280 info(ng)=0 ! random initial residual vector
281 iparam(1,ng)=1 ! exact shifts
282 iparam(3,ng)=maxitergst ! maximum number of Arnoldi iterations
283 iparam(4,ng)=1 ! block size in the recurrence
284 iparam(7,ng)=1 ! type of eigenproblem being solved
285 END DO
286!
287! ARPACK debugging parameters.
288!
289 logfil=stdout ! output logical unit
290 ndigit=-3 ! number of decimal digits
291 msaupd=1 ! iterations, timings, Ritz
292 msaup2=1 ! norms, Ritz values
293 msaitr=0
294 mseigt=0
295 msapps=0
296 msgets=0
297 mseupd=0
298!
299! Determine size of the eigenproblem (Nsize) and size of work space
300! array SworkL (LworkL).
301!
302 DO ng=1,ngrids
303 nconv(ng)=0
304 nsize(ng)=nend(ng)-nstr(ng)+1
305 END DO
306
307#ifdef CHECKPOINTING
308!
309! If restart, read in check pointing data GST restart NetCDF file.
310! Otherwise, create check pointing restart NetCDF file.
311!
312 DO ng=1,ngrids
313 IF (lrstgst) THEN
314 CALL get_gst (ng, iadm)
315 ido(ng)=-2
316 ELSE
317 CALL def_gst (ng, iadm)
318 END IF
319 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
320 END DO
321#endif
322!
323 RETURN
324 END SUBROUTINE roms_initialize
325!
326 SUBROUTINE roms_run (RunInterval)
327!
328!=======================================================================
329! !
330! This routine computes the eigenvectors of the adjoint propagator, !
331! transpose[R(t,0)]. They are computed in an analogous way to those !
332! of R(t,0). A single integration of an arbitrary perturbation state !
333! vector "u" backward in time over the interval [t,0] by the adjoint !
334! model: transpose[R(t,0)]*u. The complex conjugate eigenspectrum of !
335! transpose[R(t,0)] is computed with the Arnoldi algorithm using !
336! ARPACK library: !
337! !
338! Lehoucq, R.B., D.C. Sorensen, and C. Yang, 1997: ARPACK user's !
339! guide: solution of large scale eigenvalue problems with !
340! implicit restarted Arnoldi Methods, Rice University, 140p. !
341! !
342!=======================================================================
343!
344! Imported variable declarations
345!
346 real(dp), intent(in) :: RunInterval ! seconds
347!
348! Local variable declarations.
349!
350 logical :: ITERATE, Lcomplex
351#ifdef CHECKPOINTING
352 logical :: LwrtGST
353#endif
354!
355 integer :: Fcount, Is, Ie, i, icount, iter, ng, srec
356 integer :: NconvRitz(Ngrids)
357!
358 real(r8) :: Enorm
359!
360 TYPE (T_GST), allocatable :: ad_state(:)
361 TYPE (T_GST), allocatable :: state(:)
362!
363 character (len=55) :: string
364
365 character (len=*), parameter :: MyFile = &
366 & __FILE__//", ROMS_run"
367!
368!-----------------------------------------------------------------------
369! Implicit Restarted Arnoldi Method (IRAM) for the computation of
370! optimal perturbation Ritz eigenfunctions.
371!-----------------------------------------------------------------------
372!
373! Allocate nested grid pointers for state vectors.
374!
375 IF (.not.allocated(ad_state)) THEN
376 allocate ( ad_state(ngrids) )
377 END IF
378 IF (.not.allocated(state)) THEN
379 allocate ( state(ngrids) )
380 END IF
381!
382! Iterate until either convergence or maximum iterations has been
383! exceeded.
384!
385 iter=0
386 iterate=.true.
387#ifdef CHECKPOINTING
388 lwrtgst=.true.
389#endif
390!
391 iter_loop : DO WHILE (iterate)
392 iter=iter+1
393!
394! Reverse communication interface.
395!
396 DO ng=1,ngrids
397#ifdef PROFILE
398 CALL wclock_on (ng, iadm, 38, __line__, myfile)
399#endif
400#ifdef DISTRIBUTE
401 CALL pdnaupd (ocn_comm_world, &
402 & ido(ng), bmat, nsize(ng), which, nev, &
403 & ritz_tol, &
404 & storage(ng)%resid(nstr(ng)), ncv, &
405 & storage(ng)%Bvec(nstr(ng),1), nsize(ng), &
406 & iparam(1,ng), ipntr(1,ng), &
407 & storage(ng)%SworkD, &
408 & sworkl(1,ng), lworkl, info(ng))
409#else
410 CALL dnaupd (ido(ng), bmat, nsize(ng), which, nev, &
411 & ritz_tol, &
412 & storage(ng)%resid, ncv, &
413 & storage(ng)%Bvec, nsize(ng), &
414 & iparam(1,ng), ipntr(1,ng), &
415 & storage(ng)%SworkD, &
416 & sworkl(1,ng), lworkl, info(ng))
417#endif
418 nconv(ng)=iaup2(4)
419#ifdef PROFILE
420 CALL wclock_off (ng, iadm, 38, __line__, myfile)
421#endif
422#ifdef CHECKPOINTING
423!
424! If appropriate, write out check point data into GST restart NetCDF
425! file. Notice that the restart data is always saved if MaxIterGST
426! is reached without convergence. It is also saved when convergence
427! is achieved (ido=99).
428!
429 IF ((mod(iter,ngst).eq.0).or.(iter.ge.maxitergst).or. &
430 & (any(ido.eq.99))) THEN
431 CALL wrt_gst (ng, iadm)
432 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
433 END IF
434#endif
435 END DO
436!
437! Terminate computations if maximum number of iterations is reached.
438! This will faciliate splitting the analysis in several computational
439! cycles using the restart option.
440!
441 IF ((iter.ge.maxitergst).and.any(ido.ne.99)) THEN
442 iterate=.false.
443 EXIT iter_loop
444 END IF
445!
446! Perform matrix-vector operation: R'(t,0)u
447!
448 IF (any(abs(ido).eq.1)) THEN
449 DO ng=1,ngrids
450 fcount=adm(ng)%load
451 adm(ng)%Nrec(fcount)=0
452 adm(ng)%Rindex=0
453 END DO
454!
455! Set state vectors to process by the propagator via pointer
456! equivalence.
457!
458 DO ng=1,ngrids
459 IF (ASSOCIATED(state(ng)%vector)) THEN
460 nullify (state(ng)%vector)
461 END IF
462 is=ipntr(1,ng)
463 ie=is+nsize(ng)-1
464 state(ng)%vector => storage(ng)%SworkD(is:ie)
465
466 IF (ASSOCIATED(ad_state(ng)%vector)) THEN
467 nullify (ad_state(ng)%vector)
468 END IF
469 is=ipntr(2,ng)
470 ie=is+nsize(ng)-1
471 ad_state(ng)%vector => storage(ng)%SworkD(is:ie)
472 END DO
473
474 CALL propagator_afte (runinterval, state, ad_state)
475 IF (founderror(exit_flag, noerror, __line__, myfile)) RETURN
476
477 ELSE
478 IF (any(info.ne.0)) THEN
479 DO ng=1,ngrids
480 IF (info(ng).ne.0) THEN
481 IF (master) THEN
482 CALL iram_error (info(ng), 1, string)
483 WRITE (stdout,10) 'DNAUPD', trim(string), &
484 & ', info = ', info(ng)
485 END IF
486 RETURN
487 END IF
488 END DO
489 ELSE
490!
491! Compute Ritz vectors (the only choice left is IDO=99). They are
492! generated in ARPACK in decreasing magnitude of its eigenvalue.
493! The most significant is first.
494!
495 DO ng=1,ngrids
496 nconvritz(ng)=iparam(5,ng)
497 IF (master) THEN
498 WRITE (stdout,20) 'Number of converged Ritz values:', &
499 & iparam(5,ng)
500 WRITE (stdout,20) 'Number of Arnoldi iterations:', &
501 & iparam(3,ng)
502 END IF
503#ifdef PROFILE
504 CALL wclock_on (ng, iadm, 38, __line__, myfile)
505#endif
506#ifdef DISTRIBUTE
507 CALL pdneupd (ocn_comm_world, &
508 & lrvec, howmany, pick(1,ng), &
509 & rvaluer(1,ng), rvaluei(1,ng), &
510 & storage(ng)%Rvector(nstr(ng),1), &
511 & nsize(ng), sigmar, sigmai, &
512 & sworkev(1,ng), bmat, nsize(ng), &
513 & which, nev, ritz_tol, &
514 & storage(ng)%resid(nstr(ng)), ncv, &
515 & storage(ng)%Bvec(nstr(ng),1), nsize(ng), &
516 & iparam(1,ng), ipntr(1,ng), &
517 & storage(ng)%SworkD, &
518 & sworkl(1,ng), lworkl, info(ng))
519#else
520 CALL dneupd (lrvec, howmany, pick(1,ng), &
521 & rvaluer(1,ng), rvaluei(1,ng), &
522 & storage(ng)%Rvector, nsize(ng), &
523 & sigmar, sigmai, &
524 & sworkev(1,ng), bmat, nsize(ng), &
525 & which, nev, ritz_tol, &
526 & storage(ng)%resid, ncv, &
527 & storage(ng)%Bvec, nsize(ng), &
528 & iparam(1,ng), ipntr(1,ng), &
529 & storage(ng) % SworkD, &
530 & sworkl(1,ng), lworkl, info(ng))
531#endif
532#ifdef PROFILE
533 CALL wclock_off (ng, iadm, 38, __line__, myfile)
534#endif
535 END DO
536
537 IF (any(info.ne.0)) THEN
538 DO ng=1,ngrids
539 IF (info(ng).ne.0) THEN
540 IF (master) THEN
541 CALL iram_error (info(ng), 2, string)
542 WRITE (stdout,10) 'DNEUPD', trim(string), &
543 & ', info = ', info(ng)
544 END IF
545 RETURN
546 END IF
547 END DO
548 ELSE
549!
550! Activate writing of each eigenvector into the adjoint history NetCDF
551! file. The "ocean_time" is the eigenvector number.
552!
553 nrun=0
554 icount=0
555 lcomplex=.true.
556
557 DO i=1,maxval(nconvritz)
558 DO ng=1,ngrids
559 IF ((i.eq.1).or.lmultigst) THEN
560 fcount=adm(ng)%load
561 adm(ng)%Nrec(fcount)=0
562 adm(ng)%Rindex=0
563 END IF
564 IF (lmultigst.and.lcomplex) THEN
565 ldefadj(ng)=.true.
566 icount=icount+1
567 WRITE (adm(ng)%name,30) trim(adm(ng)%base), icount
568 END IF
569 END DO
570!
571! Compute and write Ritz eigenvectors.
572!
573 IF (any(rvaluei(i,:).eq.0.0_r8)) THEN
574!
575! Ritz value is real.
576!
577 DO ng=1,ngrids
578 is=nstr(ng)
579 ie=nend(ng)
580 IF (ASSOCIATED(state(ng)%vector)) THEN
581 nullify (state(ng)%vector)
582 END IF
583
584 IF (ASSOCIATED(ad_state(ng)%vector)) THEN
585 nullify (ad_state(ng)%vector)
586 END IF
587 state(ng)%vector => storage(ng)%Rvector(is:ie,i)
588 ad_state(ng)%vector => sworkr(is:ie)
589 END DO
590
591 CALL propagator_afte (runinterval, state, ad_state)
593 & __line__, myfile)) RETURN
594!
595 DO ng=1,ngrids
596 CALL r_norm2 (ng, iadm, nstr(ng), nend(ng), &
597 & -rvaluer(i,ng), &
598 & state(ng)%vector, &
599 & ad_state(ng)%vector, enorm)
600 norm(i,ng)=enorm
601 END DO
602
603 ELSE IF (lcomplex) THEN
604!
605! Ritz value is complex.
606!
607 DO ng=1,ngrids
608 is=nstr(ng)
609 ie=nend(ng)
610 IF (ASSOCIATED(state(ng)%vector)) THEN
611 nullify (state(ng)%vector)
612 END IF
613
614 IF (ASSOCIATED(ad_state(ng)%vector)) THEN
615 nullify (ad_state(ng)%vector)
616 END IF
617 state(ng)%vector => storage(ng)%Rvector(is:ie,i)
618 ad_state(ng)%vector => sworkr(is:ie)
619 END DO
620
621 CALL propagator_afte (runinterval, state, ad_state)
623 & __line__, myfile)) RETURN
624!
625 DO ng=1,ngrids
626 CALL c_norm2 (ng, iadm, nstr(ng), nend(ng), &
627 & -rvaluer(i,ng), rvaluei(i,ng), &
628 & storage(ng)%Rvector(nstr(ng):,i ), &
629 & storage(ng)%Rvector(nstr(ng):,i+1), &
630 & ad_state(ng)%vector, enorm)
631 norm(i,ng)=enorm
632 END DO
633!
634 DO ng=1,ngrids
635 is=nstr(ng)
636 ie=nend(ng)
637 IF (ASSOCIATED(state(ng)%vector)) THEN
638 nullify (state(ng)%vector)
639 END IF
640
641 IF (ASSOCIATED(ad_state(ng)%vector)) THEN
642 nullify (ad_state(ng)%vector)
643 END IF
644 state(ng)%vector => storage(ng)%Rvector(is:ie,i+1)
645 ad_state(ng)%vector => sworkr(is:ie)
646 END DO
647
648 CALL propagator_afte (runinterval, state, ad_state)
650 & __line__, myfile)) RETURN
651!
652 DO ng=1,ngrids
653 CALL c_norm2 (ng, iadm, nstr(ng), nend(ng), &
654 & -rvaluer(i,ng), -rvaluei(i,ng), &
655 & storage(ng)%Rvector(nstr(ng):,i+1), &
656 & storage(ng)%Rvector(nstr(ng):,i ), &
657 & ad_state(ng)%vector, enorm)
658 norm(i ,ng)=sqrt(norm(i,ng)*norm(i,ng)+ &
659 & enorm*enorm)
660 norm(i+1,ng)=norm(i,ng)
661 lcomplex=.false.
662 END DO
663 ELSE
664 lcomplex=.true.
665 END IF
666 IF (master) THEN
667 DO ng=1,ngrids
668 WRITE (stdout,40) i, norm(i,ng), &
669 & rvaluer(i,ng), rvaluei(i,ng), i
670 END DO
671 END IF
672!
673! Write out Ritz eigenvalues and Ritz eigenvector Euclidean norm
674! (residual)to NetCDF file(s).
675!
676 sourcefile=myfile
677 DO ng=1,ngrids
678 IF (lmultigst) THEN
679 IF (.not.lcomplex.or.(rvaluei(i,ng).eq.0.0_r8)) THEN
680 srec=1
681 ELSE
682 srec=2
683 END IF
684 ELSE
685 srec=i
686 END IF
687!
688 IF (lwrtadj(ng)) THEN
689 SELECT CASE (adm(ng)%IOtype)
690 CASE (io_nf90)
691 CALL netcdf_put_fvar (ng, iadm, &
692 & adm(ng)%name, &
693 & 'Ritz_rvalue', &
694 & rvaluer(i:,ng), &
695 & start = (/srec/), &
696 & total = (/1/), &
697 & ncid = adm(ng)%ncid)
698
700 & __line__, myfile)) RETURN
701!
702 CALL netcdf_put_fvar (ng, iadm, &
703 & adm(ng)%name, &
704 & 'Ritz_ivalue', &
705 & rvaluei(i:,ng), &
706 & start = (/srec/), &
707 & total = (/1/), &
708 & ncid = adm(ng)%ncid)
709
711 & __line__, myfile)) RETURN
712!
713 CALL netcdf_put_fvar (ng, iadm, &
714 & adm(ng)%name, &
715 & 'Ritz_norm', &
716 & norm(i:,ng), &
717 & start = (/srec/), &
718 & total = (/1/), &
719 & ncid = adm(ng)%ncid)
720
722 & __line__, myfile)) RETURN
723
724#if defined PIO_LIB && defined DISTRIBUTE
725 CASE (io_pio)
726 CALL pio_netcdf_put_fvar (ng, iadm, &
727 & adm(ng)%name, &
728 & 'Ritz_rvalue', &
729 & rvaluer(i:,ng), &
730 & start = (/srec/), &
731 & total = (/1/), &
732 & piofile = adm(ng)%pioFile)
733
735 & __line__, myfile)) RETURN
736!
737 CALL pio_netcdf_put_fvar (ng, iadm, &
738 & adm(ng)%name, &
739 & 'Ritz_ivalue', &
740 & rvaluei(i:,ng), &
741 & start = (/srec/), &
742 & total = (/1/), &
743 & piofile = adm(ng)%pioFile)
744
746 & __line__, myfile)) RETURN
747!
748 CALL pio_netcdf_put_fvar (ng, iadm, &
749 & adm(ng)%name, &
750 & 'Ritz_norm', &
751 & norm(i:,ng), &
752 & start = (/srec/), &
753 & total = (/1/), &
754 & piofile = adm(ng)%pioFile)
755
757 & __line__, myfile)) RETURN
758#endif
759 END SELECT
760!
761 IF (lmultigst.and.lcomplex) THEN
762 CALL close_file (ng, iadm, adm(ng), adm(ng)%name)
764 & __line__, myfile)) RETURN
765 END IF
766 END IF
767 END DO
768 END DO
769 END IF
770 END IF
771 iterate=.false.
772 END IF
773
774 END DO iter_loop
775!
776 10 FORMAT (/,1x,'Error in ',a,1x,a,a,1x,i5,/)
777 20 FORMAT (/,a,1x,i2,/)
778 30 FORMAT (a,'_',i3.3,'.nc')
779 40 FORMAT (1x,i4.4,'-th residual',1p,e14.6,0p, &
780 & ' Ritz values',1pe14.6,0p,1x,1pe14.6,2x,i4.4)
781!
782 RETURN
783 END SUBROUTINE roms_run
784!
785 SUBROUTINE roms_finalize
786!
787!=======================================================================
788! !
789! This routine terminates ROMS nonlinear and adjoint models !
790! execution. !
791! !
792!=======================================================================
793!
794! Local variable declarations.
795!
796 integer :: Fcount, ng, thread
797!
798 character (len=*), parameter :: MyFile = &
799 & __FILE__//", ROMS_finalize"
800!
801!-----------------------------------------------------------------------
802! If blowing-up, save latest model state into RESTART NetCDF file.
803!-----------------------------------------------------------------------
804!
805! If cycling restart records, write solution into the next record.
806!
807 IF (exit_flag.eq.1) THEN
808 DO ng=1,ngrids
809 IF (lwrtrst(ng)) THEN
810 IF (master) WRITE (stdout,10)
811 10 FORMAT (/,' Blowing-up: Saving latest model state into ', &
812 & ' RESTART file',/)
813 fcount=rst(ng)%load
814 IF (lcyclerst(ng).and.(rst(ng)%Nrec(fcount).ge.2)) THEN
815 rst(ng)%Rindex=2
816 lcyclerst(ng)=.false.
817 END IF
820#ifdef DISTRIBUTE
821 CALL wrt_rst (ng, myrank)
822#else
823 CALL wrt_rst (ng, -1)
824#endif
825 END IF
826 END DO
827 END IF
828!
829!-----------------------------------------------------------------------
830! Stop model and time profiling clocks, report memory requirements, and
831! close output NetCDF files.
832!-----------------------------------------------------------------------
833!
834! Stop time clocks.
835!
836 IF (master) THEN
837 WRITE (stdout,20)
838 20 FORMAT (/,'Elapsed wall CPU time for each process (seconds):',/)
839 END IF
840!
841 DO ng=1,ngrids
842 DO thread=thread_range
843 CALL wclock_off (ng, iadm, 0, __line__, myfile)
844 END DO
845 END DO
846!
847! Report dynamic memory and automatic memory requirements.
848!
849 CALL memory
850!
851! Close IO files.
852!
853 DO ng=1,ngrids
854 CALL close_inp (ng, iadm)
855 END DO
856 CALL close_out
857!
858 RETURN
859 END SUBROUTINE roms_finalize
860!
861 SUBROUTINE iram_error (info, icall, string)
862!
863!=======================================================================
864! !
865! This routine decodes internal error messages from the Implicit !
866! Restarted Arnoldi Method (IRAM) for the computation of optimal !
867! perturbation Ritz eigenfunctions. !
868! !
869!=======================================================================
870!
871! imported variable declarations.
872!
873 integer, intent(in) :: info, icall
874!
875 character (len=*), intent(out) :: string
876!
877!-----------------------------------------------------------------------
878! Decode error message from IRAM.
879!-----------------------------------------------------------------------
880!
881 IF (info.eq.0) THEN
882 string='Normal exit '
883 ELSE IF (info.eq.1) THEN
884 IF (icall.eq.1) THEN
885 string='Maximum number of iterations taken '
886 ELSE
887 string='Could not reorder Schur vectors '
888 END IF
889 ELSE IF (info.eq.3) THEN
890 string='No shifts could be applied during an IRAM cycle '
891 ELSE IF (info.eq.-1) THEN
892 string='Nstate must be positive '
893 ELSE IF (info.eq.-2) THEN
894 string='NEV must be positive '
895 ELSE IF (info.eq.-3) THEN
896 string='NCV must be greater NEV and less than or equal Nstate '
897 ELSE IF (info.eq.-4) THEN
898 string='Maximum number of iterations must be greater than zero '
899 ELSE IF (info.eq.-5) THEN
900 string='WHICH must be one of LM, SM, LA, SA or BE '
901 ELSE IF (info.eq.-6) THEN
902 string='BMAT must be one of I or G '
903 ELSE IF (info.eq.-7) THEN
904 string='Length of private work array SworkL is not sufficient '
905 ELSE IF (info.eq.-8) THEN
906 IF (icall.eq.1) THEN
907 string='Error return from LAPACK eigenvalue calculation '
908 ELSE
909 string='Error in DLAHQR in the Shurn vectors calculation '
910 END IF
911 ELSE IF (info.eq.-9) THEN
912 IF (icall.eq.1) THEN
913 string='Starting vector is zero'
914 ELSE
915 string='Error in DTREVC in the eigenvectors calculation '
916 END IF
917 ELSE IF (info.eq.-10) THEN
918 string='IPARAM(7) must be 1, 2, 3, 4, 5 '
919 ELSE IF (info.eq.-11) THEN
920 string='IPARAM(7) = 1 and BMAT = G are incompatable '
921 ELSE IF (info.eq.-12) THEN
922 IF (icall.eq.1) THEN
923 string='IPARAM(1) must be equal to 0 or 1 '
924 ELSE
925 string='HOWMANY = S not yet implemented '
926 END IF
927 ELSE IF (info.eq.-13) THEN
928 string='HOWMANY must be one of A or P if Lrvec = .TRUE. '
929 ELSE IF (info.eq.-14) THEN
930 string='Did not find any eigenvalues to sufficient accuaracy '
931 ELSE IF (info.eq.-15) THEN
932 string='Different count of converge Ritz values in DNEUPD '
933 ELSE IF (info.eq.-9999) THEN
934 string='Could not build and Arnoldi factorization '
935 END IF
936!
937 RETURN
938 END SUBROUTINE iram_error
939
940 END MODULE roms_kernel_mod
subroutine ad_initial(ng)
Definition ad_initial.F:4
subroutine edit_multifile(task)
subroutine memory
Definition memory.F:3
subroutine, public close_out
Definition close_io.F:175
subroutine, public close_file(ng, model, s, ncname, lupdate)
Definition close_io.F:43
subroutine, public close_inp(ng, model)
Definition close_io.F:92
subroutine, public def_gst(ng, model)
Definition def_gst.F:45
subroutine, public get_gst(ng, model)
Definition get_gst.F:38
subroutine, public inp_par(model)
Definition inp_par.F:56
subroutine, public roms_initialize_arrays
Definition mod_arrays.F:351
subroutine, public roms_allocate_arrays(allocate_vars)
Definition mod_arrays.F:114
type(t_io), dimension(:), allocatable adm
type(t_io), dimension(:), allocatable rst
integer stdout
character(len=256) sourcefile
integer, parameter io_nf90
Definition mod_ncparam.F:95
integer, parameter io_pio
Definition mod_ncparam.F:96
subroutine, public initialize_parallel
integer numthreads
integer, dimension(:), allocatable first_tile
integer mythread
logical master
integer, dimension(:), allocatable last_tile
integer ocn_comm_world
integer, dimension(:), allocatable nstr
Definition mod_param.F:646
integer, dimension(:), allocatable ntilex
Definition mod_param.F:685
integer, parameter iadm
Definition mod_param.F:665
integer, dimension(:), allocatable nsize
Definition mod_param.F:648
integer ngrids
Definition mod_param.F:113
integer, dimension(:), allocatable ntilee
Definition mod_param.F:686
integer, dimension(:), allocatable nend
Definition mod_param.F:647
integer, dimension(:), allocatable ntimes
logical lmultigst
integer, dimension(:), allocatable nconv
integer blowup
logical, dimension(:), allocatable lreadfrc
logical, dimension(:), allocatable ldefadj
logical, dimension(:), allocatable lcycleadj
logical, dimension(:), allocatable lwrtadj
logical lrstgst
integer exit_flag
real(dp) ritz_tol
logical, dimension(:), allocatable lwrtper
integer maxitergst
logical, dimension(:), allocatable lwrtrst
integer nrun
integer, dimension(:), allocatable nadj
logical, dimension(:), allocatable lreadfwd
integer noerror
logical, dimension(:), allocatable lcyclerst
logical, dimension(:), allocatable lreadblk
integer msaup2
integer, dimension(8) iaup2
integer, dimension(:), allocatable ido
real(r8), dimension(:,:), allocatable rvaluei
real(r8), dimension(:,:), allocatable sworkl
integer, dimension(:,:), allocatable ipntr
integer ncv
character(len=1) howmany
logical lrvec
Definition mod_storage.F:95
real(r8), dimension(:,:), allocatable sworkev
integer msaupd
real(r8) sigmai
character(len=1) bmat
integer nev
type(t_storage), dimension(:), allocatable storage
Definition mod_storage.F:91
real(r8), dimension(:,:), allocatable norm
integer, dimension(:), allocatable info
subroutine, public allocate_storage
character(len=2) which
integer lworkl
integer, dimension(:,:), allocatable iparam
integer mseigt
integer msapps
integer ndigit
integer msgets
logical, dimension(:,:), allocatable pick
Definition mod_storage.F:96
real(r8) sigmar
integer logfil
real(r8), dimension(:), pointer sworkr
real(r8), dimension(:,:), allocatable rvaluer
integer msaitr
integer mseupd
subroutine, public propagator_afte(runinterval, state, ad_state)
subroutine, public roms_finalize
Definition ad_roms.h:283
subroutine, public roms_run(runinterval)
Definition ad_roms.h:239
subroutine, private iram_error(info, icall, string)
Definition afte_roms.h:862
subroutine, public roms_initialize(first, mpicomm)
Definition ad_roms.h:52
integer function, public stdout_unit(mymaster)
Definition stdout_mod.F:48
logical, save set_stdoutunit
Definition stdout_mod.F:41
logical function, public founderror(flag, noerr, line, routine)
Definition strings.F:52
subroutine, public wrt_gst(ng, model)
Definition wrt_gst.F:39
subroutine, public wrt_rst(ng, tile)
Definition wrt_rst.F:63
subroutine c_norm2(ng, model, mstr, mend, evaluer, evaluei, evectorr, evectori, state, norm2)
Definition packing.F:75
subroutine r_norm2(ng, model, mstr, mend, evalue, evector, state, norm2)
Definition packing.F:175
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