From b0f5aceb42991a44079ced68ebaa2ce20f3f5269 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 10:16:13 -0700 Subject: [PATCH 01/34] add travis ci setup and dummy program --- lilac/.travis.yml | 28 ++++++++++++++++++++++++++++ lilac/CMakeLists.txt | 26 ++++++++++++++++++++++++++ lilac/lilac/test/simple_driver.f90 | 12 ++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 lilac/.travis.yml create mode 100644 lilac/CMakeLists.txt create mode 100644 lilac/lilac/test/simple_driver.f90 diff --git a/lilac/.travis.yml b/lilac/.travis.yml new file mode 100644 index 0000000000..bc0113b32d --- /dev/null +++ b/lilac/.travis.yml @@ -0,0 +1,28 @@ +language: c +sudo: false +dist: trusty + +matrix: + include: + - os: linux + compiler: gcc + apt: + packages: + - cmake3 + - gfortran + +before_install: + - echo "before install" + +install: + - cd ${TRAVIS_BUILD_DIR} + - mkdir -p build && cd build + - cmake .. + - make + +before_script: + - echo "before script" + +script: + - cd ${TRAVIS_BUILD_DIR} + - ./build/prog diff --git a/lilac/CMakeLists.txt b/lilac/CMakeLists.txt new file mode 100644 index 0000000000..a84296a576 --- /dev/null +++ b/lilac/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 2.8.12.1) + +project(LILAC) +enable_language(Fortran) + +if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") + set(dialect "-ffree-form -std=f2008 -fimplicit-none") + set(bounds "-fbounds-check") +endif() +if(CMAKE_Fortran_COMPILER_ID MATCHES "Intel") + set(dialect "-stand f08 -free -implicitnone") + set(bounds "-check bounds") +endif() +if(CMAKE_Fortran_COMPILER_ID MATCHES "PGI") + set(dialect "-Mfreeform -Mdclchk -Mstandard -Mallocatable=03") + set(bounds "-C") +endif() + +set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}") +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}") + +# +# Compile. +# +file(GLOB_RECURSE sources lilac/test/*.f90 lilac/test/*.h) +add_executable(prog ${sources}) diff --git a/lilac/lilac/test/simple_driver.f90 b/lilac/lilac/test/simple_driver.f90 new file mode 100644 index 0000000000..4b2d940b58 --- /dev/null +++ b/lilac/lilac/test/simple_driver.f90 @@ -0,0 +1,12 @@ +program simple_driver + implicit none + integer :: t + + t = 1 + + if (t == 1) then + write(*,*) "on this line" + else + write(*,*) "but not here" + end if +end program From 2f3a6cecefc0c8e9607f16d65df8785214176816 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 17:11:08 -0700 Subject: [PATCH 02/34] lots of cmake and travis stuff --- lilac/.travis.yml | 9 ++- lilac/CMakeLists.txt | 20 ++++-- lilac/README.md | 5 ++ lilac/ci/environment.yml | 10 +++ lilac/ci/install_esmf.sh | 15 +++++ lilac/ci/install_pfunit.sh | 20 ++++++ lilac/ci/install_python.sh | 20 ++++++ lilac/cmake/Modules/FindESMF.cmake | 70 ++++++++++++++++++++ lilac/lilac/CMakeLists.txt | 4 ++ lilac/lilac/lilac.f90 | 31 +++++++++ lilac/lilac/test/simple_driver.f90 | 12 ---- lilac/tests/CMakeLists.txt | 2 + lilac/tests/hello_world/CMakeLists.txt | 3 + lilac/tests/hello_world/main.f90 | 21 ++++++ lilac/tests/rand_atm_rand_lnd/CmakeLists.txt | 4 ++ lilac/tests/rand_atm_rand_lnd/main.f90 | 5 ++ 16 files changed, 230 insertions(+), 21 deletions(-) create mode 100644 lilac/ci/environment.yml create mode 100644 lilac/ci/install_esmf.sh create mode 100644 lilac/ci/install_pfunit.sh create mode 100644 lilac/ci/install_python.sh create mode 100644 lilac/cmake/Modules/FindESMF.cmake create mode 100644 lilac/lilac/CMakeLists.txt create mode 100644 lilac/lilac/lilac.f90 delete mode 100644 lilac/lilac/test/simple_driver.f90 create mode 100644 lilac/tests/CMakeLists.txt create mode 100644 lilac/tests/hello_world/CMakeLists.txt create mode 100644 lilac/tests/hello_world/main.f90 create mode 100644 lilac/tests/rand_atm_rand_lnd/CmakeLists.txt create mode 100644 lilac/tests/rand_atm_rand_lnd/main.f90 diff --git a/lilac/.travis.yml b/lilac/.travis.yml index bc0113b32d..1d52bb5ab3 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -1,4 +1,4 @@ -language: c +language: cpp sudo: false dist: trusty @@ -8,11 +8,14 @@ matrix: compiler: gcc apt: packages: - - cmake3 - gfortran + - cmake + - cmake-data before_install: - - echo "before install" + - ./install_python.sh + - ./install_esmf.sh + - ./install_pfunit.sh install: - cd ${TRAVIS_BUILD_DIR} diff --git a/lilac/CMakeLists.txt b/lilac/CMakeLists.txt index a84296a576..3b8e730424 100644 --- a/lilac/CMakeLists.txt +++ b/lilac/CMakeLists.txt @@ -1,8 +1,11 @@ cmake_minimum_required(VERSION 2.8.12.1) -project(LILAC) +project(LILAC Fortran) enable_language(Fortran) +# Local CMake modules +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules) + if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") set(dialect "-ffree-form -std=f2008 -fimplicit-none") set(bounds "-fbounds-check") @@ -19,8 +22,13 @@ endif() set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}") -# -# Compile. -# -file(GLOB_RECURSE sources lilac/test/*.f90 lilac/test/*.h) -add_executable(prog ${sources}) +# link to ESMF +find_package(ESMF) +include_directories(${esmf_INCLUDE_DIR}) +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ + ${ESMF_COMPILER_LINE}") +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ + ${ESMF_LINK_LINE} -g -cpp") + +add_subdirectory(lilac) +add_subdirectory(tests) diff --git a/lilac/README.md b/lilac/README.md index a7a62fb359..721cc0f08a 100644 --- a/lilac/README.md +++ b/lilac/README.md @@ -2,3 +2,8 @@ LILAC, Lightweight Infrastructure for Land Atmosphere Coupling. + +Currently working on: + - Setting up CI and CMake + - setup/test style (borrow from geostreams) + - setup unit tests with pfunit diff --git a/lilac/ci/environment.yml b/lilac/ci/environment.yml new file mode 100644 index 0000000000..af786a9279 --- /dev/null +++ b/lilac/ci/environment.yml @@ -0,0 +1,10 @@ +name: lilac +channels: + - conda-forge +dependencies: + - python=3.6 + - xarray + - esmpy + - cmake + - pip: + - cpp-coveralls diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh new file mode 100644 index 0000000000..9356efd2c0 --- /dev/null +++ b/lilac/ci/install_esmf.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -e +set -x + +cd ${HOME} + +git clone https://git.code.sf.net/p/esmf/esmf deps/esmf +cd deps/esmf +export ESMF_DIR=$PWD +export ESMF_INSTALL_PREFIX=/usr/esmf +export ESMFMKFILE=${ESMF_INSTALL_PREFIX}/esmf.mk +gmake -j8 lib +gmake install + +cd ${TRAVIS_BUILD_DIR} diff --git a/lilac/ci/install_pfunit.sh b/lilac/ci/install_pfunit.sh new file mode 100644 index 0000000000..84b5918c12 --- /dev/null +++ b/lilac/ci/install_pfunit.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -e +set -x + +cd ${HOME} + +git clone https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git ${HOME}/deps/pfunit +cd deps/pfunit + +# set environemnt variables +export F90=gfortran +export F90_VENDOR=GNU + +mkdir build +cd build +cmake .. +make install INSTALL_DIR=/usr + +cd ${TRAVIS_BUILD_DIR} diff --git a/lilac/ci/install_python.sh b/lilac/ci/install_python.sh new file mode 100644 index 0000000000..3e3739f648 --- /dev/null +++ b/lilac/ci/install_python.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -e +set -x + +cd ${HOME} + +# Install miniconda +wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ${HOME}/miniconda.sh +bash ~/miniconda.sh -b -p $HOME/miniconda +export PATH="$HOME/miniconda/bin:$PATH" +conda update conda --yes +conda clean -tipy +conda config --set always_yes yes --set changeps1 no +conda --version + +conda env create -f ci/environment.yml +source activate lilac + +cd ${TRAVIS_BUILD_DIR} diff --git a/lilac/cmake/Modules/FindESMF.cmake b/lilac/cmake/Modules/FindESMF.cmake new file mode 100644 index 0000000000..ba50c7a141 --- /dev/null +++ b/lilac/cmake/Modules/FindESMF.cmake @@ -0,0 +1,70 @@ +# +# Author: Ali Samii - The University of Texas at Austin +# +# Distributed under GPL2. For more info refer to: +# https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +# +# +# FindESMF +# -------- +# +# This script tries to find the ESMF library. You have to define +# the path to esmf.mk file in your installation directory. +# +# There are plans to extend this script to find ESMF automatically, +# but until then, you should set the environment variable +# +# ESMFMKFILE = /path/to/esmf.mk +# +# in your installation directory. The output will be +# +# ESMF_LINK_LINE : All the libraries and link line stuff +# ESMF_COMPILER_LINE : All the compiler flags and include dirs +# +# + +# Defining the ${Esc} for syntax coloring. +string(ASCII 27 Esc) + +# Checking if ESMF exists +if (NOT DEFINED ENV{ESMFMKFILE} AND NOT DEFINED ESMFMKFILE) + message (FATAL_ERROR "\n${Esc}[1;31m!! Error: You need ESMF library to \ + run this program. please set the environment \ + variable ESMFMKFILE to point to esmf.mk in \ + your ESMF installation directory. \ + Try something like: ${Esc}[m\ + export ESMFMKFILE=/path/to/esmf.mk && cmake ${CMAKE_SOURCE_DIR}") +endif () + +if (NOT EXISTS $ENV{ESMFMKFILE} AND NOT EXISTS ${ESMFMKFILE}) + message (FATAL_ERROR "${Esc}[1;31m Error: esmf.mk file is not found at \ + ${ESMFMKFILE} ${Esc}[m") +else () + message ("+>${Esc}[1;32m The config file for ESMF library is found.${Esc}[m") +endif () + +if (DEFINED ENV{ESMFMKFILE}) + set(ESMFMKFILE $ENV{ESMFMKFILE} CACHE STRING "") +endif () +set(ESMFMKFILE ${ESMFMKFILE} CACHE STRING "") + +file(STRINGS "${ESMFMKFILE}" all_vars) +foreach(str ${all_vars}) + string(REGEX MATCH "^[^#]" def ${str}) + if (def) + string(REGEX MATCH "^[^=]+" var_name ${str}) + string(REGEX MATCH "=(.+)$" var_def ${str}) + set(var_def ${CMAKE_MATCH_1}) + set(${var_name} ${var_def}) + mark_as_advanced (${var_name}) + endif() +endforeach() + +set (ESMF_LINK_LINE "${ESMF_F90LINKOPTS} \ + ${ESMF_F90LINKRPATHS} \ + ${ESMF_F90LINKPATHS} \ + ${ESMF_F90ESMFLINKLIBS}") + +set (ESMF_COMPILER_LINE "${ESMF_F90COMPILEOPTS} \ + ${ESMF_F90COMPILEPATHS} \ + ${ESMF_F90COMPILEFREENOCPP}") diff --git a/lilac/lilac/CMakeLists.txt b/lilac/lilac/CMakeLists.txt new file mode 100644 index 0000000000..afbc52c6c3 --- /dev/null +++ b/lilac/lilac/CMakeLists.txt @@ -0,0 +1,4 @@ +# Compile LILAC library +file(GLOB_RECURSE LILAC_SOURCES *.f90 *.h) +add_library(lilac ${LILAC_SOURCES}) +target_include_directories(lilac PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/lilac) diff --git a/lilac/lilac/lilac.f90 b/lilac/lilac/lilac.f90 new file mode 100644 index 0000000000..a7a862e60e --- /dev/null +++ b/lilac/lilac/lilac.f90 @@ -0,0 +1,31 @@ +module lilac + + implicit none + + !-------------------------------------------------------------------------- + ! Public interfaces + !-------------------------------------------------------------------------- + public :: lilac_init + public :: lilac_run + public :: lilac_final + +contains + + subroutine lilac_init() + implicit none + print *, "lilac_init()" + flush(6) + + end subroutine lilac_init + + subroutine lilac_run() + implicit none + print *, "lilac_run()" + end subroutine lilac_run + + subroutine lilac_final() + implicit none + print *, "lilac_final()" + end subroutine lilac_final + +end module lilac diff --git a/lilac/lilac/test/simple_driver.f90 b/lilac/lilac/test/simple_driver.f90 deleted file mode 100644 index 4b2d940b58..0000000000 --- a/lilac/lilac/test/simple_driver.f90 +++ /dev/null @@ -1,12 +0,0 @@ -program simple_driver - implicit none - integer :: t - - t = 1 - - if (t == 1) then - write(*,*) "on this line" - else - write(*,*) "but not here" - end if -end program diff --git a/lilac/tests/CMakeLists.txt b/lilac/tests/CMakeLists.txt new file mode 100644 index 0000000000..6361d9e9c2 --- /dev/null +++ b/lilac/tests/CMakeLists.txt @@ -0,0 +1,2 @@ +# Add tests here +add_subdirectory(hello_world) diff --git a/lilac/tests/hello_world/CMakeLists.txt b/lilac/tests/hello_world/CMakeLists.txt new file mode 100644 index 0000000000..0e5fbd44bc --- /dev/null +++ b/lilac/tests/hello_world/CMakeLists.txt @@ -0,0 +1,3 @@ +file(GLOB_RECURSE SOURCES *.f90 *.h) +add_executable("test_hello_world" ${SOURCES} ) +target_link_libraries(lilac) diff --git a/lilac/tests/hello_world/main.f90 b/lilac/tests/hello_world/main.f90 new file mode 100644 index 0000000000..78312075c1 --- /dev/null +++ b/lilac/tests/hello_world/main.f90 @@ -0,0 +1,21 @@ +program main + + ! modules + use ESMF + ! use lilac, ONLY : lilac_init + + implicit none + + ! local variables + integer:: rc + + ! call lilac_init() + ! TODO fix linking with lilac + call ESMF_Initialize(rc=rc) + if (rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT) + + print *, "Hello LILAC World" + + call ESMF_Finalize() + +end program main diff --git a/lilac/tests/rand_atm_rand_lnd/CmakeLists.txt b/lilac/tests/rand_atm_rand_lnd/CmakeLists.txt new file mode 100644 index 0000000000..c7c253746b --- /dev/null +++ b/lilac/tests/rand_atm_rand_lnd/CmakeLists.txt @@ -0,0 +1,4 @@ + +file(GLOB TEST_SOURCES *.f90 *.h) +add_executable(rand_atm_rand_land ${TEST_SOURCES} ) +target_link_libraries(rand_atm_rand_land) diff --git a/lilac/tests/rand_atm_rand_lnd/main.f90 b/lilac/tests/rand_atm_rand_lnd/main.f90 new file mode 100644 index 0000000000..f0c343cc4f --- /dev/null +++ b/lilac/tests/rand_atm_rand_lnd/main.f90 @@ -0,0 +1,5 @@ +program main + + + +end program main From 5d5a8183b77392164fa640674e7a8ca54977c40d Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 17:13:48 -0700 Subject: [PATCH 03/34] add travis badge to readme --- lilac/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/lilac/README.md b/lilac/README.md index 721cc0f08a..a817ad0649 100644 --- a/lilac/README.md +++ b/lilac/README.md @@ -2,6 +2,7 @@ LILAC, Lightweight Infrastructure for Land Atmosphere Coupling. +[![Build Status](https://travis-ci.org/jhamman/lilac.svg?branch=master)](https://travis-ci.org/jhamman/lilac) Currently working on: - Setting up CI and CMake From e2262420348bc0c89284d61b5000f063967463ec Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 17:16:00 -0700 Subject: [PATCH 04/34] fix travis yaml --- lilac/.travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lilac/.travis.yml b/lilac/.travis.yml index 1d52bb5ab3..3c641bfd76 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -6,11 +6,11 @@ matrix: include: - os: linux compiler: gcc - apt: - packages: - - gfortran - - cmake - - cmake-data + apt: + packages: + - gfortran + - cmake + - cmake-data before_install: - ./install_python.sh From 503908fe21b9fdaec6adfc03c438974f1da727d0 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 17:17:42 -0700 Subject: [PATCH 05/34] fix install paths --- lilac/.travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lilac/.travis.yml b/lilac/.travis.yml index 3c641bfd76..3a5e7807af 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -13,9 +13,9 @@ matrix: - cmake-data before_install: - - ./install_python.sh - - ./install_esmf.sh - - ./install_pfunit.sh + - ./ci/install_python.sh + - ./ci/install_esmf.sh + - ./ci/install_pfunit.sh install: - cd ${TRAVIS_BUILD_DIR} From 6d98282b9ef1c3bb168f769c549c326df2f6bcbe Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 17:20:50 -0700 Subject: [PATCH 06/34] more travis fixes --- lilac/.travis.yml | 2 ++ lilac/ci/install_esmf.sh | 0 lilac/ci/install_pfunit.sh | 0 lilac/ci/install_python.sh | 0 4 files changed, 2 insertions(+) mode change 100644 => 100755 lilac/ci/install_esmf.sh mode change 100644 => 100755 lilac/ci/install_pfunit.sh mode change 100644 => 100755 lilac/ci/install_python.sh diff --git a/lilac/.travis.yml b/lilac/.travis.yml index 3a5e7807af..339b78520c 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -1,6 +1,8 @@ language: cpp sudo: false dist: trusty +notifications: + email: false matrix: include: diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh old mode 100644 new mode 100755 diff --git a/lilac/ci/install_pfunit.sh b/lilac/ci/install_pfunit.sh old mode 100644 new mode 100755 diff --git a/lilac/ci/install_python.sh b/lilac/ci/install_python.sh old mode 100644 new mode 100755 From 8fdce150686ead75a799b8f59499ba08927ba8c3 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 17:26:50 -0700 Subject: [PATCH 07/34] add lilac environment name --- lilac/ci/install_python.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lilac/ci/install_python.sh b/lilac/ci/install_python.sh index 3e3739f648..b4d4452565 100755 --- a/lilac/ci/install_python.sh +++ b/lilac/ci/install_python.sh @@ -14,7 +14,7 @@ conda clean -tipy conda config --set always_yes yes --set changeps1 no conda --version -conda env create -f ci/environment.yml +conda env create --file ci/environment.yml --name lilac source activate lilac cd ${TRAVIS_BUILD_DIR} From eaf6f3b5a990c4edc13a54b2cdd919c8bbe52621 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 20:10:57 -0700 Subject: [PATCH 08/34] no env in conda install --- lilac/ci/install_python.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lilac/ci/install_python.sh b/lilac/ci/install_python.sh index b4d4452565..650acee6a4 100755 --- a/lilac/ci/install_python.sh +++ b/lilac/ci/install_python.sh @@ -14,7 +14,7 @@ conda clean -tipy conda config --set always_yes yes --set changeps1 no conda --version -conda env create --file ci/environment.yml --name lilac +conda create --file ci/environment.yml --name lilac source activate lilac cd ${TRAVIS_BUILD_DIR} From 5540ff086a663bc072bd3d607e2cfbc78c1c58d6 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 20:14:40 -0700 Subject: [PATCH 09/34] fix conda install location --- lilac/ci/install_python.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/lilac/ci/install_python.sh b/lilac/ci/install_python.sh index 650acee6a4..1e2c2426c3 100755 --- a/lilac/ci/install_python.sh +++ b/lilac/ci/install_python.sh @@ -3,8 +3,6 @@ set -e set -x -cd ${HOME} - # Install miniconda wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ${HOME}/miniconda.sh bash ~/miniconda.sh -b -p $HOME/miniconda From 4425bc6d9eb6908b59b802e7b7aa4a1a7d194e64 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 20:16:32 -0700 Subject: [PATCH 10/34] no name --- lilac/ci/environment.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/lilac/ci/environment.yml b/lilac/ci/environment.yml index af786a9279..0d0d6a023d 100644 --- a/lilac/ci/environment.yml +++ b/lilac/ci/environment.yml @@ -1,4 +1,3 @@ -name: lilac channels: - conda-forge dependencies: From 75de694b8336ab2ecede807a84d5eb6f1b5bc62b Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 20:22:21 -0700 Subject: [PATCH 11/34] back to env --- lilac/ci/install_python.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lilac/ci/install_python.sh b/lilac/ci/install_python.sh index 1e2c2426c3..2a2d2a551f 100755 --- a/lilac/ci/install_python.sh +++ b/lilac/ci/install_python.sh @@ -12,7 +12,8 @@ conda clean -tipy conda config --set always_yes yes --set changeps1 no conda --version -conda create --file ci/environment.yml --name lilac +conda env create -f ci/environment.yml --name lilac + source activate lilac cd ${TRAVIS_BUILD_DIR} From 9e69979b52dba14d7930989ba85aef8703a336d8 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 21:28:24 -0700 Subject: [PATCH 12/34] make --- lilac/ci/install_esmf.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 9356efd2c0..021ecd5bbd 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -9,7 +9,7 @@ cd deps/esmf export ESMF_DIR=$PWD export ESMF_INSTALL_PREFIX=/usr/esmf export ESMFMKFILE=${ESMF_INSTALL_PREFIX}/esmf.mk -gmake -j8 lib -gmake install +make -j8 lib +make install cd ${TRAVIS_BUILD_DIR} From 82b38e9333e7e4a530d73b4c771ec76cfb66989a Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 21:36:18 -0700 Subject: [PATCH 13/34] gnu6 for esmf --- lilac/.travis.yml | 4 +++- lilac/ci/install_esmf.sh | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lilac/.travis.yml b/lilac/.travis.yml index 339b78520c..8279b2b2f7 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -10,11 +10,13 @@ matrix: compiler: gcc apt: packages: - - gfortran + - gfortran-6 - cmake - cmake-data before_install: + - export CC=/usr/bin/gcc-6 + - export FC=/usr/bin/gfortran-6 - ./ci/install_python.sh - ./ci/install_esmf.sh - ./ci/install_pfunit.sh diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 021ecd5bbd..6b089d925b 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -4,12 +4,14 @@ set -x cd ${HOME} +ESMF_COMPILER=$FC + git clone https://git.code.sf.net/p/esmf/esmf deps/esmf cd deps/esmf export ESMF_DIR=$PWD export ESMF_INSTALL_PREFIX=/usr/esmf export ESMFMKFILE=${ESMF_INSTALL_PREFIX}/esmf.mk -make -j8 lib +make -j4 lib make install cd ${TRAVIS_BUILD_DIR} From 47c7cf5128b8f94e54fe3c0e743ff60c619e74c2 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 21:43:13 -0700 Subject: [PATCH 14/34] alias gfortran --- lilac/.travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/lilac/.travis.yml b/lilac/.travis.yml index 8279b2b2f7..03571b7a74 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -17,6 +17,7 @@ matrix: before_install: - export CC=/usr/bin/gcc-6 - export FC=/usr/bin/gfortran-6 + - alias gfortran="/usr/bin/gfortran-6" - ./ci/install_python.sh - ./ci/install_esmf.sh - ./ci/install_pfunit.sh From 095edde28edc3e6866c6d78ce4cff4d9f698838b Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 21:50:32 -0700 Subject: [PATCH 15/34] two alias for gfortran --- lilac/ci/install_esmf.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 6b089d925b..21e4a505d1 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -5,6 +5,7 @@ set -x cd ${HOME} ESMF_COMPILER=$FC +alias gfortran="/usr/bin/gfortran-6" git clone https://git.code.sf.net/p/esmf/esmf deps/esmf cd deps/esmf From 7f698cae0113f1769c9b6b78ee599cc92085daf6 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 22:43:05 -0700 Subject: [PATCH 16/34] export esmf compiler --- lilac/ci/install_esmf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 21e4a505d1..1bda90b47d 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -4,7 +4,7 @@ set -x cd ${HOME} -ESMF_COMPILER=$FC +export ESMF_COMPILER="/usr/bin/gfortran-6" alias gfortran="/usr/bin/gfortran-6" git clone https://git.code.sf.net/p/esmf/esmf deps/esmf From 105f175d7da20c5574f2e77162a735d3caa272d8 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Thu, 2 Aug 2018 22:55:37 -0700 Subject: [PATCH 17/34] more compiler env vars --- lilac/ci/install_esmf.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 1bda90b47d..68e622ae9e 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -4,6 +4,8 @@ set -x cd ${HOME} +export CC=""/usr/bin/gcc-6"" +export FC="/usr/bin/gfortran-6" export ESMF_COMPILER="/usr/bin/gfortran-6" alias gfortran="/usr/bin/gfortran-6" From 6a3a4e435a825195cf0d19c194590f95c20e6dfe Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Fri, 3 Aug 2018 08:33:13 -0700 Subject: [PATCH 18/34] default gfortran --- lilac/.travis.yml | 6 ++---- lilac/ci/install_esmf.sh | 10 ++++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lilac/.travis.yml b/lilac/.travis.yml index 03571b7a74..e3a280e1b9 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -10,14 +10,12 @@ matrix: compiler: gcc apt: packages: - - gfortran-6 + - gfortran - cmake - cmake-data before_install: - - export CC=/usr/bin/gcc-6 - - export FC=/usr/bin/gfortran-6 - - alias gfortran="/usr/bin/gfortran-6" + - export FC=/usr/bin/gfortran - ./ci/install_python.sh - ./ci/install_esmf.sh - ./ci/install_pfunit.sh diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 68e622ae9e..fef18a466f 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -4,17 +4,15 @@ set -x cd ${HOME} -export CC=""/usr/bin/gcc-6"" -export FC="/usr/bin/gfortran-6" -export ESMF_COMPILER="/usr/bin/gfortran-6" -alias gfortran="/usr/bin/gfortran-6" +export FC="/usr/bin/gfortran" +export ESMF_COMPILER="/usr/bin/gfortran" git clone https://git.code.sf.net/p/esmf/esmf deps/esmf cd deps/esmf export ESMF_DIR=$PWD -export ESMF_INSTALL_PREFIX=/usr/esmf -export ESMFMKFILE=${ESMF_INSTALL_PREFIX}/esmf.mk +export ESMF_INSTALL_PREFIX=/usr/ make -j4 lib make install +export ESMFMKFILE=${ESMF_INSTALL_PREFIX}/esmf.mk cd ${TRAVIS_BUILD_DIR} From 66efcdac2bb5a5031ddea9f5a2309e52db8b7af2 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Fri, 3 Aug 2018 08:51:37 -0700 Subject: [PATCH 19/34] add pfunit submodule --- external/pfunit | 1 + lilac/.gitmodules | 3 +++ 2 files changed, 4 insertions(+) create mode 160000 external/pfunit create mode 100644 lilac/.gitmodules diff --git a/external/pfunit b/external/pfunit new file mode 160000 index 0000000000..14339d668c --- /dev/null +++ b/external/pfunit @@ -0,0 +1 @@ +Subproject commit 14339d668c3f7440c408422dea68d750ee59ad9d diff --git a/lilac/.gitmodules b/lilac/.gitmodules new file mode 100644 index 0000000000..e266cf787f --- /dev/null +++ b/lilac/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/pfunit"] + path = external/pfunit + url = https://github.com/laristra/pfunit.git From ba3c09ba213633a79038028412d95b2acde52703 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Fri, 3 Aug 2018 09:11:23 -0700 Subject: [PATCH 20/34] add esmf as external --- external/esmf | 1 + lilac/.gitmodules | 3 +++ 2 files changed, 4 insertions(+) create mode 160000 external/esmf diff --git a/external/esmf b/external/esmf new file mode 160000 index 0000000000..d2761c276d --- /dev/null +++ b/external/esmf @@ -0,0 +1 @@ +Subproject commit d2761c276daf2ccac33193f28e925e974d180309 diff --git a/lilac/.gitmodules b/lilac/.gitmodules index e266cf787f..2f471a14d9 100644 --- a/lilac/.gitmodules +++ b/lilac/.gitmodules @@ -1,3 +1,6 @@ [submodule "external/pfunit"] path = external/pfunit url = https://github.com/laristra/pfunit.git +[submodule "external/esmf"] + path = external/esmf + url = https://git.code.sf.net/p/esmf/esmf From eb317b3a7495359f79e97cce126ee918c9b60f92 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Fri, 17 Aug 2018 17:01:00 -0700 Subject: [PATCH 21/34] updates after meeting with team in boulder, still has lots of holes --- lilac/CMakeLists.txt | 80 ++++++- lilac/lilac/atmos_comp.f90 | 39 ++++ lilac/lilac/coupler_mod.f90 | 326 ++++++++++++++++++++++++++ lilac/lilac/esmf_utils.f90 | 271 ++++++++++++++++++++++ lilac/lilac/land_comp.f90 | 1 + lilac/lilac/lilac.f90 | 41 +++- lilac/src/.dir-locals.el | 14 -- lilac/src/lilac-demo-driver.F90 | 283 ---------------------- lilac/src/lilac.F90 | 399 -------------------------------- lilac/src/lilac_api_types.F90 | 43 ---- lilac/src/lilac_constants.F90 | 18 -- lilac/src/stub_comp_mct.F90 | 8 - 12 files changed, 744 insertions(+), 779 deletions(-) create mode 100644 lilac/lilac/atmos_comp.f90 create mode 100644 lilac/lilac/coupler_mod.f90 create mode 100644 lilac/lilac/esmf_utils.f90 create mode 100644 lilac/lilac/land_comp.f90 delete mode 100644 lilac/src/.dir-locals.el delete mode 100644 lilac/src/lilac-demo-driver.F90 delete mode 100644 lilac/src/lilac.F90 delete mode 100644 lilac/src/lilac_api_types.F90 delete mode 100644 lilac/src/lilac_constants.F90 delete mode 100644 lilac/src/stub_comp_mct.F90 diff --git a/lilac/CMakeLists.txt b/lilac/CMakeLists.txt index 3b8e730424..56d348a737 100644 --- a/lilac/CMakeLists.txt +++ b/lilac/CMakeLists.txt @@ -4,7 +4,6 @@ project(LILAC Fortran) enable_language(Fortran) # Local CMake modules -list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules) if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") set(dialect "-ffree-form -std=f2008 -fimplicit-none") @@ -22,13 +21,78 @@ endif() set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}") -# link to ESMF -find_package(ESMF) -include_directories(${esmf_INCLUDE_DIR}) -set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ - ${ESMF_COMPILER_LINE}") -set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ - ${ESMF_LINK_LINE} -g -cpp") +if(DEFINED PFUNIT_INSTALL) + message(STATUS "Manual setup of variable PFUNIT_INSTALL: ${PFUNIT_INSTALL}") + set(PFUNIT_DIR ${PFUNIT_INSTALL}) +else() + include(ExternalProject) + + set(ExternalProjectCMakeArgs + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/external/pfunit + -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER} + ) + ExternalProject_Add(pfunit + DOWNLOAD_COMMAND git submodule update + DOWNLOAD_DIR ${PROJECT_SOURCE_DIR} + SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/pfunit + BINARY_DIR ${PROJECT_BINARY_DIR}/external/pfunit-build + STAMP_DIR ${PROJECT_BINARY_DIR}/external/pfunit-stamp + TMP_DIR ${PROJECT_BINARY_DIR}/external/pfunit-tmp + INSTALL_DIR ${PROJECT_BINARY_DIR}/external + CMAKE_ARGS ${ExternalProjectCMakeArgs} + ) + include_directories(${PROJECT_BINARY_DIR}/external/pfunit/mod) + set(PFUNIT_DIR ${PROJECT_BINARY_DIR}/external/pfunit) +endif() + + +if(DEFINED ESMF_INSTALL) + message(STATUS "Manual setup of variable ESMF_INSTALL: ${ESMF_INSTALL}") + set(ESMF_DIR ${ESMF_INSTALL}) + +else() + message(STATUS "We will build ESMF") + include(ExternalProject) + + # set(ENV{ESMFMKFILE} "${PROJECT_BINARY_DIR}/external/esmf/esmf.mk") + + set(ExternalProjectCMakeArgs + ESMF_DIR=${ESMF_DIR} + ESMF_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/external + ESMF_INSTALL_BINDIR=${PROJECT_BINARY_DIR}/bin/ + ESMF_INSTALL_DOCDIR=${PROJECT_BINARY_DIR}/doc/ + ESMF_INSTALL_HEADERDIR=${PROJECT_BINARY_DIR}/include/ + ESMF_INSTALL_LIBDIR=${PROJECT_BINARY_DIR}/lib/ + ESMF_INSTALL_MODDIR=${PROJECT_BINARY_DIR}/mod/ + ) + + ExternalProject_Add(esmf + DOWNLOAD_COMMAND git submodule update + DOWNLOAD_DIR ${PROJECT_SOURCE_DIR}/external + SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/esmf + INSTALL_DIR ${PROJECT_BINARY_DIR}/external + BUILD_IN_SOURCE TRUE + CMAKE_ARGS ${ExternalProjectCMakeArgs} + CONFIGURE_COMMAND "" + BUILD_COMMAND make + INSTALL_COMMAND pwd && make install + ) + + # link to ESMF + # find_package(ESMF) + # include_directories(${PROJECT_BINARY_DIR}/include/) + # set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ ${ESMF_COMPILER_LINE}") + # set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_LINK_LINE} -g -cpp") + # TODO figure out how to get these out once ESMF is compiled + set(ESMF_COMPILER_LINE, "-O -m64 -mcmodel=small -ffree-line-length-none -fopenmp -I/Users/jhamman/Dropbox/src/lilac/external/esmf/mod/modO/Darwin.gfortran.64.mpiuni.default -I/Users/jhamman/Dropbox/src/lilac/external/esmf/src/include -ffree-form") + set(ESMF_LINK_LINE, "-m64 -mcmodel=small -fopenmp -L/Users/jhamman/Dropbox/src/lilac/external/esmf/lib/libO/Darwin.gfortran.64.mpiuni.default -L/opt/local/lib/gcc5/gcc/x86_64-apple-darwin17/5.5.0/../../../ -lesmf -lstdc++") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_COMPILER_LINE}") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_LINK_LINE} -g -cpp") + + + +endif() add_subdirectory(lilac) add_subdirectory(tests) diff --git a/lilac/lilac/atmos_comp.f90 b/lilac/lilac/atmos_comp.f90 new file mode 100644 index 0000000000..b8ecec4a2d --- /dev/null +++ b/lilac/lilac/atmos_comp.f90 @@ -0,0 +1,39 @@ + +module atmos_comp + + ! ESMF Framework module + use ESMF + implicit none + + public atmos_register + +contains + + + subroutine atmos_register(comp, rc) + type(ESMF_GridComp) :: comp + integer, intent(out) :: rc + + ! Initialize return code + rc = ESMF_SUCCESS + + print *, "Atmosphere Register starting" + + ! Register the callback routines. + + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=atmos_init, & + rc=rc) + if (rc/=ESMF_SUCCESS) return ! bail out + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=atmos_run, & + rc=rc) + if (rc/=ESMF_SUCCESS) return ! bail out + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=atmos_final, & + rc=rc) + if (rc/=ESMF_SUCCESS) return ! bail out + + print *, "Registered Initialize, Run, and Finalize routines" + print *, "Atmosphere Register returning" + + end subroutine atmos_register + +end module atmos_comp diff --git a/lilac/lilac/coupler_mod.f90 b/lilac/lilac/coupler_mod.f90 new file mode 100644 index 0000000000..36354e7c88 --- /dev/null +++ b/lilac/lilac/coupler_mod.f90 @@ -0,0 +1,326 @@ + module CouplerMod + + use ESMF + + implicit none + + private + + ! Public entry point + public Coupler_register + + contains + + +!------------------------------------------------------------------------------ +!BOPI +! !IROUTINE: Coupler_register - public SetServices entry point + +! !INTERFACE: + subroutine Coupler_register(comp, rc) +! +! !ARGUMENTS: + type(ESMF_CplComp) :: comp + integer, intent(out) :: rc +! +! !DESCRIPTION: +! User-supplied setservices routine. +! +! The arguments are: +! \begin{description} +! \item[comp] +! Component. +! \item[rc] +! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, +! otherwise {\tt ESMF\_FAILURE}. +! \end{description} +! +!EOPI + + ! because none of the arguments to this subroutine will ever be optional, + ! go ahead and set rc to an initial return code before using it below. + ! (this makes some eager error-checking compilers happy.) + rc = ESMF_FAILURE + + ! Register the callback routines. + + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=coupler_init, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=coupler_run, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=coupler_final, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + print *, "CouplerMod: Registered Initialize, Run, and Finalize routines" + + end subroutine + + +!------------------------------------------------------------------------------ +!BOPI +! !IROUTINE: coupler_init - coupler init routine + +! !INTERFACE: + subroutine coupler_init(comp, importState, exportState, clock, rc) + +! +! !ARGUMENTS: + type(ESMF_CplComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc +! +! !DESCRIPTION: +! User-supplied init routine. +! +! The arguments are: +! \begin{description} +! \item[comp] +! Component. +! \item[importState] +! Nested state object containing import data. +! \item[exportState] +! Nested state object containing export data. +! \item[clock] +! External clock. +! \item[rc] +! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, +! otherwise {\tt ESMF\_FAILURE}. +! \end{description} +! +!EOPI + +! ! Local variables + type(ESMF_Field) :: src_field, dst_field + type(ESMF_VM) :: vm + character(ESMF_MAXSTR) :: statename + + print *, "Coupler Init starting" + + ! because none of the arguments to this subroutine will ever be optional, + ! go ahead and set rc to an initial return code before using it below. + ! (this makes some eager error-checking compilers happy.) + rc = ESMF_FAILURE + + ! Get VM from coupler component to use in computing redistribution + call ESMF_CplCompGet(comp, vm=vm, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + ! Use placeholder SIE + call ESMF_StateGet(importState, name=statename, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call ESMF_StateGet(importState, "SIE", src_field, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call ESMF_StateGet(exportState, "SIE", dst_field, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + ! Compute routehandle + ! Since state items are needed by default, mark Fields not needed during coupling + if (trim(statename) .eq. "FlowSolver Feedback") then + call setFieldNeeded(importState, "U", .false., rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call setFieldNeeded(importState, "P", .false., rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call setFieldNeeded(importState, "Q", .false., rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + call ESMF_FieldRedistStore(src_field, dst_field, & + routehandle=fromFlow_rh, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + endif + + if (trim(statename) .eq. "Injection Feedback") then + call setFieldNeeded(importState, "U", .false., rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call setFieldNeeded(importState, "P", .false., rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call setFieldNeeded(importState, "Q", .false., rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call setFieldNeeded(importState, "FLAG", .false., rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + call ESMF_FieldRedistStore(src_field, dst_field, & + routehandle=fromInject_rh, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + endif + + print *, "Coupler Init returning" + + end subroutine coupler_init + + +!------------------------------------------------------------------------------ +!BOPI +! !IROUTINE: coupler_run - coupler run routine + +! !INTERFACE: + subroutine coupler_run(comp, importState, exportState, clock, rc) + +! +! !ARGUMENTS: + type(ESMF_CplComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc +! +! !DESCRIPTION: +! User-supplied run routine. +! +! The arguments are: +! \begin{description} +! \item[comp] +! Component. +! \item[importState] +! Nested state object containing import data. +! \item[exportState] +! Nested state object containing export data. +! \item[clock] +! External clock. +! \item[rc] +! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, +! otherwise {\tt ESMF\_FAILURE}. +! \end{description} +! +!EOPI + + ! Local variables + type(ESMF_Field) :: srcfield, dstfield + type(ESMF_RouteHandle) :: rh + + character(len=ESMF_MAXSTR) :: statename + + integer :: i, datacount + character(len=ESMF_MAXSTR), dimension(7) :: datanames + + ! none of the arguments to this subroutine will ever be optional, so + ! go ahead and set rc to an initial return code before using it below. + ! (this makes some eager error-checking compilers happy.) + rc = ESMF_FAILURE + + datacount = 7 + datanames(1) = "SIE" + datanames(2) = "U" + datanames(3) = "V" + datanames(4) = "RHO" + datanames(5) = "P" + datanames(6) = "Q" + datanames(7) = "FLAG" + + ! In this case, the coupling is symmetric - you call redist going + ! both ways - so we only care about the coupling direction in order + ! to get the right routehandle selected. + call ESMF_StateGet(importState, name=statename, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + if (trim(statename) .eq. "FlowSolver Feedback") then + rh = fromFlow_rh + else + rh = fromInject_rh + endif + + do i=1, datacount + + ! check isneeded flag here + if (.not. isFieldNeeded(importState, datanames(i), rc=rc)) then + !print *, "skipping field ", trim(datanames(i)), " not needed" + cycle + endif + + !print *, "processing field ", trim(datanames(i)), " as needed" +!BOE +! !DESCRIPTION: +! \subsubsection{Example of Redist Usage} +! +! The following piece of code provides an example of calling the data +! redistribution routine between two Fields in the Coupler Component. +! Unlike regrid, which translates between +! different Grids, redist translates between different DELayouts on +! the same Grid. The first two lines get the Fields from the +! States, each corresponding to a different subcomponent. One is +! an Export State and the other is an Import State. +! +!BOC + call ESMF_StateGet(importState, datanames(i), srcfield, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call ESMF_StateGet(exportState, datanames(i), dstfield, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) +!EOC +! +! The redist routine uses information contained in the Fields and the +! Coupler VM object to call the communication routines to move the data. +! Because many Fields may share the same Grid association, the same +! routing information may be needed repeatedly. Route information is +! saved so the precomputed information can be retained. The following +! is an example of a Field redist call: +! +!BOC + call ESMF_FieldRedist(srcfield, dstfield, routehandle=rh, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + +!EOC +!EOE + + enddo + + ! rc has the last error code already + + end subroutine coupler_run + + +!------------------------------------------------------------------------------ +!BOPI +! !IROUTINE: coupler_final - finalization routine + +! !INTERFACE: + subroutine coupler_final(comp, importState, exportState, clock, rc) + +! +! !ARGUMENTS: + type(ESMF_CplComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc +! +! !DESCRIPTION: +! User-supplied finalize routine. +! +! The arguments are: +! \begin{description} +! \item[comp] +! Component. +! \item[importState] +! Nested state object containing import data. +! \item[exportState] +! Nested state object containing export data. +! \item[clock] +! External clock. +! \item[rc] +! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, +! otherwise {\tt ESMF\_FAILURE}. +! \end{description} +! +!EOPI + + print *, "Coupler Final starting" + + ! none of the arguments to this subroutine will ever be optional, so + ! go ahead and set rc to an initial return code before using it below. + ! (this makes some eager error-checking compilers happy.) + rc = ESMF_FAILURE + + ! Only thing to do here is release redist and route handles + call ESMF_FieldRedistRelease(fromFlow_rh, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + call ESMF_FieldRedistRelease(fromInject_rh, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + rc = ESMF_SUCCESS + + print *, "Coupler Final returning" + + end subroutine coupler_final + + + end module CouplerMod diff --git a/lilac/lilac/esmf_utils.f90 b/lilac/lilac/esmf_utils.f90 new file mode 100644 index 0000000000..4d2a817b41 --- /dev/null +++ b/lilac/lilac/esmf_utils.f90 @@ -0,0 +1,271 @@ +module esmf_utils + +! Wrappers and derived types exposing ESMF components to LILAC + + +#include "ESMF.h" + use ESMF + + implicit none + private + + ! Consider renaming ESMFInfoType (add lilac to name) + type, public :: ESMFInfoType + private + character(len=MAXFILELENGTH) :: name + + type(ESMF_VM) :: vm + type(ESMF_State) :: land_import + type(ESMF_State) :: land_export + type(ESMF_State) :: atmos_import + type(E SMF_State) :: atmos_export + type(ESMF_GridComp) :: atmos_comp + type(ESMF_GridComp) :: land_comp + type(ESMF_CplComp) :: cpl_comp + + contains + procedure, public :: init => init + procedure, public :: run => run + procedure, public :: final => final + + procedure, private :: atmos_register => atmos_register + procedure, private :: land_register => land_register + procedure, private :: cpl_register => cpl_register + end type ESMFInfoType + +contains + + subroutine init(self, name) + implicit none + class(ESMFInfoType), intent(inout) :: self + character(len=MAXVARLENGTH), intent(in) :: name + + ! TODO define subroutines: https://stackoverflow.com/questions/32809769/how-to-pass-subroutine-names-as-arguments-in-fortran + + ! Local variables + integer :: localPet, petCount, localrc, rc=ESMF_SUCCESS, userrc=ESMF_SUCCESS + character(len=ESMF_MAXSTR) :: cname1, cname2 + + print *, "esmf_info%init()" + + self%name = name + + ! Create section + !------------------------------------------------------------------------- + + ! Initialize framework and get back default global VM + + ! only run if not esmf_isintialized() + call ESMF_Initialize(vm=self%vm, defaultlogfilename="lilac.log", logkindflag=ESMF_LOGKIND_MULTI, rc=localrc) + call check(localrc, rc) + + ! Get number of PETs we are running with + call ESMF_VMGet(self%vm, petCount=petCount, localPet=localPet, rc=localrc) + call check(localrc, rc) + + ! Create the 2 model components and a coupler + cname1 = "land" + ! use petList to define land on all PET + self%land_grid = ESMF_GridCompCreate(name=cname1, rc=localrc) + print *, "Created component ", trim(cname1), "rc =", localrc + call check(localrc, rc) + + cname2 = "atmosphere" + ! use petList to define atmosphere on all PET + self%atmos_comp = ESMF_GridCompCreate(name=cname2, rc=localrc) + print *, "Created component ", trim(cname2), "rc =", localrc + call check(localrc, rc) + + cplname = "lilac coupler" + ! no petList means that coupler component runs on all PETs + self%cpl_comp = ESMF_CplCompCreate(name=cplname, rc=localrc) + print *, "Created component ", trim(cplname), ", rc =", localrc + call check(localrc, rc) + + print *, "Comp Creates finished" + + ! Register section + !------------------------------------------------------------------------- + call ESMF_GridCompSetServices(self%atmos_comp, userRoutine=atmos_register, userRc=userrc, rc=localrc) + print *, "atmos SetServices finished, rc= ", localrc + call check(localrc, rc) + call check(userrc, rc) + + call ESMF_GridCompSetServices(self%land_comp, userRoutine=land_register, userRc=userrc, rc=localrc) + print *, "land SetServices finished, rc= ", localrc + call check(localrc, rc) + call check(userrc, rc) + + call ESMF_CplCompSetServices(self%cpl_comp, userRoutine=cpl_register, userRc=userrc, rc=localrc) + print *, "Cpl SetServices finished, rc= ", localrc + call check(localrc, rc) + call check(userrc, rc) + + ! Init section + !------------------------------------------------------------------------- + ! land import/export states + self%land_import = ESMF_StateCreate(name="land import", stateintent=ESMF_STATEINTENT_IMPORT, rc=localrc) + call check(localrc, rc) + self%land_export = ESMF_StateCreate(name="land export", stateintent=ESMF_STATEINTENT_EXPORT, rc=localrc) + call check(localrc, rc) + call ESMF_GridCompInitialize(land, importState=self%land_import, exportState=self%land_export, userRc=userrc, rc=localrc) + call check(localrc, rc) + call check(userrc, rc) + print *, "Land Initialize finished, rc =", localrc + + ! atmosphere import/export state + self%atmos_import = ESMF_StateCreate(name="atmos import", & + stateintent=ESMF_STATEINTENT_IMPORT, rc=localrc) + call check(localrc, rc) + + self%atmos_export = ESMF_StateCreate(name="atmos export", & + stateintent=ESMF_STATEINTENT_EXPORT, rc=localrc) + call check(localrc, rc) + call ESMF_GridCompInitialize(self%atmos_comp, exportState=self%atmos_export, userRc=userrc, rc=localrc) + print *, "Atmosphere Initialize finished, rc =", localrc + call check(localrc, rc) + call check(userrc, rc) + + ! call ESMF_CPLCompInitialize twice (once for each grid comp) + + end subroutine init + + subroutine run(self) + implicit none + integer :: localrc, rc=ESMF_SUCCESS, userrc=ESMF_SUCCESS + print *, "esmf_info%run()" + + ! TODO: need some help on order of imports/exports/runs and whether the land/atm both need import/export states + + ! atmosphere run + ! copy the atmos state and put it into atmos export + call ESMF_GridCompRun(self%atmos_comp, exportState=self%atmos_export, phase=1, userRc=userrc, rc=localrc) + print *, "Atmosphere Run returned, rc =", localrc + call check(localrc, rc) + call check(userrc, rc) + + ! coupler run + call ESMF_CplCompRun(self%cpl_comp, importState=self%atoms_export, exportState=self%land_import, & + userRc=userrc, rc=localrc) + print *, "Coupler Run returned, rc =", localrc + call check(localrc, rc) + call check(userrc, rc) + + ! land run + call ESMF_GridCompRun(self%land_comp, importState=self%land_import, exportState=self%land_export, userRc=userrc, rc=localrc) + print *, "Land Run returned, rc =", localrc + call check(localrc, rc) + call check(userrc, rc) + + ! coupler run + call ESMF_CplCompRun(self%cpl_comp, importState=self%land_export, exportState=self%atmos_import, & + userRc=userrc, rc=localrc) + print *, "Coupler Run returned, rc =", localrc + call check(localrc, rc) + call check(userrc, rc) + + call ESMF_GridCompRun(self%atmos_comp, importState%atmos_import, phase=2, userRc=userrc, rc=localrc) + print *, "Atmosphere Run returned, rc =", localrc + call check(localrc, rc) + call check(userrc, rc) + + end subroutine run + + subroutine final(self) + implicit none + class(ESMFInfoType), intent(inout) :: self + integer :: localrc, rc=ESMF_SUCCESS + + print *, "esmf_info%final()" + + ! Destroy section + call ESMF_GridCompDestroy(self%atmos_comp, rc=localrc) + check(localrc, rc) + call ESMF_GridCompDestroy(self%land_comp, rc=localrc) + check(localrc, rc) + call ESMF_CplCompDestroy(self%cpl_comp, rc=localrc) + check(localrc, rc) + + call ESMF_StateDestroy(self%land_export, rc=localrc) + call ESMF_StateDestroy(self%land_import, rc=localrc) + check(localrc, rc) + call ESMF_StateDestroy(self%atmos_export, rc=localrc) + call ESMF_StateDestroy(self%atmos_import, rc=localrc) + ! do this everywhere + if return_error(localrc, rc) return + + print *, "All Destroy routines done" + + end subroutine final + + subroutine atoms_register(comp, rc) + type(ESMF_GridComp) :: comp ! must not be optional + integer, intent(out) :: rc ! must not be optional + + ! Set the entry points for standard ESMF Component methods + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & + userRoutine=atoms_init, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & + userRoutine=atoms_copy_atm_to_lilac, phase=1, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & + userRoutine=atoms_copy_lilac_to_atm, phase=2, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & + userRoutine=atoms_final, rc=rc) + ! TODO: check rcs + + rc = ESMF_SUCCESS + + end subroutine + + subroutine land_register(comp, rc) + type(ESMF_GridComp) :: comp ! must not be optional + integer, intent(out) :: rc ! must not be optional + + ! land_* comes from ctsm esmf cap + + ! Set the entry points for standard ESMF Component methods + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & + userRoutine=land_init, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & + userRoutine=land_run, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & + userRoutine=land_final, rc=rc) + ! TODO: check rcs + + rc = ESMF_SUCCESS + + end subroutine + + subroutine cpl_register(comp, rc) + type(ESMF_GridComp) :: comp ! must not be optional + integer, intent(out) :: rc ! must not be optional + + rc = ESMF_FAILURE + + ! Register the callback routines. + + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=coupler_init, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=coupler_run, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=coupler_final, rc=rc) + if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) + + print *, "CouplerMod: Registered Initialize, Run, and Finalize routines" + + rc = ESMF_SUCCESS + + end subroutine + + function return_error(rc, returnrc) + ! fight with this later + integer, intent(in) :: rc, returnrc + if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, rcToReturn=returnrc)) then + return_error = .true. + else + return_error = .false. + endif + + end function return_error + +end module esmf_utils diff --git a/lilac/lilac/land_comp.f90 b/lilac/lilac/land_comp.f90 new file mode 100644 index 0000000000..1a4baf536d --- /dev/null +++ b/lilac/lilac/land_comp.f90 @@ -0,0 +1 @@ + diff --git a/lilac/lilac/lilac.f90 b/lilac/lilac/lilac.f90 index a7a862e60e..b6393f9164 100644 --- a/lilac/lilac/lilac.f90 +++ b/lilac/lilac/lilac.f90 @@ -1,5 +1,12 @@ module lilac +#include "ESMF.h" + use ESMF + + use atmos_comp, only : atmos_setvm, atmos_register + use land_comp, only : land_setvm, land_register + use coupler_comp, only : usercpl_setvm, usercpl_register + implicit none !-------------------------------------------------------------------------- @@ -9,23 +16,45 @@ module lilac public :: lilac_run public :: lilac_final + type(LilacType), save :: lilac_obj + +contains + + type, public :: LilacType + private + + type(ESMFInfoType) :: esmf_info + + contains + procedure, public :: init => init + procedure, public :: run => run + procedure, public :: final => final + end type LilacType + contains - subroutine lilac_init() + subroutine lilac_init(self) implicit none + print *, "lilac_init()" - flush(6) + + ! Initialize ESMF structures + call self%esmf_info%init("lilac") end subroutine lilac_init - subroutine lilac_run() + subroutine lilac_run(self) implicit none - print *, "lilac_run()" + + call self%esmf_info%run() + end subroutine lilac_run - subroutine lilac_final() + subroutine lilac_final(self) implicit none - print *, "lilac_final()" + + call self%esmf_info%final() + end subroutine lilac_final end module lilac diff --git a/lilac/src/.dir-locals.el b/lilac/src/.dir-locals.el deleted file mode 100644 index 4edf085c03..0000000000 --- a/lilac/src/.dir-locals.el +++ /dev/null @@ -1,14 +0,0 @@ -;;; Directory Local Variables -;;; For more information see (info "(emacs) Directory Variables") - -((f90-mode - (f90-program-indent . 3) - (f90-associate-indent . 3) - (f90-do-indent . 3) - (f90-if-indent . 3) - (f90-type-indent . 3) - (f90-program-indent . 3) - (f90-continuation-indent . 5) - (fill-column . 80) - (indent-tabs-mode))) - diff --git a/lilac/src/lilac-demo-driver.F90 b/lilac/src/lilac-demo-driver.F90 deleted file mode 100644 index 328b869cf8..0000000000 --- a/lilac/src/lilac-demo-driver.F90 +++ /dev/null @@ -1,283 +0,0 @@ -program lilac_demo_driver - - use lnd_comp_mct , only: lnd_init_mct, lnd_run_mct, lnd_final_mct - use seq_flds_mod , only: & - seq_flds_x2l_states, seq_flds_x2l_fluxes, seq_flds_x2l_fields, & - seq_flds_l2x_states, seq_flds_l2x_fluxes, seq_flds_l2x_fields, & - seq_flds_dom_coord, seq_flds_dom_other, seq_flds_dom_fields - use seq_cdata_mod, only: seq_cdata - use seq_infodata_mod, only: seq_infodata_type, seq_infodata_putdata, seq_infodata_getdata - use shr_sys_mod , only: shr_sys_flush, shr_sys_abort - use shr_orb_mod , only: shr_orb_params - use shr_pio_mod , only: shr_pio_init1, shr_pio_init2 - use mct_mod - use ESMF - - implicit none - -#include ! mpi library include file - - !----- Clocks ----- - type(ESMF_Clock) :: driver_clock - type(ESMF_Time) :: CurrTime, StartTime, StopTime - type(ESMF_TimeInterval) :: TimeStep - type(ESMF_Alarm) :: EAlarm_stop, EAlarm_rest - type(ESMF_Calendar), target :: Calendar - integer :: yy, mm, dd, sec - - !----- MPI/MCT ----- - integer :: mpicom_lilac ! local mpicom - integer :: ID_lilac ! mct ID - integer :: ncomps ! number of separate components for MCT - integer :: ntasks, mytask ! mpicom size and rank - integer :: global_comm ! copy of mpi_comm_world for pio - integer, allocatable :: comp_id(:) ! for pio init2 - logical, allocatable :: comp_iamin(:) ! for pio init2 - character(len=64), allocatable :: comp_name(:) ! for pio init2 - integer, allocatable :: comp_comm(:), comp_comm_iam(:) ! for pio_init2 - - !----- Land Coupling Data ----- - type(seq_cdata) :: cdata ! Input land-model driver data - type(seq_infodata_type), target :: infodata ! infodata type - type(mct_aVect) :: x2l, l2x ! land model import and export states - type(mct_gGrid), target :: dom_lnd ! domain data for clm - type(mct_gsMap), target :: gsmap_lnd ! gsmap data for clm - integer :: orb_iyear ! Orbital - real*8 :: orb_eccen, orb_obliq, orb_mvelp, orb_obliqr, orb_lambm0, orb_mvelpp - character(len=128) :: case_name, case_desc, model_version, hostname, username - character(len=128) :: start_type - logical :: brnch_retain_casename, single_column, atm_aero - real*8 :: scmlat, scmlon - integer :: idx_Sa_z, idx_Sa_u, idx_Sa_v, idx_Sa_tbot, idx_Sa_ptem, & - idx_Sa_shum, idx_Sa_pbot, idx_Faxa_rainc, idx_Faxa_rainl, & - idx_Faxa_snowc, idx_Faxa_snowl, idx_Faxa_lwdn, idx_Faxa_swndr, & - idx_Faxa_swvdr, idx_Faxa_swndf, idx_Faxa_swvdf - - !----- Atm Model ----- - integer :: atm_nx, atm_ny - integer :: gsize, lsize, gstart, gend ! domain decomp info - integer, allocatable :: gindex(:) ! domain decomp info - type(mct_aVect) :: x2l_a ! data for land on atm decomp - type(mct_aVect) :: l2x_a ! data from land on atm decomp - type(mct_gsMap) :: gsmap_atm ! gsmap data for atm - type(mct_rearr) :: rearr_atm2lnd ! rearranger for atm to land - type(mct_rearr) :: rearr_lnd2atm ! rearranger for land to atm - - !----- Other ----- - integer :: n, m ! counter - character(len=128) :: string ! temporary string - integer :: ierr, rc ! local error status - integer :: iunit = 250 ! lilac log unit number - integer :: sunit = 249 ! share log unit number - character(len=*), parameter :: subname = 'lilac_demo_driver' - - logical :: debug = true - !---------------------------------------------- - type(lilac_init_data_t) :: lilac_init_data - type(lilac_clock_data_t) :: lilac_clock_data - class(lilac_t) :: lilac - - ! - ! Initialize the driver - ! - call setup_demo_driver_clock(driver_clock) - - ! - ! Initialize lilac - ! - - ! Hard code values normally supplied by the driver - call MPI_Comm_Dup(MPI_COMM_WORLD, lilac_init_data%mpicom_lilac, ierr) - call MPI_Comm_Dup(MPI_COMM_WORLD, lilac_init_data%mpicom_component, ierr) - call MPI_Comm_Dup(MPI_COMM_WORLD, lilac_init_data%mpicom_global_shared, ierr) - lilac_init_data%output_unit_lilac = 250 - lilac_init_data%output_unit_component = 251 - lilac_init_data%output_unit_global_shared = 252 - - lilac_init_data%component_name = MODEL_NAME_CTSM - - ! FIXME(bja, 2018-02) use namelist so the demo driver can serve as a test driver - lilac_clock_data%calendar_is_leap = .false. - lilac_clock_data%start_year = 2000 - lilac_clock_data%start_month = 1 - lilac_clock_data%start_day = 1 - lilac_clock_data%start_seconds = 0 - lilac_clock_data%stop_year = 2000 - lilac_clock_data%stop_month = 1 - lilac_clock_data%stop_day = 5 - lilac_clock_data%stop_seconds = 0 - lilac_clock_data%timestep_seconds = 3600 - - call lilac%Init(lilac_init_data, lilac_clock_data, debug) - - ! FIXME(bja, 2018-02) don't want to use the cdata structure, but we still - ! need to provide this information to the component?! - - !--- set mpicom and cdata memory - cdata%name = 'cdata_lilac' - cdata%ID = ID_lilac - cdata%mpicom = mpicom_lilac - cdata%dom => dom_lnd - cdata%gsmap => gsmap_lnd - cdata%infodata => infodata - - !--- set case information - case_name = 'lilac' - case_desc = 'lilac with clm' - model_version = 'lilac-v0.1' - hostname = 'undefined' - username = 'undefined' - start_type = 'startup' - brnch_retain_casename = .true. - single_column = .false. - scmlat = 0.0 - scmlon = 0.0 - atm_aero = .true. - call seq_infodata_putData(infodata, case_name=case_name, & - case_desc=case_desc, single_column=single_column, & - scmlat=scmlat, scmlon=scmlon, & - brnch_retain_casename=brnch_retain_casename, & - start_type=start_type, model_version=model_version, & - hostname=hostname, username=username, & - atm_aero=atm_aero ) - - !---------------------------------------------- - !--- lnd_init --- - !---------------------------------------------- - - !---------------------------------------------- - !--- atm and atm/lnd coupling init --- - !---------------------------------------------- - - !---------------------------------------------- - !--- Time Loop --- - !---------------------------------------------- - - call ESMF_ClockGet(driver_clock, currTime=driver_current_time, rc=rc) - do while (driver_current_time < driver_stop_time) - call ESMF_ClockAdvance(driver_clock, rc=rc) - call ESMF_ClockGet(driver_clock, currTime=driver_current_time, rc=rc) - call ESMF_TimeGet(driver_current_time, yy=yy, mm=mm, dd=dd, s=sec, rc=rc ) - write(iunit,'(1x,2a,4i6)') subname,'lilac demo driver ymds=', yy, mm, dd, sec - call shr_sys_flush(iunit) - - ! can manually override the alarms as needed - call ESMF_AlarmRingerOff(EAlarm_rest, rc=rc) - if (mod(dd, 5)==0 .and. sec==0) call ESMF_AlarmRingerOn(EAlarm_rest, rc) - - ! set the coupling data that is sent to the land model, this is on atm decomp - ! this is just sample test data - x2l_a%rAttr(:,:) = 0.0 - x2l_a%rAttr(idx_Sa_z ,:) = 30.0 ! m - x2l_a%rAttr(idx_Sa_u ,:) = 0.0 ! m/s - x2l_a%rAttr(idx_Sa_v ,:) = 0.0 ! m/s - x2l_a%rAttr(idx_Sa_tbot ,:) = 280.0 ! degK - x2l_a%rAttr(idx_Sa_ptem ,:) = 280.0 ! degK - x2l_a%rAttr(idx_Sa_shum ,:) = 0.0004 ! kg/kg - x2l_a%rAttr(idx_Sa_pbot ,:) = 100100.0 ! Pa - x2l_a%rAttr(idx_Faxa_rainc,:) = 4.0e-8 ! kg/m2s - x2l_a%rAttr(idx_Faxa_rainl,:) = 3.0e-8 ! kg/m2s - x2l_a%rAttr(idx_Faxa_snowc,:) = 1.0e-8 ! kg/m2s - x2l_a%rAttr(idx_Faxa_snowl,:) = 2.0e-8 ! kg/m2s - x2l_a%rAttr(idx_Faxa_lwdn ,:) = 200.0 ! W/m2 - x2l_a%rAttr(idx_Faxa_swndr,:) = 100.0 ! W/m2 - x2l_a%rAttr(idx_Faxa_swvdr,:) = 90.0 ! W/m2 - x2l_a%rAttr(idx_Faxa_swndf,:) = 20.0 ! W/m2 - x2l_a%rAttr(idx_Faxa_swvdf,:) = 40.0 ! W/m2 - - ! rearrange data to land decomposition - call mct_rearr_rearrange(x2l_a, x2l, rearr_atm2lnd) - - ! diagnose - write(iunit,*) subname,' x2l fields: ', yy, mm, dd, sec - ! call diag_avect(x2l_a, mpicom_lilac,'x2l_a') - call diag_avect(x2l, mpicom_lilac,'x2l') - - ! run clm - write(iunit,*) subname,' call lnd_run_mct', yy, mm, dd, sec - call lnd_run_mct(Eclock, cdata, x2l, l2x) - - ! rearrange data from land decomposition - call mct_rearr_rearrange(l2x, l2x_a, rearr_lnd2atm) - - ! diagnose - write(iunit,*) subname,' l2x fields: ', yy, mm, dd, sec - call diag_avect(l2x, mpicom_lilac,'l2x') - ! call diag_avect(l2x_a, mpicom_lilac,'l2x_a') - enddo - - lilac%Shutdown() - -contains - !====================================================================== - - SUBROUTINE diag_avect(av, mpicom, comment) - - use seq_infodata_mod - - implicit none - - ! !INPUT/OUTPUT PARAMETERS: - - type(mct_aVect) , intent(in) :: av - integer , intent(in) :: mpicom - character(len=*), intent(in) :: comment - - !--- local --- - integer :: n, k ! counters - integer :: npts, nptsg ! number of local/global pts in AV - integer :: kflds ! number of fields in AV - real*8, pointer :: sumbuf (:) ! sum buffer - real*8, pointer :: sumbufg(:) ! sum buffer reduced - integer :: iam ! pe number - type(mct_string) :: mstring ! mct char type - character(len=128):: itemc ! string converted to char - - !----- formats ----- - character(*), parameter :: subName = '(diag_avect) ' - - !---------------------------------------------------------------- - - npts = mct_aVect_lsize(AV) - kflds = mct_aVect_nRattr(AV) - allocate(sumbuf(kflds), sumbufg(kflds)) - - sumbuf = 0.0 - - do k = 1, kflds - do n = 1, npts - sumbuf(k) = sumbuf(k) + (AV%rAttr(k, n)) - enddo - enddo - - call MPI_REDUCE(sumbuf, sumbufg, kflds, MPI_REAL8, MPI_SUM, 0, mpicom, ierr) - call MPI_COMM_RANK(mpicom, iam, ierr) - - if (iam == 0) then - do k = 1, kflds - call mct_aVect_getRList(mstring, k, AV) - itemc = mct_string_toChar(mstring) - call mct_string_clean(mstring) - write(iunit, 101) trim(comment), k, sumbufg(k), trim(itemc) - enddo - call shr_sys_flush(iunit) - endif - - deallocate(sumbuf, sumbufg) - -101 format('comm_diag ', a, 1x, i3, es26.19, 1x, a) - - end subroutine diag_avect - - !====================================================================== - - subroutine setup_demo_driver_clocks() - - implicit none - - - - end subroutine setup_demo_driver_clocks - -end program lilac_demo_driver - diff --git a/lilac/src/lilac.F90 b/lilac/src/lilac.F90 deleted file mode 100644 index 9f89e97d9f..0000000000 --- a/lilac/src/lilac.F90 +++ /dev/null @@ -1,399 +0,0 @@ -module lilac - ! - ! Public interface to lilac - ! - - implicit none - - private - - integer, parameter :: LILAC_MASTER_PROC = 0 - integer, parameter :: LILAC_NUM_COMPONENTS = 1 - - type, public :: lilac_t - private - character(len=STRING_32) :: component_name - logical :: debug - - integer :: mpicom_lilac - integer :: my_mpi_rank_lilac - integer :: num_mpi_tasks_lilac - integer :: mct_comp_id - - type(ESMF_Clock) :: lilac_clock - type(ESMF_Time) :: start_time - type(ESMF_Time) :: stop_time - type(ESMF_TimeInterval) :: time_step - type(ESMF_Alarm) :: alarm_stop - type(ESMF_Alarm) :: alarm_restart - - contains - ! Public API - procedure, public :: Init => lilac_init - procedure, public :: Shutdown => lilac_shutdown - procudure, public :: AdvanceTime => lilac_advance_time - - ! private initialization routines - procedure, private :: lilac_init_parallel - procedure, private :: lilac_init_logging - procedure, private :: lilac_init_io - procedure, private :: lilac_init_clocks - procedure, private :: lilac_init_fields - procedure, private :: lilac_init_orbit - procedure, private :: lilac_init_land - procedure, private :: lilac_init_coupling - - ! private shudown routines - procedure, private :: lilac_shutdown_land - procedure, private :: lilac_shutdown_parallel - - end type lilac_t - - - -contains - - ! - ! Public API - ! - subroutine lilac_init(this, init_data, clock_data, debug) - - use lilac_api_types, only : lilac_clock_data_t - use mct_mod, only : mct_world_init - - implicit none - - class(lilac_t), intent(inout) :: this - type(lilac_init_data_t), intent(in) :: init_data - type(lilac_clock_data_t), intent(in) :: clock_data - logical, intent(in) :: debug - - this%debug = debug - this%component_name = init_data%component_name - - call this%lilac_init_parallel(init_data%mpicom_lilac, & - init_data%mpicom_component, init_data%mpicom_global_shared) - - call this%lilac_init_logging(init_data%output_unit_lilac, init_data%output_unit_component) - call this%lilac_init_io() - call this%lilac_init_clocks(clock_data) - ! TODO(bja, 2018-03) use init_data%component_name to do some model - ! specific setup, including getting a list of hard coded input and output - ! exchange fields. - call this%lilac_init_fields() - call this%lilac_init_orbit() - call this%lilac_init_land() - call this%lilac_init_coupling() - - end subroutine lilac_init - - subroutine lilac_advance_time(this) - - implicit none - - class(lilac_t), intent(inout) :: this - - end subroutine lilac_advance_time - - subroutine lilac_shutdown(this) - - implicit none - - class(lilac_t), intent(inout) :: this - - if (this%my_mpi_rank_lilac == LILAC_MASTER_PROC) then - write(this%output_unit, *) 'Shutting down lilac interface for component ', this%component_name, ' ...' - end if - - call shr_sys_flush(this%output_unit) - - call this%lilac_shutdown_land() - call this%lilac_shutdown_parallel() - - if (this%my_mpi_rank_lilac == LILAC_MASTER_PROC) then - write(this%output_unit, *) 'lilac shut down for component ', this%component_name, ' complete.' - end if - - end subroutine lilac_shutdown - - ! - ! Private work functions - ! - subroutine lilac_init_parallel(this, mpicom_lilac, mpicom_component, mpicom_global_shared) - ! Initialize parallel components, e.g. MPI, MCT - - implicit none - - class(lilac_t), intent(inout) :: this - - ! should be safe if previously initialized - call MPI_Init(ierr) - - this%mpicom_lilac = mpicom_lilac - this%mpicom_component = mpicom_component - - call MPI_COMM_RANK(this%mpicom_lilac, this%my_lilac_mpi_rank, ierr) - call MPI_COMM_SIZE(this%mpicom_lilac, this%num_lilac_mpi_tasks, ierr) - - ! FIXME(bja, 2018-03) 1 (component | lilac) or two (component & lilac)? - this%mct_num_comps = 1 - this%mct_comp_id = 1 - ! NOTE(bja, 2018-02) MPI_COMM_WORLD should eventually be initialized on - ! the union of the lilac and component communicators! If 2, then need arrays?! - call mct_world_init(this%mct_num_comps, MPI_COMM_WORLD, this%mpicom_lilac, this%mct_comp_id) - - end subroutine lilac_init_parallel - - subroutine lilac_init_logging(this, output_unit_lilac, output_unit_global_shared) - - implicit none - - class(lilac_t), intent(inout) :: this - - character(len=*), parameter :: subname = 'lilac_init_logging' - ! open logfile for lilac - - this%output_unit = output_unit_lilac - - ! FIXME(bja, 2018-03) do we want a single shared log file, or one per rank? - write(log_file_name,'(a,i4.4)') 'lilac.log.', this%my_mpi_rank_lilac - open(this%output_unit, file=trim(log_file_name)) - if (this%my_mpi_rank_lilac == LILAC_MASTER_PROC) then - write(this%output_unit, *) subname, ': Starting lilac interface for component: ', this%component_name - write(this%output_unit, *) subname, ': num lilac tasks = ', this%num_mpi_tasks_lilac - write(this%output_unit, *) subname, ': my mpi rank = ', this%my_mpi_rank_lilac - write(this%output_unit, *) subname, ': mct component ID = ', this%mct_comp_id_lilac - call shr_sys_flush(this%output_unit) - end if - - ! NOTE(bja, 2018-02) these are setting global variables within the shr code! - call shr_file_setLogUnit(output_unit_global_shared) - call shr_file_setLogLevel(1) - - end subroutine lilac_init_logging - - subroutine lilac_init_io(this) - ! NOTE(bja, 2018-02) There is only a *single science component* in each - ! lilac instance. For now assuming just the science component interacts - ! with pio, but lilac may have some parallel data I/O needs. If so it - ! needs to be added to these data structures! - - implicit none - - class(lilac_t), intent(inout) :: this - - ! - call shr_pio_init1(LILAC_NUM_COMPONENTS, 'pio_in', this%mpicom_lilac) - allocate( & - comp_id(LILAC_NUM_COMPONENTS), & - comp_name(LILAC_NUM_COMPONENTS), & - comp_iamin(LILAC_NUM_COMPONENTS), & - comp_comm(LILAC_NUM_COMPONENTS), & - comp_comm_iam(LILAC_NUM_COMPONENTS)) - - index = 1 - comp_id(index) = 1 - comp_name(index) = MODEL_NAME_LILAC // '_' // trim(this%component_name) - comp_iamin(index) = .true. - comp_comm(index) = this%mpicom_lilac - comp_comm_iam(index) = this%my_mpi_rank_lilac - - ! TODO(bja, 2018-03) Never have more than one science component, remove loop? - do n = 1, LILAC_NUM_COMPONENTS - index = index + n - comp_id(index) = ID_component - comp_name(index) = this%component_name - comp_iamin(index) = .true. - comp_comm(index) = this%mpicom_component - comp_comm_iam(index) = mytask ! FIXME(bja, 2018-02) when land and lilac are on different comms?? - enddo - - call shr_pio_init2(comp_id, comp_name, comp_iamin, comp_comm, comp_comm_iam) - - deallocate(comp_id, comp_name, comp_iamin, comp_comm, comp_comm_iam) - - end subroutine lilac_init_io - - subroutine lilac_init_clocks(this, clock_data) - - use ESMF - - implicit none - - class(lilac_t), intent(inout) :: this - type(lilac_clock_data_t), intent(in) :: clock_data - - type(ESMF_Calendar), target :: calendar ! FIXME(bja, 2018-02) does not need to be freed?! - integer :: cal_kind_flag - integer :: year, month, day, sec - - if (clock_data%calendar_is_leap == .false.) then - cal_kind_flag = ESMF_CALKIND_NOLEAP - else - ! FIXME(bja, 2018-03) not implemented error! ESMF_CALKIND_GREGORIAN? - end if - - if (ESMF_IsInitialized() /= .true.) then - ! NOTE(bja, 2018-03) allocates and operates on global data! - call ESMF_Initialize(rc=rc) - end if - - calendar = ESMF_CalendarCreate( name='lilac', calkindflag=cal_kind_flag, rc=rc ) - call ESMF_TimeSet(this%start_time, yy=clock_data%start_year, mm=clock_data%start_month, & - dd=clock_data%start_day, s=clock_data%start_seconds, calendar=calendar, rc=rc) - - call ESMF_TimeSet(this%stop_time , yy=clock_data%stop_year, mm=clock_data%stop_month, & - dd=clock_data%stop_day, s=clock_data%stop_seconds, calendar=calendar, rc=rc) - - call ESMF_TimeIntervalSet(this%time_step, s=clock_data%time_step_seconds, rc=rc) - - this%lilac_clock = ESMF_ClockCreate(name='lilac_clock', & - TimeStep=this%time_step, startTime=this%start_time, & - RefTime=this%start_time, stopTime=this%stop_time, rc=rc) - - this%alarm_stop = ESMF_AlarmCreate(name='alarm_stop' , & - clock=this%lilac_clock, ringTime=this%stop_time, rc=rc) - this%alarm_rest = ESMF_AlarmCreate(name='alarm_restart', & - clock=this%lilac_clock, ringTime=this%stop_time, rc=rc) - - if (this%debug .and. this%my_mpi_rank_lilac == LILAC_MASTER_PROC) then - call ESMF_TimeGet( start_time, yy=year, mm=month, dd=day, s=sec, rc=rc ) - write(this%output_unit, '(1x,2a,4i6)') subname,': start time ymds=', year, month, day, sec - call ESMF_TimeGet( stop_time, yy=year, mm=month, dd=day, s=sec, rc=rc ) - write(this%output_unit, '(1x,2a,4i6)') subname,': stop time ymds=', year, month, day, sec - call shr_sys_flush(this%output_unit) - end if - - end subroutine lilac_init_clocks - - subroutine lilac_init_fields(this) - ! Set coupling fields. - - implicit none - - class(lilac_t), intent(inout) :: this - - ! FIXME(bja, 2018-02) this should be dynamically created at runtime - ! instead of hard coded! - - seq_flds_dom_coord='lat:lon' - seq_flds_dom_other='area:aream:mask:frac' - seq_flds_dom_fields=trim(seq_flds_dom_coord)//':'//trim(seq_flds_dom_other) - - seq_flds_x2l_states= 'Sa_z:Sa_u:Sa_v:Sa_tbot:Sa_ptem:Sa_shum:Sa_pbot:Sg_icemask:Sg_icemask_coupled_fluxes' - seq_flds_x2l_fluxes= 'Faxa_rainc:Faxa_rainl:Faxa_snowc:Faxa_snowl:Faxa_lwdn:Faxa_swndr:Faxa_swvdr:Faxa_swndf:Faxa_swvdf:Faxa_bcphidry:Faxa_bcphodry:Faxa_bcphiwet:Faxa_ocphidry:Faxa_ocphodry:Faxa_ocphiwet:Faxa_dstwet1:Faxa_dstwet2:Faxa_dstwet3:Faxa_dstwet4:Faxa_dstdry1:Faxa_dstdry2:Faxa_dstdry3:Faxa_dstdry4:Flrr_flood:Flrr_volr' - seq_flds_x2l_fields= trim(seq_flds_x2l_states)//':'//trim(seq_flds_x2l_fluxes) - - seq_flds_l2x_states= 'Sl_avsdr:Sl_anidr:Sl_avsdf:Sl_anidf:Sl_tref:Sl_qref:Sl_t:Sl_fv:Sl_ram1:Sl_snowh:Sl_u10' - seq_flds_l2x_fluxes= 'Fall_swnet:Fall_taux:Fall_tauy:Fall_lat:Fall_sen:Fall_lwup:Fall_evap:Fall_flxdst1:Fall_flxdst2:Fall_flxdst3:Fall_flxdst4:Flrl_rofl:Flrl_rofi:Fall_voc001:Fall_voc002:Fall_voc003:Fall_voc004:Fall_voc005:Fall_voc006:Fall_voc007:Fall_voc008' - seq_flds_l2x_fields= trim(seq_flds_l2x_states)//':'//trim(seq_flds_l2x_fluxes) - - - end subroutine lilac_init_fields - - subroutine lilac_init_orbit(this) - - implicit none - - class(lilac_t), intent(inout) :: this - - !--- set orbital params - orb_iyear = 1990 - call shr_orb_params(orb_iyear, orb_eccen, orb_obliq, orb_mvelp, & - orb_obliqr, orb_lambm0, orb_mvelpp, .true.) - call seq_infodata_putData(infodata, orb_eccen=orb_eccen, orb_mvelpp=orb_mvelpp, & - orb_lambm0=orb_lambm0, orb_obliqr=orb_obliqr ) - - - end subroutine lilac_init_orbit - - subroutine lilac_init_land(this) - - implicit none - - write(this%output_unit,*) subname,' calling lnd_init_mct' - call shr_sys_flush(this%output_unit) - call lnd_init_mct(Eclock, cdata, x2l, l2x) - - call diag_avect(l2x, mpicom_lilac,'l2x_init') - - idx_Sa_z = mct_avect_indexra(x2l,'Sa_z') - idx_Sa_u = mct_avect_indexra(x2l,'Sa_u') - idx_Sa_v = mct_avect_indexra(x2l,'Sa_v') - idx_Sa_tbot = mct_avect_indexra(x2l,'Sa_tbot') - idx_Sa_ptem = mct_avect_indexra(x2l,'Sa_ptem') - idx_Sa_shum = mct_avect_indexra(x2l,'Sa_shum') - idx_Sa_pbot = mct_avect_indexra(x2l,'Sa_pbot') - idx_Faxa_rainc = mct_avect_indexra(x2l,'Faxa_rainc') - idx_Faxa_rainl = mct_avect_indexra(x2l,'Faxa_rainl') - idx_Faxa_snowc = mct_avect_indexra(x2l,'Faxa_snowc') - idx_Faxa_snowl = mct_avect_indexra(x2l,'Faxa_snowl') - idx_Faxa_lwdn = mct_avect_indexra(x2l,'Faxa_lwdn') - idx_Faxa_swndr = mct_avect_indexra(x2l,'Faxa_swndr') - idx_Faxa_swvdr = mct_avect_indexra(x2l,'Faxa_swvdr') - idx_Faxa_swndf = mct_avect_indexra(x2l,'Faxa_swndf') - idx_Faxa_swvdf = mct_avect_indexra(x2l,'Faxa_swvdf') - - end subroutine lilac_init_land - - subroutine lilac_init_coupling(this) - - implicit none - - class(lilac_t), intent(inout) :: this - - ! set atm grid size to land grid size in this example. for a real - ! atmosphere model, the atm and land grids should agree at the outset. - call seq_infodata_getData(infodata, lnd_nx=atm_nx, lnd_ny=atm_ny) - - ! atm decomp - gstart = ((mytask * atm_nx * atm_ny) / ntasks) + 1 - gend = (((mytask+1) * atm_nx * atm_ny) / ntasks) - lsize = gend - gstart + 1 - gsize = atm_nx * atm_ny - allocate(gindex(lsize)) - do n = gstart, gend - m = n-gstart+1 - gindex(m) = n - end do - write(this%output_unit,'(1x,2a,5i8)') subname,' atm decomp = ', mytask, gsize, lsize, gstart, gend - - ! initialize land grid on atm decomp - call mct_gsMap_init(gsmap_atm, gindex, mpicom_lilac, ID_lilac, lsize, gsize) - deallocate(gindex) - - ! initialize rearrangers between atm and land decomps - call mct_rearr_init(gsmap_atm, gsmap_lnd, mpicom_lilac, rearr_atm2lnd) - call mct_rearr_init(gsmap_lnd, gsmap_atm, mpicom_lilac, rearr_lnd2atm) - - ! initialize atm avects from land avects with atm lsize - call mct_avect_init(x2l_a, x2l, lsize) - call mct_avect_zero(x2l_a) - call mct_avect_init(l2x_a, l2x, lsize) - call mct_avect_zero(l2x_a) - - end subroutine lilac_init_coupling - - subroutine lilac_shutdown_land(this) - - implicit none - - class(lilac_t), intent(inout) :: this - - write(this%output_unit, *) 'lilac shutting down component ', this%comp_name - call lnd_final_mct(Eclock, cdata, x2l, l2x) - - end subroutine lilac_shutdown_land - - subroutine lilac_shutdown_parallel(this) - - implicit none - - class(lilac_t), intent(inout) :: this - - ! FIXME(bja, 2018-02) need to determine if it is our responsibility to shutdown mpi or the caller!? - ! call MPI_Finalize(ierr) - - end subroutine lilac_shutdown_parallel - -end module lilac diff --git a/lilac/src/lilac_api_types.F90 b/lilac/src/lilac_api_types.F90 deleted file mode 100644 index da66aefe04..0000000000 --- a/lilac/src/lilac_api_types.F90 +++ /dev/null @@ -1,43 +0,0 @@ -module lilac_api_types - - implicit none - - use lilac_constants, only : STRING_128 - -contains - - type :: lilac_init_data_t - character(len=STRING_32) :: component_name - integer :: mpicom_lilac - integer :: mpicom_component - integer :: output_unit_lilac - integer :: output_unit_global_shared ! this should be the same for all instances of lilac! - integer :: output_unit_component - - end type lilac_init_data_t - - type :: lilac_clock_data_t - logical :: calendar_is_leap - integer :: start_year - integer :: start_month - integer :: start_day - integer :: start_second ! seconds since midnight - - integer :: stop_year - integer :: stop_month - integer :: stop_day - integer :: stop_second ! seconds since midnight - - integer :: time_step_seconds - end type lilac_clock_data_t - - - type :: lilac_exchange_fields_t - character(len=STRING_128) :: long_name - character(len=STRING_128) :: short_name - character(len=STRING_128) :: field_name - character(len=STRING_128) :: units - integer :: field_type - end type lilac_exchange_fields_t - -end module lilac_api_types diff --git a/lilac/src/lilac_constants.F90 b/lilac/src/lilac_constants.F90 deleted file mode 100644 index d9e6442206..0000000000 --- a/lilac/src/lilac_constants.F90 +++ /dev/null @@ -1,18 +0,0 @@ -module lilac_constants - - implicit none - -contains - - integer, parameter :: STRING_128 = 128 - integer, parameter :: STRING_32 = 32 - - integer, parameter :: FIELD_TYPE_INTEGER = 0 - integer, parameter :: FIELD_TYPE_REAL_8BYTE = 1 - - ! known models names - character(len=*), parameter :: MODEL_NAME_LILAC = 'lilac' - character(len=*), parameter :: MODEL_NAME_CTSM = 'ctsm' - character(len=*), parameter :: MODEL_NAME_TEST = 'test' - -end module lilac_constants diff --git a/lilac/src/stub_comp_mct.F90 b/lilac/src/stub_comp_mct.F90 deleted file mode 100644 index de792d6c58..0000000000 --- a/lilac/src/stub_comp_mct.F90 +++ /dev/null @@ -1,8 +0,0 @@ -module stub_comp_mct - - implicit none - -contains - - -end module stub_comp_mct From 702363f681b695057c92c7a1aff98c8c73ce3df5 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 10 Sep 2018 12:21:03 -0700 Subject: [PATCH 22/34] move to dockerfile, builds deps and should run on travis now --- external/esmf | 2 +- lilac/.dockerignore | 328 +++++++++++++++++++++++++++++++++++++ lilac/.travis.yml | 28 +--- lilac/Dockerfile | 19 +++ lilac/ci/environment.yml | 6 +- lilac/ci/install_esmf.sh | 10 +- lilac/ci/install_pfunit.sh | 9 +- lilac/ci/install_python.sh | 11 +- 8 files changed, 366 insertions(+), 47 deletions(-) create mode 100644 lilac/.dockerignore create mode 100644 lilac/Dockerfile diff --git a/external/esmf b/external/esmf index d2761c276d..3a9c142262 160000 --- a/external/esmf +++ b/external/esmf @@ -1 +1 @@ -Subproject commit d2761c276daf2ccac33193f28e925e974d180309 +Subproject commit 3a9c142262b247189abd8dbca0d63e6dbb3a8207 diff --git a/lilac/.dockerignore b/lilac/.dockerignore new file mode 100644 index 0000000000..96c67bd53f --- /dev/null +++ b/lilac/.dockerignore @@ -0,0 +1,328 @@ +# Created by .ignore support plugin (hsz.mobi) + +### Vim template +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ + +# auto-generated tag files +tags + +### Cpp template +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Makefile +cmake_install.cmake +install_manifest.txt +CTestTestfile.cmake + +### Emacs template +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile### VirtualEnv template +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json + +### Linux template +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +### C template +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su + +### Windows template +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### KDevelop4 template +*.kdev4 +.kdev4/ + +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# IPython Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# dotenv +.env + +# virtualenv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +### NodeJS template +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git +node_modules + diff --git a/lilac/.travis.yml b/lilac/.travis.yml index e3a280e1b9..5f8d66aede 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -1,34 +1,20 @@ language: cpp -sudo: false +sudo: required dist: trusty notifications: email: false -matrix: - include: - - os: linux - compiler: gcc - apt: - packages: - - gfortran - - cmake - - cmake-data +services: + - docker before_install: - - export FC=/usr/bin/gfortran - - ./ci/install_python.sh - - ./ci/install_esmf.sh - - ./ci/install_pfunit.sh + - docker version install: - - cd ${TRAVIS_BUILD_DIR} - - mkdir -p build && cd build - - cmake .. - - make + - docker build -t lilac . before_script: - - echo "before script" + - docker images script: - - cd ${TRAVIS_BUILD_DIR} - - ./build/prog + - docker run -t lilac diff --git a/lilac/Dockerfile b/lilac/Dockerfile new file mode 100644 index 0000000000..ae9bd09913 --- /dev/null +++ b/lilac/Dockerfile @@ -0,0 +1,19 @@ +FROM centos:latest +LABEL description="LILAC development environment" + + +RUN yum install -y curl; yum upgrade -y; yum update -y; yum clean all +RUN yum -y install wget bzip2 gcc gcc-c++ gcc-gfortran mpich make + +ADD ./ /usr/src/lilac +RUN cd /usr/src/lilac && mkdir -p build + +WORKDIR /usr/src/lilac +ENV PATH /usr/local/miniconda/bin:$PATH +RUN /usr/src/lilac/ci/install_python.sh +RUN /usr/src/lilac/ci/install_esmf.sh +RUN /usr/src/lilac/ci/install_pfunit.sh + +# RUN mkdir -p /usr/src/lilac/build && cd /usr/src/lilac/build && cmake .. + +CMD /bin/bash -c "ctest" diff --git a/lilac/ci/environment.yml b/lilac/ci/environment.yml index 0d0d6a023d..735c333293 100644 --- a/lilac/ci/environment.yml +++ b/lilac/ci/environment.yml @@ -2,8 +2,4 @@ channels: - conda-forge dependencies: - python=3.6 - - xarray - - esmpy - - cmake - - pip: - - cpp-coveralls + - cmake>=3 diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index fef18a466f..95c89cef7e 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -2,17 +2,15 @@ set -e set -x -cd ${HOME} +cd external/esmf -export FC="/usr/bin/gfortran" -export ESMF_COMPILER="/usr/bin/gfortran" +export FC="gfortran" +export ESMF_COMPILER="gfortran" -git clone https://git.code.sf.net/p/esmf/esmf deps/esmf -cd deps/esmf export ESMF_DIR=$PWD export ESMF_INSTALL_PREFIX=/usr/ make -j4 lib make install export ESMFMKFILE=${ESMF_INSTALL_PREFIX}/esmf.mk -cd ${TRAVIS_BUILD_DIR} +cd - \ No newline at end of file diff --git a/lilac/ci/install_pfunit.sh b/lilac/ci/install_pfunit.sh index 84b5918c12..9a2aff43e3 100755 --- a/lilac/ci/install_pfunit.sh +++ b/lilac/ci/install_pfunit.sh @@ -3,18 +3,15 @@ set -e set -x -cd ${HOME} - -git clone https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git ${HOME}/deps/pfunit -cd deps/pfunit +cd external/pfunit # set environemnt variables export F90=gfortran export F90_VENDOR=GNU -mkdir build +mkdir -p build cd build cmake .. make install INSTALL_DIR=/usr -cd ${TRAVIS_BUILD_DIR} +cd - diff --git a/lilac/ci/install_python.sh b/lilac/ci/install_python.sh index 2a2d2a551f..02a15e043c 100755 --- a/lilac/ci/install_python.sh +++ b/lilac/ci/install_python.sh @@ -4,16 +4,11 @@ set -e set -x # Install miniconda -wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ${HOME}/miniconda.sh -bash ~/miniconda.sh -b -p $HOME/miniconda -export PATH="$HOME/miniconda/bin:$PATH" +wget --quiet http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /usr/src/miniconda.sh +bash /usr/src/miniconda.sh -b -p /usr/local/miniconda conda update conda --yes conda clean -tipy conda config --set always_yes yes --set changeps1 no conda --version -conda env create -f ci/environment.yml --name lilac - -source activate lilac - -cd ${TRAVIS_BUILD_DIR} +conda install -c conda-forge cmake>=3 From 69f6b3e7eda97279e85df9182d8c8ec6b738844a Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 10 Sep 2018 17:35:12 -0700 Subject: [PATCH 23/34] cleanup and move to docker-compose --- lilac/.dockerignore | 1 + lilac/.gitignore | 2 + lilac/.travis.yml | 5 +- lilac/CMakeLists.txt | 78 ++----------------- lilac/Dockerfile | 30 ++++--- lilac/ci/build_and_test_lilac.sh | 16 ++++ lilac/ci/install_esmf.sh | 6 +- lilac/ci/install_pfunit.sh | 4 +- .../{Modules => CMakeModules}/FindESMF.cmake | 29 +++---- lilac/docker-compose.yml | 10 +++ 10 files changed, 78 insertions(+), 103 deletions(-) create mode 100755 lilac/ci/build_and_test_lilac.sh rename lilac/cmake/{Modules => CMakeModules}/FindESMF.cmake (74%) create mode 100644 lilac/docker-compose.yml diff --git a/lilac/.dockerignore b/lilac/.dockerignore index 96c67bd53f..2fc5d54e03 100644 --- a/lilac/.dockerignore +++ b/lilac/.dockerignore @@ -326,3 +326,4 @@ build/Release # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git node_modules +build/ \ No newline at end of file diff --git a/lilac/.gitignore b/lilac/.gitignore index 411de5d96e..21537a4ee9 100644 --- a/lilac/.gitignore +++ b/lilac/.gitignore @@ -12,3 +12,5 @@ components/ # generated python files *.pyc + +build/ diff --git a/lilac/.travis.yml b/lilac/.travis.yml index 5f8d66aede..40f2c1981a 100644 --- a/lilac/.travis.yml +++ b/lilac/.travis.yml @@ -9,12 +9,13 @@ services: before_install: - docker version + - docker-compose version install: - - docker build -t lilac . + - docker-compose build lilac before_script: - - docker images + - docker-compose images script: - docker run -t lilac diff --git a/lilac/CMakeLists.txt b/lilac/CMakeLists.txt index 56d348a737..9d94ba5afe 100644 --- a/lilac/CMakeLists.txt +++ b/lilac/CMakeLists.txt @@ -3,6 +3,10 @@ cmake_minimum_required(VERSION 2.8.12.1) project(LILAC Fortran) enable_language(Fortran) +set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/CMakeModules") + +find_package (ESMF) + # Local CMake modules if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU") @@ -21,78 +25,8 @@ endif() set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}") -if(DEFINED PFUNIT_INSTALL) - message(STATUS "Manual setup of variable PFUNIT_INSTALL: ${PFUNIT_INSTALL}") - set(PFUNIT_DIR ${PFUNIT_INSTALL}) -else() - include(ExternalProject) - - set(ExternalProjectCMakeArgs - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/external/pfunit - -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER} - ) - ExternalProject_Add(pfunit - DOWNLOAD_COMMAND git submodule update - DOWNLOAD_DIR ${PROJECT_SOURCE_DIR} - SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/pfunit - BINARY_DIR ${PROJECT_BINARY_DIR}/external/pfunit-build - STAMP_DIR ${PROJECT_BINARY_DIR}/external/pfunit-stamp - TMP_DIR ${PROJECT_BINARY_DIR}/external/pfunit-tmp - INSTALL_DIR ${PROJECT_BINARY_DIR}/external - CMAKE_ARGS ${ExternalProjectCMakeArgs} - ) - include_directories(${PROJECT_BINARY_DIR}/external/pfunit/mod) - set(PFUNIT_DIR ${PROJECT_BINARY_DIR}/external/pfunit) -endif() - - -if(DEFINED ESMF_INSTALL) - message(STATUS "Manual setup of variable ESMF_INSTALL: ${ESMF_INSTALL}") - set(ESMF_DIR ${ESMF_INSTALL}) - -else() - message(STATUS "We will build ESMF") - include(ExternalProject) - - # set(ENV{ESMFMKFILE} "${PROJECT_BINARY_DIR}/external/esmf/esmf.mk") - - set(ExternalProjectCMakeArgs - ESMF_DIR=${ESMF_DIR} - ESMF_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/external - ESMF_INSTALL_BINDIR=${PROJECT_BINARY_DIR}/bin/ - ESMF_INSTALL_DOCDIR=${PROJECT_BINARY_DIR}/doc/ - ESMF_INSTALL_HEADERDIR=${PROJECT_BINARY_DIR}/include/ - ESMF_INSTALL_LIBDIR=${PROJECT_BINARY_DIR}/lib/ - ESMF_INSTALL_MODDIR=${PROJECT_BINARY_DIR}/mod/ - ) - - ExternalProject_Add(esmf - DOWNLOAD_COMMAND git submodule update - DOWNLOAD_DIR ${PROJECT_SOURCE_DIR}/external - SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/esmf - INSTALL_DIR ${PROJECT_BINARY_DIR}/external - BUILD_IN_SOURCE TRUE - CMAKE_ARGS ${ExternalProjectCMakeArgs} - CONFIGURE_COMMAND "" - BUILD_COMMAND make - INSTALL_COMMAND pwd && make install - ) - - # link to ESMF - # find_package(ESMF) - # include_directories(${PROJECT_BINARY_DIR}/include/) - # set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ ${ESMF_COMPILER_LINE}") - # set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_LINK_LINE} -g -cpp") - # TODO figure out how to get these out once ESMF is compiled - set(ESMF_COMPILER_LINE, "-O -m64 -mcmodel=small -ffree-line-length-none -fopenmp -I/Users/jhamman/Dropbox/src/lilac/external/esmf/mod/modO/Darwin.gfortran.64.mpiuni.default -I/Users/jhamman/Dropbox/src/lilac/external/esmf/src/include -ffree-form") - set(ESMF_LINK_LINE, "-m64 -mcmodel=small -fopenmp -L/Users/jhamman/Dropbox/src/lilac/external/esmf/lib/libO/Darwin.gfortran.64.mpiuni.default -L/opt/local/lib/gcc5/gcc/x86_64-apple-darwin17/5.5.0/../../../ -lesmf -lstdc++") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_COMPILER_LINE}") - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_LINK_LINE} -g -cpp") - - - -endif() +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ ${ESMF_COMPILER_LINE}") +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_LINK_LINE} -g -cpp") add_subdirectory(lilac) add_subdirectory(tests) diff --git a/lilac/Dockerfile b/lilac/Dockerfile index ae9bd09913..ef7b9610b0 100644 --- a/lilac/Dockerfile +++ b/lilac/Dockerfile @@ -1,19 +1,29 @@ FROM centos:latest LABEL description="LILAC development environment" - RUN yum install -y curl; yum upgrade -y; yum update -y; yum clean all -RUN yum -y install wget bzip2 gcc gcc-c++ gcc-gfortran mpich make +RUN yum -y install wget bzip2 gcc gcc-c++ gcc-gfortran mpich make git + +WORKDIR /usr/src/lilac/ + +RUN mkdir -p external +RUN mkdir -p ci -ADD ./ /usr/src/lilac -RUN cd /usr/src/lilac && mkdir -p build +COPY external/esmf external/esmf +COPY external/pfunit external/pfunit +COPY ci/* ci/ -WORKDIR /usr/src/lilac +# Install some remaining dependencies ENV PATH /usr/local/miniconda/bin:$PATH -RUN /usr/src/lilac/ci/install_python.sh -RUN /usr/src/lilac/ci/install_esmf.sh -RUN /usr/src/lilac/ci/install_pfunit.sh +RUN ./ci/install_python.sh -# RUN mkdir -p /usr/src/lilac/build && cd /usr/src/lilac/build && cmake .. +# Install ESMF +# TODO: what's up with the .../lib/lib0/... maybe move this somewhere more logical? +RUN pwd +RUN ls $PWD +RUN ./ci/install_esmf.sh +ENV ESMF_CONFIG_FILE /usr/lib/libO/Linux.gfortran.64.mpiuni.default/esmf.mk -CMD /bin/bash -c "ctest" +# # Install PFUNIT +RUN ./ci/install_pfunit.sh +ENV PFUNIT_INSTALL /usr/pfunit diff --git a/lilac/ci/build_and_test_lilac.sh b/lilac/ci/build_and_test_lilac.sh new file mode 100755 index 0000000000..ce8b993ae4 --- /dev/null +++ b/lilac/ci/build_and_test_lilac.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +set -e +set -x + +echo "building lilac" + +# build lilac +mkdir -p /lilac/build +cd /lilac/build && cmake .. +make -j 4 + +echo "done building lilac, time to run the tests..." + +# run test suite +ctest \ No newline at end of file diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 95c89cef7e..d14f747771 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -2,15 +2,15 @@ set -e set -x -cd external/esmf +cd ./external/esmf export FC="gfortran" export ESMF_COMPILER="gfortran" export ESMF_DIR=$PWD -export ESMF_INSTALL_PREFIX=/usr/ +export ESMF_INSTALL_PREFIX=/usr make -j4 lib make install -export ESMFMKFILE=${ESMF_INSTALL_PREFIX}/esmf.mk +export ESMFMKFILE=/usr/lib/libO/Linux.gfortran.64.mpiuni.default/esmf.mk cd - \ No newline at end of file diff --git a/lilac/ci/install_pfunit.sh b/lilac/ci/install_pfunit.sh index 9a2aff43e3..9290ab7306 100755 --- a/lilac/ci/install_pfunit.sh +++ b/lilac/ci/install_pfunit.sh @@ -3,7 +3,7 @@ set -e set -x -cd external/pfunit +cd ./external/pfunit # set environemnt variables export F90=gfortran @@ -12,6 +12,6 @@ export F90_VENDOR=GNU mkdir -p build cd build cmake .. -make install INSTALL_DIR=/usr +make install INSTALL_DIR=/usr/pfunit cd - diff --git a/lilac/cmake/Modules/FindESMF.cmake b/lilac/cmake/CMakeModules/FindESMF.cmake similarity index 74% rename from lilac/cmake/Modules/FindESMF.cmake rename to lilac/cmake/CMakeModules/FindESMF.cmake index ba50c7a141..b8fb622ee8 100644 --- a/lilac/cmake/Modules/FindESMF.cmake +++ b/lilac/cmake/CMakeModules/FindESMF.cmake @@ -1,24 +1,24 @@ -# +# # Author: Ali Samii - The University of Texas at Austin # # Distributed under GPL2. For more info refer to: # https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html # -# +# # FindESMF # -------- -# +# # This script tries to find the ESMF library. You have to define # the path to esmf.mk file in your installation directory. # # There are plans to extend this script to find ESMF automatically, # but until then, you should set the environment variable # -# ESMFMKFILE = /path/to/esmf.mk +# ESMF_CONFIG_FILE = /path/to/esmf.mk # # in your installation directory. The output will be # -# ESMF_LINK_LINE : All the libraries and link line stuff +# ESMF_LINK_LINE : All the libraries and link line stuff # ESMF_COMPILER_LINE : All the compiler flags and include dirs # # @@ -27,28 +27,28 @@ string(ASCII 27 Esc) # Checking if ESMF exists -if (NOT DEFINED ENV{ESMFMKFILE} AND NOT DEFINED ESMFMKFILE) +if (NOT DEFINED ENV{ESMF_CONFIG_FILE} AND NOT DEFINED ESMF_CONFIG_FILE) message (FATAL_ERROR "\n${Esc}[1;31m!! Error: You need ESMF library to \ run this program. please set the environment \ - variable ESMFMKFILE to point to esmf.mk in \ + variable ESMF_CONFIG_FILE to point to esmf.mk in \ your ESMF installation directory. \ Try something like: ${Esc}[m\ - export ESMFMKFILE=/path/to/esmf.mk && cmake ${CMAKE_SOURCE_DIR}") + export ESMF_CONFIG_FILE=/path/to/esmf.mk && cmake ${CMAKE_SOURCE_DIR}") endif () -if (NOT EXISTS $ENV{ESMFMKFILE} AND NOT EXISTS ${ESMFMKFILE}) +if (NOT EXISTS $ENV{ESMF_CONFIG_FILE} AND NOT EXISTS ${ESMF_CONFIG_FILE}) message (FATAL_ERROR "${Esc}[1;31m Error: esmf.mk file is not found at \ - ${ESMFMKFILE} ${Esc}[m") + ${ESMF_CONFIG_FILE} ${Esc}[m") else () message ("+>${Esc}[1;32m The config file for ESMF library is found.${Esc}[m") endif () -if (DEFINED ENV{ESMFMKFILE}) - set(ESMFMKFILE $ENV{ESMFMKFILE} CACHE STRING "") +if (DEFINED ENV{ESMF_CONFIG_FILE}) + set(ESMF_CONFIG_FILE $ENV{ESMF_CONFIG_FILE} CACHE STRING "") endif () -set(ESMFMKFILE ${ESMFMKFILE} CACHE STRING "") +set(ESMF_CONFIG_FILE ${ESMF_CONFIG_FILE} CACHE STRING "") -file(STRINGS "${ESMFMKFILE}" all_vars) +file(STRINGS "${ESMF_CONFIG_FILE}" all_vars) foreach(str ${all_vars}) string(REGEX MATCH "^[^#]" def ${str}) if (def) @@ -68,3 +68,4 @@ set (ESMF_LINK_LINE "${ESMF_F90LINKOPTS} \ set (ESMF_COMPILER_LINE "${ESMF_F90COMPILEOPTS} \ ${ESMF_F90COMPILEPATHS} \ ${ESMF_F90COMPILEFREENOCPP}") + diff --git a/lilac/docker-compose.yml b/lilac/docker-compose.yml new file mode 100644 index 0000000000..422b0bc607 --- /dev/null +++ b/lilac/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3' + +services: + lilac: + build: . + container_name: lilac + volumes: + - .:/lilac + command: /lilac/ci/build_and_test_lilac.sh + From bc96784d64dcf019e6ab09ecf26383dffeb80f74 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 10 Sep 2018 23:07:23 -0700 Subject: [PATCH 24/34] boiler plat docs --- lilac/docs/Makefile | 20 ++++++ lilac/docs/conf.py | 164 +++++++++++++++++++++++++++++++++++++++++++ lilac/docs/index.rst | 24 +++++++ 3 files changed, 208 insertions(+) create mode 100644 lilac/docs/Makefile create mode 100644 lilac/docs/conf.py create mode 100644 lilac/docs/index.rst diff --git a/lilac/docs/Makefile b/lilac/docs/Makefile new file mode 100644 index 0000000000..0e382f9883 --- /dev/null +++ b/lilac/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = lilac +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/lilac/docs/conf.py b/lilac/docs/conf.py new file mode 100644 index 0000000000..767f7287b1 --- /dev/null +++ b/lilac/docs/conf.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/stable/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'lilac' +copyright = '2018, Joseph Hamman' +author = 'Joseph Hamman' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.intersphinx', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'lilacdoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'lilac.tex', 'lilac Documentation', + 'Joseph Hamman', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'lilac', 'lilac Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'lilac', 'lilac Documentation', + author, 'lilac', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} \ No newline at end of file diff --git a/lilac/docs/index.rst b/lilac/docs/index.rst new file mode 100644 index 0000000000..4549b0c639 --- /dev/null +++ b/lilac/docs/index.rst @@ -0,0 +1,24 @@ +.. lilac documentation master file, created by + sphinx-quickstart on Mon Sep 10 22:59:54 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to lilac's documentation! +================================= + +LILAC, Lightweight Infrastructure for Land Atmosphere Coupling. + +More coming soon. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` From ec59330c32844c10e8458c308802d8ccfca02d17 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 10 Sep 2018 23:08:25 -0700 Subject: [PATCH 25/34] add docs badge --- lilac/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/lilac/README.md b/lilac/README.md index a817ad0649..b3315ab04a 100644 --- a/lilac/README.md +++ b/lilac/README.md @@ -3,6 +3,7 @@ LILAC, Lightweight Infrastructure for Land Atmosphere Coupling. [![Build Status](https://travis-ci.org/jhamman/lilac.svg?branch=master)](https://travis-ci.org/jhamman/lilac) +[![Documentation Status](https://readthedocs.org/projects/ctsm-lilac/badge/?version=latest)](https://ctsm-lilac.readthedocs.io/en/latest/?badge=latest) Currently working on: - Setting up CI and CMake From eba309c7136587ab0a42441f4676d10034736579 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Wed, 26 Sep 2018 12:55:09 -0700 Subject: [PATCH 26/34] more build and doc updates --- lilac/CMakeLists.txt | 10 +- lilac/Dockerfile | 2 +- lilac/ci/build_and_test_lilac.sh | 5 +- lilac/ci/code_format.sh | 11 + lilac/ci/emacs-fortran-formating-script.lisp | 46 +++ lilac/ci/install_esmf.sh | 15 +- lilac/cmake/CMakeModules/FindESMF.cmake | 6 +- lilac/docs/api.rst | 14 + lilac/docs/index.rst | 41 ++- lilac/lilac/atmos_comp.f90 | 39 --- lilac/lilac/coupler_mod.f90 | 326 ------------------- lilac/lilac/esmf_utils.f90 | 28 +- lilac/lilac/land_comp.f90 | 1 - lilac/lilac/lilac.f90 | 13 +- 14 files changed, 153 insertions(+), 404 deletions(-) create mode 100755 lilac/ci/code_format.sh create mode 100644 lilac/ci/emacs-fortran-formating-script.lisp create mode 100644 lilac/docs/api.rst delete mode 100644 lilac/lilac/atmos_comp.f90 delete mode 100644 lilac/lilac/coupler_mod.f90 delete mode 100644 lilac/lilac/land_comp.f90 diff --git a/lilac/CMakeLists.txt b/lilac/CMakeLists.txt index 9d94ba5afe..8e7c0cf87a 100644 --- a/lilac/CMakeLists.txt +++ b/lilac/CMakeLists.txt @@ -3,9 +3,10 @@ cmake_minimum_required(VERSION 2.8.12.1) project(LILAC Fortran) enable_language(Fortran) -set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/CMakeModules") +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/CMakeModules") -find_package (ESMF) +find_package(MPI REQUIRED) +find_package(ESMF REQUIRED) # Local CMake modules @@ -25,8 +26,11 @@ endif() set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}") -set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}\ ${ESMF_COMPILER_LINE}") +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_COMPILER_LINE}") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_LINK_LINE} -g -cpp") +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -I /usr/include/ -I/usr/src/lilac/external/esmf/src/Infrastructure/Util/include") + +message("CMAKE_Fortran_FLAGS:" ${CMAKE_Fortran_FLAGS}) add_subdirectory(lilac) add_subdirectory(tests) diff --git a/lilac/Dockerfile b/lilac/Dockerfile index ef7b9610b0..c7b5923a04 100644 --- a/lilac/Dockerfile +++ b/lilac/Dockerfile @@ -2,7 +2,7 @@ FROM centos:latest LABEL description="LILAC development environment" RUN yum install -y curl; yum upgrade -y; yum update -y; yum clean all -RUN yum -y install wget bzip2 gcc gcc-c++ gcc-gfortran mpich make git +RUN yum -y install wget bzip2 gcc gcc-c++ gcc-gfortran mpich-devel make git WORKDIR /usr/src/lilac/ diff --git a/lilac/ci/build_and_test_lilac.sh b/lilac/ci/build_and_test_lilac.sh index ce8b993ae4..176478a5c6 100755 --- a/lilac/ci/build_and_test_lilac.sh +++ b/lilac/ci/build_and_test_lilac.sh @@ -7,8 +7,11 @@ echo "building lilac" # build lilac mkdir -p /lilac/build + +export CMAKE_PREFIX_PATH=/usr/lib64/mpich/bin + cd /lilac/build && cmake .. -make -j 4 +make # -j 4 echo "done building lilac, time to run the tests..." diff --git a/lilac/ci/code_format.sh b/lilac/ci/code_format.sh new file mode 100755 index 0000000000..828b0e229a --- /dev/null +++ b/lilac/ci/code_format.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# Run emacs/list on all Fortran source files +format_fortran () { + echo "Parsing $1 as language Fortran" + emacs --batch -l ./emacs-fortran-formating-script.lisp \ + -f f90-batch-indent-region $1 +} +export -f format_fortran +find ../lilac/ -iregex ".*\.F[0-9]*" -exec bash -c 'format_fortran "$0"' {} \; +find ../tests/ -iregex ".*\.F[0-9]*" -exec bash -c 'format_fortran "$0"' {} \; diff --git a/lilac/ci/emacs-fortran-formating-script.lisp b/lilac/ci/emacs-fortran-formating-script.lisp new file mode 100644 index 0000000000..99ed3f3981 --- /dev/null +++ b/lilac/ci/emacs-fortran-formating-script.lisp @@ -0,0 +1,46 @@ +(defun f90-batch-indent-region () + "Run `f90-batch-beatify-region' on the specified filename. +Use this from the command line, with `-batch'; +it won't work in an interactive Emacs. +For example, invoke \"emacs -batch -l ~/.emacs-batch-f90-indent -f f90-batch-indent-region file.f\"" + (if (not noninteractive) + (error "`f90-batch-indent-region' is to be used only with -batch")) + (let ((make-backup-files nil) + (version-control nil) + (auto-save-default nil) + (find-file-run-dired nil) + (kept-old-versions 259259) + (kept-new-versions 259259)) + (let ((error 0) + file + (files ())) + (while command-line-args-left + (setq file (expand-file-name (car command-line-args-left))) + (cond ((not (file-exists-p file)) + (message ">> %s does not exist!" file) + (setq error 1 + command-line-args-left (cdr command-line-args-left))) + ((file-directory-p file) + (setq command-line-args-left + (nconc (directory-files file) + (cdr command-line-args-left)))) + (t + (setq files (cons file files) + command-line-args-left (cdr command-line-args-left))))) + (while files + (setq file (car files) + files (cdr files)) + (condition-case err + (progn + (if buffer-file-name (kill-buffer (current-buffer))) + (find-file file) + (buffer-disable-undo (current-buffer)) + (set-buffer-modified-p nil) + (f90-mode) + (message (file-name-nondirectory buffer-file-name)) + ; compute indentation of first + ; line + (f90-indent-subprogram) + (f90-downcase-keywords) + (save-buffer) +)))))) diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index d14f747771..0f39bae1e1 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -5,12 +5,21 @@ set -x cd ./external/esmf export FC="gfortran" -export ESMF_COMPILER="gfortran" + +# export PATH="/usr/lib64/mpich/bin/":${PATH} export ESMF_DIR=$PWD -export ESMF_INSTALL_PREFIX=/usr +export ESMF_COMM="mpiuni" +export ESMF_COMPILER="gfortran" +export ESMF_INSTALL_PREFIX="/usr/local" +export ESMF_INSTALL_LIBDIR="/usr/local/lib" +export ESMF_INSTALL_MODDIR="/usr/local/mod" +export ESMF_INSTALL_BINDIR="/usr/local/bin" +export ESMF_INSTALL_DOCDIR="/usr/local/doc" +export ESMFMKFILE="${ESMF_INSTALL_LIBDIR}/esmf.mk" + make -j4 lib make install -export ESMFMKFILE=/usr/lib/libO/Linux.gfortran.64.mpiuni.default/esmf.mk +make install check cd - \ No newline at end of file diff --git a/lilac/cmake/CMakeModules/FindESMF.cmake b/lilac/cmake/CMakeModules/FindESMF.cmake index b8fb622ee8..39b00447c1 100644 --- a/lilac/cmake/CMakeModules/FindESMF.cmake +++ b/lilac/cmake/CMakeModules/FindESMF.cmake @@ -36,7 +36,7 @@ if (NOT DEFINED ENV{ESMF_CONFIG_FILE} AND NOT DEFINED ESMF_CONFIG_FILE) export ESMF_CONFIG_FILE=/path/to/esmf.mk && cmake ${CMAKE_SOURCE_DIR}") endif () -if (NOT EXISTS $ENV{ESMF_CONFIG_FILE} AND NOT EXISTS ${ESMF_CONFIG_FILE}) +if (NOT EXISTS ENV{ESMF_CONFIG_FILE} AND NOT EXISTS ${ESMF_CONFIG_FILE}) message (FATAL_ERROR "${Esc}[1;31m Error: esmf.mk file is not found at \ ${ESMF_CONFIG_FILE} ${Esc}[m") else () @@ -44,10 +44,12 @@ else () endif () if (DEFINED ENV{ESMF_CONFIG_FILE}) - set(ESMF_CONFIG_FILE $ENV{ESMF_CONFIG_FILE} CACHE STRING "") + set(ESMF_CONFIG_FILE ENV{ESMF_CONFIG_FILE} CACHE STRING "") endif () set(ESMF_CONFIG_FILE ${ESMF_CONFIG_FILE} CACHE STRING "") +message ("Parsing ESMF_CONFIG_FILE: " ${ESMF_CONFIG_FILE}) + file(STRINGS "${ESMF_CONFIG_FILE}" all_vars) foreach(str ${all_vars}) string(REGEX MATCH "^[^#]" def ${str}) diff --git a/lilac/docs/api.rst b/lilac/docs/api.rst new file mode 100644 index 0000000000..6859fd3e1a --- /dev/null +++ b/lilac/docs/api.rst @@ -0,0 +1,14 @@ +LILAC API +========= + +LILAC provides a high-level API (in Fortran) for coupling to CTSM. +LILAC was built using the assumption that the Atmosphere model +component in each LILAC application would opperate as the "driver". + +The atmosphere component will need to call each of the following subroutines: + + * `lilac_init` + * `lilac_run` + * `lilac_final` + +TODO: fill in this section as the api comes together. diff --git a/lilac/docs/index.rst b/lilac/docs/index.rst index 4549b0c639..f6c4a09751 100644 --- a/lilac/docs/index.rst +++ b/lilac/docs/index.rst @@ -1,12 +1,39 @@ -.. lilac documentation master file, created by - sphinx-quickstart on Mon Sep 10 22:59:54 2018. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +LILAC: Lightweight Infrastructure for Land Atmosphere Coupling +============================================================== + +LILAC is a new coupling interface for the Community Terrestrial Systems Model +(CTSM). It provides a high-level Fortran API for coupling CTSM to atmospheric +models such as the Weather Research and Forecast (WRF) model. LILAC makes +extensive use of the Earth System Modeling Framework (ESMF). + +Building LILAC +-------------- + +LILAC can be build using CMake. + + $ cd /lilac/build && cmake .. + $ make + +For development and testing purposes, LILAC can also be built using a +`docker-compose` script. + + $ docker-compose build + # docker-compose run + +Testing LILAC +------------- + +LILAC includes a full test suite including unit tests and a number of +simplified coupled model tests. To run these tests, simply run the `ctest` +command: + + $ ctest + +Note, if you are using the docker-compose development, the `docker-compose run` +command will build and run LILAC automatically. + -Welcome to lilac's documentation! -================================= -LILAC, Lightweight Infrastructure for Land Atmosphere Coupling. More coming soon. diff --git a/lilac/lilac/atmos_comp.f90 b/lilac/lilac/atmos_comp.f90 deleted file mode 100644 index b8ecec4a2d..0000000000 --- a/lilac/lilac/atmos_comp.f90 +++ /dev/null @@ -1,39 +0,0 @@ - -module atmos_comp - - ! ESMF Framework module - use ESMF - implicit none - - public atmos_register - -contains - - - subroutine atmos_register(comp, rc) - type(ESMF_GridComp) :: comp - integer, intent(out) :: rc - - ! Initialize return code - rc = ESMF_SUCCESS - - print *, "Atmosphere Register starting" - - ! Register the callback routines. - - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=atmos_init, & - rc=rc) - if (rc/=ESMF_SUCCESS) return ! bail out - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=atmos_run, & - rc=rc) - if (rc/=ESMF_SUCCESS) return ! bail out - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=atmos_final, & - rc=rc) - if (rc/=ESMF_SUCCESS) return ! bail out - - print *, "Registered Initialize, Run, and Finalize routines" - print *, "Atmosphere Register returning" - - end subroutine atmos_register - -end module atmos_comp diff --git a/lilac/lilac/coupler_mod.f90 b/lilac/lilac/coupler_mod.f90 deleted file mode 100644 index 36354e7c88..0000000000 --- a/lilac/lilac/coupler_mod.f90 +++ /dev/null @@ -1,326 +0,0 @@ - module CouplerMod - - use ESMF - - implicit none - - private - - ! Public entry point - public Coupler_register - - contains - - -!------------------------------------------------------------------------------ -!BOPI -! !IROUTINE: Coupler_register - public SetServices entry point - -! !INTERFACE: - subroutine Coupler_register(comp, rc) -! -! !ARGUMENTS: - type(ESMF_CplComp) :: comp - integer, intent(out) :: rc -! -! !DESCRIPTION: -! User-supplied setservices routine. -! -! The arguments are: -! \begin{description} -! \item[comp] -! Component. -! \item[rc] -! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, -! otherwise {\tt ESMF\_FAILURE}. -! \end{description} -! -!EOPI - - ! because none of the arguments to this subroutine will ever be optional, - ! go ahead and set rc to an initial return code before using it below. - ! (this makes some eager error-checking compilers happy.) - rc = ESMF_FAILURE - - ! Register the callback routines. - - call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=coupler_init, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=coupler_run, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=coupler_final, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - print *, "CouplerMod: Registered Initialize, Run, and Finalize routines" - - end subroutine - - -!------------------------------------------------------------------------------ -!BOPI -! !IROUTINE: coupler_init - coupler init routine - -! !INTERFACE: - subroutine coupler_init(comp, importState, exportState, clock, rc) - -! -! !ARGUMENTS: - type(ESMF_CplComp) :: comp - type(ESMF_State) :: importState, exportState - type(ESMF_Clock) :: clock - integer, intent(out) :: rc -! -! !DESCRIPTION: -! User-supplied init routine. -! -! The arguments are: -! \begin{description} -! \item[comp] -! Component. -! \item[importState] -! Nested state object containing import data. -! \item[exportState] -! Nested state object containing export data. -! \item[clock] -! External clock. -! \item[rc] -! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, -! otherwise {\tt ESMF\_FAILURE}. -! \end{description} -! -!EOPI - -! ! Local variables - type(ESMF_Field) :: src_field, dst_field - type(ESMF_VM) :: vm - character(ESMF_MAXSTR) :: statename - - print *, "Coupler Init starting" - - ! because none of the arguments to this subroutine will ever be optional, - ! go ahead and set rc to an initial return code before using it below. - ! (this makes some eager error-checking compilers happy.) - rc = ESMF_FAILURE - - ! Get VM from coupler component to use in computing redistribution - call ESMF_CplCompGet(comp, vm=vm, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - ! Use placeholder SIE - call ESMF_StateGet(importState, name=statename, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call ESMF_StateGet(importState, "SIE", src_field, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call ESMF_StateGet(exportState, "SIE", dst_field, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - ! Compute routehandle - ! Since state items are needed by default, mark Fields not needed during coupling - if (trim(statename) .eq. "FlowSolver Feedback") then - call setFieldNeeded(importState, "U", .false., rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call setFieldNeeded(importState, "P", .false., rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call setFieldNeeded(importState, "Q", .false., rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - call ESMF_FieldRedistStore(src_field, dst_field, & - routehandle=fromFlow_rh, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - endif - - if (trim(statename) .eq. "Injection Feedback") then - call setFieldNeeded(importState, "U", .false., rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call setFieldNeeded(importState, "P", .false., rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call setFieldNeeded(importState, "Q", .false., rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call setFieldNeeded(importState, "FLAG", .false., rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - call ESMF_FieldRedistStore(src_field, dst_field, & - routehandle=fromInject_rh, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - endif - - print *, "Coupler Init returning" - - end subroutine coupler_init - - -!------------------------------------------------------------------------------ -!BOPI -! !IROUTINE: coupler_run - coupler run routine - -! !INTERFACE: - subroutine coupler_run(comp, importState, exportState, clock, rc) - -! -! !ARGUMENTS: - type(ESMF_CplComp) :: comp - type(ESMF_State) :: importState, exportState - type(ESMF_Clock) :: clock - integer, intent(out) :: rc -! -! !DESCRIPTION: -! User-supplied run routine. -! -! The arguments are: -! \begin{description} -! \item[comp] -! Component. -! \item[importState] -! Nested state object containing import data. -! \item[exportState] -! Nested state object containing export data. -! \item[clock] -! External clock. -! \item[rc] -! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, -! otherwise {\tt ESMF\_FAILURE}. -! \end{description} -! -!EOPI - - ! Local variables - type(ESMF_Field) :: srcfield, dstfield - type(ESMF_RouteHandle) :: rh - - character(len=ESMF_MAXSTR) :: statename - - integer :: i, datacount - character(len=ESMF_MAXSTR), dimension(7) :: datanames - - ! none of the arguments to this subroutine will ever be optional, so - ! go ahead and set rc to an initial return code before using it below. - ! (this makes some eager error-checking compilers happy.) - rc = ESMF_FAILURE - - datacount = 7 - datanames(1) = "SIE" - datanames(2) = "U" - datanames(3) = "V" - datanames(4) = "RHO" - datanames(5) = "P" - datanames(6) = "Q" - datanames(7) = "FLAG" - - ! In this case, the coupling is symmetric - you call redist going - ! both ways - so we only care about the coupling direction in order - ! to get the right routehandle selected. - call ESMF_StateGet(importState, name=statename, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - if (trim(statename) .eq. "FlowSolver Feedback") then - rh = fromFlow_rh - else - rh = fromInject_rh - endif - - do i=1, datacount - - ! check isneeded flag here - if (.not. isFieldNeeded(importState, datanames(i), rc=rc)) then - !print *, "skipping field ", trim(datanames(i)), " not needed" - cycle - endif - - !print *, "processing field ", trim(datanames(i)), " as needed" -!BOE -! !DESCRIPTION: -! \subsubsection{Example of Redist Usage} -! -! The following piece of code provides an example of calling the data -! redistribution routine between two Fields in the Coupler Component. -! Unlike regrid, which translates between -! different Grids, redist translates between different DELayouts on -! the same Grid. The first two lines get the Fields from the -! States, each corresponding to a different subcomponent. One is -! an Export State and the other is an Import State. -! -!BOC - call ESMF_StateGet(importState, datanames(i), srcfield, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call ESMF_StateGet(exportState, datanames(i), dstfield, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) -!EOC -! -! The redist routine uses information contained in the Fields and the -! Coupler VM object to call the communication routines to move the data. -! Because many Fields may share the same Grid association, the same -! routing information may be needed repeatedly. Route information is -! saved so the precomputed information can be retained. The following -! is an example of a Field redist call: -! -!BOC - call ESMF_FieldRedist(srcfield, dstfield, routehandle=rh, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - -!EOC -!EOE - - enddo - - ! rc has the last error code already - - end subroutine coupler_run - - -!------------------------------------------------------------------------------ -!BOPI -! !IROUTINE: coupler_final - finalization routine - -! !INTERFACE: - subroutine coupler_final(comp, importState, exportState, clock, rc) - -! -! !ARGUMENTS: - type(ESMF_CplComp) :: comp - type(ESMF_State) :: importState, exportState - type(ESMF_Clock) :: clock - integer, intent(out) :: rc -! -! !DESCRIPTION: -! User-supplied finalize routine. -! -! The arguments are: -! \begin{description} -! \item[comp] -! Component. -! \item[importState] -! Nested state object containing import data. -! \item[exportState] -! Nested state object containing export data. -! \item[clock] -! External clock. -! \item[rc] -! Return code; equals {\tt ESMF\_SUCCESS} if there are no errors, -! otherwise {\tt ESMF\_FAILURE}. -! \end{description} -! -!EOPI - - print *, "Coupler Final starting" - - ! none of the arguments to this subroutine will ever be optional, so - ! go ahead and set rc to an initial return code before using it below. - ! (this makes some eager error-checking compilers happy.) - rc = ESMF_FAILURE - - ! Only thing to do here is release redist and route handles - call ESMF_FieldRedistRelease(fromFlow_rh, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - call ESMF_FieldRedistRelease(fromInject_rh, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - rc = ESMF_SUCCESS - - print *, "Coupler Final returning" - - end subroutine coupler_final - - - end module CouplerMod diff --git a/lilac/lilac/esmf_utils.f90 b/lilac/lilac/esmf_utils.f90 index 4d2a817b41..62e96759d6 100644 --- a/lilac/lilac/esmf_utils.f90 +++ b/lilac/lilac/esmf_utils.f90 @@ -1,9 +1,9 @@ module esmf_utils -! Wrappers and derived types exposing ESMF components to LILAC + ! Wrappers and derived types exposing ESMF components to LILAC -#include "ESMF.h" +#include "ESMC.h" use ESMF implicit none @@ -204,18 +204,18 @@ subroutine atoms_register(comp, rc) ! Set the entry points for standard ESMF Component methods call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & - userRoutine=atoms_init, rc=rc) + userRoutine=atoms_init, rc=rc) call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & - userRoutine=atoms_copy_atm_to_lilac, phase=1, rc=rc) + userRoutine=atoms_copy_atm_to_lilac, phase=1, rc=rc) call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & - userRoutine=atoms_copy_lilac_to_atm, phase=2, rc=rc) + userRoutine=atoms_copy_lilac_to_atm, phase=2, rc=rc) call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & - userRoutine=atoms_final, rc=rc) + userRoutine=atoms_final, rc=rc) ! TODO: check rcs rc = ESMF_SUCCESS - end subroutine + end subroutine atoms_register subroutine land_register(comp, rc) type(ESMF_GridComp) :: comp ! must not be optional @@ -225,16 +225,16 @@ subroutine land_register(comp, rc) ! Set the entry points for standard ESMF Component methods call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & - userRoutine=land_init, rc=rc) + userRoutine=land_init, rc=rc) call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & - userRoutine=land_run, rc=rc) + userRoutine=land_run, rc=rc) call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & - userRoutine=land_final, rc=rc) + userRoutine=land_final, rc=rc) ! TODO: check rcs rc = ESMF_SUCCESS - end subroutine + end subroutine land_register subroutine cpl_register(comp, rc) type(ESMF_GridComp) :: comp ! must not be optional @@ -255,15 +255,15 @@ subroutine cpl_register(comp, rc) rc = ESMF_SUCCESS - end subroutine + end subroutine cpl_register function return_error(rc, returnrc) ! fight with this later integer, intent(in) :: rc, returnrc if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, rcToReturn=returnrc)) then - return_error = .true. + return_error = .true. else - return_error = .false. + return_error = .false. endif end function return_error diff --git a/lilac/lilac/land_comp.f90 b/lilac/lilac/land_comp.f90 deleted file mode 100644 index 1a4baf536d..0000000000 --- a/lilac/lilac/land_comp.f90 +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lilac/lilac/lilac.f90 b/lilac/lilac/lilac.f90 index b6393f9164..b80c3c8616 100644 --- a/lilac/lilac/lilac.f90 +++ b/lilac/lilac/lilac.f90 @@ -1,6 +1,5 @@ module lilac -#include "ESMF.h" use ESMF use atmos_comp, only : atmos_setvm, atmos_register @@ -21,14 +20,14 @@ module lilac contains type, public :: LilacType - private + private - type(ESMFInfoType) :: esmf_info + type(ESMFInfoType) :: esmf_info - contains - procedure, public :: init => init - procedure, public :: run => run - procedure, public :: final => final + contains + procedure, public :: init => init + procedure, public :: run => run + procedure, public :: final => final end type LilacType contains From 6050f2276ca2eed4dfac1252889c83cd93ef3054 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Tue, 2 Oct 2018 22:50:16 -0700 Subject: [PATCH 27/34] fixes for linking to esmf, still working on linking to mpi --- lilac/Dockerfile | 17 ++++++++------- lilac/README.md | 1 + lilac/ci/install_esmf.sh | 6 ++--- lilac/cmake/CMakeModules/FindESMF.cmake | 29 ++++--------------------- 4 files changed, 16 insertions(+), 37 deletions(-) diff --git a/lilac/Dockerfile b/lilac/Dockerfile index c7b5923a04..bebcc00428 100644 --- a/lilac/Dockerfile +++ b/lilac/Dockerfile @@ -1,8 +1,12 @@ FROM centos:latest LABEL description="LILAC development environment" -RUN yum install -y curl; yum upgrade -y; yum update -y; yum clean all +RUN yum install -y curl +RUN yum upgrade -y +RUN yum update -y +RUN yum clean all RUN yum -y install wget bzip2 gcc gcc-c++ gcc-gfortran mpich-devel make git +ENV PATH="/usr/lib64/mpich/bin:${PATH}" WORKDIR /usr/src/lilac/ @@ -18,12 +22,9 @@ ENV PATH /usr/local/miniconda/bin:$PATH RUN ./ci/install_python.sh # Install ESMF -# TODO: what's up with the .../lib/lib0/... maybe move this somewhere more logical? -RUN pwd -RUN ls $PWD RUN ./ci/install_esmf.sh -ENV ESMF_CONFIG_FILE /usr/lib/libO/Linux.gfortran.64.mpiuni.default/esmf.mk +ENV ESMF_CONFIG_FILE /usr/local/lib/esmf.mk -# # Install PFUNIT -RUN ./ci/install_pfunit.sh -ENV PFUNIT_INSTALL /usr/pfunit +# Install PFUNIT +# RUN ./ci/install_pfunit.sh +# ENV PFUNIT_INSTALL /usr/pfunit diff --git a/lilac/README.md b/lilac/README.md index b3315ab04a..4184eb80d3 100644 --- a/lilac/README.md +++ b/lilac/README.md @@ -9,3 +9,4 @@ Currently working on: - Setting up CI and CMake - setup/test style (borrow from geostreams) - setup unit tests with pfunit + diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index 0f39bae1e1..d68f33969c 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -6,10 +6,8 @@ cd ./external/esmf export FC="gfortran" -# export PATH="/usr/lib64/mpich/bin/":${PATH} - export ESMF_DIR=$PWD -export ESMF_COMM="mpiuni" +export ESMF_COMM="mpich3" export ESMF_COMPILER="gfortran" export ESMF_INSTALL_PREFIX="/usr/local" export ESMF_INSTALL_LIBDIR="/usr/local/lib" @@ -20,6 +18,6 @@ export ESMFMKFILE="${ESMF_INSTALL_LIBDIR}/esmf.mk" make -j4 lib make install -make install check +# make install check cd - \ No newline at end of file diff --git a/lilac/cmake/CMakeModules/FindESMF.cmake b/lilac/cmake/CMakeModules/FindESMF.cmake index 39b00447c1..943ffd6087 100644 --- a/lilac/cmake/CMakeModules/FindESMF.cmake +++ b/lilac/cmake/CMakeModules/FindESMF.cmake @@ -26,31 +26,9 @@ # Defining the ${Esc} for syntax coloring. string(ASCII 27 Esc) -# Checking if ESMF exists -if (NOT DEFINED ENV{ESMF_CONFIG_FILE} AND NOT DEFINED ESMF_CONFIG_FILE) - message (FATAL_ERROR "\n${Esc}[1;31m!! Error: You need ESMF library to \ - run this program. please set the environment \ - variable ESMF_CONFIG_FILE to point to esmf.mk in \ - your ESMF installation directory. \ - Try something like: ${Esc}[m\ - export ESMF_CONFIG_FILE=/path/to/esmf.mk && cmake ${CMAKE_SOURCE_DIR}") -endif () +message ("Parsing ESMF_CONFIG_FILE: " $ENV{ESMF_CONFIG_FILE}) -if (NOT EXISTS ENV{ESMF_CONFIG_FILE} AND NOT EXISTS ${ESMF_CONFIG_FILE}) - message (FATAL_ERROR "${Esc}[1;31m Error: esmf.mk file is not found at \ - ${ESMF_CONFIG_FILE} ${Esc}[m") -else () - message ("+>${Esc}[1;32m The config file for ESMF library is found.${Esc}[m") -endif () - -if (DEFINED ENV{ESMF_CONFIG_FILE}) - set(ESMF_CONFIG_FILE ENV{ESMF_CONFIG_FILE} CACHE STRING "") -endif () -set(ESMF_CONFIG_FILE ${ESMF_CONFIG_FILE} CACHE STRING "") - -message ("Parsing ESMF_CONFIG_FILE: " ${ESMF_CONFIG_FILE}) - -file(STRINGS "${ESMF_CONFIG_FILE}" all_vars) +file(STRINGS "$ENV{ESMF_CONFIG_FILE}" all_vars) foreach(str ${all_vars}) string(REGEX MATCH "^[^#]" def ${str}) if (def) @@ -69,5 +47,6 @@ set (ESMF_LINK_LINE "${ESMF_F90LINKOPTS} \ set (ESMF_COMPILER_LINE "${ESMF_F90COMPILEOPTS} \ ${ESMF_F90COMPILEPATHS} \ - ${ESMF_F90COMPILEFREENOCPP}") + ${ESMF_F90COMPILEFREENOCPP} \ + ${ESMF_CXXCOMPILEPATHS}") From 26dc01727de6ca198194fd143f6ceb0027745dd7 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Fri, 5 Oct 2018 13:23:43 -0700 Subject: [PATCH 28/34] lots of updates including a mostly working build, still a WIP --- lilac/CMakeLists.txt | 6 +- lilac/ci/build_and_test_lilac.sh | 4 +- lilac/ci/install_esmf.sh | 2 +- lilac/lilac/CMakeLists.txt | 2 +- lilac/lilac/esmf_utils.f90 | 163 ++++++++++++++++--------------- 5 files changed, 93 insertions(+), 84 deletions(-) diff --git a/lilac/CMakeLists.txt b/lilac/CMakeLists.txt index 8e7c0cf87a..4268ea956d 100644 --- a/lilac/CMakeLists.txt +++ b/lilac/CMakeLists.txt @@ -6,6 +6,8 @@ enable_language(Fortran) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/CMakeModules") find_package(MPI REQUIRED) +# TODO: This should be found from the find_package call but its not working +set(CMAKE_Fortran_COMPILER "/usr/lib64/mpich/bin/mpif90") find_package(ESMF REQUIRED) # Local CMake modules @@ -28,8 +30,8 @@ set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_COMPILER_LINE}") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${ESMF_LINK_LINE} -g -cpp") -set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -I /usr/include/ -I/usr/src/lilac/external/esmf/src/Infrastructure/Util/include") - +# TODO: This should not be necessary but certain header files are missing from the build +set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -I /usr/include/ -I/usr/src/lilac/external/esmf/src/Infrastructure/Util/include -I/usr/src/lilac/external/esmf/build_config/Linux.gfortran.default -I /usr/src/lilac/external/esmf/src/include") message("CMAKE_Fortran_FLAGS:" ${CMAKE_Fortran_FLAGS}) add_subdirectory(lilac) diff --git a/lilac/ci/build_and_test_lilac.sh b/lilac/ci/build_and_test_lilac.sh index 176478a5c6..3b7fca20f5 100755 --- a/lilac/ci/build_and_test_lilac.sh +++ b/lilac/ci/build_and_test_lilac.sh @@ -10,8 +10,8 @@ mkdir -p /lilac/build export CMAKE_PREFIX_PATH=/usr/lib64/mpich/bin -cd /lilac/build && cmake .. -make # -j 4 +cd /lilac/build && cmake -D CMAKE_BUILD_TYPE=DEBUG .. +make VERBOSE=1 # -j 4 echo "done building lilac, time to run the tests..." diff --git a/lilac/ci/install_esmf.sh b/lilac/ci/install_esmf.sh index d68f33969c..bbd21faddb 100755 --- a/lilac/ci/install_esmf.sh +++ b/lilac/ci/install_esmf.sh @@ -4,7 +4,7 @@ set -x cd ./external/esmf -export FC="gfortran" +export FC="mpif90" export ESMF_DIR=$PWD export ESMF_COMM="mpich3" diff --git a/lilac/lilac/CMakeLists.txt b/lilac/lilac/CMakeLists.txt index afbc52c6c3..a92669e0ff 100644 --- a/lilac/lilac/CMakeLists.txt +++ b/lilac/lilac/CMakeLists.txt @@ -1,4 +1,4 @@ # Compile LILAC library file(GLOB_RECURSE LILAC_SOURCES *.f90 *.h) add_library(lilac ${LILAC_SOURCES}) -target_include_directories(lilac PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/lilac) +target_include_directories(lilac PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/lilac/lilac/esmf_utils.f90 b/lilac/lilac/esmf_utils.f90 index 62e96759d6..7357a9cab0 100644 --- a/lilac/lilac/esmf_utils.f90 +++ b/lilac/lilac/esmf_utils.f90 @@ -3,22 +3,25 @@ module esmf_utils ! Wrappers and derived types exposing ESMF components to LILAC -#include "ESMC.h" +#include "ESMF.h" +#include use ESMF implicit none private + character(*), parameter :: modname = "(esmf_utils)" + ! Consider renaming ESMFInfoType (add lilac to name) type, public :: ESMFInfoType private - character(len=MAXFILELENGTH) :: name + character(len=ESMF_MAXSTR) :: name type(ESMF_VM) :: vm type(ESMF_State) :: land_import type(ESMF_State) :: land_export type(ESMF_State) :: atmos_import - type(E SMF_State) :: atmos_export + type(ESMF_State) :: atmos_export type(ESMF_GridComp) :: atmos_comp type(ESMF_GridComp) :: land_comp type(ESMF_CplComp) :: cpl_comp @@ -28,9 +31,6 @@ module esmf_utils procedure, public :: run => run procedure, public :: final => final - procedure, private :: atmos_register => atmos_register - procedure, private :: land_register => land_register - procedure, private :: cpl_register => cpl_register end type ESMFInfoType contains @@ -38,17 +38,19 @@ module esmf_utils subroutine init(self, name) implicit none class(ESMFInfoType), intent(inout) :: self - character(len=MAXVARLENGTH), intent(in) :: name + character(len=ESMF_MAXSTR), intent(in) :: name ! TODO define subroutines: https://stackoverflow.com/questions/32809769/how-to-pass-subroutine-names-as-arguments-in-fortran ! Local variables - integer :: localPet, petCount, localrc, rc=ESMF_SUCCESS, userrc=ESMF_SUCCESS - character(len=ESMF_MAXSTR) :: cname1, cname2 + character(len=ESMF_MAXSTR) :: cname1, cname2, cplname + integer :: localPet, petCount, localrc, rc=ESMF_SUCCESS, userrc=ESMF_SUCCESS + + character(len=*) :: subname=trim(modname)//':(init) ' - print *, "esmf_info%init()" + call ESMF_LogWrite(subname//"esmf_info%init()", ESMF_LOGMSG_INFO) - self%name = name + self%name = trim(name) ! Create section !------------------------------------------------------------------------- @@ -57,74 +59,74 @@ subroutine init(self, name) ! only run if not esmf_isintialized() call ESMF_Initialize(vm=self%vm, defaultlogfilename="lilac.log", logkindflag=ESMF_LOGKIND_MULTI, rc=localrc) - call check(localrc, rc) + if (return_error(localrc, rc)) return ! Get number of PETs we are running with call ESMF_VMGet(self%vm, petCount=petCount, localPet=localPet, rc=localrc) - call check(localrc, rc) + if (return_error(localrc, rc)) return ! Create the 2 model components and a coupler cname1 = "land" ! use petList to define land on all PET - self%land_grid = ESMF_GridCompCreate(name=cname1, rc=localrc) - print *, "Created component ", trim(cname1), "rc =", localrc - call check(localrc, rc) + self%land_comp = ESMF_GridCompCreate(name=cname1, rc=localrc) + call ESMF_LogWrite(subname//"Created "//trim(cname1)//" component", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return cname2 = "atmosphere" ! use petList to define atmosphere on all PET self%atmos_comp = ESMF_GridCompCreate(name=cname2, rc=localrc) - print *, "Created component ", trim(cname2), "rc =", localrc - call check(localrc, rc) + call ESMF_LogWrite(subname//"Created "//trim(cname2)//" component", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return cplname = "lilac coupler" ! no petList means that coupler component runs on all PETs self%cpl_comp = ESMF_CplCompCreate(name=cplname, rc=localrc) - print *, "Created component ", trim(cplname), ", rc =", localrc - call check(localrc, rc) + call ESMF_LogWrite(subname//"Created "//trim(cplname)//" component", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return - print *, "Comp Creates finished" + call ESMF_LogWrite(subname//"Comp Creates finished", ESMF_LOGMSG_INFO) ! Register section !------------------------------------------------------------------------- call ESMF_GridCompSetServices(self%atmos_comp, userRoutine=atmos_register, userRc=userrc, rc=localrc) - print *, "atmos SetServices finished, rc= ", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"atmos SetServices finished", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return call ESMF_GridCompSetServices(self%land_comp, userRoutine=land_register, userRc=userrc, rc=localrc) - print *, "land SetServices finished, rc= ", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"land SetServices finished", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return call ESMF_CplCompSetServices(self%cpl_comp, userRoutine=cpl_register, userRc=userrc, rc=localrc) - print *, "Cpl SetServices finished, rc= ", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"Cpl SetServices finished", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return ! Init section !------------------------------------------------------------------------- ! land import/export states self%land_import = ESMF_StateCreate(name="land import", stateintent=ESMF_STATEINTENT_IMPORT, rc=localrc) - call check(localrc, rc) + if (return_error(localrc, rc)) return self%land_export = ESMF_StateCreate(name="land export", stateintent=ESMF_STATEINTENT_EXPORT, rc=localrc) - call check(localrc, rc) - call ESMF_GridCompInitialize(land, importState=self%land_import, exportState=self%land_export, userRc=userrc, rc=localrc) - call check(localrc, rc) - call check(userrc, rc) - print *, "Land Initialize finished, rc =", localrc + if (return_error(localrc, rc)) return + call ESMF_GridCompInitialize(self%land_comp, importState=self%land_import, exportState=self%land_export, userRc=userrc, rc=localrc) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return + call ESMF_LogWrite(subname//"Land Initialize finished", ESMF_LOGMSG_INFO) ! atmosphere import/export state self%atmos_import = ESMF_StateCreate(name="atmos import", & stateintent=ESMF_STATEINTENT_IMPORT, rc=localrc) - call check(localrc, rc) + if (return_error(localrc, rc)) return self%atmos_export = ESMF_StateCreate(name="atmos export", & stateintent=ESMF_STATEINTENT_EXPORT, rc=localrc) - call check(localrc, rc) + if (return_error(localrc, rc)) return call ESMF_GridCompInitialize(self%atmos_comp, exportState=self%atmos_export, userRc=userrc, rc=localrc) - print *, "Atmosphere Initialize finished, rc =", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"Atmosphere Initialize finished", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return ! call ESMF_CPLCompInitialize twice (once for each grid comp) @@ -132,42 +134,45 @@ end subroutine init subroutine run(self) implicit none + class(ESMFInfoType), intent(inout) :: self integer :: localrc, rc=ESMF_SUCCESS, userrc=ESMF_SUCCESS - print *, "esmf_info%run()" + character(len=*), parameter :: subname=trim(modname)//':(init) ' + + call ESMF_LogWrite(subname//"esmf_info%run()", ESMF_LOGMSG_INFO) ! TODO: need some help on order of imports/exports/runs and whether the land/atm both need import/export states ! atmosphere run ! copy the atmos state and put it into atmos export call ESMF_GridCompRun(self%atmos_comp, exportState=self%atmos_export, phase=1, userRc=userrc, rc=localrc) - print *, "Atmosphere Run returned, rc =", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"Atmosphere Run returned", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return ! coupler run - call ESMF_CplCompRun(self%cpl_comp, importState=self%atoms_export, exportState=self%land_import, & + call ESMF_CplCompRun(self%cpl_comp, importState=self%atmos_export, exportState=self%land_import, & userRc=userrc, rc=localrc) - print *, "Coupler Run returned, rc =", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"Coupler Run returned", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return ! land run call ESMF_GridCompRun(self%land_comp, importState=self%land_import, exportState=self%land_export, userRc=userrc, rc=localrc) - print *, "Land Run returned, rc =", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"Land Run returned", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return ! coupler run call ESMF_CplCompRun(self%cpl_comp, importState=self%land_export, exportState=self%atmos_import, & userRc=userrc, rc=localrc) - print *, "Coupler Run returned, rc =", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_LogWrite(subname//"Coupler Run returned", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return - call ESMF_GridCompRun(self%atmos_comp, importState%atmos_import, phase=2, userRc=userrc, rc=localrc) - print *, "Atmosphere Run returned, rc =", localrc - call check(localrc, rc) - call check(userrc, rc) + call ESMF_GridCompRun(self%atmos_comp, importState=self%atmos_import, phase=2, userRc=userrc, rc=localrc) + call ESMF_LogWrite(subname//"Atmosphere Run returned", ESMF_LOGMSG_INFO) + if (return_error(localrc, rc)) return + if (return_error(userrc, rc)) return end subroutine run @@ -175,32 +180,34 @@ subroutine final(self) implicit none class(ESMFInfoType), intent(inout) :: self integer :: localrc, rc=ESMF_SUCCESS + character(len=*), parameter :: subname=trim(modname)//':(final) ' - print *, "esmf_info%final()" + call ESMF_LogWrite(subname//"esmf_info%final()", ESMF_LOGMSG_INFO) ! Destroy section call ESMF_GridCompDestroy(self%atmos_comp, rc=localrc) - check(localrc, rc) + if (return_error(localrc, rc)) return call ESMF_GridCompDestroy(self%land_comp, rc=localrc) - check(localrc, rc) + if (return_error(localrc, rc)) return call ESMF_CplCompDestroy(self%cpl_comp, rc=localrc) - check(localrc, rc) + if (return_error(localrc, rc)) return call ESMF_StateDestroy(self%land_export, rc=localrc) call ESMF_StateDestroy(self%land_import, rc=localrc) - check(localrc, rc) + if (return_error(localrc, rc)) return call ESMF_StateDestroy(self%atmos_export, rc=localrc) call ESMF_StateDestroy(self%atmos_import, rc=localrc) ! do this everywhere - if return_error(localrc, rc) return + if (return_error(localrc, rc)) return - print *, "All Destroy routines done" + call ESMF_LogWrite(subname//"All Destroy routines done", ESMF_LOGMSG_INFO) end subroutine final - subroutine atoms_register(comp, rc) + subroutine atmos_register(comp, rc) type(ESMF_GridComp) :: comp ! must not be optional integer, intent(out) :: rc ! must not be optional + character(len=*), parameter :: subname=trim(modname)//':(atmos_register) ' ! Set the entry points for standard ESMF Component methods call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & @@ -215,21 +222,19 @@ subroutine atoms_register(comp, rc) rc = ESMF_SUCCESS - end subroutine atoms_register + end subroutine atmos_register subroutine land_register(comp, rc) type(ESMF_GridComp) :: comp ! must not be optional integer, intent(out) :: rc ! must not be optional + character(len=*), parameter :: subname=trim(modname)//':(lnd_register) ' ! land_* comes from ctsm esmf cap ! Set the entry points for standard ESMF Component methods - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & - userRoutine=land_init, rc=rc) - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & - userRoutine=land_run, rc=rc) - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & - userRoutine=land_final, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=land_init, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=land_run, rc=rc) + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=land_final, rc=rc) ! TODO: check rcs rc = ESMF_SUCCESS @@ -239,6 +244,7 @@ end subroutine land_register subroutine cpl_register(comp, rc) type(ESMF_GridComp) :: comp ! must not be optional integer, intent(out) :: rc ! must not be optional + character(len=*), parameter :: subname=trim(modname)//':(cpl_register) ' rc = ESMF_FAILURE @@ -251,19 +257,20 @@ subroutine cpl_register(comp, rc) call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=coupler_final, rc=rc) if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - print *, "CouplerMod: Registered Initialize, Run, and Finalize routines" + call ESMF_LogWrite(subname//"CouplerMod: Registered Initialize, Run, and Finalize routines", ESMF_LOGMSG_INFO) rc = ESMF_SUCCESS end subroutine cpl_register - function return_error(rc, returnrc) + function return_error(rc, returnrc) result(error) ! fight with this later integer, intent(in) :: rc, returnrc + logical :: error if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, rcToReturn=returnrc)) then - return_error = .true. + error = .true. else - return_error = .false. + error = .false. endif end function return_error From 1190c2e08756c0771d38f6cd613af602290568a2 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Fri, 5 Oct 2018 13:25:09 -0700 Subject: [PATCH 29/34] remove unecessary header file --- lilac/lilac/esmf_utils.f90 | 1 - 1 file changed, 1 deletion(-) diff --git a/lilac/lilac/esmf_utils.f90 b/lilac/lilac/esmf_utils.f90 index 7357a9cab0..6a40202bf7 100644 --- a/lilac/lilac/esmf_utils.f90 +++ b/lilac/lilac/esmf_utils.f90 @@ -4,7 +4,6 @@ module esmf_utils #include "ESMF.h" -#include use ESMF implicit none From 4f1b63a3723af70c3b39a71063acf28b4c4463b5 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 8 Oct 2018 10:55:40 -0700 Subject: [PATCH 30/34] passing build --- lilac/lilac/core.f90 | 317 +++++++++++++++++++++++++++++++++++++ lilac/lilac/esmf_utils.f90 | 230 ++++++++++----------------- lilac/lilac/lilac.f90 | 59 ------- 3 files changed, 404 insertions(+), 202 deletions(-) create mode 100644 lilac/lilac/core.f90 delete mode 100644 lilac/lilac/lilac.f90 diff --git a/lilac/lilac/core.f90 b/lilac/lilac/core.f90 new file mode 100644 index 0000000000..7feec6eac2 --- /dev/null +++ b/lilac/lilac/core.f90 @@ -0,0 +1,317 @@ +module lilac + + use ESMF + use esmf_utils + + implicit none + + character(*), parameter :: modname = "(core)" + + !-------------------------------------------------------------------------- + ! Public interfaces + !-------------------------------------------------------------------------- + public :: init + public :: run + public :: final + + private :: atmos_register + private :: land_register + private :: cpl_register + + type, public :: LilacType + private + + type(ESMFInfoType) :: esmf_info + character(len=ESMF_MAXSTR) :: name + + contains + procedure, public :: init => init + procedure, public :: run => run + procedure, public :: final => final + + ! register methods + procedure, nopass, private :: atmos_register => atmos_register + procedure, nopass, private :: land_register => land_register + procedure, nopass, private :: cpl_register => cpl_register + + ! Init methods + procedure, nopass, private :: atmos_init => atmos_init + procedure, nopass, private :: land_init => land_init + procedure, nopass, private :: coupler_init => coupler_init + + ! Run methods + procedure, nopass, private :: atmos_copy_atm_to_lilac => atmos_copy_atm_to_lilac + procedure, nopass, private :: atmos_copy_lilac_to_atm => atmos_copy_lilac_to_atm + procedure, nopass, private :: land_run => land_run + procedure, nopass, private :: coupler_run => coupler_run + + ! Final methods + procedure, nopass, private :: atmos_final => atmos_final + procedure, nopass, private :: land_final => land_final + procedure, nopass, private :: coupler_final => coupler_final + + end type LilacType + +contains + + subroutine init(self, name) + implicit none + class(LilacType), intent(inout) :: self + character(len=ESMF_MAXSTR), intent(in) :: name + + character(len=*), parameter :: subname=trim(modname)//':(init) ' + + call ESMF_LogWrite(subname//"Initializing lilac", ESMF_LOGMSG_INFO) + + self%name = trim(name) + + ! Initialize ESMF structures + call self%esmf_info%init(name, atmos_register, land_register, cpl_register) + + end subroutine init + + subroutine run(self) + implicit none + class(LilacType), intent(inout) :: self + + character(len=*), parameter :: subname=trim(modname)//':(run) ' + + call ESMF_LogWrite(subname//"Running lilac", ESMF_LOGMSG_INFO) + + call self%esmf_info%run() + + end subroutine run + + subroutine final(self) + implicit none + class(LilacType), intent(inout) :: self + + character(len=*), parameter :: subname=trim(modname)//':(final) ' + + call ESMF_LogWrite(subname//"Finalizing lilac", ESMF_LOGMSG_INFO) + + call self%esmf_info%final() + + end subroutine final + + subroutine atmos_register(comp, rc) + type(ESMF_GridComp) :: comp ! must not be optional + integer, intent(out) :: rc ! must not be optional + character(len=*), parameter :: subname=trim(modname)//':(atmos_register) ' + + ! Set the entry points for standard ESMF Component methods + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & + userRoutine=atmos_init, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & + userRoutine=atmos_copy_atm_to_lilac, phase=1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & + userRoutine=atmos_copy_lilac_to_atm, phase=2, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & + userRoutine=atmos_final, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + rc = ESMF_SUCCESS + + end subroutine atmos_register + + subroutine land_register(comp, rc) + type(ESMF_GridComp) :: comp ! must not be optional + integer, intent(out) :: rc ! must not be optional + character(len=*), parameter :: subname=trim(modname)//':(lnd_register) ' + + ! land_* comes from ctsm esmf cap + + ! Set the entry points for standard ESMF Component methods + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=land_init, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=land_run, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=land_final, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + rc = ESMF_SUCCESS + + end subroutine land_register + + subroutine cpl_register(comp, rc) + type(ESMF_CplComp) :: comp ! must not be optional + integer, intent(out) :: rc ! must not be optional + character(len=*), parameter :: subname=trim(modname)//':(cpl_register) ' + + rc = ESMF_FAILURE + + ! Register the callback routines. + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=coupler_init, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=coupler_run, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=coupler_final, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_LogWrite(subname//"CouplerMod: Registered Initialize, Run, and Finalize routines", ESMF_LOGMSG_INFO) + + rc = ESMF_SUCCESS + + end subroutine cpl_register + +subroutine atmos_init(comp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(atmos_init) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"atmos_init has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine atmos_init + +subroutine land_init(comp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(land_init) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"land_init has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine land_init + +subroutine coupler_init(comp, importState, exportState, clock, rc) + type(ESMF_CplComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(coupler_init) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"coupler_init has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine coupler_init + +subroutine atmos_copy_atm_to_lilac(comp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(atmos_copy_atm_to_lilac) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"atmos_copy_atm_to_lilac has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine atmos_copy_atm_to_lilac + +subroutine atmos_copy_lilac_to_atm(comp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(atmos_copy_lilac_to_atm) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"atmos_copy_lilac_to_atm has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine atmos_copy_lilac_to_atm + +subroutine land_run(comp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(land_run) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"land_run has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine land_run + +subroutine coupler_run(comp, importState, exportState, clock, rc) + type(ESMF_CplComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(coupler_run) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"coupler_run has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine coupler_run + +subroutine atmos_final(comp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(atmos_final) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"atmos_final has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine atmos_final + +subroutine land_final(comp, importState, exportState, clock, rc) + type(ESMF_GridComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(land_final) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"land_final has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine land_final + +subroutine coupler_final(comp, importState, exportState, clock, rc) + type(ESMF_CplComp) :: comp + type(ESMF_State) :: importState, exportState + type(ESMF_Clock) :: clock + integer, intent(out) :: rc + + character(len=*), parameter :: subname=trim(modname)//':(coupler_final) ' + + ! Initialize return code + rc = ESMF_SUCCESS + + call ESMF_LogWrite(subname//"coupler_final has not been implemented yet", ESMF_LOGMSG_INFO) + +end subroutine coupler_final + +end module lilac diff --git a/lilac/lilac/esmf_utils.f90 b/lilac/lilac/esmf_utils.f90 index 6a40202bf7..57f9cf0168 100644 --- a/lilac/lilac/esmf_utils.f90 +++ b/lilac/lilac/esmf_utils.f90 @@ -11,6 +11,24 @@ module esmf_utils character(*), parameter :: modname = "(esmf_utils)" + interface + subroutine userRoutine(gridcomp, rc) + use ESMF_CompMod + implicit none + type(ESMF_GridComp) :: gridcomp ! must not be optional + integer, intent(out) :: rc ! must not be optional + end subroutine userRoutine + end interface + + interface + subroutine userCplRoutine(cplcomp, rc) + use ESMF_CompMod + implicit none + type(ESMF_CplComp) :: cplcomp ! must not be optional + integer, intent(out) :: rc ! must not be optional + end subroutine userCplRoutine + end interface + ! Consider renaming ESMFInfoType (add lilac to name) type, public :: ESMFInfoType private @@ -34,18 +52,19 @@ module esmf_utils contains - subroutine init(self, name) + subroutine init(self, name, atmos_register, land_register, cpl_register) implicit none - class(ESMFInfoType), intent(inout) :: self - character(len=ESMF_MAXSTR), intent(in) :: name - - ! TODO define subroutines: https://stackoverflow.com/questions/32809769/how-to-pass-subroutine-names-as-arguments-in-fortran + class(ESMFInfoType), intent(inout) :: self + character(len=ESMF_MAXSTR), intent(in) :: name + procedure(userRoutine) :: atmos_register + procedure(userRoutine) :: land_register + procedure(userCplRoutine) :: cpl_register ! Local variables character(len=ESMF_MAXSTR) :: cname1, cname2, cplname - integer :: localPet, petCount, localrc, rc=ESMF_SUCCESS, userrc=ESMF_SUCCESS + integer :: localPet, petCount, rc=ESMF_SUCCESS - character(len=*) :: subname=trim(modname)//':(init) ' + character(len=*), parameter :: subname=trim(modname)//':(init) ' call ESMF_LogWrite(subname//"esmf_info%init()", ESMF_LOGMSG_INFO) @@ -57,75 +76,71 @@ subroutine init(self, name) ! Initialize framework and get back default global VM ! only run if not esmf_isintialized() - call ESMF_Initialize(vm=self%vm, defaultlogfilename="lilac.log", logkindflag=ESMF_LOGKIND_MULTI, rc=localrc) - if (return_error(localrc, rc)) return + call ESMF_Initialize(vm=self%vm, defaultlogfilename="lilac.log", logkindflag=ESMF_LOGKIND_MULTI, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out ! Get number of PETs we are running with - call ESMF_VMGet(self%vm, petCount=petCount, localPet=localPet, rc=localrc) - if (return_error(localrc, rc)) return + call ESMF_VMGet(self%vm, petCount=petCount, localPet=localPet, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out ! Create the 2 model components and a coupler cname1 = "land" ! use petList to define land on all PET - self%land_comp = ESMF_GridCompCreate(name=cname1, rc=localrc) + self%land_comp = ESMF_GridCompCreate(name=cname1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Created "//trim(cname1)//" component", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return cname2 = "atmosphere" ! use petList to define atmosphere on all PET - self%atmos_comp = ESMF_GridCompCreate(name=cname2, rc=localrc) + self%atmos_comp = ESMF_GridCompCreate(name=cname2, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Created "//trim(cname2)//" component", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return cplname = "lilac coupler" ! no petList means that coupler component runs on all PETs - self%cpl_comp = ESMF_CplCompCreate(name=cplname, rc=localrc) + self%cpl_comp = ESMF_CplCompCreate(name=cplname, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Created "//trim(cplname)//" component", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return call ESMF_LogWrite(subname//"Comp Creates finished", ESMF_LOGMSG_INFO) ! Register section !------------------------------------------------------------------------- - call ESMF_GridCompSetServices(self%atmos_comp, userRoutine=atmos_register, userRc=userrc, rc=localrc) + call ESMF_GridCompSetServices(self%atmos_comp, userRoutine=atmos_register, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"atmos SetServices finished", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return - call ESMF_GridCompSetServices(self%land_comp, userRoutine=land_register, userRc=userrc, rc=localrc) + call ESMF_GridCompSetServices(self%land_comp, userRoutine=land_register, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"land SetServices finished", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return - call ESMF_CplCompSetServices(self%cpl_comp, userRoutine=cpl_register, userRc=userrc, rc=localrc) + call ESMF_CplCompSetServices(self%cpl_comp, userRoutine=cpl_register, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Cpl SetServices finished", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return ! Init section !------------------------------------------------------------------------- ! land import/export states - self%land_import = ESMF_StateCreate(name="land import", stateintent=ESMF_STATEINTENT_IMPORT, rc=localrc) - if (return_error(localrc, rc)) return - self%land_export = ESMF_StateCreate(name="land export", stateintent=ESMF_STATEINTENT_EXPORT, rc=localrc) - if (return_error(localrc, rc)) return - call ESMF_GridCompInitialize(self%land_comp, importState=self%land_import, exportState=self%land_export, userRc=userrc, rc=localrc) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return + self%land_import = ESMF_StateCreate(name="land import", stateintent=ESMF_STATEINTENT_IMPORT, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + self%land_export = ESMF_StateCreate(name="land export", stateintent=ESMF_STATEINTENT_EXPORT, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_GridCompInitialize(self%land_comp, importState=self%land_import, exportState=self%land_export, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Land Initialize finished", ESMF_LOGMSG_INFO) ! atmosphere import/export state - self%atmos_import = ESMF_StateCreate(name="atmos import", & - stateintent=ESMF_STATEINTENT_IMPORT, rc=localrc) - if (return_error(localrc, rc)) return - - self%atmos_export = ESMF_StateCreate(name="atmos export", & - stateintent=ESMF_STATEINTENT_EXPORT, rc=localrc) - if (return_error(localrc, rc)) return - call ESMF_GridCompInitialize(self%atmos_comp, exportState=self%atmos_export, userRc=userrc, rc=localrc) + self%atmos_import = ESMF_StateCreate(name="atmos import", stateintent=ESMF_STATEINTENT_IMPORT, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + self%atmos_export = ESMF_StateCreate(name="atmos export", stateintent=ESMF_STATEINTENT_EXPORT, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out + + call ESMF_GridCompInitialize(self%atmos_comp, exportState=self%atmos_export, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Atmosphere Initialize finished", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return ! call ESMF_CPLCompInitialize twice (once for each grid comp) @@ -134,8 +149,8 @@ end subroutine init subroutine run(self) implicit none class(ESMFInfoType), intent(inout) :: self - integer :: localrc, rc=ESMF_SUCCESS, userrc=ESMF_SUCCESS - character(len=*), parameter :: subname=trim(modname)//':(init) ' + integer :: rc=ESMF_SUCCESS + character(len=*), parameter :: subname=trim(modname)//':(run) ' call ESMF_LogWrite(subname//"esmf_info%run()", ESMF_LOGMSG_INFO) @@ -143,135 +158,64 @@ subroutine run(self) ! atmosphere run ! copy the atmos state and put it into atmos export - call ESMF_GridCompRun(self%atmos_comp, exportState=self%atmos_export, phase=1, userRc=userrc, rc=localrc) + call ESMF_GridCompRun(self%atmos_comp, exportState=self%atmos_export, phase=1, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Atmosphere Run returned", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return ! coupler run call ESMF_CplCompRun(self%cpl_comp, importState=self%atmos_export, exportState=self%land_import, & - userRc=userrc, rc=localrc) + rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Coupler Run returned", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return ! land run - call ESMF_GridCompRun(self%land_comp, importState=self%land_import, exportState=self%land_export, userRc=userrc, rc=localrc) + call ESMF_GridCompRun(self%land_comp, importState=self%land_import, exportState=self%land_export, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Land Run returned", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return ! coupler run - call ESMF_CplCompRun(self%cpl_comp, importState=self%land_export, exportState=self%atmos_import, & - userRc=userrc, rc=localrc) + call ESMF_CplCompRun(self%cpl_comp, importState=self%land_export, exportState=self%atmos_import, rc=rc) call ESMF_LogWrite(subname//"Coupler Run returned", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - call ESMF_GridCompRun(self%atmos_comp, importState=self%atmos_import, phase=2, userRc=userrc, rc=localrc) + call ESMF_GridCompRun(self%atmos_comp, importState=self%atmos_import, phase=2, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out call ESMF_LogWrite(subname//"Atmosphere Run returned", ESMF_LOGMSG_INFO) - if (return_error(localrc, rc)) return - if (return_error(userrc, rc)) return end subroutine run subroutine final(self) implicit none class(ESMFInfoType), intent(inout) :: self - integer :: localrc, rc=ESMF_SUCCESS + integer :: rc=ESMF_SUCCESS character(len=*), parameter :: subname=trim(modname)//':(final) ' call ESMF_LogWrite(subname//"esmf_info%final()", ESMF_LOGMSG_INFO) ! Destroy section - call ESMF_GridCompDestroy(self%atmos_comp, rc=localrc) - if (return_error(localrc, rc)) return - call ESMF_GridCompDestroy(self%land_comp, rc=localrc) - if (return_error(localrc, rc)) return - call ESMF_CplCompDestroy(self%cpl_comp, rc=localrc) - if (return_error(localrc, rc)) return - - call ESMF_StateDestroy(self%land_export, rc=localrc) - call ESMF_StateDestroy(self%land_import, rc=localrc) - if (return_error(localrc, rc)) return - call ESMF_StateDestroy(self%atmos_export, rc=localrc) - call ESMF_StateDestroy(self%atmos_import, rc=localrc) - ! do this everywhere - if (return_error(localrc, rc)) return - - call ESMF_LogWrite(subname//"All Destroy routines done", ESMF_LOGMSG_INFO) - - end subroutine final + call ESMF_GridCompDestroy(self%atmos_comp, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - subroutine atmos_register(comp, rc) - type(ESMF_GridComp) :: comp ! must not be optional - integer, intent(out) :: rc ! must not be optional - character(len=*), parameter :: subname=trim(modname)//':(atmos_register) ' + call ESMF_GridCompDestroy(self%land_comp, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - ! Set the entry points for standard ESMF Component methods - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, & - userRoutine=atoms_init, rc=rc) - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & - userRoutine=atoms_copy_atm_to_lilac, phase=1, rc=rc) - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, & - userRoutine=atoms_copy_lilac_to_atm, phase=2, rc=rc) - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, & - userRoutine=atoms_final, rc=rc) - ! TODO: check rcs + call ESMF_CplCompDestroy(self%cpl_comp, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - rc = ESMF_SUCCESS + call ESMF_StateDestroy(self%land_export, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - end subroutine atmos_register + call ESMF_StateDestroy(self%land_import, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - subroutine land_register(comp, rc) - type(ESMF_GridComp) :: comp ! must not be optional - integer, intent(out) :: rc ! must not be optional - character(len=*), parameter :: subname=trim(modname)//':(lnd_register) ' + call ESMF_StateDestroy(self%atmos_export, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - ! land_* comes from ctsm esmf cap + call ESMF_StateDestroy(self%atmos_import, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - ! Set the entry points for standard ESMF Component methods - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=land_init, rc=rc) - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=land_run, rc=rc) - call ESMF_GridCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=land_final, rc=rc) - ! TODO: check rcs - - rc = ESMF_SUCCESS - - end subroutine land_register - - subroutine cpl_register(comp, rc) - type(ESMF_GridComp) :: comp ! must not be optional - integer, intent(out) :: rc ! must not be optional - character(len=*), parameter :: subname=trim(modname)//':(cpl_register) ' - - rc = ESMF_FAILURE - - ! Register the callback routines. - - call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=coupler_init, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=coupler_run, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=coupler_final, rc=rc) - if(rc /= ESMF_SUCCESS) call ESMF_Finalize(endflag=ESMF_END_ABORT, rc=rc) - - call ESMF_LogWrite(subname//"CouplerMod: Registered Initialize, Run, and Finalize routines", ESMF_LOGMSG_INFO) - - rc = ESMF_SUCCESS - - end subroutine cpl_register - - function return_error(rc, returnrc) result(error) - ! fight with this later - integer, intent(in) :: rc, returnrc - logical :: error - if (ESMF_LogFoundError(rc, ESMF_ERR_PASSTHRU, ESMF_CONTEXT, rcToReturn=returnrc)) then - error = .true. - else - error = .false. - endif + call ESMF_LogWrite(subname//"All Destroy routines done", ESMF_LOGMSG_INFO) - end function return_error + end subroutine final end module esmf_utils diff --git a/lilac/lilac/lilac.f90 b/lilac/lilac/lilac.f90 deleted file mode 100644 index b80c3c8616..0000000000 --- a/lilac/lilac/lilac.f90 +++ /dev/null @@ -1,59 +0,0 @@ -module lilac - - use ESMF - - use atmos_comp, only : atmos_setvm, atmos_register - use land_comp, only : land_setvm, land_register - use coupler_comp, only : usercpl_setvm, usercpl_register - - implicit none - - !-------------------------------------------------------------------------- - ! Public interfaces - !-------------------------------------------------------------------------- - public :: lilac_init - public :: lilac_run - public :: lilac_final - - type(LilacType), save :: lilac_obj - -contains - - type, public :: LilacType - private - - type(ESMFInfoType) :: esmf_info - - contains - procedure, public :: init => init - procedure, public :: run => run - procedure, public :: final => final - end type LilacType - -contains - - subroutine lilac_init(self) - implicit none - - print *, "lilac_init()" - - ! Initialize ESMF structures - call self%esmf_info%init("lilac") - - end subroutine lilac_init - - subroutine lilac_run(self) - implicit none - - call self%esmf_info%run() - - end subroutine lilac_run - - subroutine lilac_final(self) - implicit none - - call self%esmf_info%final() - - end subroutine lilac_final - -end module lilac From 9a1b5bdc46c2022ccbe884ac154c605d11a6c4a8 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 8 Oct 2018 12:16:16 -0700 Subject: [PATCH 31/34] fixup formatting --- lilac/lilac/core.f90 | 46 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/lilac/lilac/core.f90 b/lilac/lilac/core.f90 index 7feec6eac2..91ff33fd6c 100644 --- a/lilac/lilac/core.f90 +++ b/lilac/lilac/core.f90 @@ -62,7 +62,7 @@ subroutine init(self, name) character(len=*), parameter :: subname=trim(modname)//':(init) ' call ESMF_LogWrite(subname//"Initializing lilac", ESMF_LOGMSG_INFO) - + self%name = trim(name) ! Initialize ESMF structures @@ -151,10 +151,10 @@ subroutine cpl_register(comp, rc) ! Register the callback routines. call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_INITIALIZE, userRoutine=coupler_init, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_RUN, userRoutine=coupler_run, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out - + call ESMF_CplCompSetEntryPoint(comp, ESMF_METHOD_FINALIZE, userRoutine=coupler_final, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) return ! bail out @@ -164,7 +164,7 @@ subroutine cpl_register(comp, rc) end subroutine cpl_register -subroutine atmos_init(comp, importState, exportState, clock, rc) + subroutine atmos_init(comp, importState, exportState, clock, rc) type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -177,9 +177,9 @@ subroutine atmos_init(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"atmos_init has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine atmos_init + end subroutine atmos_init -subroutine land_init(comp, importState, exportState, clock, rc) + subroutine land_init(comp, importState, exportState, clock, rc) type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -192,9 +192,9 @@ subroutine land_init(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"land_init has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine land_init + end subroutine land_init -subroutine coupler_init(comp, importState, exportState, clock, rc) + subroutine coupler_init(comp, importState, exportState, clock, rc) type(ESMF_CplComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -207,9 +207,9 @@ subroutine coupler_init(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"coupler_init has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine coupler_init + end subroutine coupler_init -subroutine atmos_copy_atm_to_lilac(comp, importState, exportState, clock, rc) + subroutine atmos_copy_atm_to_lilac(comp, importState, exportState, clock, rc) type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -222,9 +222,9 @@ subroutine atmos_copy_atm_to_lilac(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"atmos_copy_atm_to_lilac has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine atmos_copy_atm_to_lilac + end subroutine atmos_copy_atm_to_lilac -subroutine atmos_copy_lilac_to_atm(comp, importState, exportState, clock, rc) + subroutine atmos_copy_lilac_to_atm(comp, importState, exportState, clock, rc) type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -237,9 +237,9 @@ subroutine atmos_copy_lilac_to_atm(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"atmos_copy_lilac_to_atm has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine atmos_copy_lilac_to_atm + end subroutine atmos_copy_lilac_to_atm -subroutine land_run(comp, importState, exportState, clock, rc) + subroutine land_run(comp, importState, exportState, clock, rc) type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -252,9 +252,9 @@ subroutine land_run(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"land_run has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine land_run + end subroutine land_run -subroutine coupler_run(comp, importState, exportState, clock, rc) + subroutine coupler_run(comp, importState, exportState, clock, rc) type(ESMF_CplComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -267,9 +267,9 @@ subroutine coupler_run(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"coupler_run has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine coupler_run + end subroutine coupler_run -subroutine atmos_final(comp, importState, exportState, clock, rc) + subroutine atmos_final(comp, importState, exportState, clock, rc) type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -282,9 +282,9 @@ subroutine atmos_final(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"atmos_final has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine atmos_final + end subroutine atmos_final -subroutine land_final(comp, importState, exportState, clock, rc) + subroutine land_final(comp, importState, exportState, clock, rc) type(ESMF_GridComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -297,9 +297,9 @@ subroutine land_final(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"land_final has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine land_final + end subroutine land_final -subroutine coupler_final(comp, importState, exportState, clock, rc) + subroutine coupler_final(comp, importState, exportState, clock, rc) type(ESMF_CplComp) :: comp type(ESMF_State) :: importState, exportState type(ESMF_Clock) :: clock @@ -312,6 +312,6 @@ subroutine coupler_final(comp, importState, exportState, clock, rc) call ESMF_LogWrite(subname//"coupler_final has not been implemented yet", ESMF_LOGMSG_INFO) -end subroutine coupler_final + end subroutine coupler_final end module lilac From 5473eb753849ad8677ddbb4703a887e2f06173c1 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 8 Oct 2018 13:25:44 -0700 Subject: [PATCH 32/34] autodoc fortran codes --- lilac/docs/api.rst | 8 ++++++- lilac/docs/conf.py | 27 +++++++++++++++++++++-- lilac/docs/developers.rst | 28 ++++++++++++++++++++++++ lilac/docs/index.rst | 45 +++++---------------------------------- 4 files changed, 65 insertions(+), 43 deletions(-) create mode 100644 lilac/docs/developers.rst diff --git a/lilac/docs/api.rst b/lilac/docs/api.rst index 6859fd3e1a..dac6446ce8 100644 --- a/lilac/docs/api.rst +++ b/lilac/docs/api.rst @@ -11,4 +11,10 @@ The atmosphere component will need to call each of the following subroutines: * `lilac_run` * `lilac_final` -TODO: fill in this section as the api comes together. +LILAC Core +---------- +.. f:autosrcfile:: core.f90 + +ESMF Utils +---------- +.. f:autosrcfile:: esmf_utils.f90 diff --git a/lilac/docs/conf.py b/lilac/docs/conf.py index 767f7287b1..f8c67d5d2b 100644 --- a/lilac/docs/conf.py +++ b/lilac/docs/conf.py @@ -12,7 +12,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -# import os +import os # import sys # sys.path.insert(0, os.path.abspath('.')) @@ -39,7 +39,14 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.imgmath', + 'sphinx.ext.ifconfig', 'sphinx.ext.intersphinx', + 'sphinxfortran.fortran_domain', + 'sphinxfortran.fortran_autodoc', ] # Add any paths that contain templates here, relative to this directory. @@ -50,6 +57,7 @@ # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' +fortran_src = '*f90' # The master toctree document. master_doc = 'index' @@ -161,4 +169,19 @@ # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} \ No newline at end of file +intersphinx_mapping = {'https://docs.python.org/': None} + + +## -- Options for Sphinx-Fortran --------------------------------------------- +# List of possible extensions in the case of a directory listing +fortran_ext = ['f90', 'F90', 'f95', 'F95'] + +# This variable must be set with file pattern, like "*.f90", or a list of them. +# It is also possible to specify a directory name; in this case, all files than +# have an extension matching those define by the config variable `fortran_ext` +# are used. +fortran_src = [os.path.abspath('../lilac/')] + +# Indentation string or length (default 4). If it is an integer, +# indicates the number of spaces. +fortran_indent = 4 diff --git a/lilac/docs/developers.rst b/lilac/docs/developers.rst new file mode 100644 index 0000000000..f4910d80d6 --- /dev/null +++ b/lilac/docs/developers.rst @@ -0,0 +1,28 @@ +Developers Guide to Using LILAC +=============================== + +Building LILAC +-------------- + +LILAC can be build using CMake:: + + $ cd /lilac/build && cmake .. + $ make + +For development and testing purposes, LILAC can also be built using a +`docker-compose` script:: + + $ docker-compose build + $ docker-compose run + +Testing LILAC +------------- + +LILAC includes a full test suite including unit tests and a number of +simplified coupled model tests. To run these tests, simply run the `ctest` +command:: + + $ ctest + +Note, if you are using the docker-compose development, the `docker-compose run` +command will build and run LILAC automatically. diff --git a/lilac/docs/index.rst b/lilac/docs/index.rst index f6c4a09751..e7c7a097f7 100644 --- a/lilac/docs/index.rst +++ b/lilac/docs/index.rst @@ -4,48 +4,13 @@ LILAC: Lightweight Infrastructure for Land Atmosphere Coupling LILAC is a new coupling interface for the Community Terrestrial Systems Model (CTSM). It provides a high-level Fortran API for coupling CTSM to atmospheric models such as the Weather Research and Forecast (WRF) model. LILAC makes -extensive use of the Earth System Modeling Framework (ESMF). - -Building LILAC --------------- - -LILAC can be build using CMake. - - $ cd /lilac/build && cmake .. - $ make - -For development and testing purposes, LILAC can also be built using a -`docker-compose` script. - - $ docker-compose build - # docker-compose run - -Testing LILAC -------------- - -LILAC includes a full test suite including unit tests and a number of -simplified coupled model tests. To run these tests, simply run the `ctest` -command: - - $ ctest - -Note, if you are using the docker-compose development, the `docker-compose run` -command will build and run LILAC automatically. - - - - -More coming soon. +extensive use of the Earth System Modeling Framework (ESMF). .. toctree:: :maxdepth: 2 :caption: Contents: - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` +Contents +--------------- +* :doc:`developers` +* :doc:`api` From 09ad7d04e7da83cee3435253eb6f711e23c6184d Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 8 Oct 2018 13:31:19 -0700 Subject: [PATCH 33/34] add reqs for doc build --- lilac/.gitmodules | 2 ++ lilac/docs/requirements.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 lilac/docs/requirements.txt diff --git a/lilac/.gitmodules b/lilac/.gitmodules index 2f471a14d9..3836c21e6b 100644 --- a/lilac/.gitmodules +++ b/lilac/.gitmodules @@ -1,6 +1,8 @@ [submodule "external/pfunit"] path = external/pfunit url = https://github.com/laristra/pfunit.git + shallow = true [submodule "external/esmf"] path = external/esmf url = https://git.code.sf.net/p/esmf/esmf + shallow = true diff --git a/lilac/docs/requirements.txt b/lilac/docs/requirements.txt new file mode 100644 index 0000000000..5edaa385f9 --- /dev/null +++ b/lilac/docs/requirements.txt @@ -0,0 +1,2 @@ +numpy +sphinx-fortran From ef3cb0c4e60787b21d50a278e4df7cf0b25a7886 Mon Sep 17 00:00:00 2001 From: Joseph Hamman Date: Mon, 8 Oct 2018 13:34:22 -0700 Subject: [PATCH 34/34] pip sphinx --- lilac/docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/lilac/docs/requirements.txt b/lilac/docs/requirements.txt index 5edaa385f9..f3d707325c 100644 --- a/lilac/docs/requirements.txt +++ b/lilac/docs/requirements.txt @@ -1,2 +1,3 @@ numpy sphinx-fortran +sphinx==1.6.7 \ No newline at end of file