Skip to content

Commit

Permalink
Do multiple crops at once
Browse files Browse the repository at this point in the history
  • Loading branch information
burggraaff committed Apr 17, 2024
1 parent 43fd85e commit 2ab58c4
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 22 deletions.
10 changes: 5 additions & 5 deletions fpcup/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def __str__(self) -> str:
PCSEParameter = PCSEFlag | PCSELabel | PCSENumericParameter | PCSETabularParameter

### Parameters
# Parameter information from "A gentle introduction to WOFOST" (De Wit & Boogaard 2021), CABO file descriptions, YAML file descriptions
# Parameter information from "A gentle introduction to WOFOST" (De Wit & Boogaard 2021), CABO file descriptions, YAML file descriptions, WOFOSTSiteProvider defaults
C = "°C"
Cday = f"{C} day"
cm3percm3 = "cm^3 / cm^3"
Expand All @@ -100,10 +100,10 @@ def __str__(self) -> str:
n = PCSENumericParameter(name="n", description="Number of sites")
area = PCSENumericParameter(name="area", description="Total plot area", unit="ha")
WAV = PCSENumericParameter(name="WAV", description="Initial amount of water in rootable zone in excess of wilting point", plotname="Initial excess water", unit="cm", bounds=(0, 50), default=10)
NOTINF = PCSENumericParameter(name="NOTINF", description="Non-infiltrating fraction", bounds=(0, 1))
SMLIM = PCSENumericParameter(name="SMLIM", description="Maximum initial soil moisture in rooted zone", plotname="Maximum initial soil moisture", unit="cm", bounds=(0, 10))
SSI = PCSENumericParameter(name="SSI", description="Initial surface storage", unit="cm", bounds=(0, 2))
SSMAX = PCSENumericParameter(name="SSMAX", description="Maximum surface storage capacity", unit="cm", bounds=(0, 2))
NOTINF = PCSENumericParameter(name="NOTINF", description="Non-infiltrating fraction", bounds=(0, 1), default=0)
SMLIM = PCSENumericParameter(name="SMLIM", description="Maximum initial soil moisture in rooted zone", plotname="Maximum initial soil moisture", unit="cm", bounds=(0, 10), default=0.4)
SSI = PCSENumericParameter(name="SSI", description="Initial surface storage", unit="cm", bounds=(0, 2), default=0)
SSMAX = PCSENumericParameter(name="SSMAX", description="Maximum surface storage capacity", unit="cm", bounds=(0, 2), default=0)
CRAIRC = PCSENumericParameter(name="CRAIRC", description="Critical soil air content for aeration (used when IOX = 1)", plotname="Critical soil air content for aeration", unit=cm3percm3, bounds=(0.04, 0.1))
SM0 = PCSENumericParameter(name="SM0", description="Soil moisture content of saturated soil", plotname="Saturated soil moisture content", unit=cm3percm3, bounds=(0.3, 0.9))
SMFCF = PCSENumericParameter(name="SMFCF", description="Soil moisture content at field capacity", unit=cm3percm3, bounds=(0.05, 0.74))
Expand Down
9 changes: 8 additions & 1 deletion fpcup/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
from copy import copy
from functools import partial
from itertools import product
from itertools import chain, product
from textwrap import indent
indent2 = partial(indent, prefix=" ")

Expand All @@ -17,6 +17,13 @@
RUNNING_IN_IPYTHON = True


def flatten_list(x: Iterable[Iterable[object]]) -> list[object]:
"""
Flatten a list of lists (or other iterables), using itertools.chain.
"""
return list(chain(x))


def make_iterable(x: object, exclude: Iterable[type]=[str]) -> Iterable:
"""
Check if x is an iterable.
Expand Down
44 changes: 28 additions & 16 deletions wofost_ensemble_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
Run a PCSE ensemble for different values of input parameters to determine their effect.
All available soil types are tested.
A specified number of sites, roughly central to the Netherlands, are used.
By default, three crops (spring barley, green maize, winter wheat) are used; a single crop can be specified with -c.
Example:
python wofost_ensemble_parameters.py rdmsol wav -n 100 -v -c barley -s 16
python wofost_ensemble_parameters.py rdmsol wav -n 100 -v
To simulate only multiple sowing dates, simply leave out the other parameters, e.g.:
python wofost_ensemble_parameters.py -v -c barley -s 16 -d
Expand All @@ -17,7 +18,7 @@
parser.add_argument("parameter_names", help="parameter(s) to iterate over", type=str.upper, nargs="*")
parser.add_argument("-n", "--number", help="number of values per parameter; note the exponential increase in runs when doing multiple parameters", type=int, default=100)
parser.add_argument("-d", "--sowdates", help="run the simulation for multiple sowing dates (based on the crop's range)", action="store_true")
parser.add_argument("-c", "--crop", help="crop to run simulations on", default="barley", type=fpcup.crop.select_crop)
parser.add_argument("-c", "--crops", help="crop(s) to run simulations on", default=None)
parser.add_argument("-s", "--number_sites", help="number of sites; result may be lower due to rounding", type=int, default=16)
parser.add_argument("--data_dir", help="folder to load PCSE data from", type=fpcup.io.Path, default=fpcup.settings.DEFAULT_DATA)
parser.add_argument("--output_dir", help="folder to save PCSE outputs to (default: generated from parameters)", type=fpcup.io.Path, default=None)
Expand All @@ -40,7 +41,7 @@
if __name__ == "__main__":
fpcup.multiprocessing.freeze_support()

### SETUP
### GENERAL SETUP
# Check that enough inputs were provided
assert len(args.parameter_names) > 0 or args.sowdates, "Please provide parameters to iterate over and/or use the -d flag to iterate over sowing dates."

Expand All @@ -49,6 +50,16 @@
if args.verbose:
print(f"Save folder: {args.output_dir.absolute()}")


### ITERABLE SETUP
# Get crop data
if args.crops is None: # Default
args.crops = [fpcup.crop.crops["barley (spring)"], fpcup.crop.crops["maize (green)"], fpcup.crop.crops["wheat (winter)"]]
elif isinstance(args.crops, str): # Single crop
args.crops = [fpcup.crop.select_crop(args.crops)]
else:
raise ValueError(f"Cannot determine target crop from input '{args.crops}'")

# Generate the parameter iterable
if args.parameter_names:
combined_parameters = fpcup.parameters.generate_ensemble_space(*args.parameter_names, n=args.number)
Expand All @@ -57,22 +68,22 @@
if args.verbose:
print(f"Iterating over the following parameters: {args.parameter_names}")

# Mix in agromanagement data
# Generate one or multiple agromanagement calendars, corresponding to sowing dates
if args.sowdates:
agromanagements = args.crop.agromanagement_all_sowingdates(YEAR)
variables = {"agromanagement": agromanagements, **variables}
# Mix in agromanagement
if args.sowdates: # Multiple sowing dates
agromanagements = fpcup.tools.flatten_list(c.agromanagement_all_sowingdates(YEAR) for c in args.crops)
else: # Single sowing date
agromanagements = [c.agromanagement_first_sowingdate(YEAR) for c in args.crops]

first, last = agromanagements[0].crop_start_date, agromanagements[-1].crop_start_date
if len(agromanagements) == 1: # Single crop, single sowing date
CONSTANTS = {"agromanagement": agromanagements[0], **CONSTANTS}
if args.verbose:
print(f"Generated {len(agromanagements)} agromanagement calendars ({first} -- {last}).")
else:
agromanagements = args.crop.agromanagement_first_sowingdate(YEAR)
CONSTANTS = {"agromanagement": agromanagements, **CONSTANTS}
if args.verbose:
print("Loaded agro management data:")
print(agromanagements)
print("Generated 1 agromanagement calendar:")
print(agromanagements[0])
print()
else: # Multiple crops and/or multiple sowing dates
variables = {"agromanagement": agromanagements, **variables}
if args.verbose:
print(f"Generated {len(agromanagements)} agromanagement calendars for {len(args.crops)} crops.")

# Generate the coordinates
coords = fpcup.site.generate_sites_space(latitude=(51, 53), longitude=(4, 6), n=args.number_sites)
Expand All @@ -84,6 +95,7 @@

if args.verbose:
print(f"Expected total runs: {args.number}**{len(args.parameter_names)} parameter values"
f" * {len(args.crops)} crops"
f" * {len(agromanagements) if args.sowdates else 1} sowing dates"
f" * {len(SOILTYPES)} soil types"
f" * {len(coords)} sites"
Expand Down

0 comments on commit 2ab58c4

Please sign in to comment.