diff --git a/.travis.yml b/.travis.yml index 2c5b194..6088d6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,27 @@ -sudo: false +sudo: false # use container-based build language: fortran -compiler: - - gfortran -os: - - linux +notifications: + email: false + +compiler: gfortran-6 +os: linux +env: TESTID='gard_linux' addons: apt: sources: - ubuntu-toolchain-r-test packages: - - gfortran - - libnetcdf-dev - liblapack-dev + - libnetcdf-dev + - gfortran-6 +before_install: + - source ci/gard_install_utils + - gard_before_install +install: + - gard_install script: - - sed -i "s|NCDF_PATH = /usr/local|NCDF_PATH = /usr|" src/makefile - - sed -i "s|LAPACK_PATH = /usr/local|LAPACK_PATH = /usr|" src/makefile - - make -C src -j4 test - - make -C src -j4 + - gard_script +after_success: + - gard_after_success +after_failure: + - gard_after_failure diff --git a/ci/gard_install_utils b/ci/gard_install_utils new file mode 100644 index 0000000..fc90bf8 --- /dev/null +++ b/ci/gard_install_utils @@ -0,0 +1,115 @@ +#!/usr/bin/env bash + +set -e +set -x + +export CC=/usr/bin/gcc-6 +export FC=/usr/bin/gfortran-6 + +if [ -z "$WORKDIR" ]; then + export WORKDIR=$HOME/workdir + mkdir -p $WORKDIR +fi + +if [ -z "$INSTALLDIR" ]; then + export INSTALLDIR=$HOME/installdir + mkdir -p $INSTALLDIR +fi + +function install_szip { + echo install_szip + cd $WORKDIR + wget --no-check-certificate -q http://www.hdfgroup.org/ftp/lib-external/szip/2.1/src/szip-2.1.tar.gz + tar -xzf szip-2.1.tar.gz + cd szip-2.1 + ./configure --prefix=$INSTALLDIR &> config.log + make &> make.log + make install + export CPPFLAGS="$CPPFLAGS -I${INSTALLDIR}/include" + export LDFLAGS="$LDFLAGS -L${INSTALLDIR}/lib" +} + +function install_hdf5 { + echo install_hdf5 + cd $WORKDIR + wget --no-check-certificate -q http://www.hdfgroup.org/ftp/HDF5/current/src/hdf5-1.10.0-patch1.tar.gz + tar -xzf hdf5-1.10.0-patch1.tar.gz + cd hdf5-1.10.0-patch1 + ./configure --prefix=$INSTALLDIR &> config.log + make &> make.log + make install + export LIBDIR=${INSTALLDIR}/lib +} + +function install_netcdf_c { + echo install_netcdf_c + cd $WORKDIR + wget --no-check-certificate -q ftp://ftp.unidata.ucar.edu/pub/netcdf/netcdf-4.4.1.tar.gz + tar -xzf netcdf-4.4.1.tar.gz + cd netcdf-4.4.1 + ./configure --prefix=$INSTALLDIR &> config.log + make &> make.log + make install + export LD_LIBRARY_PATH=${INSTALLDIR}/lib +} + +function install_netcdf_fortran { + echo install_netcdf_fortran + cd $WORKDIR + wget --no-check-certificate -q ftp://ftp.unidata.ucar.edu/pub/netcdf/netcdf-fortran-4.4.4.tar.gz + tar -xzf netcdf-fortran-4.4.4.tar.gz + cd netcdf-fortran-4.4.4 + ./configure --prefix=$INSTALLDIR &> config.log + make &> make.log + make install +} + +function gard_before_install { + echo gard_before_install + # Install szip (used by hdf5) + install_szip + # Install HDF5 + install_hdf5 + # Install NetCDF-C + install_netcdf_c + # Install NetCDF fortran + install_netcdf_fortran +} + +function gard_install { + echo gard_install + cd ${TRAVIS_BUILD_DIR} + sed -i "s|NCDF_PATH = /usr/local|NCDF_PATH = ${INSTALLDIR}|" src/makefile + sed -i "s|LAPACK_PATH = /usr/local|LAPACK_PATH = /usr|" src/makefile + make -C src clean; make -C src -j4 test + make -C src clean; make -C src -j4 MODE=debugslow + make -C src clean; make -C src -j4 MODE=debug + make -C src clean; make -C src -j4 MODE=debugompslow + make -C src clean; make -C src -j4 MODE=debugomp + make -C src clean; make -C src -j4 MODE=profile + make -C src clean; make -C src -j4 MODE=fast + make -C src clean; make -C src -j4 + echo "GARD install succeeded" +} + +function gard_script { + cd ./src + ./gard --version + ./gard -h + ./test_calendar + # ./test_random + ./test_regression + # ./test_config ../run/downscale_options.txt + cd ../ + echo "GARD script succeeded" +} + +function gard_after_success { + echo gard_after_success + echo "GARD build succeeded" +} + +function gard_after_failure { + echo gard_after_failure + echo "GARD build failed" +} diff --git a/docs/running.md b/docs/running.md index 16c0402..1cce4a4 100644 --- a/docs/running.md +++ b/docs/running.md @@ -13,6 +13,8 @@ GARD has the following dependencies: 1. LAPACK — Linear Algebra PACKage. 1. netCDF4 - Network Common Data Form. +*Note: GARD allocates memory to the stack. Users should set the "The maximum stack size." to "unlimited" prior to building/running GARD. `ulimit -s unlimited`* + ## Building GARD GARD is built using a standard `makefile`. From the command line, simply run the following command: diff --git a/src/config/configuration.f90 b/src/config/configuration.f90 index e8616f4..ddc4ad2 100644 --- a/src/config/configuration.f90 +++ b/src/config/configuration.f90 @@ -1,6 +1,6 @@ !>------------------------------------------------ !! Reads the configuration input file -!! Also looks for commandline arguments to for an config filename +!! Also looks for command line arguments to for an config filename !! !! @author !! Ethan Gutmann (gutmann@ucar.edu) @@ -19,6 +19,7 @@ module config_mod logical :: module_debug public :: read_config public :: read_files_list, read_data_type, get_options_file ! only need to be public for test_config + public :: print_model_init contains !>------------------------------------------------ @@ -762,6 +763,16 @@ function get_options_file() result(options_file) ! read the commandline argument call get_command_argument(1,options_file, status=error) + if (trim(options_file) == '--version') then + write(*, *) 'GARD '//trim(kVERSION_STRING) + stop + elseif (trim(options_file) == '-h') then + call print_model_init() + stop + else + call print_model_init() + endif + ! if there was an error, return the default filename if (error>0) then options_file = kDEFAULT_OPTIONS_FILENAME @@ -772,8 +783,8 @@ function get_options_file() result(options_file) stop "ERROR: options filename too long" endif else - ! if not commandline options were given, assume a default filename - options_file = kDEFAULT_OPTIONS_FILENAME + call print_model_init() + stop endif ! check to see if the expected filename even exists on disk @@ -786,4 +797,37 @@ function get_options_file() result(options_file) write(*,*) "Using options file = ", trim(options_file) end function get_options_file + !>------------------------------------------------ + !! Prints model configuration info before running + !! + !! Prints a welcome and version string as well. + !!------------------------------------------------ + subroutine print_model_init() + implicit none + + write(*,*) "Generalized Analog Regression Downscaling (GARD)" + write(*,*) "-----------------------------------------------------------" + write(*,*) "GARD Version : "//trim(kVERSION_STRING) + ! TODO: Add compile time options + write(*,*) "" + write(*,*) " The Generalized Analog Regression Downscaling (GARD)" + write(*,*) " downscaling tool, version "//trim(kVERSION_STRING)//", Copyright (C) 2017 The" + write(*,*) " National Center for Atmospheric Research. GARD comes with" + write(*,*) " ABSOLUTELY NO WARRANTY. This is free software, you may " + write(*,*) " redistribute it under certain conditions; see LICENSE.txt" + write(*,*) " for details." + write(*,*) "" + write(*,*) " Online Documentation : http://gard.readthedocs.io" + write(*,*) " Report Bugs and Issues to : https://github.com/NCAR/GARD/issues" + write(*,*) "" + write(*,*) "-----------------------------------------------------------" + write(*,*) "Usage: gard [-h] [--version] options_file" + write(*,*) "" + write(*,*) "-h Help information for GARD" + write(*,*) "--version Print the version number" + write(*,*) "options_file Input options file name" + write(*,*) "" + + end subroutine print_model_init + end module config_mod diff --git a/src/downscaling_stats/regression.f90 b/src/downscaling_stats/regression.f90 index 06348e0..d1b3c4a 100644 --- a/src/downscaling_stats/regression.f90 +++ b/src/downscaling_stats/regression.f90 @@ -118,7 +118,7 @@ function compute_regression(x, training_x, training_y, coefficients, y_test, err if (size(weights)/=size(training_y_lp)) then !$omp critical (print_lock) write(*,*) "ERROR size of weights /= data" - write(*,*), shape(weights), shape(training_y_lp) + write(*,*) shape(weights), shape(training_y_lp) !$omp end critical (print_lock) endif if (present(y_test)) then @@ -207,8 +207,8 @@ subroutine weighted_least_squares(X, Y, B, W) real, intent(inout), dimension(:,:) :: X real, intent(inout), dimension(:) :: Y, W real(8), intent(inout), dimension(:) :: B - real, dimension(:,:), allocatable :: X_weighted, W_full - real, dimension(:), allocatable :: Y_weighted, Bs, output_y + real, dimension(:,:), allocatable :: W_full + real, dimension(:), allocatable :: Bs, output_y real, dimension(10000) :: WORK integer :: i, n, m, nrhs, LDX, LDY, LDW, LWORK, INFO, p @@ -281,7 +281,6 @@ subroutine logistic_regression(X, Y, B) real, allocatable :: YN(:), XV(:,:) integer :: nvars, ntimes, i, t, f, it - real :: d integer :: info ! skip the logistic regression and force the result to be 1 diff --git a/src/downscaling_stats/sampling.f90 b/src/downscaling_stats/sampling.f90 index 6a40819..1eef61d 100644 --- a/src/downscaling_stats/sampling.f90 +++ b/src/downscaling_stats/sampling.f90 @@ -61,17 +61,18 @@ subroutine sample_distribution(output, mean_values, error_term, & ! if random number is greater than the non-exceedence probability, then we have exceeded it... ! rescale the uniform random number for the region of exceedence and convert to a normal random number - random_normal = get_normal_from_cdf((uniform(i) - (1 - exceedence_probability(i))) / (exceedence_probability(i)) ) - + random_normal = get_normal_from_cdf((uniform(i) - (1 - exceedence_probability(i))) & + / (exceedence_probability(i))) + ! ultimately this is the same equation as below for variables without an exceedence threshold output(i) = mean_values(i) + error_term(i) * random_normal - + ! also check, if the random term has pushed the value below the threshold anyway, then just set to the threshold if (output(i) < threshold_internal) then output(i) = threshold_internal endif else - ! if this value did not exceed the threshold, then just set it to the threshold. + ! if this value did not exceed the threshold, then just set it to the threshold. output(i) = threshold_internal endif else diff --git a/src/io/io_routines.f90 b/src/io/io_routines.f90 index a419fd2..fe904ac 100644 --- a/src/io/io_routines.f90 +++ b/src/io/io_routines.f90 @@ -922,7 +922,7 @@ subroutine io_write2d(filename,varname,data_out) ! Close the file, freeing all resources. call check( nf90_close(ncid) ) end subroutine io_write2d - + subroutine io_write1d(filename,varname,data_out) implicit none ! This is the name of the data file and variable we will read. @@ -1218,7 +1218,7 @@ subroutine check(status,extra) print *, trim(nf90_strerror(status)) if(present(extra)) then ! print any optionally provided context - write(*,*), trim(extra) + write(*,*) trim(extra) endif ! STOP the program execute stop "Stopped" diff --git a/src/io/output.f90 b/src/io/output.f90 index 147b039..7bd752a 100644 --- a/src/io/output.f90 +++ b/src/io/output.f90 @@ -13,7 +13,7 @@ subroutine write_output(output, options) implicit none type(config), intent(in) :: options type(results), intent(in) :: output - + character(len=MAXFILELENGTH) :: filename character(len=MAXFILELENGTH) :: dimnames(3) real, dimension(:,:,:), allocatable :: output_data @@ -145,9 +145,9 @@ subroutine memory_error(error, variable_name, dims) character(len=*), intent(in) :: variable_name integer, intent(in), dimension(:) :: dims - write(*,*), "Error allocating memory for variable: ", trim(variable_name) - write(*,*), " ERROR = ", error - write(*,*), " Dimensions = ", dims + write(*,*) "Error allocating memory for variable: ", trim(variable_name) + write(*,*) " ERROR = ", error + write(*,*) " Dimensions = ", dims stop "MEMORY ALLOCATION ERROR" diff --git a/src/main/init.f90 b/src/main/init.f90 index bf93d9b..c49c878 100644 --- a/src/main/init.f90 +++ b/src/main/init.f90 @@ -18,45 +18,9 @@ module init_mod implicit none private - public :: model_init, print_model_init + public :: model_init contains - !>------------------------------------------------ - !! Prints model configuration info before running - !! - !! Prints a welcome and version string as well. - !! Only prints configuration info if debug == true - !! - !!------------------------------------------------ - subroutine print_model_init() - implicit none - - write(*,*) "" - write(*,*) " ====================================================== " - write(*,*) "" - write(*,*) " Downscaling Model " - write(*,*) " Version : "//trim(kVERSION_STRING) - write(*,*) "" - write(*,*) " Developed at NCAR: " - write(*,*) " The National Center for Atmospheric Research " - write(*,*) " NCAR is supported by the National Science Foundation " - write(*,*) " ------------------------------------------------------ " - write(*,*) " ------------------------------------------------------ " - write(*,*) "" - write(*,*) " WARNING WARNING WARNING WARNING WARNING WARNING " - write(*,*) "" - write(*,*) " This is pre-release not-even-beta code. " - write(*,*) "" - write(*,*) " WARNING WARNING WARNING WARNING WARNING WARNING " - write(*,*) "" - write(*,*) " ------------------------------------------------------ " - write(*,*) " ------------------------------------------------------ " - write(*,*) " ====================================================== " - write(*,*) "" - - end subroutine print_model_init - - !>------------------------------------------------ !! Initialize the model !! diff --git a/src/main/main.f90 b/src/main/main.f90 index 99aa246..4c39fb4 100644 --- a/src/main/main.f90 +++ b/src/main/main.f90 @@ -12,7 +12,7 @@ program stat_down use model_constants use config_mod, only : read_config use atm_mod, only : read_atm - use init_mod, only : model_init, print_model_init + use init_mod, only : model_init use obs_mod, only : read_obs use geo, only : geo_LUT use io_routines, only : io_write @@ -29,8 +29,6 @@ program stat_down integer :: i - call print_model_init() - options = read_config() call model_init(options) diff --git a/src/makefile b/src/makefile index 247e3a3..5525520 100644 --- a/src/makefile +++ b/src/makefile @@ -17,7 +17,7 @@ ################################################################### ################################################################### -FC=gfortran +FC=gfortran-6 NCDF_PATH = /usr/local LAPACK_PATH = /usr/local INSTALL_DIR = ~/bin @@ -52,7 +52,7 @@ ifeq ($(NODENAME), Nomad.local) LAPACK_PATH=/usr/local/opt/lapack endif -ifeq ($(NODENAME), foil.local) +ifeq ($(NODENAME), foil.hydro.washington.edu) FC=gfortran NCDF_PATH=/opt/local LAPACK_PATH=/opt/local/lib/lapack @@ -96,6 +96,8 @@ endif # get GIT version info GIT_VERSION := $(shell git describe --long --dirty --all --always | sed -e's/heads\///') +UNAME_S := $(shell uname -s) +HOSTNAME := $(shell uname -n) ################################################################### ################################################################### @@ -111,6 +113,13 @@ ifeq ($(FC), gfortran) PREPROC=-cpp MODOUTPUT=-J $(BUILD) endif +ifeq ($(FC), gfortran-6) + COMP=-fopenmp -lgomp -O3 -ffree-line-length-none -ftree-vectorize -fimplicit-none -funroll-loops \ + -fno-protect-parens -ffast-math #-flto # + LINK=-fopenmp -lgomp + PREPROC=-cpp + MODOUTPUT=-J $(BUILD) +endif # Intel fortran ifeq ($(FC), ifort) COMP= -u -qopenmp -O3 -no-prec-div -xHost -ftz @@ -247,7 +256,7 @@ $(info $$NCDF_PATH = ${NCDF_PATH}) $(info $$GIT_VERSION = ${GIT_VERSION}) $(info $$COMP = ${COMP}) $(info $$LINK = ${LINK}) -$(info $$PREPROC = ${GIT_VERSION}) +$(info $$PREPROC = ${PREPROC}) $(info $$MODOUTPUT = ${MODOUTPUT}) $(info $$MODE = ${MODE}) @@ -263,6 +272,7 @@ $(info $$MODE = ${MODE}) # flags forall FCFLAGS = $(COMP) $(PROF) -I$(NCDF_PATH)/include -I$(BUILD) $(INC_NCAR) + # libraries needed for linking LDFLAGS = $(LINK) $(PROF) -L$(NCDF_PATH)/lib -lnetcdf -lnetcdff $(LIB_NCAR) -L$(LAPACK_PATH)/lib -llapack #-lblas diff --git a/src/objects/model_constants.f90 b/src/objects/model_constants.f90 index d43bafb..55d747c 100644 --- a/src/objects/model_constants.f90 +++ b/src/objects/model_constants.f90 @@ -3,7 +3,7 @@ module model_constants implicit none ! Model source code version number - character(len=*),public,parameter :: kVERSION_STRING = "0.3" + character(len=*),public,parameter :: kVERSION_STRING = "0.4" ! ------------------------------------------------ ! String constants diff --git a/src/tests/test_qm.f90 b/src/tests/test_qm.f90 index 6852a3b..4933347 100644 --- a/src/tests/test_qm.f90 +++ b/src/tests/test_qm.f90 @@ -39,7 +39,7 @@ program test_qm ! test a negative gain and offset call random_number(matching_data) - matching_data = matching_data * -3 - 3 + matching_data = (matching_data * (-3)) - 3 call test_mapping(input_data, matching_data, "Negative Values") ! Then test a fourth root transformation @@ -121,7 +121,8 @@ subroutine test_mapping(input_data, matching_data, name) !------------------------------- ! Develop the Quantile mapping !------------------------------- - call develop_qm(input_data(1:size(input_data)/2), matching_data, qm, min(300,min(size(input_data)/2, size(matching_data)/2))) + call develop_qm(input_data(1:size(input_data) / 2), matching_data, qm, & + min(300, min(size(input_data) / 2, size(matching_data) / 2))) call system_clock(end_time, COUNT_RATE, COUNT_MAX) if (start_time>end_time) end_time=end_time+COUNT_MAX @@ -138,7 +139,8 @@ subroutine test_mapping(input_data, matching_data, name) call system_clock(end_time, COUNT_RATE, COUNT_MAX) if (start_time>end_time) end_time=end_time+COUNT_MAX - call show_results(output_data, matching_data, name, (end_time-start_time) / real(COUNT_RATE)) + call show_results(output_data, matching_data, name, & + (end_time-start_time) / real(COUNT_RATE)) end subroutine test_mapping subroutine pass_fail(error, name) @@ -149,7 +151,7 @@ subroutine pass_fail(error, name) if (abs(error) < acceptable_error) then print*, trim(name), " PASSED" else - print*, trim(name), " FAILED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + print*, trim(name), " FAILED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" endif end subroutine pass_fail