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