Skip to content

Commit

Permalink
Merge branch 'PecanProject:develop' into SDA_observation
Browse files Browse the repository at this point in the history
  • Loading branch information
DongchenZ authored Feb 28, 2025
2 parents d76875f + edc14b8 commit 96972d8
Show file tree
Hide file tree
Showing 17 changed files with 570 additions and 374 deletions.
17 changes: 10 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ MODELS_D := $(MODELS:%=.doc/%)
MODULES_D := $(MODULES:%=.doc/%)
ALL_PKGS_D := $(BASE_D) $(MODULES_D) $(MODELS_D)

SRCS_TO_CLEAN := $(strip $(foreach d,$(ALL_PKGS),$(wildcard ${d}/src)))

SETROPTIONS := "options(Ncpus = ${NCPUS})"

EXPECTED_ROXYGEN_VERSION := 7.3.2
Expand Down Expand Up @@ -101,7 +103,7 @@ depends = .doc/$(1) .install/$(1) .check/$(1) .test/$(1)

### Rules

.PHONY: all install check test document shiny \
.PHONY: all install check test document clean shiny \
check_base check_models check_modules document help

all: install document
Expand All @@ -125,13 +127,19 @@ book:
.doc .install .check .test .shiny_depends $(call depends,base) $(call depends,models) $(call depends,modules):
mkdir -p $@

clean:
rm -rf .install .check .test .doc
for p in $(SRCS_TO_CLEAN); do \
find "$$p" \( -name \*.mod -o -name \*.o -o -name \*.so \) -delete; \
done

help:
@echo "Usage: make [target]"
@echo ""
@echo "Examples:"
@echo " make all"
@echo " make document"
@echo " make document modules/assim.sequential # Generate documentation for a specific package"
@echo " make .doc/modules/assim.sequential # Generate documentation for a specific package"
@echo ""
@echo "Notes:"
@echo " - Components not included: cable (models), data.mining and DART (modules)."
Expand Down Expand Up @@ -163,11 +171,6 @@ $(subst .doc/models/template,,$(MODELS_D)): .install/models/template
# target need not be rebuilt when a prerequisite changes)
include Makefile.depends

clean:
rm -rf .install .check .test .doc
find modules/rtm/src \( -name \*.mod -o -name \*.o -o -name \*.so \) -delete
find models/basgra/src \( -name \*.mod -o -name \*.o -o -name \*.so \) -delete

.install/devtools: | .install
+ ./scripts/time.sh "devtools ${1}" Rscript -e ${SETROPTIONS} -e "if(!requireNamespace('devtools', quietly = TRUE)) install.packages('devtools')"
echo `date` > $@
Expand Down
7 changes: 7 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ services:
# ----------------------------------------------------------------------
bety:
image: pecan/bety:${BETY_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand All @@ -97,6 +98,7 @@ services:
# PEcAn documentation as well as PEcAn home page
docs:
image: pecan/docs:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand Down Expand Up @@ -152,6 +154,7 @@ services:
executor:
user: "${UID:-1001}:${GID:-1001}"
image: pecan/executor:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand All @@ -174,6 +177,7 @@ services:
basgra:
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-basgra-basgra_n_v1.0:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand All @@ -188,6 +192,7 @@ services:
sipnet:
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-sipnet-git:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand All @@ -203,6 +208,7 @@ services:
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-ed2-2.2.0:${PECAN_VERSION:-latest}
restart: unless-stopped
platform: linux/amd64
networks:
- pecan
environment:
Expand All @@ -216,6 +222,7 @@ services:
maespa:
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-maespa-git:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand Down
11 changes: 11 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ services:
# ----------------------------------------------------------------------
rstudio:
hostname: rstudio
platform: linux/amd64
image: pecan/base:${PECAN_VERSION:-latest}
command: /work/rstudio.sh
restart: unless-stopped
Expand Down Expand Up @@ -158,6 +159,7 @@ services:
docs:
hostname: docs
image: pecan/docs:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand Down Expand Up @@ -207,6 +209,7 @@ services:
hostname: monitor
user: "${UID:-1001}:${GID:-1001}"
image: pecan/monitor:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand Down Expand Up @@ -236,6 +239,7 @@ services:
hostname: executor
user: "${UID:-1001}:${GID:-1001}"
image: pecan/executor:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand Down Expand Up @@ -276,6 +280,7 @@ services:
hostname: basgra
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-basgra-basgra_n_v1.0:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand All @@ -292,6 +297,7 @@ services:
hostname: sipnet-git
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-sipnet-git:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand Down Expand Up @@ -322,6 +328,7 @@ services:
# PEcAn MAESPA model runner
maespa:
hostname: maespa-git
platform: linux/amd64
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-maespa-git:${PECAN_VERSION:-latest}
restart: unless-stopped
Expand All @@ -340,6 +347,7 @@ services:
hostname: biocro-0_95
user: "${UID:-1001}:${GID:-1001}"
image: pecan/model-biocro-0.95:${PECAN_VERSION:-latest}
platform: linux/amd64
restart: unless-stopped
networks:
- pecan
Expand All @@ -357,6 +365,7 @@ services:
# PEcAn DB Sync visualization
dbsync:
hostname: dbsync
platform: linux/amd64
image: pecan/shiny-dbsync:${PECAN_VERSION:-latest}
restart: unless-stopped
networks:
Expand All @@ -380,6 +389,7 @@ services:
# ----------------------------------------------------------------------
api:
hostname: api
platform: linux/amd64
user: "${UID:-1001}:${GID:-1001}"
image: pecan/api:${PECAN_VERSION:-latest}
restart: unless-stopped
Expand Down Expand Up @@ -428,3 +438,4 @@ volumes:
pecan:
rstudio:


2 changes: 0 additions & 2 deletions docker/depends/pecan_package_dependencies.csv
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@
"keras3",">= 1.0.0","modules/assim.sequential","Suggests",FALSE
"knitr","*","base/visualization","Suggests",FALSE
"knitr","*","models/biocro","Suggests",FALSE
"knitr","*","models/ed","Suggests",FALSE
"knitr","*","models/maat","Suggests",FALSE
"knitr","*","modules/data.atmosphere","Suggests",FALSE
"knitr","*","modules/priors","Suggests",FALSE
Expand Down Expand Up @@ -495,7 +494,6 @@
"rlist","*","modules/assim.sequential","Suggests",FALSE
"rmarkdown","*","base/visualization","Suggests",FALSE
"rmarkdown","*","models/biocro","Suggests",FALSE
"rmarkdown","*","models/ed","Suggests",FALSE
"rmarkdown","*","models/maat","Suggests",FALSE
"rmarkdown","*","modules/data.atmosphere","Suggests",FALSE
"rmarkdown","*","modules/priors","Suggests",FALSE
Expand Down
3 changes: 0 additions & 3 deletions models/ed/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,10 @@ Imports:
Suggests:
testthat (>= 1.0.2),
devtools,
knitr,
rmarkdown,
withr
Additional_repositories: https://pecanproject.r-universe.dev/
License: BSD_3_clause + file LICENSE
Copyright: Authors
VignetteBuilder: knitr, rmarkdown
LazyData: true
Encoding: UTF-8
RoxygenNote: 7.3.2
Expand Down
21 changes: 12 additions & 9 deletions models/lpjguess/R/adjust.biomass.LPJGUESS.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
##' adjustments to the litter pools.
##'
##' @param individual A nested list which encapsulates an LPJ-GUESS 'Individual' as read from a binary state file
##' @param rel.change A numeric by which to scale the density and C and N pools
##' @param biomass.inc A numeric value specifying the biomass increment to be applied.
##' @param sla The SLA (specific leaf area) (per PFT parameter)
##' @param k_latosa The leaf area to sapwood area ratio (per PFT parameter)
##' @param k_allom2,k_allom3, Allometry coefficients (per PFT parameters)
##' @param wooddens Wood density (kgC/m^2) (per PFT parameter)
##' @param crownarea_max Maximum allowed crown area (m^2) (per PFT parameter)
##' @param lifeform An integer code for the lifeform of this individual (cohort): 1 = Tree, 2 = Grass
##' @param k_latosa The leaf area to sapwood area ratio (per PFT parameter)
##' @param k_allom2,k_allom3, Allometry coefficients (per PFT parameters)
##' @param trace Logical; if TRUE, prints details of biomass adjustment process.
##'
##' The changes in C pools are determined by the allocation. The changes in the N pools are designed to
##' maintain the pre-exisiing C:N ratios, so N is just scaled using the updated C with the initial C:N ratio.
Expand All @@ -21,13 +21,13 @@
##'
##' Note that after this function is called the function \code{allometry} should be used to update the individual
##' and to check that the newly updated individual has a 'valid' allometry. The litter pools should also be updated.
##' This is implemented in the \code{updateState} function following the call to this \code{adjustBiomass} function.
##' This is implemented in the \code{update.state.LPJGUESS} function following the call to this \code{adjust.biomass.LPJGUESS} function.
##'
##'
##' @keywords internal
##' @return the scaled 'individual' (the initial nested list with update values)
##' @author Matthew Forrest
adjust.biomass.LPJGUESS <- function(individual, rel.change, sla, wooddens, lifeform, k_latosa, k_allom2, k_allom3){
adjust.biomass.LPJGUESS <- function(individual, biomass.inc, sla, wooddens, lifeform, k_latosa, k_allom2, k_allom3, trace = TRUE){

# dummy input values to the allocation function below
# note that they are not actually updated by the function, the updated values are in the returned list
Expand All @@ -41,9 +41,12 @@ adjust.biomass.LPJGUESS <- function(individual, rel.change, sla, wooddens, life
exceeds_cmass <- 0

# calculate the total biomass and the absolute change based on this
biomass.total <- individual$cmass_leaf+individual$cmass_root+individual$cmass_heart+individual$cmass_sap-individual$cmass_debt
biomass.inc <- (biomass.total * rel.change) - biomass.total

biomass.total <- TotalCarbon(individual)
rel.change <- (biomass.total + biomass.inc) / biomass.total
if(trace) {
print(paste(" ------- DURING BIOMASS ADJUSTMENT -------"))
print(paste(" ***** Total Biomass Increment =", biomass.inc))
}

updated.pools <- allocation(
# vegetation state
Expand Down
71 changes: 24 additions & 47 deletions models/lpjguess/R/calculateGridcellVariablePerPFT.LPJGUESS.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
##' @param variable A character string specifying what variable to extract. This can be chosen based on the LPJ-GUESS variable name
##' as recorded in the big list of list (that represents describes the model state in R). Once special case is "biomass" which
##' returns the sum of "cmass_leaf", "cmass_root", "cmass_sap" and "cmass_heart"
##' @param pft.params A data frame containing PFT parameters such as allometric coefficients.
##' @param min.diam Minimum tree diameter (in cm) required for inclusion in calculations.
##' @return A numeric vector, with one entry per PFT
##' @export
##' @author Matthew Forrest
calculateGridcellVariablePerPFT <- function(model.state, variable) {
calculateGridcellVariablePerPFT <- function(model.state, variable, pft.params, min.diam = 5 ) {

# nstands - should always be 1 but lets make sure
nstands <- unlist(model.state$nstands)
Expand All @@ -34,19 +36,12 @@ calculateGridcellVariablePerPFT <- function(model.state, variable) {

# arrays to store the aggregated gridcell level properties
gc.sum <- numeric(length(model.state$Stand[[stand.counter]]$Standpft$active))

# loop through each patch
print(length(model.state$Stand[[stand.counter]]$Patch))
for(patch.counter in 1:npatches) {


print("-------------------------------------------------------------------------------------")
print(paste("-------------------------------- PATCH ", patch.counter, " -------------------------------------"))
print("-------------------------------------------------------------------------------------")


this.patch <- model.state$Stand[[stand.counter]]$Patch[[patch.counter]]

# pull out the number of individuals and a list of them
nindividuals <- length(this.patch$Vegetation)
all.individuals <- this.patch$Vegetation$Individuals
Expand All @@ -55,54 +50,36 @@ calculateGridcellVariablePerPFT <- function(model.state, variable) {
for(individual.counter in 1:length(all.individuals)) {
this.individual <- all.individuals[[individual.counter]]

# print(paste("id = ", this.individual$indiv.pft.id))
# print(paste("leaf =" , this.individual$cmass_leaf))
# print(paste("root =" , this.individual$cmass_root))
# print(paste("sap =" , this.individual$cmass_sap))
# print(paste("heart =" , this.individual$cmass_heart))
# print(paste("debt =" , this.individual$cmass_debt))
print(paste("alive =" , this.individual$alive))
print(individual.counter)

if(this.individual$alive) {
# get PFT index and covert the PFT from '0-indexed' C++ style to '1-indexed' R style
this.pft.id <- this.individual$indiv.pft.id
pft.index <- this.pft.id + 1

# calculate diameter to exclude small trees (converted to cm)
diam = ((this.individual$height / pft.params[pft.index, "k_allom2"]) ^ (1.0 / pft.params[pft.index, "k_allom3"])) * 100
print(diam)
if(this.individual$alive && diam > min.diam) {

# get the PFT ID
this.pft.id <- this.individual$indiv.pft.id


if(!this.pft.id %in% active.PFTs) stop(paste0("Found individual of PFT id = ",this.pft.id,
" but this doesn't seem to be active in the LPJ-GUESS run"))

# covert the PFT from '0-indexed' C++ style to '1-indexed' R style
pft.index <- this.pft.id+1

# calculate the total cmass and density of individuals per PFT
if(variable == "cmass") {
gc.sum[pft.index] <- gc.sum[pft.index] + (this.individual$cmass_leaf+this.individual$cmass_root+this.individual$cmass_heart+this.individual$cmass_sap-this.individual$cmass_debt)/npatches


print(paste("id = ", this.individual$indiv.pft.id))
print(paste("leaf =" , this.individual$cmass_leaf))
print(paste("root =" , this.individual$cmass_root))
print(paste("sap =" , this.individual$cmass_sap))
print(paste("heart =" , this.individual$cmass_heart))
print(paste("debt =" , this.individual$cmass_debt))

print(gc.sum)


}
}

else if(variable == "nmass") {
gc.sum[pft.index] <- gc.sum[pft.index] + ((this.individual$nmass_leaf+this.individual$nmass_root+this.individual$nmass_heart+
this.individual$nmass_sap+this.individual$nstore_labile+this.individual$nstore_longterm)/npatches)
#gc.sum[pft.index] <- gc.sum[pft.index] + ((this.individual$nmass_leaf+this.individual$nmass_root+this.individual$nmass_heart+
# this.individual$nmass_sap)/npatches)


#print(paste("leaf =" , this.individual$nmass_leaf))
#print(paste("root =" , this.individual$nmass_root))
#print(paste("sap =" , this.individual$nmass_sap))
#print(paste("heart =" , this.individual$nmass_heart))

this.individual$nmass_sap+this.individual$nstore_labile+this.individual$nstore_longterm)/npatches)
}

else if(variable == "AbvGrndWood") {
gc.sum[pft.index] <- gc.sum[pft.index] + (AbvGrndWood(this.individual)/npatches)
}

else gc.sum[pft.index] <- gc.sum[pft.index] + (this.individual[[variable]]/npatches)

}
Expand All @@ -114,7 +91,7 @@ calculateGridcellVariablePerPFT <- function(model.state, variable) {
}




}

Expand Down
Loading

0 comments on commit 96972d8

Please sign in to comment.