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