Using cropwatMUL for Crop-Water Assessment Across Multiple Locations

Introduction

cropwatMUL is an R package for estimating reference evapotranspiration, crop evapotranspiration, effective rainfall, crop-water requirements, root-zone water balance, and irrigation schedules for one crop across multiple locations.

The package uses a temperature-based implementation of the FAO-56 Penman-Monteith method and a workflow inspired by the ‘CROPWAT’ software.

The package is an independent implementation and is not affiliated with or endorsed by the Food and Agriculture Organization of the United Nations.

Input workbook structure

The input Excel workbook requires three worksheets:

  1. climate
  2. soil
  3. crop

Climate worksheet

The climate worksheet contains one row for every month and location.

Important fields include:

Optional fields include:

Soil worksheet

The soil worksheet contains one record for each location.

Required fields include:

Crop worksheet

The crop worksheet contains crop growth and crop-coefficient parameters.

Required fields include:

Load the package

library(cropwatMUL)

Locate the representative workbook

The package includes a synthetic workbook generated for demonstration.

input_file <- system.file(
  "extdata",
  "cropwat_example.xlsx",
  package = "cropwatMUL"
)

stopifnot(nzchar(input_file))
basename(input_file)
#> [1] "cropwat_example.xlsx"

The example data are simulated and should not be interpreted as observed climate, soil, or crop measurements.

Validate the input workbook

Validate the workbook before running the simulation:

validate_cropwat_input(
  input_file = input_file,
  crop_name = "Potato"
)

The validation function checks:

Run the multilocation simulation

result <- run_cropwat_one_crop_multilocation(
  input_file = input_file,
  crop_name = "Potato",
  irrigation_efficiency = 0.70,
  critical_depletion = 0.35,
  root_initial_m = 0.15,
  u2 = 2,
  krs = 0.16,
  altitude_m = 0,
  initial_depletion_mm = 0
)

Examine the result object

The returned object is a named list.

names(result)
#>  [1] "input_file"       "crop"             "summaries"        "daily"           
#>  [5] "dekadal"          "monthly"          "soil"             "climate"         
#>  [9] "location_results" "settings"

Important components include:

Seasonal summary

result$summaries
#> # A tibble: 3 × 18
#>   DISTRICT       crop   planting_date harvest_date crop_duration_days latitude
#>   <chr>          <chr>  <date>        <date>                    <dbl>    <dbl>
#> 1 Example_Hill   Potato 2026-10-15    2027-02-11                  120     25.7
#> 2 Example_Plain  Potato 2026-10-15    2027-02-11                  120     26.2
#> 3 Example_Valley Potato 2026-10-15    2027-02-11                  120     24.8
#> # ℹ 12 more variables: longitude <dbl>, soil_texture <chr>, AWC_mm_m <dbl>,
#> #   total_yearly_rainfall_mm <dbl>, total_yearly_effective_rainfall_mm <dbl>,
#> #   seasonal_ET_crop_mm <dbl>, seasonal_effective_rainfall_mm <dbl>,
#> #   irrigation_requirement_mm <dbl>, total_net_irrigation_mm <dbl>,
#> #   total_gross_irrigation_mm <dbl>, irrigation_efficiency <dbl>,
#> #   critical_depletion <dbl>

The summary includes:

Monthly climate and reference evapotranspiration

head(result$monthly)
#> # A tibble: 6 × 9
#>   DISTRICT     month_no month TMAX_C TMIN_C RAINFALL_mm effective_rainfall_mm
#>   <chr>           <int> <chr>  <dbl>  <dbl>       <dbl>                 <dbl>
#> 1 Example_Hill        1 Jan     16.5    7.8        40.7                  38.0
#> 2 Example_Hill        2 Feb     19.4    8.5        19                    18.4
#> 3 Example_Hill        3 Mar     21.9   11.6        45.6                  42.3
#> 4 Example_Hill        4 Apr     23.4   14.6        45.8                  42.4
#> 5 Example_Hill        5 May     24.9   15         132.                  104. 
#> 6 Example_Hill        6 Jun     26.4   16.9       210.                  139. 
#> # ℹ 2 more variables: ETo_midmonth_mm_day <dbl>, ETo_monthly_total_mm <dbl>

The monthly output includes:

Dekadal crop-water requirement

head(result$dekadal)
#> # A tibble: 6 × 12
#>   DISTRICT crop  dekad_id period_start period_end  days ETo_mm Kc_mean ETcrop_mm
#>   <chr>    <chr> <chr>    <date>       <date>     <int>  <dbl>   <dbl>     <dbl>
#> 1 Example… Pota… 2026-10… 2026-10-15   2026-10-20     6   16.5   0.5        8.23
#> 2 Example… Pota… 2026-10… 2026-10-21   2026-10-31    11   28.5   0.5       14.2 
#> 3 Example… Pota… 2026-11… 2026-11-01   2026-11-10    10   24.0   0.506     12.1 
#> 4 Example… Pota… 2026-11… 2026-11-11   2026-11-20    10   22.2   0.662     14.7 
#> 5 Example… Pota… 2026-11… 2026-11-21   2026-11-30    10   20.9   0.879     18.3 
#> 6 Example… Pota… 2026-12… 2026-12-01   2026-12-10    10   19.5   1.09      21.2 
#> # ℹ 3 more variables: effective_rainfall_mm <dbl>, rainfall_event_mm <dbl>,
#> #   irrigation_requirement_mm <dbl>

The dekadal table includes:

Daily irrigation schedule

head(
  result$daily[
    result$daily$in_crop,
  ]
)
#> # A tibble: 6 × 23
#>   date       ETo_mm eff_rain_mm rain_mm DISTRICT     crop   latitude longitude
#>   <date>      <dbl>       <dbl>   <dbl> <chr>        <chr>     <dbl>     <dbl>
#> 1 2026-10-15   2.79        2.58     0   Example_Hill Potato     25.7      91.9
#> 2 2026-10-16   2.77        2.53     0   Example_Hill Potato     25.7      91.9
#> 3 2026-10-17   2.75        2.48    14.6 Example_Hill Potato     25.7      91.9
#> 4 2026-10-18   2.73        2.42     0   Example_Hill Potato     25.7      91.9
#> 5 2026-10-19   2.72        2.38     0   Example_Hill Potato     25.7      91.9
#> 6 2026-10-20   2.70        2.33     0   Example_Hill Potato     25.7      91.9
#> # ℹ 15 more variables: soil_texture <chr>, AWC_mm_m <dbl>, in_crop <lgl>,
#> #   DAS <dbl>, Kc <dbl>, root_depth_m <dbl>, ETc_mm <dbl>, TAW_mm <dbl>,
#> #   RAW_mm <dbl>, dekad_id <chr>, dekad_no <dbl>, depletion_start_mm <dbl>,
#> #   net_irrigation_mm <dbl>, gross_irrigation_mm <dbl>, depletion_end_mm <dbl>

The daily schedule includes:

Export results

The export function creates:

vignette_output_dir <- tempfile("cropwatMUL-vignette-")
dir.create(
  vignette_output_dir,
  recursive = TRUE,
  showWarnings = FALSE
)

output <- write_cropwat_outputs(
  results = result,
  output_dir = vignette_output_dir,
  prefix = "Potato_cropwatMUL_example"
)

c(
  excel_file = basename(output$excel_file),
  txt_directory = basename(output$txt_dir),
  summary_file = basename(output$all_locations_summary)
)
#>                              excel_file                           txt_directory 
#>        "Potato_cropwatMUL_example.xlsx" "Potato_cropwatMUL_example_txt_outputs" 
#>                            summary_file 
#>             "all_locations_summary.txt"

unlink(
  vignette_output_dir,
  recursive = TRUE,
  force = TRUE
)

The example writes only to an R session temporary directory and removes the generated files immediately after the demonstration. The TXT outputs are tab-delimited and contain complete rows and columns without tibble abbreviation.

Reference evapotranspiration assumptions

When measured humidity, radiation, or wind data are unavailable:

These assumptions should be evaluated for the climatic region in which the package is applied.

Effective rainfall

Monthly effective rainfall is estimated using the USDA-SCS relationship implemented in:

usda_scs_effective_rain(
  c(50, 150, 300)
)
#> [1]  46 114 155

Reference evapotranspiration example

pm_temp_estimated(
  tmax = 25,
  tmin = 15,
  lat = 25.7,
  doy = 100,
  altitude_m = 1000,
  u2 = 2,
  krs = 0.16
)
#> [1] 3.815224

Limitations

The package does not claim exact numerical equivalence with every version or configuration of the official CROPWAT software.

Differences may arise from:

Users should validate the outputs against local observations, independent calculations, or established software before operational decision-making.