Browse Source

Merge branch 'INPUT_DIR' into REAL_4B

master
Knut 2 years ago
parent
commit
d25470dbb6
  1. 2
      compilers/compiler.IFC
  2. 3
      schemas/getm-2.5.defaults
  3. 1
      schemas/getm-2.5.schema
  4. 89
      src/3d/gotm.F90
  5. 45
      src/3d/m3d.F90
  6. 43
      src/Makefile
  7. 40
      src/Rules.make
  8. 36
      src/coupling/Makefile
  9. 6
      src/coupling/Rules.make_ESMF
  10. 4
      src/coupling/Rules.make_OASIS
  11. 94
      src/coupling/getm_esmf.F90
  12. 768
      src/coupling/getm_nuopc.F90
  13. 11
      src/getm/compilation_options.F90
  14. 9
      src/getm/main.F90
  15. 1
      src/waves/vortex_force.F90
  16. 1
      src/waves/vortex_force_3d.F90

2
compilers/compiler.IFC

@ -14,5 +14,5 @@ EXTRAS = -w95 -e95 -static
DEBUG_FLAGS = -g -C
PROF_FLAGS = -qp -p
PROD_FLAGS = -O3 -mp
EXTRA_LIBS += -lPEPCF90 -lpthread
SYS_LIBS += -lPEPCF90 -lpthread
endif

3
schemas/getm-2.5.defaults

@ -410,6 +410,9 @@
<smooth_bvf_ver>
False
</smooth_bvf_ver>
<c_lc>
0.0
</c_lc>
<nonhyd_method>
0
</nonhyd_method>

1
schemas/getm-2.5.schema

@ -620,6 +620,7 @@
</element>
<element name="smooth_bvf_hor" type="bool" label="smooth buoyancy frequency in the horizontal"/>
<element name="smooth_bvf_ver" type="bool" label="smooth buoyancy frequency in the vertical"/>
<element name="c_lc" type="float" label="Langmuir parameter (0.125 in Axell, 2002)" unit="1"/>
<element name="nonhyd_method" type="int" label="nonhydrostatic options">
<options>
<option value="-1" label="passive screening"/>

89
src/3d/gotm.F90

@ -60,6 +60,7 @@
use turbulence, only: tke1d => tke, eps1d => eps, L1d => L
use turbulence, only: num1d => num, nuh1d => nuh
use getm_timers, only: tic, toc, TIM_GOTM, TIM_GOTMTURB, TIM_GOTMH
use meteo, only: wind
IMPLICIT NONE
!
! !REVISION HISTORY:
@ -98,6 +99,8 @@
if (az(i,j) .ge. 1 ) then
xP = _ZERO_
#ifdef STRUCTURE_FRICTION
! BJB-TODO: Change all constants to double
do k=1,kmax
@ -108,6 +111,7 @@
+(velv3d(i ,j-1,k))**2*(sf(i ,j-1,k)+sf(i ,j ,k)))
end do
#endif
u_taus = sqrt(taus(i,j))
u_taub = sqrt(taub(i,j))
do k=0,kmax
@ -129,6 +133,10 @@
+max( z0(i,j) , zvb(i ,j-1) , zvb(i,j) ) )
if (z0s .gt. D(i,j)/10.) z0s= D(i,j)/10.
#ifndef NO_BAROCLINIC
call langmuir(kmax,wind(i,j),h,NN1d,xP)
#endif
#ifdef PARABOLIC_VISCOSITY
zz = _ZERO_
do k=1,kmax-1
@ -181,6 +189,87 @@
end subroutine gotm
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: langmuir - source term parameterisation for Langmuir turbulence
!
! !INTERFACE:
subroutine langmuir(nlev,wind,h,NN,xP)
!
! !DESCRIPTION:
!
! !USES:
use m3d, only: c_lc
IMPLICIT NONE
!
! !INPUT PARAMETERS:
integer , intent(in) :: nlev
REALTYPE, intent(in) :: wind
REALTYPE, intent(in) :: h(0:nlev)
REALTYPE, intent(in) :: NN(0:nlev)
!
! !INPUT/OUTPUT PARAMETERS:
REALTYPE, intent(inout) :: xP(0:nlev)
!
! !REVISION HISTORY:
! Original author(s): Knut Klingbeil
!
! !LOCAL VARIABLES:
integer, parameter :: rk = kind(_ONE_)
REALTYPE, parameter :: grav = 9.81_rk
REALTYPE, parameter :: pi = 3.14159265358979323846_rk
integer :: i
REALTYPE :: zi(0:nlev),L_lc,us,epot,H_lc,ekin,w_lc,H_lc_inv
! REALTYPE, parameter :: c_lc=0.125_rk
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'langmuir() # ',Ncall
#endif
! Axell (2002)
if (c_lc .le. _ZERO_) return
! calculate the depth z from the cell heights (negative, downward from the surface)
zi(nlev) = _ZERO_
do i=nlev-1,0,-1
zi(i) = zi(i+1) - h(i+1)
end do
epot = _ZERO_
H_lc = _ZERO_
us = 0.016_rk * wind ! Stokes drift velocity at the surface (m/s)
ekin = 0.5_rk * us*us ! kinetic energy of water parcel at surface (m2/s2)
! see how deep a surface water parcel could travel using its potential energy
do i=nlev-1,1,-1
if ( epot .gt. ekin ) then
exit
end if
epot = epot - NN(i)*zi(i)*h(i+1) !add (remember that z<0) potential energy required to pass layer i+1 (m2/s2)
H_lc = H_lc + h(i+1)
end do
H_lc_inv = _ONE_ / H_lc
do i=1,nlev-1
if ( -H_lc .lt. zi(i) ) then
w_lc = abs(c_lc * us * sin( -pi * zi(i) * H_lc_inv )) ! velocity scale (m/s)
xP(i) = xP(i) + w_lc*w_lc*w_lc * H_lc_inv ! TKE production (m2/s3)
end if
end do
#ifdef DEBUG
write(debug,*) 'Leaving langmuir()'
write(debug,*)
#endif
return
end subroutine langmuir
!EOC
!-----------------------------------------------------------------------
! Copyright (C) 2001 - Hans Burchard and Karsten Bolding !
!-----------------------------------------------------------------------

45
src/3d/m3d.F90

@ -72,6 +72,7 @@
integer :: turb_adv_ver=0
logical :: smooth_bvf_hor=.false.
logical :: smooth_bvf_ver=.false.
REALTYPE :: c_lc=_ZERO_
logical :: calc_temp=.false.
logical :: calc_salt=.false.
logical :: update_temp=.false.
@ -140,6 +141,7 @@
turb_adv_split,turb_adv_hor,turb_adv_ver, &
calc_temp,calc_salt, &
use_gotm,avmback,avhback,smooth_bvf_hor,smooth_bvf_ver, &
c_lc, &
nonhyd_method,ip_method,ip_ramp, &
vel_check,min_vel,max_vel
!EOP
@ -257,27 +259,40 @@
num=1.d-15
nuh=1.d-15
#ifdef SMOOTH_BVF_HORI
if (.not. smooth_bvf_hor) then
LEVEL2 "reset smooth_bvf_hor=T because of obsolete"
LEVEL2 "SMOOTH_BVF_HORI macro. Note that this"
LEVEL2 "behaviour will be removed in the future."
smooth_bvf_hor = .true.
#ifndef NO_BAROCLINIC
if (c_lc .gt. _ZERO_) then
LEVEL2 "Langmuir parameter c_lc = ",real(c_lc)
else
LEVEL2 "no Langmuir turbulence parameterization"
end if
#endif
LEVEL2 "smooth_bvf_hor = ",smooth_bvf_hor
#ifdef _SMOOTH_BVF_VERT_
if (.not. smooth_bvf_ver) then
LEVEL2 "reset smooth_bvf_ver=T because of obsolete"
LEVEL2 "_SMOOTH_BVF_VERT_ macro. Note that this"
LEVEL2 "behaviour will be removed in the future."
smooth_bvf_ver = .true.
end if
end if
#ifndef NO_BAROCLINIC
#ifdef SMOOTH_BVF_HORI
if (.not. smooth_bvf_hor) then
LEVEL2 "reset smooth_bvf_hor=T because of obsolete"
LEVEL2 "SMOOTH_BVF_HORI macro. Note that this"
LEVEL2 "behaviour will be removed in the future."
smooth_bvf_hor = .true.
end if
#endif
LEVEL2 "smooth_bvf_ver = ",smooth_bvf_ver
LEVEL2 "smooth_bvf_hor = ",smooth_bvf_hor
#ifdef _SMOOTH_BVF_VERT_
if (.not. smooth_bvf_ver) then
LEVEL2 "reset smooth_bvf_ver=T because of obsolete"
LEVEL2 "_SMOOTH_BVF_VERT_ macro. Note that this"
LEVEL2 "behaviour will be removed in the future."
smooth_bvf_ver = .true.
end if
#endif
LEVEL2 "smooth_bvf_ver = ",smooth_bvf_ver
#endif
call init_vertical_coordinates()

43
src/Makefile

@ -25,38 +25,49 @@ $(GETMDIR)/src/input \
$(GETMDIR)/src/getm \
$(GETMDIR)/src/coupling
ifeq ($(GETM_ESMF_EXEC),true)
ifneq ($(or $(findstring true,$(GETM_NUOPC_EXEC)), $(findstring true,$(GETM_ESMF_EXEC)) ),)
CORE_LIBS = \
-lgetm_esmf${buildtype}
$(LIBDIR)/libgetm_esmf${buildtype}.a
else
ifeq ($(GETM_OASIS),true)
CORE_LIBS = \
-lgetm_oasis${buildtype}
$(LIBDIR)/libgetm_oasis${buildtype}.a
endif
endif
CORE_LIBS += \
-lgetm${buildtype} \
-loutput${buildtype} \
-lmeteo${buildtype}
$(LIBDIR)/libgetm${buildtype}.a \
$(LIBDIR)/liboutput${buildtype}.a \
$(LIBDIR)/libmeteo${buildtype}.a
ifneq ($(GETM_NO_3D),true)
CORE_LIBS += \
-l3d${buildtype}
$(LIBDIR)/lib3d${buildtype}.a
endif
CORE_LIBS += \
-l2d${buildtype} \
-lwaves${buildtype} \
-lles${buildtype} \
-lpool${buildtype} \
-ldomain${buildtype} \
-linput${buildtype} \
-lncdfio${buildtype} \
-lfutils${buildtype}
$(LIBDIR)/lib2d${buildtype}.a \
$(LIBDIR)/libwaves${buildtype}.a \
$(LIBDIR)/libles${buildtype}.a \
$(LIBDIR)/libpool${buildtype}.a \
$(LIBDIR)/libdomain${buildtype}.a \
$(LIBDIR)/libinput${buildtype}.a \
$(LIBDIR)/libncdfio${buildtype}.a \
$(LIBDIR)/libfutils${buildtype}.a
# -lhalo${buildtype} \
LIBS = $(CORE_LIBS) $(EXTRA_LIBS)
all: GIT FORTRAN ../VERSION getm$(buildtype)_$(FORTRAN_COMPILER) install confdir
ifeq ($(GETM_ESMF),true)
$(AR) TruUs $(LIBDIR)/libgetm_all.a $(LIBDIR)/libgetm_esmf${buildtype}.a $(LIBS)
ifeq ($(GETM_NUOPC),true)
$(MAKE) -C coupling nuopc
endif
endif
ifeq ($(GETM_NUOPC),true)
nuopc nuopcinstall: all
$(MAKE) -C coupling $@ DESTDIR=$(DESTDIR)
endif
../VERSION: ../Makefile Makefile Rules.make
$(MAKE) -C ..
@ -94,7 +105,7 @@ GIT FORTRAN:
$(MAKE) -C .. $@
getm$(buildtype)_$(FORTRAN_COMPILER): makedirs subdirs
$(FC) -o $@ getm/main.F90 $(LINKFLAGS) $(LIBS)
$(FC) -o $@ getm/main.F90 $(F90FLAGS) $(EXTRA_FFLAGS) $(LINKFLAGS) $(LIBS) $(SYS_LIBS)
install: getm$(buildtype)_$(FORTRAN_COMPILER)
mkdir -p $(BINDIR)

40
src/Rules.make

@ -26,17 +26,29 @@ $(warning the directory GOTMDIR=$(GOTMDIR) is not a valid GOTM directory)
endif
# ESMF specific settings
ifeq ($(GETM_NUOPC_EXEC),true)
export GETM_OASIS=false
export GETM_NUOPC=true
export GETM_ESMF_EXEC=false
DEFINES += -D_GETM_NUOPC_EXEC_
endif
ifeq ($(GETM_ESMF_EXEC),true)
export GETM_OASIS=false
export GETM_ESMF=true
DEFINES += -D_GETM_ESMF_EXEC_
endif
ifeq ($(GETM_NUOPC),true)
export GETM_ESMF=true
DEFINES += -D_GETM_NUOPC_
endif
ifeq ($(GETM_ESMF),true)
DEFINES += -D_GETM_ESMF_
include $(GETMDIR)/src/coupling/Rules.make_ESMF
endif
# OASIS specific settings
ifeq ($(GETM_OASIS),true)
DEFINES += -D_GETM_OASIS_
include $(GETMDIR)/src/coupling/Rules.make_OASIS
endif
@ -134,15 +146,15 @@ ifdef GOTM_PREFIX
GOTMINCDIR = $(GOTM_PREFIX)/include
GOTMLIBDIR = $(GOTM_PREFIX)/lib
LINKDIRS += -L$(GOTMLIBDIR)
EXTRA_LIBS += -loutput_manager
EXTRA_LIBS += $(GOTMLIBDIR)/liboutput_manager.a
ifeq ($(FABM),true)
EXTRA_LIBS += -lgotm_fabm
EXTRA_LIBS += $(GOTMLIBDIR)/libgotm_fabm.a
endif
ifneq ($(wildcard $(GOTMLIBDIR)/libfield_manager.*), )
DEFINES += -D_NEW_GOTM_
EXTRA_LIBS += -lfield_manager -lyaml
EXTRA_LIBS += $(GOTMLIBDIR)/libfield_manager.a $(GOTMLIBDIR)/libyaml.a
endif
EXTRA_LIBS += -lturbulence $(GOTMLIBDIR)/libutil.a
EXTRA_LIBS += $(GOTMLIBDIR)/libturbulence.a $(GOTMLIBDIR)/libutil.a
INCDIRS += -I$(GOTMINCDIR)
else
@ -151,9 +163,9 @@ GOTMINCDIR = $(GOTMDIR)/modules/$(FORTRAN_COMPILER)
GOTMLIBDIR = $(GOTMDIR)/lib/$(FORTRAN_COMPILER)
LINKDIRS += -L$(GOTMLIBDIR)
ifeq ($(FABM),true)
EXTRA_LIBS += -lgotm_fabm$(buildtype)
EXTRA_LIBS += $(GOTMLIBDIR)/libgotm_fabm$(buildtype).a
endif
EXTRA_LIBS += -lturbulence$(buildtype) $(GOTMLIBDIR)/libutil$(buildtype).a
EXTRA_LIBS += $(GOTMLIBDIR)/libturbulence$(buildtype).a $(GOTMLIBDIR)/libutil$(buildtype).a
INCDIRS += -I$(GOTMINCDIR)
endif
@ -170,7 +182,7 @@ export GETM_BIO=false
# first check for FABM library installed and used by GOTM
ifneq ($(wildcard $(GOTMLIBDIR)/libfabm.*), )
FABMINCDIR = $(GOTMINCDIR)
EXTRA_LIBS += -lfabm
EXTRA_LIBS += $(GOTMLIBDIR)/libfabm.a
else
ifdef FABM_PREFIX
@ -181,7 +193,7 @@ else
FABMINCDIR = $(FABM_PREFIX)/include
INCDIRS += -I$(FABMINCDIR)
LINKDIRS += -L$(FABM_PREFIX)/lib
EXTRA_LIBS += -lfabm
EXTRA_LIBS += $(FABM_PREFIX)/lib/libfabm.a
endif
else
@ -195,7 +207,7 @@ $(warning the directory FABMDIR=$(FABMDIR) is not a valid FABM directory)
else
INCDIRS += -I$(FABMDIR)/include -I$(FABMDIR)/modules/gotm/$(FORTRAN_COMPILER) -I$(FABMDIR)/src/drivers/gotm
LINKDIRS += -L$(FABMDIR)/lib/gotm/$(FORTRAN_COMPILER)
EXTRA_LIBS += -lfabm$(buildtype)
EXTRA_LIBS += $(FABMDIR)/lib/gotm/$(FORTRAN_COMPILER)/libfabm$(buildtype).a
endif
endif
@ -211,7 +223,7 @@ endif
# Old GOTM-BIO component - deprecated
ifeq ($(GETM_BIO),true)
DEFINES += -DGETM_BIO
EXTRA_LIBS += -lbio$(buildtype)
EXTRA_LIBS += $(GOTMLIBDIR)/libbio$(buildtype).a
endif
# Where does the NetCDF include file and library reside.
@ -244,7 +256,7 @@ endif
endif
EXTRA_LIBS += $(NETCDFLIB)
SYS_LIBS += $(NETCDFLIB)
# NetCDF/HDF configuration done
# Compile for parallel execution
@ -275,7 +287,7 @@ endif
# SGI - MPI - works for Peter Holtermann on ALTIX 3700.
ifeq ($(MPI),SGIMPI)
EXTRA_LIBS += -lmpi
MPILIB = -lmpi
endif
# obsolete - use either OPenMPI or MPICH2
@ -300,7 +312,7 @@ LINKFLAGS += -L$(MPILIBDIR)
LINKDIRS += -L$(MPILIBDIR)
endif
endif
EXTRA_LIBS += $(MPILIB)
SYS_LIBS += $(MPILIB)
endif
endif
@ -349,7 +361,7 @@ PROTEX = protex -b -n -s
CPPFLAGS = $(DEFINES) $(INCDIRS)
FFLAGS = $(DEFINES) $(FLAGS) $(MODULES) $(INCDIRS) $(EXTRAS)
F90FLAGS = $(FFLAGS)
LINKFLAGS = $(LDFLAGS) $(FFLAGS) $(LINKDIRS)
LINKFLAGS = $(LDFLAGS) $(LINKDIRS)
#
# Special variables which should not be exported

36
src/coupling/Makefile

@ -10,7 +10,7 @@ LIB = $(LIB_ESMF) $(LIB_OASIS)
SRC =
ifeq ($(GETM_ESMF),true)
SRC += getm_esmf.F90
SRC += getm_esmf.F90 getm_nuopc.F90
endif
ifeq ($(GETM_OASIS),true)
SRC += getm_oasis.F90
@ -20,6 +20,9 @@ MOD =
ifeq ($(GETM_ESMF),true)
MOD += ${LIB_ESMF}(getm_esmf.o)
endif
ifeq ($(GETM_NUOPC),true)
MOD += ${LIB_ESMF}(getm_nuopc.o)
endif
ifeq ($(GETM_OASIS),true)
MOD += ${LIB_OASIS}(getm_oasis.o)
endif
@ -32,12 +35,41 @@ modules: $(MOD)
objects: $(OBJ)
ifeq ($(GETM_NUOPC),true)
# this target builds your model and your NUOPC cap
nuopc: getm_nuopc.o $(MODDIR)/getm_nuopc.mk
mv $(GETMDIR)/src/coupling/getm_nuopc.o $(LIBDIR)/
# this target installs your NUOPC-compliant model to DESTDIR
nuopcinstall:
.PRECIOUS: getm_nuopc.o
.PHONY: $(MODDIR)/getm_nuopc.mk
$(MODDIR)/getm_nuopc.mk:
@echo "# ESMF self-describing build dependency makefile fragment" > $@
@echo >> $@
@echo "# ESMF_DEP_FRONT: name of module file, header file or shared object (without extension)" >> $@
@echo "# ESMF_DEP_INCPATH: absolute path to module or header file" >> $@
@echo "# ESMF_DEP_CMPL_OBJS: object files that need to be considered as compile dependencies (with absolute path, space-separated)" >> $@
@echo "# ESMF_DEP_LINK_OBJS: object files that need to be considered as link dependencies (with absolute path, space-separated)" >> $@
@echo "# ESMF_DEP_SHRD_PATH: list of absolute paths to find shared libraries during link-time (and during run-time unless overridden by LD_LIBRARY_PATH)" >> $@
@echo "# ESMF_DEP_SHRD_LIBS: list of shared libraries that need to be specified during link-time, and must be available during run-time (with absolute path)" >> $@
@echo >> $@
@echo "ESMF_DEP_FRONT = getm_nuopc" >> $@
@echo "ESMF_DEP_INCPATH = $(MODDIR)" >> $@
@echo "ESMF_DEP_CMPL_OBJS = $(LIBDIR)/getm_nuopc.o" >> $@
@echo "ESMF_DEP_LINK_OBJS = $(LIBDIR)/libgetm_all.a" >> $@
@echo "ESMF_DEP_SHRD_PATH = " >> $@
@echo "ESMF_DEP_SHRD_LIBS = " >> $@
endif
doc: $(SRC)
$(PROTEX) $(SRC) > $(DOCDIR)/coupling.tex
touch doc
clean:
$(RM) ${LIB} $(MODDIR)/{getm_esmf,getm_oasis}.{m.mod}
$(RM) ${LIB} $(MODDIR)/{getm_esmf,getm_nuopc,getm_oasis}.{m.mod}
realclean: clean
$(RM) *.o doc

6
src/coupling/Rules.make_ESMF

@ -2,7 +2,6 @@ ifndef ESMFMKFILE
$(error ESMFMKFILE must be defined for GETM_ESMF=true)
endif
DEFINES += -D_GETM_ESMF_
include $(ESMFMKFILE)
ESMF_COMM = $(strip $(shell grep "\# ESMF_COMM:" $(ESMFMKFILE) | cut -d':' -f2-))
@ -69,8 +68,9 @@ export FORTRAN_COMPILER:=$(ESMF_FORTRAN_COMPILER)
endif
INCDIRS = $(ESMF_F90COMPILEPATHS)
ifeq ($(GETM_ESMF_EXEC),true)
#ifeq ($(GETM_ESMF_EXEC),true)
ifneq ($(or $(findstring true,$(GETM_NUOPC_EXEC)), $(findstring true,$(GETM_ESMF_EXEC)) ),)
LINKDIRS = $(ESMF_F90LINKPATHS) $(ESMF_F90LINKRPATHS)
EXTRA_LIBS = $(ESMF_F90ESMFLINKLIBS)
SYS_LIBS = $(ESMF_F90ESMFLINKLIBS)
# What about ESMF_F90LINKOPTS?
endif

4
src/coupling/Rules.make_OASIS

@ -1,9 +1,7 @@
ARCHDIR = $(OASIS_ARCHDIR)
CHAN = $(OASIS_CHAN)
DEFINES += -D_GETM_OASIS_
INCDIRS = -I$(ARCHDIR)/build/lib/psmile.$(CHAN)
LINKDIRS = -L$(ARCHDIR)/lib
EXTRA_LIBS = -lpsmile.$(CHAN) -lmct -lmpeu -lscrip
SYS_LIBS = -lpsmile.$(CHAN) -lmct -lmpeu -lscrip

94
src/coupling/getm_esmf.F90

@ -1,5 +1,4 @@
#include "cppdefs.h"
#define _GETM_NUOPC_
!-----------------------------------------------------------------------
!BOP
!
@ -23,6 +22,8 @@
public SetServices ! (NUOPC requires this name), must be public
!public SetVM ! optional
public do_getm_esmf
public InitializeP1, InitializeP2, RunP1, FinalizeP1
public createGetmClock
!
! !PRIVATE DATA MEMBERS:
type type_getmInternalStateStruct
@ -481,7 +482,7 @@
InitializePhaseMap(1) = "IPDv00p1=1"
InitializePhaseMap(2) = "IPDv00p2=2"
#ifdef _GETM_NUOPC_
#if 1
call NUOPC_CompAttributeAdd(getmComp,(/"InitializePhaseMap"/),rc=rc)
abort = ESMF_LogFoundError(rc,line=__LINE__,file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
@ -1007,9 +1008,11 @@
! Add whatever code here needed (deallocation,close files,flush results)
call toc(TIM_ESMF)
call clean_up(dryrun,runtype,MaxN)
#if ! ( defined(_GETM_NUOPC_EXEC_) || defined(_GETM_ESMF_EXEC_) )
#ifndef NO_TIMERS
STDERR LINE
call write_getm_timers
#endif
#endif
call tic(TIM_ESMF)
@ -2976,6 +2979,89 @@ if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: createGetmClock - creates and sets clock from getm.inp
!
! !INTERFACE:
function createGetmClock() result(clock)
!
! !DESCRIPTION:
! So far missing extension to ESMF_TimeSet().
!
! !USES:
IMPLICIT NONE
!
! !INPUT PARAMETERS:
!
! !OUTPUT PARAMETERS:
type(ESMF_Clock) :: clock
!
! !REVISION HISTORY:
! Original Author(s): Knut Klingbeil
!
! !LOCAL VARIABLES
integer :: yy,mm,dd,h,m,s,rc
logical :: abort
#if (defined GETM_PARALLEL && defined INPUT_DIR)
character(len=PATH_MAX) :: input_dir=INPUT_DIR
#else
character(len=PATH_MAX) :: input_dir='./'
#endif
REALTYPE :: timestep
integer :: timefmt=1
integer :: nlast
character(len=19) :: start='2000-01-01 00:00:00',stop
namelist /time/ timestep,timefmt,nlast,start,stop
type(ESMF_Time) :: startTime, stopTime
type(ESMF_TimeInterval) :: timeInterval
!
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'createGetmClock() # ',Ncall
#endif
open(NAMLST, status='unknown', file=trim(input_dir) // "/getm.inp")
read(NAMLST, nml=time)
close(NAMLST)
start(11:11) = 'T'
stop(11:11) = 'T'
call ESMF_TimeIntervalSet(timeInterval, s_r8=real(timestep, kind=ESMF_KIND_R8))
select case (timefmt)
case (1)
start='2000-01-01T00:00:00'
call TimeStringISOFrac2ESMFtime(start, startTime)
stopTime = startTime + nlast*timeInterval
case (2)
call TimeStringISOFrac2ESMFtime(start, startTime)
call TimeStringISOFrac2ESMFtime(stop, stopTime)
case (3)
call TimeStringISOFrac2ESMFtime(start, startTime)
stopTime = startTime + nlast*timeInterval
case default
call ESMF_LogWrite('createGetmClock: timefmt not supported', &
ESMF_LOGMSG_ERROR,line=__LINE__,file=FILENAME)
call ESMF_Finalize(endflag=ESMF_END_ABORT)
end select
timeInterval = stopTime - startTime
clock = ESMF_ClockCreate(timeInterval, startTime, stopTime=stopTime)
#ifdef DEBUG
write(debug,*) 'Leaving createGetmClock()'
write(debug,*)
#endif
return
end function createGetmClock
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: createCoordArrays1D -
!
! !INTERFACE:
@ -3457,7 +3543,7 @@ if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
return
end if
#ifdef _GETM_NUOPC_
#if 1
if (NUOPC_FieldDictionaryHasEntry(trim(name))) then
call NUOPC_Advertise(state, trim(name), Units=units, rc=rc)
abort = ESMF_LogFoundError(rc,line=__LINE__,file=FILENAME)
@ -3581,7 +3667,7 @@ if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
end if
#ifndef _GETM_NUOPC_
#if 0
call ESMF_StateAdd(state,(/field/),rc=rc)
abort = ESMF_LogFoundError(rc,line=__LINE__,file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)

768
src/coupling/getm_nuopc.F90

@ -0,0 +1,768 @@
#include "cppdefs.h"
!-----------------------------------------------------------------------
!BOP
!
! !MODULE: getm_nuopc - routines to integrate GETM into NUOPC
!
! !INTERFACE:
module getm_nuopc
!
! !DESCRIPTION:
!
! !USES:
use esmf
use NUOPC
IMPLICIT NONE
private
!
! !PUBLIC DATA MEMBERS:
public SetServices ! (NUOPC requires this name), must be public
public do_getm_nuopc
! Note (KK): __FILE__ includes full path, thus too long for log
character(len=*),parameter :: FILENAME="getm_nuopc.F90"
!EOP
!-----------------------------------------------------------------------
contains
!-----------------------------------------------------------------------
subroutine SetServices(model, rc)
IMPLICIT NONE
type(ESMF_GridComp) :: model
integer, intent(out) :: rc
call model_SetServices(model, rc)
end subroutine SetServices
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: do_getm_nuopc
!
! !INTERFACE:
subroutine do_getm_nuopc()
!
! !USES:
use getm_esmf, only: createGetmClock
use getm_timers, only: tic, toc, TIM_ESMF
IMPLICIT NONE
!
! !LOCAL VARIABLES:
type(ESMF_Clock) :: mainClock
type(ESMF_GridComp) :: getmDriver
integer :: rc
logical :: abort
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'do_getm_nuopc() # ',Ncall
#endif
call tic(TIM_ESMF)
call ESMF_Initialize(defaultLogFileName='getmNUOPC_LogFile', &
defaultCalKind=ESMF_CALKIND_GREGORIAN)
call ESMF_LogSet(flush=.true., &
logmsgList=(/ESMF_LOGMSG_WARNING,ESMF_LOGMSG_ERROR/))
mainClock = createGetmClock()
getmDriver = ESMF_GridCompCreate(name="getmDriver", clock=mainClock, rc=rc)
abort = ESMF_LogFoundError(rc,line=__LINE__,file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call ESMF_GridCompSetServices(getmDriver, driver_SetServices)
call ESMF_GridCompInitialize(getmDriver)
call ESMF_GridCompRun(getmDriver)
call ESMF_GridCompFinalize(getmDriver)
call ESMF_GridCompDestroy(getmDriver)
call ESMF_Finalize()
call toc(TIM_ESMF)
#ifdef DEBUG
write(debug,*) 'Leaving do_getm_nuopc()'
write(debug,*)
#endif
return
end subroutine do_getm_nuopc
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: driver_SetServices
!
! !INTERFACE:
subroutine driver_SetServices(driver, rc)
!
! !DESCRIPTION:
! Derive driver from generic NUOPC driver and attach specializing
! routines.
! required: SetModelServices
! optional: SetRunSequence
! ModifyInitializePhaseMap
! ModifyCplLists
! SetRunClock
! ExecuteRunSequence
! Finalize
!
! !USES:
use NUOPC_Driver, only: driverSS => SetServices, label_SetModelServices
IMPLICIT NONE
!
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_GridComp) :: driver
!
! !OUTPUT PARAMETERS:
integer,intent(out) :: rc
!
! !LOCAL VARIABLES:
logical :: abort
type(ESMF_Clock) :: clock
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'driver_SetServices() # ',Ncall
#endif
call NUOPC_CompDerive(driver, driverSS, rc=rc)
abort = ESMF_LogFoundError(rc,line=__LINE__,file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call NUOPC_CompAttributeSet(driver, name="Verbosity", value="max", rc=rc)
! required specialization
call NUOPC_CompSpecialize(driver, specLabel = label_SetModelServices, &
specRoutine = driver_SetModelServices, rc=rc)
abort = ESMF_LogFoundError(rc,line=__LINE__,file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
! Usually the driverClock must be set here...
!call ESMF_GridCompSet(driver, clock=clock, rc=rc)
!abort = ESMF_LogFoundError(rc,line=__LINE__,file=FILENAME)
!if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
#ifdef DEBUG
write(debug,*) 'Leaving driver_SetServices()'
write(debug,*)
#endif
return
end subroutine driver_SetServices
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: driver_SetModelServices
!
! !INTERFACE:
subroutine driver_SetModelServices(driver, rc)
!
! !DESCRIPTION:
! Add child components to driver.
! Optionally replace default driverClock (copy of clock provided to
! GridCompCreate(driver), if valid).
!
! !USES:
use NUOPC_Driver, only: NUOPC_DriverAddComp
IMPLICIT NONE
!
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_GridComp) :: driver
!
! !OUTPUT PARAMETERS:
integer,intent(out) :: rc
!
! !LOCAL VARIABLES:
type(ESMF_GridComp) :: getmModel
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'driver_SetModelServices() # ',Ncall
#endif
call NUOPC_DriverAddComp(driver, "getmModel", model_SetServices, comp=getmModel, rc=rc)
call NUOPC_CompAttributeSet(getmModel, name="Verbosity", value="max", rc=rc)
#ifdef DEBUG
write(debug,*) 'Leaving driver_SetModelServices()'
write(debug,*)
#endif
return
end subroutine driver_SetModelServices
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: model_SetServices - register GriddedComponent GETM
!
! !INTERFACE:
subroutine model_SetServices(model, rc)
!
! !DESCRIPTION:
! Register user-code subroutines.
! For the NUOPC Layer this routine must be named SetServices().
! The toplevel component can inquire rc via optional keyword argument
! userRc to ESMF_GridCompSetServices().
!
! !USES:
use NUOPC_Model, only: modelSS=>SetServices, label_Advance
use NUOPC_Model, only: label_AdvanceClock, label_Finalize
use getm_esmf, only: InitializeP1, InitializeP2
use getm_timers, only: tic, toc, TIM_ESMF
IMPLICIT NONE
!
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_GridComp) :: model
!
! !OUTPUT PARAMETERS:
integer, intent(out) :: rc
!
! !REVISION HISTORY:
!
! !LOCAL VARIABLES
logical :: abort
character(len=ESMF_MAXSTR) :: name
!
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'model_SetServices() # ',Ncall
#endif
call tic(TIM_ESMF)
call NUOPC_CompGet(model, name=name, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call ESMF_LogWrite(trim(name)//"::model_SetServices...", ESMF_LOGMSG_TRACE)
call NUOPC_CompDerive(model , modelSS, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
! TODO: calling NUOPC_CompSetEntryPoint() is deprecated.
! change to Specialize(label_Advertise)!
call NUOPC_CompSetEntryPoint(model, ESMF_METHOD_INITIALIZE, &
phaseLabelList = (/"IPDv00p1"/), &
userRoutine = InitializeP1, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
! TODO: calling NUOPC_CompSetEntryPoint() is deprecated.
! change to Specialize(label_RealizeAccepted)!
call NUOPC_CompSetEntryPoint(model, ESMF_METHOD_INITIALIZE, &
phaseLabelList = (/ "IPDv00p2" /), &
userRoutine = InitializeP2, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
! required specialization
call NUOPC_CompSpecialize(model, specLabel = label_Advance, &
specRoutine = Advance, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
! clock is already advanced in getm_esmf.F90::RunP1()
call NUOPC_CompSpecialize(model, specLabel = label_AdvanceClock, &
specRoutine = NUOPC_NoOp, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call NUOPC_CompSpecialize(model, specLabel = label_Finalize, &
specRoutine = Finalize, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call toc(TIM_ESMF)
#ifdef DEBUG
write(debug,*) 'Leaving model_SetServices()'
write(debug,*)
#endif
return
end subroutine model_SetServices
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: Advance - advance the model forward in time
!
! !INTERFACE:
subroutine Advance(model, rc)
!
! !DESCRIPTION:
! A specialization method that advances the model (including clock!)
! forward in time by one timestep of the internal clock.
! This method will be called iteratively by the default run phase
! until reaching the stop time on the internal clock.
! If not overridden, the default method SetRunClock() will check that
! the internal clock and incoming clock agree on the current time and
! that the time step of the incoming clock is a multiple of the
! internal clock time step.
! Under these conditions the internal stop time is set to one time step
! interval of the incoming clock.
! Otherwise exit with error, flagging an incompatibility.
!
! !USES:
use NUOPC_Model, only: NUOPC_ModelGet
use getm_esmf, only: RunP1
use getm_timers, only: tic, toc, TIM_ESMF
implicit none
!
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_GridComp) :: model
!
! !OUTPUT PARAMETERS:
integer, intent(out) :: rc
!
! !REVISION HISTORY:
!
! !LOCAL VARIABLES
type(ESMF_State) :: importState, exportState
type(ESMF_Clock) :: modelClock, clock
type(ESMF_Time) :: stopTime, currTime
type(ESMF_TimeInterval) :: timeStep
logical :: abort
character(len=ESMF_MAXSTR) :: name
!
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'Advance() # ',Ncall
#endif
call tic(TIM_ESMF)
call NUOPC_CompGet(model, name=name, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call ESMF_LogWrite(trim(name)//"::Advance...",ESMF_LOGMSG_TRACE)
call NUOPC_ModelGet(model, modelClock = modelClock, &
importState = importState, &
exportState = exportState, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
clock = ESMF_ClockCreate(modelClock, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
! getm_esmf.F90::RunP1() advances until nextTime of incoming clock.
! Set up incoming clock to cover whole driverTimeStep instead of only
! one modelTimeStep such that driver needs to call this Advance() only
! once and data in states need to be im/exported only once as well.
call ESMF_ClockGet(clock, stopTime=stopTime, currTime=currTime, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
timeStep = stopTime - currTime
call ESMF_ClockSet(clock, timeStep=timeStep, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call RunP1(model, clock = clock, importState = importState, &
exportState = exportState, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call ESMF_ClockDestroy(clock, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call toc(TIM_ESMF)
#ifdef DEBUG
write(debug,*) 'Leaving Advance()'
write(debug,*)
#endif
return
end subroutine Advance
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: Finalize - finalize the model
!
! !INTERFACE:
subroutine Finalize(model, rc)
!
! !DESCRIPTION:
! An optional specialization method.
!
! !USES:
use NUOPC_Model, only: NUOPC_ModelGet
use getm_esmf, only: FinalizeP1
use getm_timers, only: tic, toc, TIM_ESMF
implicit none
!
! !INPUT/OUTPUT PARAMETERS:
type(ESMF_GridComp) :: model
!
! !OUTPUT PARAMETERS:
integer, intent(out) :: rc
!
! !REVISION HISTORY:
!
! !LOCAL VARIABLES
type(ESMF_State) :: importState, exportState
type(ESMF_Clock) :: modelClock
logical :: abort
character(len=ESMF_MAXSTR) :: name
!
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'Finalize() # ',Ncall
#endif
call tic(TIM_ESMF)
call NUOPC_CompGet(model, name=name, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call ESMF_LogWrite(trim(name)//"::Finalize...",ESMF_LOGMSG_TRACE)
call NUOPC_ModelGet(model, modelClock = modelClock, &
importState = importState, &
exportState = exportState, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call FinalizeP1(model, clock = modelClock, importState = importState, &
exportState = exportState, rc=rc)
abort = ESMF_LogFoundError(rc, line=__LINE__, file=FILENAME)
if (abort) call ESMF_Finalize(endflag=ESMF_END_ABORT)
call toc(TIM_ESMF)
#ifdef DEBUG
write(debug,*) 'Leaving Finalize()'
write(debug,*)
#endif
return
end subroutine Finalize
!EOC
!-----------------------------------------------------------------------
#if 0
subroutine InitializeP1(gridComp,importState,exportState,clock,rc)
call getmCmp_init_variables()
! advertise export fields
if (associated(sst)) then
call advertise_field("sea_surface_temperature",sst,exportState)
end if
call getmCmp_update_exportState()
end subroutine InitializeP1
subroutine InitializeP2(gridComp,importState,exportState,clock,rc)
if (associated(sst)) then
call realize_field("sea_surface_temperature",exportState)!,sst)
end if
end subroutine InitializeP2
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: getmCmp_init_variables
!
! !INTERFACE:
#undef ESMF_METHOD
#define ESMF_METHOD "getmCmp_init_variables"
subroutine getmCmp_init_variables()
!
! !DESCRIPTION:
!
! !USES:
use domain, only: imin, jmin, imax, jmax
#ifndef NO_3D
#ifndef NO_BAROCLINIC
use m3d , only: calc_temp
#endif
#endif
IMPLICIT NONE
!
! !INPUT/OUTPUT PARAMETERS:
!
! !REVISION HISTORY:
! Original Author(s): Knut Klingbeil
!
! !LOCAL VARIABLES
REALTYPE :: getmreal
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'getmCmp_init_variables() # ',Ncall
#endif
noKindMatch = ( kind(getmreal) .ne. ESMF_KIND_R8 )
#ifndef NO_3D
#ifndef NO_BAROCLINIC
if (calc_temp) then
allocate(sst(I2DFIELD))
end if
#endif
#endif
#ifdef DEBUG
write(debug,*) 'getmCmp_init_variables()'
write(debug,*)
#endif
return
end subroutine getmCmp_init_variables
!EOC
!-----------------------------------------------------------------------
!BOP
!
! !ROUTINE: getmCmp_update_exportState -
!
! !INTERFACE:
#undef ESMF_METHOD
#define ESMF_METHOD "getmCmp_update_exportState"
subroutine getmCmp_update_exportState()
!
! !DESCRIPTION:
!
! !USES:
use domain ,only: kmax
use initialise ,only: runtype
#ifndef NO_3D
#ifndef NO_BAROCLINIC
use m3d ,only: calc_temp
use variables_3d ,only: T
#endif
#endif
IMPLICIT NONE
!
! !INPUT/OUTPUT PARAMETERS:
!
! !REVISION HISTORY:
! Original Author(s): Knut Klingbeil
!
! !LOCAL VARIABLES
!
!EOP
!-----------------------------------------------------------------------
!BOC
#ifdef DEBUG
integer, save :: Ncall = 0
Ncall = Ncall+1
write(debug,*) 'getmCmp_update_exportState() # ',Ncall
#endif
#ifndef NO_3D
if (runtype .gt. 1) then
#ifndef NO_BAROCLINIC
if (calc_temp) then
! transform from degC to K
sst = T(:,:,kmax) + 273.15d0
end if
#endif
end if
#endif
#ifdef DEBUG
write(debug,*) 'getmCmp_update_exportState()'
write(debug,*)