5 & MPI_COMM_Atmos => COMM_local, &
8 & component_master_rank_local, &
9 & process_rank_local, &
13 & MPI_INTEGER,MPI_STATUS_SIZE, &
14 & kind_REAL,kind_alt_REAL, &
15 & MPI_kind_REAL,MPI_kind_alt_REAL
19 integer,parameter:: ND=2
20 integer Ocean_spec /-1/, WM_id /-10/
23 real dtc, & !<- Coupling period
24 & dta, & !<- AM time step ("physical")
25 & dta2dtc !<- AM time step / Coupling period
26 integer i_dtc2dta /100/ !<- Coupling period / AM time step
27 integer & !,dimension(ND)::
28 &ims,ime,jms,jme,its,ite,jts,jte,ids,idf,jds,jdf, NGP
29 integer kms,kme,kts,kte,kds,kde
30 integer,parameter:: kind_R=kind_alt_REAL
31 !c integer,parameter:: kind_tiling=kind_R
32 integer,parameter:: kind_sfcflux=kind_R, &
37 &MPI_kind_sfcflux,MPI_kind_SST,MPI_kind_SLM,MPI_kind_lonlat
38 integer n_ts(ND) /0,0/, gid
41 & SLM_OS_value=1., &!<-must be real open sea mask value in AM
42 & unrealistically_low_SST=0.01, & ! <- must be unreal low but >=0.,
43 ! see interp. --- check!
44 & unrealistically_low_SV=-1.E30, &
45 ! <- must be negative unreal low surface flux
46 ! or other surface value to be sent
47 ! to Coupler, see Coupler code
48 & unrealistically_low_SF=unrealistically_low_SV, & !<- same thing
49 & unrealistically_low_SVp=0.99*unrealistically_low_SV
51 logical initialized /.false./
52 logical PHYS,zeroSF,nrmSF,sendSF,getSST
55 real(kind=kind_SST),dimension(:,:),pointer:: a
58 real(kind=kind_sfcflux),dimension(:,:,:),pointer:: a
61 TYPE (SST_ARRAY), dimension(ND):: SST_cc
62 TYPE (SF_ARRAY), dimension(ND):: sf
67 integer nunit_announce /6/, VerbLev /3/
73 !C***********************************************************************
75 SUBROUTINE ATM_CMP_START(atm_comm)
83 integer Atmos_id /1/, Atmos_master_rank_local /0/, Atmos_spec /1/
88 !<-id of OM as a component of the coupled system
89 call CMP_INIT(Atmos_id,1)
90 !<-"flexibility level"
91 if (Coupler_id.ge.0) VerbLev=min(VerbLev,ibuffer(4))
92 write(s,'(i2)') VerbLev
94 call CMP_INTRO(Atmos_master_rank_local)
95 call ATM_ANNOUNCE('back from CMP_INTRO, VerbLev='//s,2)
99 call CMP_INTEGER_SEND(Atmos_spec,1)
101 call CMP_gnr_RECV(Ocean_spec,1,MPI_INTEGER)
102 write(s,'(i2)') Ocean_spec
103 call ATM_ANNOUNCE('back from CMP_INTEGER_RECV, OM spec is '//s,2)
104 call MPI_BCAST(Ocean_spec,1,MPI_INTEGER, &
105 &component_master_rank_local,MPI_COMM_Atmos,ierr)
106 call ATM_ANNOUNCE('ATM_CMP_START: Ocean_spec broadcast',2)
108 call CMP_gnr_RECV(WM_id,1,MPI_INTEGER)
109 write(s,'(i2)') WM_id
110 call ATM_ANNOUNCE('back from CMP_INTEGER_RECV, WM id is '//s,2)
111 call MPI_BCAST(WM_id,1,MPI_INTEGER, &
112 &component_master_rank_local,MPI_COMM_Atmos,ierr)
113 call ATM_ANNOUNCE('ATM_CMP_START: WM_id broadcast',2)
120 if (Ocean_spec.eq.1) then
122 else if (Ocean_spec.eq.2) then
124 else if (Ocean_spec.eq.0) then
126 else if (Coupler_id.ge.0) then
127 call GLOB_ABORT(Ocean_spec-1, &
128 & 'ATM_CMP_START received wrong Ocean_spec value, aborted',rc)
132 call ATM_ANNOUNCE('AM is standalone: Ocean_spec=1, NSF=4'// &
133 & ' assigned (as if for POM coupling)',2)
136 if (kind_R.eq.kind_REAL) then
137 MPI_kind_R=MPI_kind_REAL
139 MPI_kind_R=MPI_kind_alt_REAL
141 if (kind_sfcflux.eq.kind_REAL) then
142 MPI_kind_sfcflux=MPI_kind_REAL
144 MPI_kind_sfcflux=MPI_kind_alt_REAL
146 if (kind_SST.eq.kind_REAL) then
147 MPI_kind_SST=MPI_kind_REAL
149 MPI_kind_SST=MPI_kind_alt_REAL
151 if (kind_SLM.eq.kind_REAL) then
152 MPI_kind_SLM=MPI_kind_REAL
154 MPI_kind_SLM=MPI_kind_alt_REAL
156 if (kind_lonlat.eq.kind_REAL) then
157 MPI_kind_lonlat=MPI_kind_REAL
159 MPI_kind_lonlat=MPI_kind_alt_REAL
162 atm_comm=MPI_COMM_Atmos
167 !C***********************************************************************
169 SUBROUTINE ATM_INIT_CHECK(s)
171 USE ATM_cc, ONLY: initialized,rc
177 if (.not. initialized) call GLOB_ABORT(1,s,rc)
182 !C***********************************************************************
184 subroutine ATM_TSTEP_INIT(NTSD,NPHS,gid_,dta_, &
185 &ids_,idf_,jds_,jdf_,its_,ite_,jts_,jte_,ims_,ime_,jms_,jme_, &
186 !<-"domain" !<-"tile" !<-"memory" (tile+halo)
187 &kds_,kde_,kts_,kte_,kms_,kme_, &
188 &HLON,HLAT,VLON,VLAT, &
190 &i_parent_start,j_parent_start)
196 integer NTSD,NPHS,gid_
198 integer ids_,idf_,jds_,jdf_,its_,ite_,jts_,jte_, &
199 &ims_,ime_,jms_,jme_,kds_,kde_,kts_,kte_,kms_,kme_
200 real(kind=kind_lonlat),dimension(ims_:ime_,jms_:jme_):: &
202 real(kind=kind_SLM),dimension(ims_:ime_,jms_:jme_):: SLM
203 integer i_parent_start,j_parent_start
205 integer KDT,buf(2) /0,0/
213 call GLOB_ABORT((gid-1)*(gid-2), &
214 &'Abort: in ATM_TSTEP_INIT gid is neither 1 nor 2',rc)
216 PHYS=MOD(NTSD,NPHS).eq.0 ! .and. gid.eq.1 <-removed to bring MG in
219 write(s1,'("gid=",i1," NTSD=",i5," NPHS=",i3," KDT=",i5,'// &
220 &'" PHYS=",L1)') gid,NTSD,NPHS,KDT,PHYS
221 call ATM_ANNOUNCE('ATM_TSTEP_INIT entered: '//trim(s1),3)
223 !c IF (n_ts.eq.-1 .and. PHYS) THEN
225 !c n_ts=0 ! init. value must be -1 . But if PHYS does not need
226 !c ! this correction, init. value must be 0 (whereas this
227 !c ! IF statement may stay)
236 n_ts(gid)=n_ts(gid)+1 ! init. value must be 0 ***0***
237 write(s,'(2i8)') KDT,n_ts(gid)
238 write(sgid,'(" grid id = ",i1)') gid
239 call ATM_ANNOUNCE('ATM_TSTEP_INIT working:'// &
240 &sgid//'; KDT, n_ts: '//s,3)
241 call GLOB_ABORT(KDT-n_ts(gid), &
242 &'Abort: in ATM_TSTEP_INIT KDT, n_ts(gid) differ '//s,rc)
246 zeroSF=((n_ts(gid)-1)/i_dtc2dta)*i_dtc2dta .eq. n_ts(gid)-1
247 nrmSF=(n_ts(gid)/i_dtc2dta)*i_dtc2dta .eq. n_ts(gid)
248 sendSF=(n_ts(gid)/i_dtc2dta)*i_dtc2dta .eq. n_ts(gid)
249 !<-check, this depends
250 ! on where ATM_SENDFLUXES is called.
251 ! MOD(n_ts,i_dtc2dta).eq.0 should
252 ! be good for calling it after
253 ! ATM_DOFLUXES at the same t.s.
275 NGP=(idf-ids+1)*(jdf-jds+1)
277 call ATM_ANNOUNCE('ATM_TSTEP_INIT to allocate sf, SST_cc',3)
279 IF (n_ts(gid).eq.1) THEN
280 allocate(sf(gid)%a(ims:ime,jms:jme,NSF))
281 allocate(SST_cc(gid)%a(ims:ime,jms:jme))
285 write(s,'(2i8)') i_parent_start,j_parent_start
287 buf(1)=i_parent_start
288 buf(2)=j_parent_start
289 call CMP_INTEGER_SEND(buf,2)
291 & 'ATM_TSTEP_INIT: i_parent_start, j_parent_start sent '//s,3)
293 call GLOB_ABORT(abs(i_parent_start-buf(1))+abs(j_parent_start- &
294 & buf(2)),'NESTED GRID MOVED DURING C TIME STEP: ABORTED '// &
299 CALL ATM_SENDGRIDS(HLON,HLAT,VLON,VLAT)
301 CALL ATM_SENDSLM(SLM)
303 if (VerbLev.ge.2) print*,'AM: ATM_TSTEP_INIT: returning ',gid, &
304 &n_ts(gid),ids,idf,jds,jdf,its,ite,jts,jte,ims,ime,jms,jme,NGP,NSF
309 !C***********************************************************************
311 SUBROUTINE ATM_RECVdtc
317 real(kind=kind_R) buf(1),dtc2dta
319 logical first/.true./
324 write(s,'(1pe20.12)') dta
325 call ATM_ANNOUNCE('ATM_RECVdtc: AM time step dta='//s,3)
329 & 'ATM_RECVdtc: to receive C time step; AM time step dta='//s,2)
331 call CMP_gnr_RECV(buf,1,MPI_kind_R)
333 call MPI_BCAST(buf,1,MPI_kind_R, &
334 & component_master_rank_local,MPI_COMM_Atmos,ierr)
335 call ATM_ANNOUNCE('ATM_RECVdtc: C time step broadcast',2)
338 if (Coupler_id.lt.0) then
340 dtc=dta*2 ! just having in mind that with gid=1
341 else ! dta value is 5 times its value with
342 dtc=dta*10 ! gid=2 (at this moment, 270s and 54s
343 end if ! respectively)
344 write(s,'(1pe20.12)') dtc
345 call ATM_ANNOUNCE('ATM_RECVdtc: C time step assigned '// &
346 & trim(s)//' : standalone mode',2)
348 write(s,'(1pe20.12)') buf
350 & 'ATM_RECVdtc: C time step dtc='//s//' received',2)
355 i_dtc2dta=nint(dtc2dta)
356 if (abs(i_dtc2dta-dtc2dta).gt.1.E-5) call GLOB_ABORT(1, &
357 &'AM: ABORTED: dtc is not a multiple of dta',1)
360 if (n_ts(gid).eq.1) i=2
361 if (i_dtc2dta.eq.0) then
363 call ATM_ANNOUNCE('ratio of C/AM time steps =0, assigned 4 .'// &
364 & ' This should only occur in standalone mode and ONLY IF dtc '// &
365 & 'HAS NOT BEEN ASSIGNED A POSITIVE VALUE: ** ATTENTION **',i)
367 write(s,'(i2)') i_dtc2dta
368 call ATM_ANNOUNCE('ratio of C/AM time steps: '//trim(s),i)
378 !C***********************************************************************
380 SUBROUTINE ATM_SENDGRIDS(HLON,HLAT,VLON,VLAT)
386 real(kind=kind_lonlat),dimension(ims:ime,jms:jme):: &
389 real(kind=kind_lonlat),dimension(ids:idf,jds:jdf):: &
390 &ALONt,ALATt,ALONv,ALATv
395 !c IF (gid.ne.1) RETURN ! only "parent grid" dim. and coor. are sent
397 IF (.not.PHYS .or. n_ts(gid).ne.1) RETURN
399 !temporarily excluded if (Coupler_id.lt.0) return ! <- standalone mode
403 call ATM_ANNOUNCE('to send grid dimensions,'//sgid,1)
404 call CMP_INTEGER_SEND(buf,2)
405 call ATM_ANNOUNCE('grid dimensions sent,'//sgid,1)
407 !c IF (gid.eq.1) THEN ! only "parent grid" coordinates are sent
409 call ASSEMBLE(ALONt,HLON,kind_lonlat)
410 call ASSEMBLE(ALATt,HLAT,kind_lonlat)
411 call ASSEMBLE(ALONv,VLON,kind_lonlat)
412 call ASSEMBLE(ALATv,VLAT,kind_lonlat)
414 call ATM_ANNOUNCE('(BP) to send grid arrays (4 MPI calls)',2)
416 call CMP_gnr_SEND(ALONt,NGP,MPI_kind_lonlat)
417 call CMP_gnr_SEND(ALATt,NGP,MPI_kind_lonlat)
418 call CMP_gnr_SEND(ALONv,NGP,MPI_kind_lonlat)
419 call CMP_gnr_SEND(ALATv,NGP,MPI_kind_lonlat)
421 call ATM_ANNOUNCE('the 4 grid arrays sent',1)
425 call ATM_ANNOUNCE('(BP) ATM_SENDGRIDS: returning',2)
430 !C***********************************************************************
432 SUBROUTINE ATM_SENDSLM(SLM)
438 real(kind=kind_SLM),dimension(ims:ime,jms:jme):: SLM
440 real(kind=kind_SLM),dimension(ids:idf,jds:jdf):: SLM_g
444 !c IF (gid.ne.1) RETURN ! only "parent grid" mask is sent
445 IF (.not.PHYS .or. n_ts(gid).ne.1) RETURN
447 !temporarily excluded if (Coupler_id.lt.0) return ! <- standalone mode
449 call ASSEMBLE(SLM_g,SLM,kind_SLM)
451 call ATM_ANNOUNCE('(BP) to send SLM',2)
453 call CMP_gnr_SEND(SLM_g,NGP,MPI_kind_SLM)
454 call CMP_gnr_SEND(SLM_g,NGP,MPI_kind_SLM)
455 ! Coupler requires as many copies of mask as there are grids
457 call ATM_ANNOUNCE('(BP) ATM_SENDSLM: returning',2)
462 !C***********************************************************************
464 SUBROUTINE ATM_GETSST(SST,SLM)
470 real(kind=kind_SST) SST(ims:ime,jms:jme)
471 real(kind=kind_SLM) SLM(ims:ime,jms:jme)
474 real(kind=kind_SST) SST_g(ids:idf,jds:jdf)
477 IF (.not.PHYS) RETURN
479 call ATM_ANNOUNCE('ATM_GETSST entered (PHYS=.true.)',3)
481 getSST=((n_ts(gid)-1)/i_dtc2dta)*i_dtc2dta .eq. n_ts(gid)-1
482 if (getSST.neqv.zeroSF) then
483 call GLOB_ABORT(1,'getSST differs from zeroSF, which screws'// &
484 & ' up the design for exchanges with C',rc)
488 if (n_ts(gid).eq.1 .and. gid.eq.1) then
489 call ATM_ANNOUNCE('ATM_GETSST: to send ref. SST'//sgid,2)
490 call ASSEMBLE(SST_g,SST,kind_SST)
491 call CMP_gnr_SEND(SST_g,NGP,MPI_kind_SST)
492 call ATM_ANNOUNCE('ATM_GETSST: ref. SST sent'//sgid,2)
494 call ATM_ANNOUNCE('ATM_GETSST: to receive SST',3)
495 call CMP_gnr_RECV(SST_g,NGP,MPI_kind_SST)
496 call DISASSEMBLE(SST_g,SST_cc(gid)%a,kind_SST)
497 call ATM_ANNOUNCE('ATM_GETSST: SST received',3)
500 if (Coupler_id.lt.0) return ! <- standalone mode
504 if (abs(SLM(i,j)-SLM_OS_value).lt.0.01) then
505 ! i.e. if it is OS (open sea) AMGP
507 if (SST_cc(gid)%a(i,j).gt.unrealistically_low_SST) &
508 ! i.e. if there is a valid
509 ! result of interpolation from
511 & SST(i,j)=SST_cc(gid)%a(i,j)
519 !C***********************************************************************
521 SUBROUTINE ATM_DOFLUXES(TWBS,QWBS,RLWIN,RSWIN,RADOT,RSWOUT, &
522 !c &USTAR,U10,V10,PINT,PREC)
523 &TX,TY,PINT,PREC,U10,V10)
529 real(kind=kind_sfcflux),dimension(ims:ime,jms:jme):: &
530 &TWBS,QWBS,RLWIN,RSWIN,RADOT,RSWOUT,TX,TY,PINT,PREC,U10,V10
531 !c &TWBS,QWBS,RLWIN,RSWIN,RADOT,RSWOUT,USTAR,U10,V10,PINT,PREC
532 ! Act. arg. for PINT is a 3d array - so this only is OK if
533 ! Ps=Act.arg.(:,:.1) - actually, Ps=PINT(:,1,:)
535 real(kind=kind_sfcflux),dimension(ims:ime,jms:jme):: SWR,R
539 IF (.not.PHYS) RETURN
541 !c if (PREC(ims+3,jms+3).ne.0 .or. PREC(ims+5,jms+5).ne.0) then
542 !c print*,'ATM_DOFLUXES,gid,n_ts(gid),PREC(3,3),PREC(5,5): ',
543 !c & gid,n_ts(gid),PREC(ims+3,jms+3),PREC(ims+5,jms+5)
547 call ATM_ANNOUNCE('ATM_DOFLUXES entered',3)
551 if (zeroSF) sf(gid)%a=0.
553 SWR=-RSWIN+RSWOUT ! Check sign! here SWR is meant to be
555 !c sf(gid)%a(:,:,NSF-1)=sf(gid)%a(:,:,NSF-1)-TX
556 !c sf(gid)%a(:,:,NSF)=sf(gid)%a(:,:,NSF)-TY
557 !c ! <- signs for stress components are changed
558 !c ! so it is -stress
560 !c R=SWR+RADOT-RLWIN ! Check sign! here R (net radiation)
561 ! is meant to be positive upward
563 !oooooooooooooooooooooooooooooo
564 IF (Ocean_spec.eq.1) THEN
565 !oooooooooooooooooooooooooooooo
566 sf(gid)%a(:,:,1)=sf(gid)%a(:,:,1)-TWBS-QWBS+RADOT-RLWIN
567 ! -TWBS (-QWBS) is supposed to
568 ! be sensible (latent) heat flux,
570 sf(gid)%a(:,:,2)=sf(gid)%a(:,:,2)+SWR
571 sf(gid)%a(:,:,NSF-NSF_WM-1)=sf(gid)%a(:,:,NSF-NSF_WM-1)-TX
572 sf(gid)%a(:,:,NSF-NSF_WM)=sf(gid)%a(:,:,NSF-NSF_WM)-TY
573 ! <- signs for stress components are changed
574 !ooooooooooooooooooooooooooooooooooo
575 ELSE IF (Ocean_spec.eq.2) THEN
576 !ooooooooooooooooooooooooooooooooooo
577 sf(gid)%a(:,:,1)=sf(gid)%a(:,:,1)+PREC
578 sf(gid)%a(:,:,2)=sf(gid)%a(:,:,2)-TWBS
579 sf(gid)%a(:,:,3)=sf(gid)%a(:,:,3)-QWBS
580 sf(gid)%a(:,:,4)=sf(gid)%a(:,:,4)+PINT-101300.
581 sf(gid)%a(:,:,5)=sf(gid)%a(:,:,5)-SWR-RADOT+RLWIN
582 sf(gid)%a(:,:,6)=sf(gid)%a(:,:,6)-SWR
584 sf(gid)%a(:,:,NSF-NSF_WM-1)=sf(gid)%a(:,:,NSF-NSF_WM-1)+TX
585 sf(gid)%a(:,:,NSF-NSF_WM)=sf(gid)%a(:,:,NSF-NSF_WM)+TY
586 ! <- signs for stress components are NOT changed
588 sf(gid)%a(:,:,1)=sf(gid)%a(:,:,1)*dtainv
589 ! so this will be m/s; check what OM wants
596 !wwwwwwwwwwwwwwwwwwwwwwwww
598 !wwwwwwwwwwwwwwwwwwwwwwwww
599 sf(gid)%a(:,:,NSF-1)=sf(gid)%a(:,:,NSF-1)+U10
600 sf(gid)%a(:,:,NSF)=sf(gid)%a(:,:,NSF)+V10
606 sf(gid)%a=sf(gid)%a*dta2dtc
609 call ATM_ANNOUNCE('ATM_DOFLUXES to return',3)
614 !C***********************************************************************
616 SUBROUTINE ATM_SENDFLUXES
622 real(kind=kind_sfcflux) F(ids:idf,jds:jdf)
626 if (.not.PHYS) RETURN
628 if (.not.sendSF) then
630 & 'ATM_SENDLUXES entered with PHYS but not sendSF: returning'// &
635 call ATM_ANNOUNCE('In ATM_SENDLUXES'//sgid,3)
638 call ASSEMBLE(F,sf(gid)%a(:,:,n),kind_sfcflux)
639 call CMP_gnr_SEND(F,NGP,MPI_kind_sfcflux)
642 call ATM_ANNOUNCE('ATM_SENDFLUXES to return'//sgid,3)
647 !C***********************************************************************
649 SUBROUTINE ATM_ANNOUNCE(s,DbgLev)
651 USE ATM_cc, ONLY: nunit_announce,VerbLev,MPI_COMM_Atmos
660 if (DbgLev.le.VerbLev) then
661 if (s(1:5).eq.'(BP) ') then
662 call MPI_BARRIER(MPI_COMM_Atmos,ierr)
664 CALL CMP_ANNOUNCE(nunit_announce,'AM: '//s)