Skip to content

Commit

Permalink
Merge pull request #38 from noaa-oar-arl/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
drnimbusrain authored Jan 18, 2023
2 parents 353756a + 8f5d435 commit d06c840
Show file tree
Hide file tree
Showing 23 changed files with 12,630 additions and 10,376 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Install dependencies
run: |
sudo apt install libnetcdff-dev
- name: Debug compile and run
run: |
make clean
Expand All @@ -38,3 +42,14 @@ jobs:
env:
DEBUG: 0
FC: ${{ matrix.compiler }}

- name: Non-NetCDF comile and run
run: |
make clean
make
sed -e s/input_variables_2D.nc/input_variables.txt/g namelist.canopy > tmp && mv tmp namelist.canopy
./canopy
env:
DEBUG: 0
FC: ${{ matrix.compiler }}
NETCDF: 0
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/canopy
output*.txt
test_*.txt
test*.nc

# Prerequisites
*.d
Expand Down
43 changes: 35 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#
# Use `DEBUG=1 make` for a debug build
#
# Use `FC=<compiler> ... make` to select compiler
# Use `DEBUG=1 ... make` for a debug build
# Use `NETCDF=1 ... make` to build with NetCDF using `nf-config`

# Compiler
FC ?= gfortran
Expand All @@ -12,18 +13,37 @@ $(info FC setting: '$(FC)')
# Default to non-debug build
DEBUG ?= 0

# Default to NetCDF build
NETCDF ?= 1

# Compile flags
$(info DEBUG setting: '$(DEBUG)')
ifeq ($(DEBUG), 1)
FCFLAGS := -g -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5
else ifeq ($(DEBUG), 0)
FCFLAGS := -O3
else
$(error invalid setting for DEBUG, should be 0 or 1 but is '$(DEBUG)')
endif
$(info DEBUG setting: '$(DEBUG)')

# Link flags
FLFLAGS :=
# NETCDF Settings here
LIBS :=
INC :=
$(info NETCDF setting: '$(NETCDF)')
ifeq ($(NETCDF), 1)
NETCDF_FLIBS := $(shell nf-config --flibs)
NETCDF_INC := -I$(shell nf-config --includedir)
#
LIBS += $(NETCDF_FLIBS)
INC += $(NETCDF_INC)
FCFLAGS += -DNETCDF
else ifeq ($(NETCDF), 0)
#
else
$(error invalid setting for NETCDF, should be 0 or 1 but is '$(NETCDF)')
endif
$(info LIBS: '$(LIBS)')
$(info INC: '$(INC)')

# Source objects
OBJS :=\
Expand All @@ -38,6 +58,8 @@ OBJS :=\
canopy_alloc.o \
canopy_init.o \
canopy_txt_io_mod.o \
canopy_ncf_io_mod.o \
canopy_check_input.o \
canopy_read_txt.o \
canopy_dxcalc_mod.o \
canopy_profile_mod.o \
Expand All @@ -50,18 +72,23 @@ OBJS :=\
canopy_dealloc.o \
canopy_app.o

ifeq ($(NETCDF), 0)
_ncf_objs := canopy_check_input.o canopy_ncf_io_mod.o
OBJS := $(filter-out $(_ncf_objs),$(OBJS))
endif

# Program name
PROGRAM := canopy

# Targets
.PHONY: all clean
all: $(PROGRAM)

$(PROGRAM): $(OBJS)
$(FC) $(FCFLAGS) $^ -o $@ $(FLFLAGS)
$(PROGRAM): $(OBJS_APP) $(OBJS)
$(FC) $(FCFLAGS) $^ -o $@ $(LIBS) $(INC)

%.o: %.F90
$(FC) $(FCFLAGS) -c $<
$(FC) $(FCFLAGS) $(INC) -c $<

clean:
rm -f *.o *.mod $(PROGRAM)
39 changes: 26 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Author(s):

Patrick Campbell, Zachary Moon, and Wei-Ting Hung

Build canopy model:

Canopy-App requires NetCDF-Fortran Libraries (i.e., -lnetcdf -lnetcdff) for NetCDF I/O Option. See included Makefile for example.

Compile, edit namelist, and run canopy model:
- `make`
- `namelist.canopy`
Expand All @@ -16,7 +20,7 @@ Canopy is parameterized by foliage distribution shape functions and parameters f

Current Canopy-App components:

1. In-Canopy Winds and Wind Adjustment Factor (WAF) for wildland fire spread and air quality applications.
1. In-Canopy Winds and Wind Adjustment Factor (WAF) for wildfire spread and air quality applications.

Namelist Option : `ifcanwind`

Expand All @@ -35,27 +39,34 @@ Current Canopy-App components:

- `canopy_phot_mod.F90`

**Current Canopy-App Input:** Typical 1D/2D gridded atmospheric model input variables in 1st layer above canopy
**Current Canopy-App Input:** Typical 1D or 2D (time=1,lat,lon) gridded atmospheric model input variables in 1st layer above canopy

Namelist Option : `file_vars` Full name of input file (Supports either text or NetCDF format with following formats:
`.txt`, `.nc`, `.ncf`, or `.nc4`)

Namelist Option : `file_vars` Name of input file (Currently only in txt format, e.g., `input_variables.txt`)
- See example file inputs for variables and format (`input_variables.txt`, `input_variables_1D.nc`, or `input_variables_2D.nc`).
- Canopy-App assumes the NetCDF input files are in CF-Convention; recommend using double or float for real variables.
- Canopy-App can also be run with a single point of 1D input data in a text file (e.g. `input_variables_point.txt`).

**Current Canopy-App Output:** Outputs canopy winds/WAF, canopy vertical/eddy diffusivity values, and
canopy photolysis attenuation correction factors (currently only in txt format).
**Current Canopy-App Output:** Outputs 3D canopy winds, canopy vertical/eddy diffusivity values, and
canopy photolysis attenuation correction factors, and 2D Wind Adjustment Factor (WAF).

Namelist Option : `file_out` Prefix of output file name (Currently only in txt format, e.g., `TESTRUN`)
Namelist Option : `file_out` Prefix string (e.g., 'test') used for output file name (Currently in both 1D txt or 2D NetCDF format (only when 2D NCF input is used, i.e., infmt_opt=0).


**Table 1. Canopy-App input variables**
**Table 1. Canopy-App Required Input Variables**

| Variable Name | Variable Description and Units |
| --------------- | ------------------------------------------------- |
| LAT | Latitude (degrees) |
| LON | Longitude (degrees) |
| LON | Longitude (degrees; from 0-360) |
| TIME | Timestamp (days since YYYY-N-D 0:0:0) (NetCDF Only) |
| FH | Forest canopy height (m) |
| WS | Wind speed at reference height (m/s), e.g., 10 m |
| HREF | Reference height above canopy (m) |
| WS | Wind speed at HREF (m/s), e.g., 10 m |
| CLU | Forest clumping index (dimensionless) |
| LAI | Leaf area index (m2/m2) |
| VTYPE | Vegetation type (dimensionless), e.g., VIIRS |
| VTYPE | Vegetation type (dimensionless), VIIRS Only |
| FFRAC | Forest fraction (dimensionless) |
| UST | Friction velocity (m/s) |
| CSZ | Cosine of the solar zenith angle (dimensionless) |
Expand All @@ -67,15 +78,17 @@ Current Canopy-App components:

| Namelist Option | Namelist Description and Units |
| --------------- | ---------------------------------------------------------------------------------- |
| nlat | number of latitude cells (must match # of LAT in `file_vars` above ) |
| nlon | number of longitude cells (must match # of LON in `file_vars`above ) |
| infmt_opt | integer for choosing 1D or 2D input file format (default = 0, 2D) |
| nlat | number of latitude cells (must match # of LAT in `file_vars` above) |
| nlon | number of longitude cells (must match # of LON in `file_vars`above) |
| modlays | number of model (below and above canopy) layers |
| modres | above and below canopy model vertical resolution (m) |
| ifcanwind | logical canopy wind option (default = .FALSE.) |
| ifcanwaf | logical canopy WAF option (default = .FALSE.)** |
| ifcaneddy | logical canopy eddy Kz option (default = .FALSE.) |
| ifcanphot | logical canopy photolysis option (default = .FALSE.) |
| href | real value of reference height above canopy associated with input wind speed (m) |
| href_opt | integer for using href_set in namelist (= 0) or array from file (= 1); default = 0 |
| href_set | user set real value of reference height above canopy associated with input wind speed (m) (only used if href_opt = 0) |
| z0ghc | ratio of ground roughness length to canopy top height (Massman et al., 2017) |
| lamdars | Value representing influence of roughness sublayer (Massman et al., 2017) |
| dx_opt | 0=Calculation of dx resolution/distance from lon; 1=user set dx grid resolution |
Expand Down
35 changes: 20 additions & 15 deletions canopy_alloc.F90
Original file line number Diff line number Diff line change
Expand Up @@ -17,51 +17,56 @@ SUBROUTINE canopy_alloc
!-------------------------------------------------------------------------------
! Allocate canopy input variables
!-------------------------------------------------------------------------------
! TODO: If txt or 1D ncf...
if(.not.allocated(variables)) allocate(variables(nlat*nlon))
! TODO: If 2D ncf...
! if(.not.allocated(variables)) allocate(variables(nlat,nlon))

if(.not.allocated(variables)) allocate(variables(nlat*nlon))
if(.not.allocated(variables_2d)) allocate(variables_2d(nlat,nlon))

!-------------------------------------------------------------------------------
! Allocate arrays for Canopy Distribution
! Allocate arrays for Internal Canopy Distribution Variables
!-------------------------------------------------------------------------------

if(.not.allocated(zhc)) allocate(zhc(modlays))
if(.not.allocated(fafraczInt)) allocate(fafraczInt(modlays))

!-------------------------------------------------------------------------------
! Allocate arrays for Canopy Wind
! Allocate arrays for Canopy Wind Outputs
!-------------------------------------------------------------------------------

if (ifcanwind .or. ifcanwaf) then
write(*,*) 'Canopy wind and/or WAF option selected'
write(*,*) '-------------------------------'
if(.not.allocated(canBOT)) allocate(canBOT(modlays))
if(.not.allocated(canTOP)) allocate(canTOP(modlays))
if(.not.allocated(canWIND)) allocate(canWIND(modlays,nlat*nlon))
if(.not.allocated(dx)) allocate(dx(nlat*nlon))
if(.not.allocated(waf)) allocate(waf(nlat*nlon))
if(.not.allocated(canBOT)) allocate(canBOT(modlays))
if(.not.allocated(canTOP)) allocate(canTOP(modlays))
if(.not.allocated(canWIND)) allocate(canWIND(nlat*nlon,modlays))
if(.not.allocated(canWIND_3d)) allocate(canWIND_3d(nlat,nlon,modlays))
if(.not.allocated(dx)) allocate(dx(nlat*nlon))
if(.not.allocated(dx_2d)) allocate(dx_2d(nlat,nlon))
if(.not.allocated(waf)) allocate(waf(nlat*nlon))
if(.not.allocated(waf_2d)) allocate(waf_2d(nlat,nlon))

end if

!-------------------------------------------------------------------------------
! Allocate arrays for Canopy Diffusivity Profile
! Allocate arrays for Canopy Diffusivity Profile Outputs
!-------------------------------------------------------------------------------

if (ifcaneddy) then
write(*,*) 'Canopy eddy Kz option selected'
write(*,*) '-------------------------------'
if(.not.allocated(Kz)) allocate(Kz(modlays,nlat*nlon))
if(.not.allocated(Kz)) allocate(Kz(nlat*nlon,modlays))
if(.not.allocated(Kz_3d)) allocate(Kz_3d(nlat,nlon,modlays))
end if


!-------------------------------------------------------------------------------
! Allocate arrays for Canopy Photolysis Correction Factor
! Allocate arrays for Canopy Photolysis Correction Factor Outputs
!-------------------------------------------------------------------------------

if (ifcanphot) then
write(*,*) 'Canopy photolysis option selected'
write(*,*) '-------------------------------'
if(.not.allocated(rjcf)) allocate(rjcf(modlays,nlat*nlon))
if(.not.allocated(rjcf)) allocate(rjcf(nlat*nlon,modlays))
if(.not.allocated(rjcf_3d)) allocate(rjcf_3d(nlat,nlon,modlays))
end if


Expand Down
41 changes: 23 additions & 18 deletions canopy_app.F90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ program canopy_app
! Prototype: Patrick C. Campbell, 06/2022
! Revised : PCC (10/2022)
!-------------------------------------------------------------
use canopy_files_mod !main canopy input files
use canopy_files_mod ! main canopy input files
#ifdef NETCDF
use canopy_ncf_io_mod
#endif

implicit none

Expand All @@ -28,25 +31,15 @@ program canopy_app

call canopy_init

! TODO :: Add a separate intialize routine for gridded ncdf canopy variables
! to fit ncf file, e.g.,, call canout_ncf_init

!-------------------------------------------------------------------------------
! Read met/sfc gridded model input file (currently text or 1D or 2D ncf).
! Read met/sfc gridded model input file (currently 1D TXT or 1D/2D NETCDF).
!-------------------------------------------------------------------------------

! ... TODO: NL condition for data read from txt or netcdf 1D or 2D

#ifdef NETCDF
call canopy_check_input(file_vars(1))
#else
call canopy_read_txt(file_vars(1))

! ... TODO: add option to read met/sfc input variables from 1D ncf file
!e.g., call canopy_read_ncf_1D(file_vars(1))

! ... TODO: add option to read met/sfc input variables from 2D ncf file
!e.g., call canopy_read_ncf_2D(file_vars(1))

! ... TODO: Set nlat = nlat_user (if txt) or nlat = nlat_file (if ncf)
! ... TODO: Set nlon = nlat_user (if txt) or nlon = nlon_file (if ncf)
#endif

!-------------------------------------------------------------------------------
! Main canopy model calculations.
Expand All @@ -55,13 +48,25 @@ program canopy_app
call canopy_calcs

!-------------------------------------------------------------------------------
! Write model output of canopy model calculations.
! Allocate and initialize 2D/3D NetCDF output data structures
!-------------------------------------------------------------------------------

! ... TODO: NL condition for data write to txt or netcdf 1D or 2D
#ifdef NETCDF
call canopy_outncf_alloc

call canopy_outncf_init
#endif

!-------------------------------------------------------------------------------
! Write model output of canopy model calculations.
!-------------------------------------------------------------------------------

call canopy_write_txt(file_out(1))

#ifdef NETCDF
call canopy_write_ncf(file_out(1)) !only output if 2D input NCF is used
#endif

!-------------------------------------------------------------------------------
! Dellocate necessary variables.
!-------------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit d06c840

Please sign in to comment.