From ec69a545491319b15d0b53481947b80ff155171e Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:10:40 +0100 Subject: [PATCH 01/20] adding new fire constants --- etc/fcm-make/make-river.cfg | 2 +- .../jules-fire/HEAD/rose-meta.conf | 160 ++++++ .../jules-vegetation/HEAD/rose-meta.conf | 37 +- .../jules-standalone/HEAD/rose-meta.conf | 25 +- rose-meta/jules-standalone/versions.py | 58 ++- rose-meta/jules-um/HEAD/rose-meta.conf | 3 +- .../bin/gfortran_10_plus_rivers.json | 2 +- rose-stem/app/fab_jules/bin/intel_rivers.json | 2 +- src/control/shared/jules_inferno_mod.F90 | 458 ++++++++++++++++++ .../shared/jules_soil_biogeochem_mod.F90 | 25 +- src/control/shared/jules_vegetation_mod.F90 | 54 +-- src/control/shared/surf_couple_extra_mod.F90 | 5 +- src/control/um/diagnostics_hyd.F90 | 2 +- .../shared/check_compatible_options_mod.F90 | 6 +- src/initialisation/standalone/init.F90 | 3 + .../standalone/init_inferno_mod.F90 | 138 ++++++ .../standalone/init_jules_sf_diags_mod.F90 | 5 +- .../standalone/init_vegetation.F90 | 22 +- .../um/read_jules_namelists_mod.F90 | 31 ++ src/science/fire/inferno_io_mod.F90 | 18 +- src/science/fire/inferno_mod.F90 | 83 ++-- src/science/params/pftparm_mod.F90 | 6 +- src/science/vegetation/soilcarb_jls.F90 | 18 +- .../vegetation/soilcarb_layers_jls_mod.F90 | 24 +- src/science/vegetation/veg-veg2a_jls_mod.F90 | 4 +- 25 files changed, 955 insertions(+), 236 deletions(-) create mode 100644 rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf create mode 100644 src/control/shared/jules_inferno_mod.F90 create mode 100644 src/initialisation/standalone/init_inferno_mod.F90 diff --git a/etc/fcm-make/make-river.cfg b/etc/fcm-make/make-river.cfg index 68c43e11..eba8dd77 100644 --- a/etc/fcm-make/make-river.cfg +++ b/etc/fcm-make/make-river.cfg @@ -160,7 +160,7 @@ extract.path-incl[river] = $extract_path_incl \ src/control/imogen/imgn_vars_mod.F90 \ src/control/shared/jules_radiation_mod.F90 \ src/params/imogen/imogen_constants.F90 \ - src/science/fire/fire_mod.F90 \ + src/science/fire/fire_weather_index/fire_mod.F90 \ src/util/shared/metstats/metstats_mod.F90 \ #............................................................................... # and allocate_river_arrays diff --git a/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf new file mode 100644 index 00000000..adff37a6 --- /dev/null +++ b/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf @@ -0,0 +1,160 @@ +[namelist:jules_inferno] +compulsory=true +description=Options for inferno fire parametrisations +ns=namelist/JULES Science Settings/jules_inferno +sort-key=Section-A12g +title=Fire options +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html + +[namelist:jules_inferno=l_inferno] +compulsory=true +description=Use the INFERNO interactive fire and diagnostic emissions model +sort-key=Panel-I16 +trigger=namelist:jules_inferno=ignition_method: .true.; + =namelist:jules_inferno=l_trif_fire: .true.; + =namelist:jules_pftparm=avg_ba_io: .true.; + =namelist:jules_pftparm=ccleaf_min_io: .true.; + =namelist:jules_pftparm=ccleaf_max_io: .true.; + =namelist:jules_pftparm=ccwood_min_io: .true.; + =namelist:jules_pftparm=ccwood_max_io: .true.; + =namelist:jules_pftparm=fef_bc_io: .true.; + =namelist:jules_pftparm=fef_ch4_io: .true.; + =namelist:jules_pftparm=fef_co2_io: .true.; + =namelist:jules_pftparm=fef_co_io: .true.; + =namelist:jules_pftparm=fef_nox_io: .true.; + =namelist:jules_pftparm=fef_oc_io: .true.; + =namelist:jules_pftparm=fef_so2_io: .true.; + =namelist:jules_pftparm=fef_c2h4_io: .true.; + =namelist:jules_pftparm=fef_c2h6_io: .true.; + =namelist:jules_pftparm=fef_c3h8_io: .true.; + =namelist:jules_pftparm=fef_hcho_io: .true.; + =namelist:jules_pftparm=fef_mecho_io: .true.; + =namelist:jules_pftparm=fef_nh3_io: .true.; + =namelist:jules_pftparm=fef_dms_io: .true.; +type=logical +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_inferno + +[namelist:jules_inferno=l_trif_fire] +compulsory=true +description=Use interactive fire linked to INFERNO including interactive fire emissions. +fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); +sort-key=Panel-I1 +trigger=namelist:jules_pftparm=fire_mort_io: .true. +type=logical +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_trif_fire + +[namelist:jules_inferno=ignition_method] +compulsory=true +description=The method to use for ignitions +sort-key=Panel-I16a +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ignition_method +value-titles=(1) constant human and natural ignition sources, + =(2) constant human varying natural ignition sources, + =(3) varying human and natural ignition sources +values=1,2,3 +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ignition_method + +[namelist:jules_inferno=z_burn_max] +compulsory=true +description=Maximum burn depth for soil - soil carbon is burned above this level +range=0.0:10.0 +sort-key=b2 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::z_burn_max + +[namelist:jules_inferno=triffire_ccdpm_min] +compulsory=true +description=Minimum fraction of DPM consumed by fire +range=0.0:1.0 +sort-key=b3 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccdpm_min + +[namelist:jules_inferno=triffire_ccdpm_max] +compulsory=true +description=Maximum fraction of DPM consumed by fire +range=0.0:1.0 +sort-key=b4 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccdpm_max + +[namelist:jules_inferno=triffire_ccrpm_min] +compulsory=true +description=Minimum fraction of RPM consumed by fire +range=0.0:1.0 +sort-key=b5 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccrpm_min + +[namelist:jules_inferno=triffire_ccrpm_max] +compulsory=true +description=Maximum fraction of RPM consumed by fire +range=0.0:1.0 +sort-key=b6 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccrpm_max + +[namelist:jules_inferno=flam_rhum_low] +compulsory=true +description=Lower relative humidity threshold for flammability +range=0.0:1.0 +sort-key=b7 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_low + +[namelist:jules_inferno=flam_rhum_up] +compulsory=true +description=Upper relative humidity threshold for flammability +range=0.0:1.0 +sort-key=b8 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_up + +[namelist:jules_inferno=flam_sm_low] +compulsory=true +description=Lower soil moisture threshold for flammability +range=0.0:1.0 +sort-key=b9 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_low + +[namelist:jules_inferno=flam_sm_up] +compulsory=true +description=Upper soil moisture threshold for flammability +range=0.0:1.0 +sort-key=b10 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_up + +[namelist:jules_inferno=flam_fuel_low] +compulsory=true +description=Lower fuel load threshold for flammability +range=0.0:1.0 +sort-key=b11 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_low + +[namelist:jules_inferno=flam_fuel_up] +compulsory=true +description=Upper fuel load threshold for flammability +range=0.0:1.0 +sort-key=b12 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_up + +[namelist:jules_inferno=flam_rain_const] +compulsory=true +description=Rainfall flammability scaling constant +sort-key=b13 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rain_const + +[namelist:jules_inferno=flam_sm_func] +compulsory=true +description=Soil moisture flammability function selector +sort-key=b14 +type=integer +value-titles=(1) linear, + =(2) exponential +values=1,2 +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_func diff --git a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf index 5c8f7f03..4967a536 100644 --- a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf @@ -30,33 +30,7 @@ trigger=namelist:jules_pftparm=ief_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_bvoc_emis -[namelist:jules_vegetation=l_inferno] -compulsory=true -description=Use the INFERNO interactive fire and diagnostic emissions model -sort-key=Panel-I16 -trigger=namelist:jules_vegetation=ignition_method: .true.; - =namelist:jules_vegetation=l_trif_fire: .true.; - =namelist:jules_pftparm=avg_ba_io: .true.; - =namelist:jules_pftparm=ccleaf_min_io: .true.; - =namelist:jules_pftparm=ccleaf_max_io: .true.; - =namelist:jules_pftparm=ccwood_min_io: .true.; - =namelist:jules_pftparm=ccwood_max_io: .true.; - =namelist:jules_pftparm=fef_bc_io: .true.; - =namelist:jules_pftparm=fef_ch4_io: .true.; - =namelist:jules_pftparm=fef_co2_io: .true.; - =namelist:jules_pftparm=fef_co_io: .true.; - =namelist:jules_pftparm=fef_nox_io: .true.; - =namelist:jules_pftparm=fef_oc_io: .true.; - =namelist:jules_pftparm=fef_so2_io: .true.; - =namelist:jules_pftparm=fef_c2h4_io: .true.; - =namelist:jules_pftparm=fef_c2h6_io: .true.; - =namelist:jules_pftparm=fef_c3h8_io: .true.; - =namelist:jules_pftparm=fef_hcho_io: .true.; - =namelist:jules_pftparm=fef_mecho_io: .true.; - =namelist:jules_pftparm=fef_nh3_io: .true.; - =namelist:jules_pftparm=fef_dms_io: .true.; -type=logical -url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_inferno + [namelist:jules_vegetation=l_limit_canhc] compulsory=true @@ -96,15 +70,6 @@ trigger=namelist:jules_pftparm=sug_g0_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_sugar -[namelist:jules_vegetation=l_trif_fire] -compulsory=true -description=Use interactive fire linked to INFERNO including interactive fire emissions. -fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); -sort-key=Panel-I02c -trigger=namelist:jules_pftparm=fire_mort_io: .true. -type=logical -url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_trif_fire - [namelist:jules_vegetation=l_use_pft_psi] compulsory=true description=Use psi_open_io and psi_close_io to calculate the soil moisture stress function on vegetation. diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index e30a27c5..d1760351 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -1,6 +1,7 @@ # Please see jules:wiki:SharingJULESmetadata -import=jules-shared/jules-hydrology/HEAD +import=jules-shared/jules-fire/HEAD + =jules-shared/jules-hydrology/HEAD =jules-shared/jules-model-environment/HEAD =jules-shared/jules-nvegparm/HEAD =jules-shared/jules-pftparm/HEAD @@ -5004,7 +5005,7 @@ sort-key=b trigger=namelist:jules_soil_biogeochem=tau_resp: .true.; =namelist:jules_soil_biogeochem=l_label_frac_cs: .true.; =namelist:jules_soil_biogeochem=diff_n_pft: .true.; - =namelist:jules_soil_biogeochem=z_burn_max: .true.; + =namelist:jules_inferno=z_burn_max: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_soil_biogeochem.nml.html#JULES_SOIL_BIOGEOCHEM::l_layeredc @@ -5203,14 +5204,6 @@ sort-key=b2 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_soil_biogeochem.nml.html#JULES_SOIL_BIOGEOCHEM::tau_resp -[namelist:jules_soil_biogeochem=z_burn_max] -compulsory=true -description=Maximum burn depth for soil - soil carbon is burned above this level -range=0.0:10.0 -sort-key=b2 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_soil_biogeochem.nml.html#JULES_SOIL_BIOGEOCHEM::z_burn_max - [namelist:jules_soil_ecosse] compulsory=true ns=namelist/JULES Science Settings/jules_soil_ecosse @@ -6467,16 +6460,6 @@ value-titles=Piece-wise linear in volumetric soil moisture, Piece-wise linear in values=0,1 widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget -[namelist:jules_vegetation=ignition_method] -compulsory=true -description=The method to use for ignitions -sort-key=Panel-I16a -url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::ignition_method -value-titles=(1) constant human and natural ignition sources, - =(2) constant human varying natural ignition sources, - =(3) varying human and natural ignition sources -values=1,2,3 - [namelist:jules_vegetation=ilayers] compulsory=true description=Number of layers for canopy radiation model @@ -6698,7 +6681,7 @@ trigger=namelist:jules_vegetation=l_nrun_mid_trif: .true.; =namelist:jules_vegetation=l_nitrogen: .true.; =namelist:jules_vegetation=l_red: .true.; =namelist:jules_vegetation=l_trif_crop: .true.; - =namelist:jules_vegetation=l_trif_fire: .true.; + =namelist:jules_inferno=l_trif_fire: .true.; =namelist:jules_vegetation=l_trif_init_accum: .true.; =namelist:jules_vegetation=frac_min: .true.; =namelist:jules_vegetation=frac_seed: .true.; diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 1d4c41a9..74e0414f 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -45,15 +45,63 @@ from .version81_82 import * -class vnYY_txxxx(MacroUpgrade): - """Upgrade macro from JULES by Author""" +class vn82_t61(MacroUpgrade): - BEFORE_TAG = "vnY.Y" - AFTER_TAG = "vnY.Y_txxxx" + """Upgrade macro from JULES by Eleanor Burke""" + + BEFORE_TAG = "vn8.2" + AFTER_TAG = "vn8.2_t61" def upgrade(self, config, meta_config=None): """Upgrade a JULES runtime app configuration.""" - # Add settings + self.rename_setting(config, ["namelist:fire_switches"], + ["namelist:jules_fire_weather_index"]) + self.rename_setting(config, ["namelist:jules_fire_weather_index", + "l_fire"], + ["namelist:jules_fire_weather_index", + "l_fire_weather_index"]) + + self.add_setting(config, ["namelist:jules_inferno"]) + + source = self.get_setting_value(config, ["file:fire.nml","source"]) + source = source.replace("namelist:fire_switches", + "namelist:jules_fire_weather_index namelist:jules_inferno") + self.change_setting_value(config, ["file:fire.nml","source"], source) + + l_inferno = self.get_setting_value(config, ["namelist:jules_vegetation", "l_inferno"]) + self.add_setting(config, + ["namelist:jules_inferno", "l_inferno"], l_inferno) + self.remove_setting(config, ["namelist:jules_vegetation", "l_inferno"]) + + l_trif_fire = self.get_setting_value(config, ["namelist:jules_vegetation", "l_trif_fire"]) + self.add_setting(config, + ["namelist:jules_inferno", "l_trif_fire"], l_trif_fire) + self.remove_setting(config, ["namelist:jules_vegetation", "l_trif_fire"]) + + ignition_method = self.get_setting_value(config, ["namelist:jules_vegetation", "ignition_method"]) + self.add_setting(config, + ["namelist:jules_inferno", "ignition_method"], ignition_method) + self.remove_setting(config, ["namelist:jules_vegetation", "ignition_method"]) + + z_burn_max = self.get_setting_value(config, ["namelist:jules_soil_biogeochem", "z_burn_max"]) + self.add_setting(config, + ["namelist:jules_inferno", "z_burn_max"], z_burn_max) + self.remove_setting(config, ["namelist:jules_soil_biogeochem", "z_burn_max"]) + + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_min"], 0.8) + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_max"], 1.0) + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_min"], 0.0) + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_max"], 0.2) + + self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_low"], 0.1) + self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_up"], 0.9) + self.add_setting(config, ["namelist:jules_inferno", "flam_sm_low"], 0.0) + self.add_setting(config, ["namelist:jules_inferno", "flam_sm_up"], 2.4) + self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_low"], 0.02) + self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_up"], 0.2) + self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], -14929920000.0) + self.add_setting(config, ["namelist:jules_inferno", "flam_sm_func"], 1) + return config, self.reports diff --git a/rose-meta/jules-um/HEAD/rose-meta.conf b/rose-meta/jules-um/HEAD/rose-meta.conf index 0f8fdd05..6f27795a 100644 --- a/rose-meta/jules-um/HEAD/rose-meta.conf +++ b/rose-meta/jules-um/HEAD/rose-meta.conf @@ -8,7 +8,8 @@ # Please see jules:wiki:SharingJULESmetadata ############################################################################### -import=jules-shared/jules-hydrology/HEAD +import=jules-shared/jules-fire/HEAD + =jules-shared/jules-hydrology/HEAD =jules-shared/jules-model-environment/HEAD =jules-shared/jules-nvegparm/HEAD =jules-shared/jules-pftparm/HEAD diff --git a/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json b/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json index ee11274a..a1571c4d 100644 --- a/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json +++ b/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json @@ -140,7 +140,7 @@ "/src/science/params/trif_mod.F90", "/src/science/params/pftparm_mod.F90", "/src/science/params/ecosse_param_mod.F90", - "/src/science/fire/fire_mod.F90", + "/src/science/fire/fire_weather_index/fire_mod.F90", "/src/science/surface/sf_diags_mod.F90", "/src/science/params/urban_param_mod.F90", "/src/params/imogen/imogen_time.F90", diff --git a/rose-stem/app/fab_jules/bin/intel_rivers.json b/rose-stem/app/fab_jules/bin/intel_rivers.json index 04d24e92..38180141 100644 --- a/rose-stem/app/fab_jules/bin/intel_rivers.json +++ b/rose-stem/app/fab_jules/bin/intel_rivers.json @@ -139,7 +139,7 @@ "/src/science/params/trif_mod.F90", "/src/science/params/pftparm_mod.F90", "/src/science/params/ecosse_param_mod.F90", - "/src/science/fire/fire_mod.F90", + "/src/science/fire/fire_weather_index/fire_mod.F90", "/src/science/surface/sf_diags_mod.F90", "/src/science/params/urban_param_mod.F90", "/src/params/imogen/imogen_time.F90", diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 new file mode 100644 index 00000000..e17cf859 --- /dev/null +++ b/src/control/shared/jules_inferno_mod.F90 @@ -0,0 +1,458 @@ +! *****************************COPYRIGHT******************************* +! (C) Crown copyright Met Office. All rights reserved. +! For further details please refer to the file COPYRIGHT.txt +! which you should have received as part of this distribution. +! *****************************COPYRIGHT******************************* + +MODULE jules_inferno_mod + +USE missing_data_mod, ONLY: rmdi, imdi + +!----------------------------------------------------------------------------- +! Description: +! Contains inferno and l_trif_fire options and a namelist for setting them +! +! Code Owner: Please refer to ModuleLeaders.txt +! This file belongs in TECHNICAL +! +! Code Description: +! Language: Fortran 90. +! This code is written to JULES coding standards v1. +!----------------------------------------------------------------------------- + +USE um_types, ONLY: real_jlslsm + +IMPLICIT NONE + +!----------------------------------------------------------------------------- +! Module constants +!----------------------------------------------------------------------------- + +!----------------------------------------------------------------------------- +! Module variables +!----------------------------------------------------------------------------- + +! Items set in namelist jules_inferno. + +INTEGER :: & + ignition_method = 1, & + ! Switch for the calculation method of INFERNO fire ignitions + ! IGNITION_METHOD=1:Constant (1.67 per km2 per s) + ! IGNITION_METHOD=2:Constant (Human - 1.5 per km2 per s) + ! Varying (Lightning - see Pechony and Shindell,2009) + ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony and Shindell,2009) + flam_sm_func = 1 + ! Switch for the calculation method of INFERNO fire flammability + ! FLAM_SM_FUNC=1:Linear + ! FLAM_SM_FUNC=2:Exponential + + +LOGICAL :: & + l_inferno = .FALSE., & + ! Switch used to control whether the Interactive fire scheme is used + l_trif_fire = .FALSE. + ! Switch used to control whether interactive fire is used + ! T => if l_inferno is also true, g_burn is calculated in INFERNO +! and passed to TRIFFID to calculate emissions and vegetation + ! dynamics + ! T => if l_inferno is false, interactive fire is calculated via +! ancillary if provided, and is 0 if not provided + ! F => g_burn is calculated via ancillary if provided, and is 0 if +! not provided + +INTEGER, PARAMETER :: ignition_constant = 1 +INTEGER, PARAMETER :: ignition_vary_natural = 2 +INTEGER, PARAMETER :: ignition_vary_natural_human = 3 + + +INTEGER :: errcode ! error code to pass to ereport. + +REAL(KIND=real_jlslsm) :: & + flam_sm_low = rmdi, & + ! Lower boundary to the soil moisture + flam_sm_up = rmdi, & + ! Upper boundary to the soil moisture + flam_rhum_low = rmdi, & + ! Lower boundary to the relative humidity + flam_rhum_up = rmdi, & + ! Upper boundary to the relative humidity + flam_rain_const = rmdi, & + ! Precipitation factor (-2(day/mm)*(kg/m2/s)) + flam_fuel_low = rmdi, & + ! Lower boundary to the fuel density + flam_fuel_up = rmdi, & + ! Upper boundary to the fuel density + triffire_ccdpm_min = rmdi, & + ! Minimum decomposable plant material burn fraction + triffire_ccdpm_max = rmdi, & + ! Decomposable Plant Material burns between 80 to 100 % + triffire_ccrpm_min = rmdi, & + ! Minimum resistant plant material burn fraction + triffire_ccrpm_max = rmdi, & + ! Resistant Plant Material burns between 0 to 20 % + z_burn_max = rmdi + ! Parameter setting maximum depth of burn + +!----------------------------------------------------------------------------- +! Single namelist definition for UM and standalone +!----------------------------------------------------------------------------- +NAMELIST / jules_inferno/ & + l_trif_fire, & + l_inferno, & + ignition_method, & + flam_sm_func, & + flam_sm_low, & + flam_sm_up, & + flam_rhum_low, & + flam_rhum_up, & + flam_rain_const, & + flam_fuel_low, & + flam_fuel_up, & + triffire_ccdpm_min, & + triffire_ccdpm_max, & + triffire_ccrpm_min, & + triffire_ccrpm_max + +CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='JULES_INFERNO_MOD' + +CONTAINS + +SUBROUTINE check_jules_inferno() + +USE ereport_mod, ONLY: ereport + +USE jules_print_mgr, ONLY: jules_message +!----------------------------------------------------------------------------- +! Description: +! Checks JULES_INFERNO namelist for consistency and calculates some +! derived values. +! +! Code Owner: Please refer to ModuleLeaders.txt +! This file belongs in TECHNICAL +! +! Code Description: +! Language: Fortran 90. +! This code is written to JULES coding standards v1. +!----------------------------------------------------------------------------- + +IMPLICIT NONE + +! Local scalar parameters. +INTEGER :: errorstatus + +CHARACTER(LEN=*), PARAMETER :: & + RoutineName = 'CHECK_JULES_INFERNO' ! Name of this procedure. + +! Set error status to show a fatal error for all checks. +errorstatus = 101 + +! Check options that depend on TRIFFID if it is not enabled +!if l_triffie + +IF ( .NOT. l_inferno .AND. .NOT. l_trif_fire ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "l_inferno needs to be specified if l_trif_fire is true.") +END IF + +IF ( ABS(flam_sm_low - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_low needs to be specified.") +ELSE IF ( flam_sm_low < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_low must be >= 0.0.") +END IF + +IF ( ABS(flam_sm_up - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_up needs to be specified.") +ELSE IF ( flam_sm_up < flam_sm_low ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_up must be >= flam_sm_low") +ELSE IF ( flam_sm_up > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_up must be <= 1.0.") +END IF + +IF ( ABS(flam_rhum_low - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_low needs to be specified.") +ELSE IF ( flam_rhum_low < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_low must be >= 0.0.") +END IF + +IF ( ABS(flam_rhum_up - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_up needs to be specified.") +ELSE IF ( flam_rhum_up < flam_rhum_low ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_up must be >= flam_rhum_low") +ELSE IF ( flam_rhum_up > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_up must be <= 1.0.") +END IF + +IF ( ABS(flam_fuel_low - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_low needs to be specified.") +ELSE IF ( flam_fuel_low < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_low must be >= 0.0.") +END IF + +IF ( ABS(flam_fuel_up - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_up needs to be specified.") +ELSE IF ( flam_fuel_up < flam_fuel_low ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_up must be >= flam_fuel_low") +ELSE IF ( flam_fuel_up > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_up must be <= 1.0.") +END IF + +IF ( ABS(triffire_ccdpm_min - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_min needs to be specified.") +ELSE IF ( triffire_ccdpm_min < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_min must be >= 0.0.") +END IF + +IF ( ABS(triffire_ccdpm_max - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_max needs to be specified.") +ELSE IF ( triffire_ccdpm_max < triffire_ccdpm_min ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_max must be >= triffire_ccdpm_min") +ELSE IF ( triffire_ccdpm_max > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_max must be < 1.0.") +END IF + +IF ( ABS(triffire_ccrpm_min - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_min needs to be specified.") +ELSE IF ( triffire_ccrpm_min < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_min must be >= 0.0.") +END IF + +IF ( ABS(triffire_ccrpm_max - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_max needs to be specified.") +ELSE IF ( triffire_ccrpm_max < triffire_ccrpm_min ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_max must be >= triffire_ccrpm_min") +ELSE IF ( triffire_ccrpm_max > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_max must be < 1.0.") +END IF + +IF ( ABS(flam_rain_const - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rain_const needs to be specified.") +ELSE IF ( flam_rain_const < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rain_const must be >= 0.0.") +END IF + +! Check a suitable ignition_method was given +IF ( ignition_method /= ignition_constant .AND. & + ignition_method /= ignition_vary_natural .AND. & + ignition_method /= ignition_vary_natural_human ) THEN + errcode = 101 + CALL ereport("check_jules_vegetation", errcode, & + 'ignition_method must be 1, 2 or 3') +END IF + +! check value of z_burn_max with l_layeredc +!IF ( l_layeredc ) THEN +!! IF ( ABS( z_burn_max - rmdi ) > EPSILON(1.0) ) THEN + ! IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN + ! CALL ereport(RoutineName, errorstatus, & + ! "z_burn_max must be positive & less than 10 meters") + ! END IF + ! END IF +!END IF + + +END SUBROUTINE check_jules_inferno + +SUBROUTINE print_nlist_jules_inferno() + +USE jules_print_mgr, ONLY: jules_print +USE jules_surface_types_mod, ONLY: npft +! USE jules_soil_biogeochem_mod, ONLY: l_layeredc !ejb check that it is set or move this trap + +IMPLICIT NONE + +CHARACTER(LEN=50000) :: lineBuffer + +CALL jules_print('jules_inferno_mod', & + 'Contents of namelist jules_inferno') + +WRITE(lineBuffer,*)' l_trif_fire = ',l_trif_fire +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' l_inferno = ',l_inferno +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' flam_sm_low = ',flam_sm_low +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' flam_sm_up = ',flam_sm_up +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' flam_rhum_low = ',flam_rhum_low +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' flam_rhum_up = ',flam_rhum_up +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' flam_rain_const = ',flam_rain_const +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' flam_fuel_low = ',flam_fuel_low +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' flam_fuel_up = ',flam_fuel_up +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' triffire_ccdpm_min = ',triffire_ccdpm_min +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' triffire_ccdpm_max = ',triffire_ccdpm_max +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' triffire_ccrpm_min = ',triffire_ccrpm_min +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer,*)' triffire_ccrpm_max = ',triffire_ccrpm_max +CALL jules_print('jules_inferno_mod',lineBuffer) + +WRITE(lineBuffer, *) ' z_burn_max = ', z_burn_max +CALL jules_print('jules_soil_biogeochem_mod', lineBuffer) + +END SUBROUTINE print_nlist_jules_inferno + +#if defined(UM_JULES) && !defined(LFRIC) +SUBROUTINE read_nml_jules_inferno (unitnumber) + +! Description: +! Read the JULES_INFERNO namelist + +USE setup_namelist, ONLY: setup_nml_type +USE check_iostat_mod, ONLY: check_iostat +USE UM_parcore, ONLY: mype + +USE parkind1, ONLY: jprb, jpim +USE yomhook, ONLY: lhook, dr_hook + +USE errormessagelength_mod, ONLY: errormessagelength + +IMPLICIT NONE + +! Subroutine arguments +INTEGER, INTENT(IN) :: unitnumber +INTEGER :: my_comm +INTEGER :: mpl_nml_type +INTEGER :: ErrorStatus +INTEGER :: icode +REAL(KIND=jprb) :: zhook_handle + +CHARACTER(LEN=*), PARAMETER :: RoutineName='READ_NML_JULES_INFERNO' +INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 +INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 + +CHARACTER(LEN=errormessagelength) :: iomessage + +! set number of each type of variable in my_namelist type +INTEGER, PARAMETER :: no_of_types = 3 +INTEGER, PARAMETER :: n_int = 2 +INTEGER, PARAMETER :: n_real = 11 +INTEGER, PARAMETER :: n_log = 2 + +TYPE :: my_namelist + SEQUENCE + INTEGER :: ignition_method + INTEGER :: flam_sm_func + REAL(KIND=real_jlslsm) :: flam_sm_low + REAL(KIND=real_jlslsm) :: flam_sm_up + REAL(KIND=real_jlslsm) :: flam_rhum_low + REAL(KIND=real_jlslsm) :: flam_rhum_up + REAL(KIND=real_jlslsm) :: flam_rain_const + REAL(KIND=real_jlslsm) :: flam_fuel_low + REAL(KIND=real_jlslsm) :: flam_fuel_up + REAL(KIND=real_jlslsm) :: triffire_ccdpm_min + REAL(KIND=real_jlslsm) :: triffire_ccdpm_max + REAL(KIND=real_jlslsm) :: triffire_ccrpm_min + REAL(KIND=real_jlslsm) :: triffire_ccrpm_max + REAL(KIND=real_jlslsm) :: z_burn_max + LOGICAL :: l_trif_fire + LOGICAL :: l_inferno +END TYPE my_namelist + +TYPE (my_namelist) :: my_nml + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) + +CALL gc_get_communicator(my_comm, icode) + +CALL setup_nml_type(no_of_types, mpl_nml_type, n_int_in = n_int, & + n_real_in = n_real, n_log_in = n_log) + +IF (mype == 0) THEN + + READ (UNIT = unitnumber, NML = jules_inferno, IOSTAT = errorstatus, & + IOMSG = iomessage) + CALL check_iostat(errorstatus, "namelist jules_inferno", iomessage) + + my_nml % ignition_method = ignition_method + my_nml % flam_sm_func = flam_sm_func + my_nml % l_trif_fire = l_trif_fire + my_nml % l_inferno = l_inferno + my_nml % flam_sm_low = flam_sm_low + my_nml % flam_sm_up = flam_sm_up + my_nml % flam_rhum_low = flam_rhum_low + my_nml % flam_rhum_up = flam_rhum_up + my_nml % flam_rain_const = flam_rain_const + my_nml % flam_fuel_low = flam_fuel_low + my_nml % flam_fuel_up = flam_fuel_up + my_nml % triffire_ccdpm_min = triffire_ccdpm_min + my_nml % triffire_ccdpm_max = triffire_ccdpm_max + my_nml % triffire_ccrpm_min = triffire_ccrpm_min + my_nml % triffire_ccrpm_max = triffire_ccrpm_max + my_nml % z_burn_max = z_burn_max +END IF + +CALL mpl_bcast(my_nml,1,mpl_nml_type,0,my_comm,icode) + +IF (mype /= 0) THEN + + ignition_method = my_nml % ignition_method + flam_sm_func = my_nml % flam_sm_func + l_trif_fire = my_nml % l_trif_fire + l_inferno = my_nml % l_inferno + flam_sm_low = my_nml % flam_sm_low + flam_sm_up = my_nml % flam_sm_up + flam_rhum_low = my_nml % flam_rhum_low + flam_rhum_up = my_nml % flam_rhum_up + flam_rain_const = my_nml % flam_rain_const + flam_fuel_low = my_nml % flam_fuel_low + flam_fuel_up = my_nml % flam_fuel_up + triffire_ccdpm_min = my_nml % triffire_ccdpm_min + triffire_ccdpm_max = my_nml % triffire_ccdpm_max + triffire_ccrpm_min = my_nml % triffire_ccrpm_min + triffire_ccrpm_max = my_nml % triffire_ccrpm_max + z_burn_max = my_nml % z_burn_max +END IF + +CALL mpl_type_free(mpl_nml_type,icode) + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) +RETURN +END SUBROUTINE read_nml_jules_inferno +#endif + +END MODULE jules_inferno_mod diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index 4b6588f6..0c964877 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -180,10 +180,6 @@ MODULE jules_soil_biogeochem_mod tau_lit = rmdi ! Parameter controlling the decay of litter inputs with depth (m-1). -REAL(KIND=real_jlslsm) :: & - z_burn_max = rmdi - ! Parameter setting maximum depth of burn - !----------------------------------------------------------------------------- ! Namelist variables used in the CH4 Emission Scheme !----------------------------------------------------------------------------- @@ -256,7 +252,7 @@ MODULE jules_soil_biogeochem_mod t0_ch4, const_ch4_cs, const_ch4_npp, const_ch4_resps, q10_ch4_cs, & q10_ch4_npp, q10_ch4_resps, tau_ch4, ch4_cpow, k2_ch4, kd_ch4, rho_ch4, & q10_mic_ch4, cue_ch4, mu_ch4, alpha_ch4, frz_ch4, ev_ch4, q10_ev_ch4, & - l_label_frac_cs, z_burn_max, l_bgc_heat, heat_of_respiration, & + l_label_frac_cs, l_bgc_heat, heat_of_respiration, & fsthsat_cs_decomp_opt1 CHARACTER(LEN=*), PARAMETER, PRIVATE :: & @@ -278,7 +274,9 @@ SUBROUTINE check_jules_soil_biogeochem() USE jules_vegetation_mod, ONLY: & ! imported scalars - l_triffid, l_trif_fire, l_nitrogen, l_inferno + l_triffid, l_nitrogen + +USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire USE ereport_mod, ONLY: ereport @@ -522,15 +520,6 @@ SUBROUTINE check_jules_soil_biogeochem() END IF END IF -! check value of z_burn_max with l_layeredc -IF ( l_layeredc ) THEN - IF ( ABS( z_burn_max - rmdi ) > EPSILON(1.0) ) THEN - IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN - CALL ereport(RoutineName, errorstatus, & - "z_burn_max must be positive & less than 10 meters") - END IF - END IF -END IF ! methane q10's - these are always set IF ( ABS( q10_ch4_cs - rmdi ) < EPSILON(1.0) ) THEN @@ -748,9 +737,6 @@ SUBROUTINE print_nlist_jules_soil_biogeochem() WRITE(lineBuffer, *) ' tau_lit = ', tau_lit CALL jules_print('jules_soil_biogeochem_mod', lineBuffer) -WRITE(lineBuffer, *) ' z_burn_max = ', z_burn_max -CALL jules_print('jules_soil_biogeochem_mod', lineBuffer) - WRITE(lineBuffer, *) ' diff_n_pft = ', diff_n_pft CALL jules_print('jules_soil_biogeochem_mod', lineBuffer) @@ -911,7 +897,6 @@ SUBROUTINE read_nml_jules_soil_biogeochem (unitnumber) REAL(KIND=real_jlslsm) :: ev_ch4 REAL(KIND=real_jlslsm) :: q10_ev_ch4 REAL(KIND=real_jlslsm) :: heat_of_respiration - REAL(KIND=real_jlslsm) :: z_burn_max LOGICAL :: l_layeredC LOGICAL :: l_label_frac_cs LOGICAL :: l_q10 @@ -979,7 +964,6 @@ SUBROUTINE read_nml_jules_soil_biogeochem (unitnumber) my_nml % alpha_ch4 = alpha_ch4 my_nml % ev_ch4 = ev_ch4 my_nml % q10_ev_ch4 = q10_ev_ch4 - my_nml % z_burn_max = z_burn_max my_nml % heat_of_respiration = heat_of_respiration END IF @@ -1027,7 +1011,6 @@ SUBROUTINE read_nml_jules_soil_biogeochem (unitnumber) alpha_ch4 = my_nml % alpha_ch4 ev_ch4 = my_nml % ev_ch4 q10_ev_ch4 = my_nml % q10_ev_ch4 - z_burn_max = my_nml % z_burn_max heat_of_respiration = my_nml % heat_of_respiration END IF diff --git a/src/control/shared/jules_vegetation_mod.F90 b/src/control/shared/jules_vegetation_mod.F90 index bf222c07..ace45d15 100644 --- a/src/control/shared/jules_vegetation_mod.F90 +++ b/src/control/shared/jules_vegetation_mod.F90 @@ -152,17 +152,6 @@ MODULE jules_vegetation_mod ! switch to prevent crop and natural PFTs competing l_trif_biocrop = .FALSE., & ! Switch to enable periodic harvesting of bioenergy crop PFTs - l_inferno = .FALSE., & - ! Switch used to control whether the Interactive fire scheme is used - l_trif_fire = .FALSE., & - ! Switch used to control whether interactive fire is used - ! T => if l_inferno is also true, g_burn is calculated in INFERNO -! and passed to TRIFFID to calculate emissions and vegetation - ! dynamics - ! T => if l_inferno is false, interactive fire is calculated via -! ancillary if provided, and is 0 if not provided - ! F => g_burn is calculated via ancillary if provided, and is 0 if -! not provided l_use_pft_psi = .FALSE., & ! Switch used to control what parameters are used in the calculation ! of the soil moisture stress factor @@ -233,12 +222,6 @@ MODULE jules_vegetation_mod ! Number of layers for canopy radiation model INTEGER :: & - ignition_method = 1, & - ! Switch for the calculation method of INFERNO fire ignitions - ! IGNITION_METHOD=1:Constant (1.67 per km2 per s) - ! IGNITION_METHOD=2:Constant (Human - 1.5 per km2 per s) - ! Varying (Lightning - see Pechony and Shindell,2009) - ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony and Shindell,2009) fsmc_shape = 0, & ! shape of the soil moisture stress function fsmc ! 0: piece-wise linear in vol. soil moisture. @@ -256,10 +239,6 @@ MODULE jules_vegetation_mod stomata_model = imdi ! Chosen model of stomatal conductance. -INTEGER, PARAMETER :: ignition_constant = 1 -INTEGER, PARAMETER :: ignition_vary_natural = 2 -INTEGER, PARAMETER :: ignition_vary_natural_human = 3 - INTEGER :: & phenol_period = imdi, & ! Update frequency for leaf phenology (days) @@ -343,8 +322,8 @@ MODULE jules_vegetation_mod phenol_period, triffid_period, l_trait_phys, l_ht_compete, & l_bvoc_emis, l_o3_damage, can_model, can_rad_mod, ilayers, & frac_min, frac_seed, pow, l_landuse, l_leaf_n_resp_fix, l_stem_resp_fix, & - l_nitrogen, l_vegcan_soilfx, l_trif_crop, l_trif_fire, & - l_inferno, ignition_method, l_vegdrag_pft, l_rsl_scalar, & + l_nitrogen, l_vegcan_soilfx, l_trif_crop, & + l_vegdrag_pft, l_rsl_scalar, & cd_leaf, c1_usuh, c2_usuh, c3_usuh, dsj_coef, dsv_coef, jv25_coef, & act_j_coef, act_v_coef, & n_alloc_jmax, n_alloc_vcmax, n_day_photo_acclim, & @@ -433,15 +412,14 @@ SUBROUTINE check_jules_vegetation() ! Check options that depend on TRIFFID if it is not enabled IF ( .NOT. l_triffid .AND. ANY( [ l_veg_compete, l_trif_eq, l_landuse, & - l_ht_compete, l_nitrogen, l_trif_crop, l_trif_fire, l_trif_biocrop, & + l_ht_compete, l_nitrogen, l_trif_crop, l_trif_biocrop, & l_ag_expand ] ) ) THEN errcode = 101 WRITE(jules_message,'(A,8(1x,L1))') & 'These should be false when l_triffid = F: l_veg_compete, ' // & 'l_trif_eq, l_landuse, l_ht_compete, l_nitrogen, l_trif_crop, ' // & - 'l_trif_fire, l_trif_biocrop, l_ag_expand = ', l_veg_compete, l_trif_eq, & - l_landuse, l_ht_compete, l_nitrogen, l_trif_crop, l_trif_fire, & - l_trif_biocrop, l_ag_expand + 'l_trif_biocrop, l_ag_expand = ', l_veg_compete, l_trif_eq, & + l_landuse, l_ht_compete, l_nitrogen, l_trif_crop, l_trif_biocrop, l_ag_expand CALL ereport( "check_jules_vegetation", errcode, jules_message ) END IF @@ -775,14 +753,6 @@ SUBROUTINE check_jules_vegetation() 'prescribed fractions and crop model to be active') END IF -! Check a suitable ignition_method was given -IF ( ignition_method /= ignition_constant .AND. & - ignition_method /= ignition_vary_natural .AND. & - ignition_method /= ignition_vary_natural_human ) THEN - errcode = 101 - CALL ereport("check_jules_vegetation", errcode, & - 'ignition_method must be 1, 2 or 3') -END IF IF ( fsmc_shape == 1 .AND. .NOT. l_use_pft_psi ) THEN errcode = 101 @@ -855,9 +825,6 @@ SUBROUTINE print_nlist_jules_vegetation() WRITE(lineBuffer,*)' l_trif_biocrop = ',l_trif_biocrop CALL jules_print('jules_vegetation_mod',lineBuffer) -WRITE(lineBuffer,*)' l_trif_fire = ',l_trif_fire -CALL jules_print('jules_vegetation_mod',lineBuffer) - WRITE(lineBuffer,*)' l_trait_phys = ',l_trait_phys CALL jules_print('jules_vegetation_mod',lineBuffer) @@ -1020,7 +987,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) INTEGER, PARAMETER :: no_of_types = 3 INTEGER, PARAMETER :: n_int = 11 INTEGER, PARAMETER :: n_real = 11 + (n_photo_coef * 5) -INTEGER, PARAMETER :: n_log = 29 + npft_max +INTEGER, PARAMETER :: n_log = 27 + npft_max TYPE :: my_namelist SEQUENCE @@ -1029,7 +996,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) INTEGER :: can_model INTEGER :: can_rad_mod INTEGER :: ilayers - INTEGER :: ignition_method INTEGER :: photo_acclim_model INTEGER :: photo_act_model INTEGER :: photo_jv_model @@ -1066,7 +1032,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) LOGICAL :: l_trif_crop LOGICAL :: l_trif_biocrop LOGICAL :: l_ag_expand - LOGICAL :: l_trif_fire LOGICAL :: l_landuse LOGICAL :: l_nitrogen LOGICAL :: l_recon @@ -1074,7 +1039,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) LOGICAL :: l_stem_resp_fix LOGICAL :: l_scale_resp_pm LOGICAL :: l_vegcan_soilfx - LOGICAL :: l_inferno LOGICAL :: l_vegdrag_pft(npft_max) LOGICAL :: l_rsl_scalar LOGICAL :: l_spec_veg_z0 @@ -1103,7 +1067,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) my_nml % can_model = can_model my_nml % can_rad_mod = can_rad_mod my_nml % ilayers = ilayers - my_nml % ignition_method = ignition_method my_nml % photo_acclim_model = photo_acclim_model my_nml % photo_act_model = photo_act_model my_nml % photo_jv_model = photo_jv_model @@ -1140,7 +1103,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) my_nml % l_trif_crop = l_trif_crop my_nml % l_trif_biocrop = l_trif_biocrop my_nml % l_ag_expand = l_ag_expand - my_nml % l_trif_fire = l_trif_fire my_nml % l_landuse = l_landuse my_nml % l_nitrogen = l_nitrogen my_nml % l_recon = l_recon @@ -1148,7 +1110,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) my_nml % l_stem_resp_fix = l_stem_resp_fix my_nml % l_scale_resp_pm = l_scale_resp_pm my_nml % l_vegcan_soilfx = l_vegcan_soilfx - my_nml % l_inferno = l_inferno my_nml % l_vegdrag_pft = l_vegdrag_pft my_nml % l_rsl_scalar = l_rsl_scalar my_nml % l_spec_veg_z0 = l_spec_veg_z0 @@ -1166,7 +1127,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) can_model = my_nml % can_model can_rad_mod = my_nml % can_rad_mod ilayers = my_nml % ilayers - ignition_method = my_nml % ignition_method photo_acclim_model = my_nml % photo_acclim_model photo_act_model = my_nml % photo_act_model photo_jv_model = my_nml % photo_jv_model @@ -1203,7 +1163,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) l_trif_crop = my_nml % l_trif_crop l_trif_biocrop = my_nml % l_trif_biocrop l_ag_expand = my_nml % l_ag_expand - l_trif_fire = my_nml % l_trif_fire l_landuse = my_nml % l_landuse l_nitrogen = my_nml % l_nitrogen l_recon = my_nml % l_recon @@ -1211,7 +1170,6 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) l_stem_resp_fix = my_nml % l_stem_resp_fix l_scale_resp_pm = my_nml % l_scale_resp_pm l_vegcan_soilfx = my_nml % l_vegcan_soilfx - l_inferno = my_nml % l_inferno l_vegdrag_pft = my_nml % l_vegdrag_pft l_rsl_scalar = my_nml % l_rsl_scalar l_spec_veg_z0 = my_nml % l_spec_veg_z0 diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index 4b52d3c1..84edeb97 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -213,10 +213,11 @@ SUBROUTINE surf_couple_extra( & l_crop, l_fao_ref_evapotranspiration, & #endif l_triffid, l_trif_eq, l_phenol, phenol_period, triffid_period, & - l_inferno, ignition_method, & - ignition_vary_natural, ignition_vary_natural_human, & l_acclim, n_day_photo_acclim, l_red +USE jules_inferno_mod, ONLY: l_inferno, ignition_method, & + ignition_vary_natural, ignition_vary_natural_human + USE jules_irrig_mod, ONLY: l_irrig_dmd USE jules_water_tracers_mod, ONLY: n_wtrac_jls diff --git a/src/control/um/diagnostics_hyd.F90 b/src/control/um/diagnostics_hyd.F90 index a3086b03..f756cfb2 100644 --- a/src/control/um/diagnostics_hyd.F90 +++ b/src/control/um/diagnostics_hyd.F90 @@ -129,7 +129,7 @@ SUBROUTINE diagnostics_hyd( & ! INFERNO diagnostics USE jules_surface_types_mod, ONLY: npft -USE jules_vegetation_mod, ONLY: l_inferno +USE jules_inferno_mod, ONLY: l_inferno USE set_levels_list_mod, ONLY: set_levels_list USE set_pseudo_list_mod, ONLY: set_pseudo_list diff --git a/src/initialisation/shared/check_compatible_options_mod.F90 b/src/initialisation/shared/check_compatible_options_mod.F90 index ff64bbec..6db64700 100644 --- a/src/initialisation/shared/check_compatible_options_mod.F90 +++ b/src/initialisation/shared/check_compatible_options_mod.F90 @@ -33,12 +33,14 @@ SUBROUTINE check_compatible_options(call_type) l_albedo_obs USE jules_rivers_mod, ONLY: i_river_vn, l_rivers, rivers_um_trip, & l_inland_outflow -USE jules_soil_biogeochem_mod, ONLY: l_layeredc, z_burn_max +USE jules_soil_biogeochem_mod, ONLY: l_layeredc +USE jules_inferno_mod, ONLY: z_burn_max USE jules_soil_mod, ONLY: l_tile_soil, l_holdwater USE jules_surface_mod, ONLY: l_flake_model, l_aggregate USE jules_surface_types_mod, ONLY: urban_roof, npft, nnvg, ntype USE jules_urban_mod, ONLY: l_moruses_storage -USE jules_vegetation_mod, ONLY: l_triffid, l_inferno, l_trif_fire +USE jules_vegetation_mod, ONLY: l_triffid +USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire USE jules_water_resources_mod, ONLY: l_water_environment, & l_water_irrigation, l_water_resources,& l_water_transfers diff --git a/src/initialisation/standalone/init.F90 b/src/initialisation/standalone/init.F90 index f96a37ed..7dbae519 100644 --- a/src/initialisation/standalone/init.F90 +++ b/src/initialisation/standalone/init.F90 @@ -52,6 +52,7 @@ SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & USE init_output_mod, ONLY: init_output USE init_plant_n_uptake_mod, ONLY: init_plant_n_uptake USE init_vegetation_mod, ONLY: init_vegetation +USE init_inferno_mod, ONLY: init_inferno USE init_hydrology_mod, ONLY: init_hydrology USE init_model_environment_mod, ONLY: init_model_environment USE init_radiation_mod, ONLY: init_radiation @@ -273,6 +274,8 @@ SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & ! Must be called after init_soil to check soil tiling flags CALL init_vegetation(nml_dir) +CALL init_inferno(nml_dir) + ! Initialise irrigation options CALL init_irrigation(nml_dir) diff --git a/src/initialisation/standalone/init_inferno_mod.F90 b/src/initialisation/standalone/init_inferno_mod.F90 new file mode 100644 index 00000000..ebf1847c --- /dev/null +++ b/src/initialisation/standalone/init_inferno_mod.F90 @@ -0,0 +1,138 @@ +#if !defined(UM_JULES) +! *****************************COPYRIGHT************************************** +! (C) Crown copyright Met Office. All rights reserved. +! For further details please refer to the file COPYRIGHT.txt +! which you should have received as part of this distribution. +! *****************************COPYRIGHT************************************** +MODULE init_inferno_mod + +IMPLICIT NONE + +CONTAINS + +!----------------------------------------------------------------------------- +! Description: +! Reads in the inferno fire namelist items and checks them for consistency +! +! Code Owner: Please refer to ModuleLeaders.txt +! This file belongs in TECHNICAL +! +! Code Description: +! Language: Fortran 90. +! This code is written to JULES coding standards v1. +!----------------------------------------------------------------------------- +SUBROUTINE init_inferno(nml_dir) + +USE jules_inferno_mod, ONLY: print_nlist_jules_inferno, check_jules_inferno, & + l_inferno, l_trif_fire, flam_sm_up, flam_sm_low, flam_rhum_up, & + flam_rhum_low, flam_fuel_up, flam_fuel_low, flam_rain_const, & + triffire_ccdpm_max, triffire_ccdpm_min, triffire_ccrpm_max, & + triffire_ccrpm_min, ignition_method, ignition_constant, & + ignition_vary_natural, ignition_vary_natural_human + +USE io_constants, ONLY: namelist_unit + +USE string_utils_mod, ONLY: to_string + +USE logging_mod, ONLY: log_info,log_fatal + +USE fire_mod, ONLY: fire_cntl, l_fire_weather_index + +USE fire_allocate_mod,ONLY: fire_allocate + +USE fire_init_mod, ONLY: fire_init + +USE metstats_mod, ONLY: l_metstats + + +IMPLICIT NONE + +! Arguments +CHARACTER(LEN=*), INTENT(IN) :: nml_dir ! The directory containing the + ! namelists + +INTEGER :: ERROR ! Error indicators + +CHARACTER(LEN=*), PARAMETER :: RoutineName='INIT_INFERNO' + +!----------------------------------------------------------------------------- +! Definition of the jules_inferno namelist +!----------------------------------------------------------------------------- +NAMELIST / jules_inferno/ & + l_trif_fire, & + l_inferno, & + ignition_method, & + flam_sm_low, & + flam_sm_up, & + flam_rhum_low, & + flam_rhum_up, & + flam_rain_const, & + flam_fuel_low, & + flam_fuel_up, & + triffire_ccdpm_min, & + triffire_ccdpm_max, & + triffire_ccrpm_min, & + triffire_ccrpm_max +!----------------------------------------------------------------------------- + +!----------------------------------------------------------------------------- +! Read the namelist +!----------------------------------------------------------------------------- + +! Open the fire namelist file +OPEN(namelist_unit, FILE=(TRIM(nml_dir) // '/' // 'fire.nml'), & + STATUS='old', POSITION='rewind', ACTION='read', IOSTAT = ERROR) +IF ( ERROR /= 0 ) & + CALL log_fatal(RoutineName, "Error opening namelist file fire.nml " // & + "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") + + +! There is one namelist to read from this file for jules inferno +CALL log_info(RoutineName, "Reading JULES_INFERNO namelist...") +READ(namelist_unit, NML = jules_inferno, IOSTAT = ERROR) +IF ( ERROR /= 0 ) & + CALL log_fatal(RoutineName, & + "Error reading namelist jules_inferno " // & + "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") + +! Close the namelist file +CLOSE(namelist_unit, IOSTAT = ERROR) +IF ( ERROR /= 0 ) & + CALL log_fatal(RoutineName, & + "Error closing namelist file fire.nml " // & + "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") + +! CALL check_jules_inferno() + +CALL print_nlist_jules_inferno() + +! If not running inferno, we can bail after namelist has been read. +IF ( .NOT. l_inferno ) RETURN + + +!----------------------------------------------------------------------------- +! Print some human friendly summary information about the selected options +! does this ahve to be ehrer? +!----------------------------------------------------------------------------- + +IF ( l_inferno ) THEN + CALL log_info(RoutineName, & + "Interactive fires and emissions (INFERNO) will be diagnosed") + IF (ignition_method == ignition_constant ) THEN + CALL log_info(RoutineName, & + "Constant or ubiquitous ignitions (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural ) THEN + CALL log_info(RoutineName, & + "Constant human ignitions, varying lightning (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural_human ) THEN + CALL log_info(RoutineName, & + "Fully prescribed ignitions (INFERNO)") + END IF +END IF + + +RETURN + +END SUBROUTINE init_inferno +END MODULE init_inferno_mod +#endif diff --git a/src/initialisation/standalone/init_jules_sf_diags_mod.F90 b/src/initialisation/standalone/init_jules_sf_diags_mod.F90 index fcf8b5bf..713662f9 100644 --- a/src/initialisation/standalone/init_jules_sf_diags_mod.F90 +++ b/src/initialisation/standalone/init_jules_sf_diags_mod.F90 @@ -40,8 +40,9 @@ SUBROUTINE set_sf_diag_switches USE jules_radiation_mod, ONLY: i_sea_alb_method -USE jules_vegetation_mod, ONLY: l_crop, l_fao_ref_evapotranspiration, & - l_inferno +USE jules_vegetation_mod, ONLY: l_crop, l_fao_ref_evapotranspiration + +USE jules_inferno_mod, ONLY: l_inferno USE sf_diags_mod, ONLY: sf_diag diff --git a/src/initialisation/standalone/init_vegetation.F90 b/src/initialisation/standalone/init_vegetation.F90 index a37df63b..1b6a1b6e 100644 --- a/src/initialisation/standalone/init_vegetation.F90 +++ b/src/initialisation/standalone/init_vegetation.F90 @@ -36,10 +36,8 @@ SUBROUTINE init_vegetation(nml_dir) photo_act_pft, photo_act_gb, photo_jv_model, & jv_scale, jv_ntotal, stomata_model, & stomata_jacobs, stomata_medlyn, stomata_sox, & - l_inferno, l_trif_eq, triffid_period, & - ignition_method, check_jules_vegetation, & - ignition_constant, ignition_vary_natural, & - ignition_vary_natural_human + l_trif_eq, triffid_period, & + check_jules_vegetation USE logging_mod, ONLY: log_info, log_error, log_fatal @@ -176,22 +174,6 @@ SUBROUTINE init_vegetation(nml_dir) "Using the SOX model of stomatal conductance.") END SELECT -IF ( l_inferno ) THEN - CALL log_info("init_vegetation", & - "Interactive fires and emissions (INFERNO) will be diagnosed") - IF (ignition_method == ignition_constant ) THEN - CALL log_info("init_vegetation", & - "Constant or ubiquitous ignitions (INFERNO)") - ELSE IF (ignition_method == ignition_vary_natural ) THEN - CALL log_info("init_vegetation", & - "Constant human ignitions, varying lightning (INFERNO)") - ELSE IF (ignition_method == ignition_vary_natural_human ) THEN - CALL log_info("init_vegetation", & - "Fully prescribed ignitions (INFERNO)") - END IF -END IF - - ! Check that TRIFFID timestep (the coupling period) seems sensible ! In equilibrium mode, the coupling period should be sufficient to average ! out seasonal (and ideally interannual) variability, so a period >= 1yr diff --git a/src/initialisation/um/read_jules_namelists_mod.F90 b/src/initialisation/um/read_jules_namelists_mod.F90 index 5b0f9cc3..0c51cd6a 100644 --- a/src/initialisation/um/read_jules_namelists_mod.F90 +++ b/src/initialisation/um/read_jules_namelists_mod.F90 @@ -194,6 +194,37 @@ END SUBROUTINE read_jules_deposition_species ! ********************************************************************* +SUBROUTINE read_jules_inferno (unitnumber) + +! Description: +! Read the JULES_INFERNO namelist + +USE jules_inferno_mod, ONLY: & + print_nlist_jules_inferno, & + check_jules_inferno, read_nml_jules_inferno + +IMPLICIT NONE + +! Subroutine arguments +INTEGER, INTENT(IN) :: unitnumber + +REAL(KIND=jprb) :: zhook_handle +CHARACTER(LEN=*), PARAMETER :: RoutineName='READ_JULES_INFERNO' + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) + +CALL read_nml_jules_inferno(unitnumber) +IF (PrintStatus >= PrStatus_Oper .AND. mype == 0) THEN + CALL print_nlist_jules_inferno() +END IF +CALL check_jules_inferno() + +IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) +RETURN +END SUBROUTINE read_jules_inferno + +! ********************************************************************* + SUBROUTINE read_jules_nvegparm (unitnumber) ! Description: diff --git a/src/science/fire/inferno_io_mod.F90 b/src/science/fire/inferno_io_mod.F90 index 1fb36dda..e6ceea03 100644 --- a/src/science/fire/inferno_io_mod.F90 +++ b/src/science/fire/inferno_io_mod.F90 @@ -53,12 +53,16 @@ SUBROUTINE inferno_io( & avg_ba, fire_mort ! Average Burned Area per PFT, and fire mortality rate +USE jules_inferno_mod, ONLY: & +flam_rhum_low, flam_rhum_up, & +flam_sm_low, flam_sm_up, flam_fuel_low, & + flam_fuel_up, flam_rain_const, flam_sm_func USE qsat_mod, ONLY: qsat_wat USE jules_surface_types_mod, ONLY: npft USE parkind1, ONLY: jprb -USE jules_vegetation_mod, ONLY: l_trif_fire +USE jules_inferno_mod, ONLY: l_trif_fire USE timestep_mod, ONLY: timestep USE calc_c_comps_triffid_mod, ONLY: calc_c_comps_triffid @@ -161,11 +165,9 @@ SUBROUTINE inferno_io( & fef_c3h8_rpm = 0.0 , fef_hcho_rpm = 0.0, & fef_mecho_rpm = 0.0, & fef_nh3_rpm = 0.0 , fef_dms_rpm = 0.0, & - ! HARDCODED Emission factors for RPM in g kg-1 - pmtofuel = 0.7, & + ! HARDCODED Emission factors for DPM in g kg-1 + pmtofuel = 0.7 ! Plant Material that is available as fuel (on the surface) - fuel_low = 0.02, fuel_high = 0.2 - ! Fuel availability high/low threshold REAL(KIND=real_jlslsm) , PARAMETER :: & rain_tolerance = 1.0e-18 ! kg/m2/s @@ -313,8 +315,8 @@ SUBROUTINE inferno_io( & DO i = 1, npft ! Calculate the fuel density ! We use normalised Leaf Carbon + the available DPM - inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - fuel_low) & - /(fuel_high - fuel_low) + inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & + /(flam_fuel_up - flam_fuel_low) WHERE (inferno_fuel < 0.0) inferno_fuel = 0.0 @@ -363,6 +365,8 @@ SUBROUTINE inferno_io( & !Point Intent(IN) inferno_temp(l), inferno_rhum(l), inferno_fuel(l), & inferno_sm(l), inferno_rain(l), & + flam_rhum_low, flam_rhum_up, flam_sm_low, flam_sm_up, & + flam_rain_const, flam_sm_func, & !Point Intent(INOUT) fire_vars%flammability_ft(l,i)) diff --git a/src/science/fire/inferno_mod.F90 b/src/science/fire/inferno_mod.F90 index 3a7d18ff..3e0ecedc 100644 --- a/src/science/fire/inferno_mod.F90 +++ b/src/science/fire/inferno_mod.F90 @@ -81,7 +81,7 @@ SUBROUTINE calc_ignitions( & USE yomhook, ONLY: lhook, dr_hook USE parkind1, ONLY: jprb -USE jules_vegetation_mod, ONLY: ignition_constant, ignition_vary_natural, & +USE jules_inferno_mod, ONLY: ignition_constant, ignition_vary_natural, & ignition_vary_natural_human IMPLICIT NONE @@ -165,6 +165,8 @@ END SUBROUTINE calc_ignitions SUBROUTINE calc_flam( & !Point Intent(IN) temp_l, rhum_l, fuel_l, sm_l, rain_l, & + flam_rhum_low, flam_rhum_up, flam_sm_low, flam_sm_up, & + flam_rain_const, flam_sm_func, & !Point Intent(INOUT) flam_l) @@ -196,8 +198,21 @@ SUBROUTINE calc_flam( & ! The INFERNO soil moisture fraction (sthu's 1st level) rain_l, & ! The precipitation rate (kg.m-2.s-1) - fuel_l + fuel_l, & ! The Fuel Density (0-1) + flam_rhum_up, & + ! Upper boundary to the relative humidity + flam_rhum_low, & + ! Lower boundary to the relative humidity + flam_sm_low, & + ! Lower boundary to the soil moisture + flam_sm_up, & + ! Upper boundary to the soil moisture + flam_rain_const + ! + +INTEGER, INTENT(IN) :: & + flam_sm_func REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & flam_l @@ -212,14 +227,8 @@ SUBROUTINE calc_flam( & b = 5.02808, & f = 8.1328e-03, & h=-3.49149, & - Ts = 373.16, & + Ts = 373.16 ! Water saturation temperature - cr=-2.0 * s_in_day, & - ! Precipitation factor (-2(day/mm)*(kg/m2/s)) - rhum_up = 90.0, & - ! Upper boundary to the relative humidity - rhum_low = 10.0 - ! Lower boundary to the relative humidity REAL(KIND=real_jlslsm) :: & Z_l, & @@ -228,9 +237,8 @@ SUBROUTINE calc_flam( & ! Reciprocal of the temperature times ts f_rhum_l, & ! The factor dependence on relative humidity - f_sm_l, & + f_sm_l ! The factor dependence on soil moisture - rain_rate REAL(KIND=jprb) :: zhook_handle CHARACTER(LEN=*), PARAMETER :: RoutineName = "CALC_FLAM" @@ -243,23 +251,30 @@ SUBROUTINE calc_flam( & + c * (10.0**( d * (1.0 - TsbyT_l)) - 1.0) & + f * (10.0**( h * (TsbyT_l-1.0)) - 1.0) -f_rhum_l = (rhum_up - rhum_l) / (rhum_up - rhum_low) +f_rhum_l = (flam_rhum_up - rhum_l/100.0) / (flam_rhum_up - flam_rhum_low) ! Create boundary limits ! First for relative humidity -IF (rhum_l < rhum_low) f_rhum_l = 1.0 - ! Always fires for RH < 10% -IF (rhum_l > rhum_up) f_rhum_l = 0.0 - ! No fires for RH > 90% +IF (rhum_l < flam_rhum_low) f_rhum_l = 1.0 + ! Always fires for RH < flam_rhum_low +IF (rhum_l > flam_rhum_up) f_rhum_l = 0.0 + ! No fires for RH > flam_rhum_up -f_sm_l = (1 - sm_l) +IF (flam_sm_func == 1) THEN + f_sm_l = (1 - sm_l) ! The flammability goes down linearly with soil moisture - -rain_rate = rain_l * s_in_day - ! convert rain rate from kg/m2/s to mm/day +ELSE IF ( flam_sm_func == 2) THEN + f_sm_l = EXP(-flam_sm_up * (sm_l - flam_sm_low) ) + ! Flammability goes down exponentially with soil moisture +END IF +IF (f_sm_l < 0.0) THEN + f_sm_l = 0.0 +ELSE IF (f_sm_l > 1.0) THEN + f_sm_l = 1.0 +END IF flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & - * EXP( cr * rain_rate) ,1.0) ,0.0) + * EXP( flam_rain_const * rain_l) ,1.0) ,0.0) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -395,6 +410,9 @@ SUBROUTINE calc_emitted_carbon_soil( & ! Language: Fortran 90 ! +USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & + triffire_ccrpm_min, triffire_ccrpm_max + USE yomhook, ONLY: lhook, dr_hook USE parkind1, ONLY: jprb @@ -418,16 +436,6 @@ SUBROUTINE calc_emitted_carbon_soil( & emitted_carbon_RPM(land_pts) ! The RPM emitted carbon (kg.m-2.s-1) -REAL(KIND=real_jlslsm) , PARAMETER :: & - ccdpm_min = 0.8, & - ccdpm_max = 1.0, & - ! Decomposable Plant Material burns between 80 to 100 % - ccrpm_min = 0.0, & - ccrpm_max = 0.2 - ! Resistant Plant Material burns between 0 to 20 % - ! These values are also set soilcarb and soilcarb_layers to calculate - ! burnt_carbon_RPM using the soil pools - INTEGER :: l ! landpoint loop counter REAL(KIND=jprb) :: zhook_handle @@ -436,10 +444,12 @@ SUBROUTINE calc_emitted_carbon_soil( & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) DO l = 1,land_pts - emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (ccdpm_min + & - (ccdpm_max - ccdpm_min) * (1.0 - sm(l)))) ,0.0) - emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (ccrpm_min + & - (ccrpm_max - ccrpm_min) * (1.0 - sm(l)))) ,0.0) + emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (triffire_ccdpm_min + & + (triffire_ccdpm_max - triffire_ccdpm_min) * & + (1.0 - sm(l)))) ,0.0) + emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (triffire_ccrpm_min + & + (triffire_ccrpm_max - triffire_ccrpm_min) * & + (1.0 - sm(l)))) ,0.0) END DO IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) @@ -597,7 +607,8 @@ SUBROUTINE calc_soil_carbon_pools(land_pts, soil_pts, soil_index, dim_cs1, & ! these are used as a proxy for litter USE jules_soil_biogeochem_mod, ONLY: soil_bgc_model, soil_model_4pool, & - soil_model_1pool, z_burn_max, l_layeredc + soil_model_1pool, l_layeredc +USE jules_inferno_mod, ONLY: z_burn_max USE jules_soil_mod, ONLY: dzsoil USE ancil_info, ONLY: nsoilt, dim_cslayer diff --git a/src/science/params/pftparm_mod.F90 b/src/science/params/pftparm_mod.F90 index 68978848..53abcf38 100644 --- a/src/science/params/pftparm_mod.F90 +++ b/src/science/params/pftparm_mod.F90 @@ -893,14 +893,16 @@ SUBROUTINE check_jules_pftparm(npft,nnpft) soil_model_4pool USE jules_vegetation_mod, ONLY: can_rad_mod, l_crop, l_trait_phys, & - l_use_pft_psi, l_bvoc_emis, l_inferno, & - l_o3_damage, l_trif_fire, photo_acclim_model, & + l_use_pft_psi, l_bvoc_emis, & + l_o3_damage, photo_acclim_model, & photo_act_model, photo_act_pft, & photo_farquhar, photo_model, & stomata_jacobs, stomata_medlyn, stomata_sox, & stomata_model, l_spec_veg_z0, l_sugar, & l_scale_resp_pm +USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire + USE jules_radiation_mod, ONLY: l_spec_albedo, l_albedo_obs, l_snow_albedo USE missing_data_mod, ONLY: rmdi diff --git a/src/science/vegetation/soilcarb_jls.F90 b/src/science/vegetation/soilcarb_jls.F90 index 7d72507a..5419f873 100644 --- a/src/science/vegetation/soilcarb_jls.F90 +++ b/src/science/vegetation/soilcarb_jls.F90 @@ -45,7 +45,8 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & USE jules_soil_mod, ONLY: cs_min, sm_levels USE ancil_info, ONLY: dim_cslayer, nsoilt, dim_cs1 -USE jules_vegetation_mod, ONLY: l_trif_fire !usage inside ifdef +USE jules_inferno_mod, ONLY: l_trif_fire, triffire_ccdpm_min, triffire_ccdpm_max, & + triffire_ccrpm_min, triffire_ccrpm_max USE dpm_rpm_mod, ONLY: dpm_rpm USE decay_mod, ONLY: decay @@ -137,15 +138,6 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & !----------------------------------------------------------------------------- REAL(KIND=real_jlslsm), PARAMETER :: lit_cn = 300.0 REAL(KIND=real_jlslsm), PARAMETER :: nminl_gas = 0.01 -REAL(KIND=real_jlslsm), PARAMETER :: & - ccdpm_min = 0.8, & - ccdpm_max = 1.0, & - ! Decomposable Plant Material burns between 80 to 100 % - ccrpm_min = 0.0, & - ccrpm_max = 0.2 - ! Resistant Plant Material burns between 0 to 20 % - ! These values are also set in inferno_mod to calculate emitted_carbon_DPM - ! and emitted_carbon_RPM, and are also set in soilcarb_layers !----------------------------------------------------------------------------- ! Local variables. @@ -356,10 +348,12 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & DO t = 1,trif_pts l = trif_index(t) burnt_carbon_dpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,1) * (ccdpm_min + (ccdpm_max - ccdpm_min) & + (cs(l,1,1) * (triffire_ccdpm_min + & + (triffire_ccdpm_max - triffire_ccdpm_min) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) burnt_carbon_rpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,2) * (ccrpm_min + (ccrpm_max - ccrpm_min) & + (cs(l,1,2) * (triffire_ccrpm_min + & + (triffire_ccrpm_max - triffire_ccrpm_min) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) cs(l,1,1) = cs(l,1,1) - burnt_carbon_dpm(l) / r_gamma cs(l,1,2) = cs(l,1,2) - burnt_carbon_rpm(l) / r_gamma diff --git a/src/science/vegetation/soilcarb_layers_jls_mod.F90 b/src/science/vegetation/soilcarb_layers_jls_mod.F90 index 1bd9b62a..f4b94872 100644 --- a/src/science/vegetation/soilcarb_layers_jls_mod.F90 +++ b/src/science/vegetation/soilcarb_layers_jls_mod.F90 @@ -37,17 +37,19 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & USE jules_surface_types_mod, ONLY: npft -USE jules_soil_biogeochem_mod, ONLY: bio_hum_cn, tau_lit, l_label_frac_cs, & - z_burn_max +USE jules_soil_biogeochem_mod, ONLY: bio_hum_cn, tau_lit, l_label_frac_cs +USE jules_inferno_mod, ONLY: z_burn_max USE soilcarb_tracer_age_mod, ONLY: soilcarb_tracer_age USE jules_vegetation_mod, ONLY: l_nitrogen +USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & + triffire_ccrpm_min, triffire_ccrpm_max USE jules_soil_mod, ONLY: cs_min, dzsoil, sm_levels USE veg_param, ONLY: litc_norm USE pftparm, ONLY: rootd_ft USE ancil_info, ONLY: dim_cslayer, nsoilt, dim_cs1 -USE jules_vegetation_mod, ONLY: l_trif_fire +USE jules_inferno_mod, ONLY: l_trif_fire USE root_frac_mod, ONLY: root_frac USE soilcarb_mix_mod, ONLY: soilcarb_mix USE dpm_rpm_mod, ONLY: dpm_rpm @@ -152,16 +154,6 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & REAL(KIND=real_jlslsm), PARAMETER :: nminl_gas = 0.01 ! Fraction of net mineralisation of N that is lost as gas. -REAL(KIND=real_jlslsm), PARAMETER :: & - ccdpm_min = 0.8, & - ccdpm_max = 1.0, & - ! Decomposable Plant Material burns between 80 to 100 % - ccrpm_min = 0.0, & - ccrpm_max = 0.2 - ! Resistant Plant Material burns between 0 to 20 % - ! These values are also set in inferno_mod to calculate emitted_carbon_DPM - ! and emitted_carbon_RPM, and are also set in soilcarb - !----------------------------------------------------------------------------- ! Local variables. !----------------------------------------------------------------------------- @@ -521,10 +513,12 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & END IF burnt_carbon_layer_dpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & - (cs(l,n,1) * (ccdpm_min + (ccdpm_max - ccdpm_min) & + (cs(l,n,1) * (triffire_ccdpm_min + & + (triffire_ccdpm_max - triffire_ccdpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) burnt_carbon_layer_rpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & - (cs(l,n,2) * (ccrpm_min + (ccrpm_max - ccrpm_min) & + (cs(l,n,2) * (triffire_ccrpm_min + & + (triffire_ccrpm_max - triffire_ccrpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) ! Need to introduce a check because it is updated before updating soil C burnt_carbon_layer_dpm(l,n) = MAX(MIN(burnt_carbon_layer_dpm(l,n), & diff --git a/src/science/vegetation/veg-veg2a_jls_mod.F90 b/src/science/vegetation/veg-veg2a_jls_mod.F90 index 07b9670c..6f384b7c 100644 --- a/src/science/vegetation/veg-veg2a_jls_mod.F90 +++ b/src/science/vegetation/veg-veg2a_jls_mod.F90 @@ -66,8 +66,8 @@ SUBROUTINE veg2( & USE jules_surface_types_mod, ONLY: npft, nnpft, ncpft, ntype USE jules_vegetation_mod, ONLY: frac_min, l_crop, & - l_trif_crop, can_model, & - l_inferno, l_trif_fire + l_trif_crop, can_model +USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire USE veg_param, ONLY: litc_norm, agric From e2126f3713dde82a1e660a3a8c7809c56fdad321 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Fri, 21 Aug 2026 21:23:39 +0100 Subject: [PATCH 02/20] minor fixes --- .../jules-fire/HEAD/rose-meta.conf | 1 - rose-meta/jules-standalone/versions.py | 24 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf index adff37a6..aeb900b3 100644 --- a/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf @@ -153,7 +153,6 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Soil moisture flammability function selector sort-key=b14 -type=integer value-titles=(1) linear, =(2) exponential values=1,2 diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 74e0414f..7a815569 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -90,18 +90,18 @@ def upgrade(self, config, meta_config=None): ["namelist:jules_inferno", "z_burn_max"], z_burn_max) self.remove_setting(config, ["namelist:jules_soil_biogeochem", "z_burn_max"]) - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_min"], 0.8) - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_max"], 1.0) - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_min"], 0.0) - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_max"], 0.2) + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_min"], "0.8") + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_max"], "1.0") + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_min"], "0.0") + self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_max"], "0.2") - self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_low"], 0.1) - self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_up"], 0.9) - self.add_setting(config, ["namelist:jules_inferno", "flam_sm_low"], 0.0) - self.add_setting(config, ["namelist:jules_inferno", "flam_sm_up"], 2.4) - self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_low"], 0.02) - self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_up"], 0.2) - self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], -14929920000.0) - self.add_setting(config, ["namelist:jules_inferno", "flam_sm_func"], 1) + self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_low"], "0.1") + self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_up"], "0.9") + self.add_setting(config, ["namelist:jules_inferno", "flam_sm_low"], "0.0") + self.add_setting(config, ["namelist:jules_inferno", "flam_sm_up"], "2.4") + self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_low"], "0.02") + self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_up"], "0.2") + self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], "-14929920000.0") + self.add_setting(config, ["namelist:jules_inferno", "flam_sm_func"], "1") return config, self.reports From 9a10f681c808bc7afe2a5b86cb24546d9e6ef9e4 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Mon, 24 Aug 2026 10:02:24 +0100 Subject: [PATCH 03/20] doc conflict resolved --- doc/source/namelists/fire.nml.rst | 142 +++++++++++++++++- .../namelists/jules_soil_biogeochem.nml.rst | 7 - doc/source/namelists/jules_vegetation.nml.rst | 49 ------ .../jules-fire/HEAD/rose-meta.conf | 2 +- src/control/shared/jules_inferno_mod.F90 | 10 +- src/initialisation/standalone/init.F90 | 1 + .../standalone/init_inferno_mod.F90 | 8 +- src/science/fire/inferno_io_mod.F90 | 8 +- src/science/fire/inferno_mod.F90 | 63 ++++++-- src/science/vegetation/soilcarb_jls.F90 | 16 +- .../vegetation/soilcarb_layers_jls_mod.F90 | 8 +- 11 files changed, 223 insertions(+), 91 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index 96c8f492..7a4cfccd 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -1,7 +1,8 @@ ``fire.nml`` =================== -This file contains a single namelist called :nml:lst:`FIRE_SWITCHES` that sets time-invariant parameters for performing wildfire-related calculations. +This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that contains switches used to calculate the different fire weather indices available. +. The second namelist is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` ``FIRE_SWITCHES`` namelist members ----------------------------------- @@ -57,3 +58,142 @@ This file contains a single namelist called :nml:lst:`FIRE_SWITCHES` that sets t :default: F Switch for calculating the Nesterov Index. + + +``JULES_INFERNO`` namelist members +----------------------------------- + +.. nml:namelist:: JULES_INFERNO + + .. nml:member:: l_inferno + + :type: boolean + :default: F + + Switch that determines whether interactive fires (INFERNO) is + used. This allows for the diagnostic of burnt area, burnt carbon + and a variety of fire emissions. + + TRUE + INFERNO is used to provide diagnostic fire variables + + FALSE + INFERNO is not used. + +.. nml:member:: ignition_method + + :type: integer + :permitted: 1, 2, 3 + :default: 1 + + Switch to determine the type of ignition used (ubiquitous or prescribed with population and lightning) + + 1. INFERNO uses ubiquitous (constant) ignitions, of 1.67 fires km\ + :sup:`-2` s\ :sup:`-1` (1.5 from humans, 0.17 from lightning). + + 2. INFERNO uses prescribed lightning ignitions, either from an ancillary or the UM. + Meanwhile humans are assumed to ignite 1.5 fires km\ :sup:`-2` s\ :sup:`-1`. + + 3. INFERNO uses prescribed ignition using Population Density and Lightning Frequency (Cloud-to-Ground). + These must be provided as prescribed data to the JULES run. + +.. nml:member:: l_trif_fire + + :type: boolean + :default: F + + Switch that determines whether interactive fire is used. This allows for burnt area to link with dynamic + vegetation. + + Only used if :nml:mem:`JULES_VEGETATION::l_triffid` = TRUE. + + TRUE + Burnt area is calculated in INFERNO and passed to TRIFFID to + calculate vegetation dynamics. Carbon is also removed from DPM + and RPM pools in SOILCARB. + FALSE + Burnt area is zero unless prescribed via an ancillary file. + + .. nml:member:: z_burn_max + + :type: real + :default: 0.2 + + Parameter controlling the depth to which fire burns soil litter carbon in metres. At depths shallower than this value, the fire can burn soil carbon in the two litter pools (dpm and rpm). If z_burn_max falls within a layer only a proportion of the soil carbon is burnt. Only used with layered soil carbon scheme (:nml:mem:`JULES_SOIL_BIOGEOCHEM::l_layeredc` = TRUE) and fire (either :nml:mem:`JULES_INFERNO::l_trif_fire` or :nml:mem:`JULES_INFERNO::l_inferno` or both). In reality the burn depth varies so please check whether the default value of 0.2 is suitable for your application. + + .. nml:member:: flam_sm_func + + :type: integer + :permitted: 1, 2 + :default: 1 + + .. nml:member:: flam_sm_low + + :type: real + :default: 0.0 + + Only used if :nml:mem:`flam_sm_func` = 2. + + .. nml:member:: flam_sm_up + + :type: real + :default: 2.4 + + + Only used if :nml:mem:`flam_sm_func` = 2. + + .. nml:member:: flam_rhum_low + + :type: real + :default: 0.1 + + .. nml:member:: flam_rhum_up + + :type: real + :default: 0.9 + + .. nml:member:: flam_rain_const + + :type: real + :default: -14929920000.0 + + +buggy + + .. nml:member:: flam_fuel_low + + :type: real + :default: 0.02 + + .. nml:member:: flam_fuel_up + :type: real + :default: 0.2 + + .. nml:member:: triffire_ccdpm_min + + :type: real + :default: 0.8 + + Minimum DPM soil carbon pool combustion completness fraction. + + .. nml:member:: triffire_ccdpm_max + + :type: real + :default: 1.0 + + Maximum DPM soil carbon pool combustion completness fraction. + + .. nml:member:: triffire_ccrpm_min + + :type: real + :default: 0.0 + + Minimum RPM soil carbon pool combustion completness fraction. + + + .. nml:member:: triffire_ccrpm_max + + :type: real + :default: 0.2 + + Maximum RPM soil carbon pool combustion completness fraction. diff --git a/doc/source/namelists/jules_soil_biogeochem.nml.rst b/doc/source/namelists/jules_soil_biogeochem.nml.rst index b90452db..6f3f255f 100644 --- a/doc/source/namelists/jules_soil_biogeochem.nml.rst +++ b/doc/source/namelists/jules_soil_biogeochem.nml.rst @@ -259,13 +259,6 @@ If using the ECOSSE soil model, most soil parameters are read from a separate fi Parameter controlling the rate of re-filling of the available inorganic nitrogen pool (1/360 days). This parameter determines how quickly the inorganic nitrogen reaches the roots after the roots uptake from the soil around them. This should be quicker than the turnover rate of inorganic nitrogen. In addition, it has to be small compared with the triffid timestep (360/triffid_period) otherwise the available inorganic nitrogen becomes unstable. Hence the choice of the default value 5. Only used with layered soil carbon and nitrogen scheme (:nml:mem:`l_layeredc` = TRUE and :nml:mem:`JULES_VEGETATION::l_nitrogen` = TRUE). When :nml:mem:`JULES_VEGETATION::l_trif_eq` = TRUE or :nml:mem:`JULES_SOIL_BIOGEOCHEM::diff_n_pft` is greater than (0.5 * 360 / :nml:mem:`JULES_VEGETATION::triffid_period`) then all of the inorganic nitrogen pool is deemed to be available. - .. nml:member:: z_burn_max - - :type: real - :default: 0.2 - - Parameter controlling the depth to which fire burns soil litter carbon in metres. At depths shallower than this value, the fire can burn soil carbon in the two litter pools (dpm and rpm). If z_burn_max falls within a layer only a proportion of the soil carbon is burnt. Only used with layered soil carbon scheme (:nml:mem:`l_layeredc` = TRUE) and fire (either :nml:mem:`JULES_VEGETATION::l_trif_fire` or :nml:mem:`JULES_VEGETATION::l_inferno` or both). In reality the burn depth varies so please check whether the default value of 0.2 is suitable for your application. - .. nml:group:: Parameters for the 4-pool- or ECOSSE-based models (only used if :nml:mem:`soil_bgc_model` = 2 or 3): diff --git a/doc/source/namelists/jules_vegetation.nml.rst b/doc/source/namelists/jules_vegetation.nml.rst index ccdf9aa2..d4092a1f 100644 --- a/doc/source/namelists/jules_vegetation.nml.rst +++ b/doc/source/namelists/jules_vegetation.nml.rst @@ -586,55 +586,6 @@ This file sets the vegetation options. It contains one namelist called :nml:lst: See Hadley Centre Technical Note 24, Eq.3. -.. nml:member:: l_inferno - - :type: logical - :default: F - - Switch that determines whether interactive fires (INFERNO) is - used. This allows for the diagnostic of burnt area, burnt carbon - and a variety of fire emissions. - - TRUE - INFERNO is used to provide diagnostic fire variables - - FALSE - INFERNO is not used. - -.. nml:member:: ignition_method - - :type: integer - :permitted: 1, 2, 3 - :default: 1 - - Switch to determine the type of ignition used (ubiquitous or prescribed with population and lightning) - - 1. INFERNO uses ubiquitous (constant) ignitions, of 1.67 fires km\ - :sup:`-2` s\ :sup:`-1` (1.5 from humans, 0.17 from lightning). - - 2. INFERNO uses prescribed lightning ignitions, either from an ancillary or the UM. - Meanwhile humans are assumed to ignite 1.5 fires km\ :sup:`-2` s\ :sup:`-1`. - - 3. INFERNO uses prescribed ignition using Population Density and Lightning Frequency (Cloud-to-Ground). - These must be provided as prescribed data to the JULES run. - -.. nml:member:: l_trif_fire - - :type: logical - :default: F - - Switch that determines whether interactive fire is used. This allows for burnt area to link with dynamic - vegetation. - - Only used if :nml:mem:`l_triffid` = TRUE. - - TRUE - Burnt area is calculated in INFERNO and passed to TRIFFID to - calculate vegetation dynamics. Carbon is also removed from DPM - and RPM pools in SOILCARB. - FALSE - Burnt area is zero unless prescribed via an ancillary file. - .. nml:member:: l_vegdrag_pft :type: logical(npft) diff --git a/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf index aeb900b3..f8c12874 100644 --- a/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf @@ -121,7 +121,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_sm_up] compulsory=true description=Upper soil moisture threshold for flammability -range=0.0:1.0 +range=0.0:10.0 sort-key=b10 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_up diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index e17cf859..66b7c67b 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -35,7 +35,7 @@ MODULE jules_inferno_mod ! Items set in namelist jules_inferno. INTEGER :: & - ignition_method = 1, & + ignition_method = imdi, & ! Switch for the calculation method of INFERNO fire ignitions ! IGNITION_METHOD=1:Constant (1.67 per km2 per s) ! IGNITION_METHOD=2:Constant (Human - 1.5 per km2 per s) @@ -100,7 +100,7 @@ MODULE jules_inferno_mod l_trif_fire, & l_inferno, & ignition_method, & - flam_sm_func, & + flam_sm_func, & flam_sm_low, & flam_sm_up, & flam_rhum_low, & @@ -111,7 +111,8 @@ MODULE jules_inferno_mod triffire_ccdpm_min, & triffire_ccdpm_max, & triffire_ccrpm_min, & - triffire_ccrpm_max + triffire_ccrpm_max, & + z_burn_max CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='JULES_INFERNO_MOD' @@ -298,6 +299,9 @@ SUBROUTINE print_nlist_jules_inferno() WRITE(lineBuffer,*)' l_inferno = ',l_inferno CALL jules_print('jules_inferno_mod',lineBuffer) +WRITE(lineBuffer,*)' ignition_method = ',ignition_method +CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_sm_low = ',flam_sm_low CALL jules_print('jules_inferno_mod',lineBuffer) diff --git a/src/initialisation/standalone/init.F90 b/src/initialisation/standalone/init.F90 index 7dbae519..ab9c0d80 100644 --- a/src/initialisation/standalone/init.F90 +++ b/src/initialisation/standalone/init.F90 @@ -274,6 +274,7 @@ SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & ! Must be called after init_soil to check soil tiling flags CALL init_vegetation(nml_dir) +! initialase inferno options CALL init_inferno(nml_dir) ! Initialise irrigation options diff --git a/src/initialisation/standalone/init_inferno_mod.F90 b/src/initialisation/standalone/init_inferno_mod.F90 index ebf1847c..88240ff9 100644 --- a/src/initialisation/standalone/init_inferno_mod.F90 +++ b/src/initialisation/standalone/init_inferno_mod.F90 @@ -24,10 +24,10 @@ MODULE init_inferno_mod SUBROUTINE init_inferno(nml_dir) USE jules_inferno_mod, ONLY: print_nlist_jules_inferno, check_jules_inferno, & - l_inferno, l_trif_fire, flam_sm_up, flam_sm_low, flam_rhum_up, & + l_inferno, l_trif_fire, flam_sm_up, flam_sm_low, flam_sm_func, flam_rhum_up, & flam_rhum_low, flam_fuel_up, flam_fuel_low, flam_rain_const, & triffire_ccdpm_max, triffire_ccdpm_min, triffire_ccrpm_max, & - triffire_ccrpm_min, ignition_method, ignition_constant, & + triffire_ccrpm_min, z_burn_max, ignition_method, ignition_constant, & ignition_vary_natural, ignition_vary_natural_human USE io_constants, ONLY: namelist_unit @@ -64,6 +64,7 @@ SUBROUTINE init_inferno(nml_dir) ignition_method, & flam_sm_low, & flam_sm_up, & + flam_sm_func, & flam_rhum_low, & flam_rhum_up, & flam_rain_const, & @@ -72,7 +73,8 @@ SUBROUTINE init_inferno(nml_dir) triffire_ccdpm_min, & triffire_ccdpm_max, & triffire_ccrpm_min, & - triffire_ccrpm_max + triffire_ccrpm_max, & + z_burn_max !----------------------------------------------------------------------------- !----------------------------------------------------------------------------- diff --git a/src/science/fire/inferno_io_mod.F90 b/src/science/fire/inferno_io_mod.F90 index e6ceea03..d22c1792 100644 --- a/src/science/fire/inferno_io_mod.F90 +++ b/src/science/fire/inferno_io_mod.F90 @@ -53,9 +53,9 @@ SUBROUTINE inferno_io( & avg_ba, fire_mort ! Average Burned Area per PFT, and fire mortality rate -USE jules_inferno_mod, ONLY: & -flam_rhum_low, flam_rhum_up, & -flam_sm_low, flam_sm_up, flam_fuel_low, & +USE jules_inferno_mod, ONLY: & +flam_rhum_low, flam_rhum_up, & +flam_sm_low, flam_sm_up, flam_fuel_low, & flam_fuel_up, flam_rain_const, flam_sm_func USE qsat_mod, ONLY: qsat_wat @@ -315,7 +315,7 @@ SUBROUTINE inferno_io( & DO i = 1, npft ! Calculate the fuel density ! We use normalised Leaf Carbon + the available DPM - inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & + inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & /(flam_fuel_up - flam_fuel_low) WHERE (inferno_fuel < 0.0) inferno_fuel = 0.0 diff --git a/src/science/fire/inferno_mod.F90 b/src/science/fire/inferno_mod.F90 index 3e0ecedc..78114fff 100644 --- a/src/science/fire/inferno_mod.F90 +++ b/src/science/fire/inferno_mod.F90 @@ -165,8 +165,8 @@ END SUBROUTINE calc_ignitions SUBROUTINE calc_flam( & !Point Intent(IN) temp_l, rhum_l, fuel_l, sm_l, rain_l, & - flam_rhum_low, flam_rhum_up, flam_sm_low, flam_sm_up, & - flam_rain_const, flam_sm_func, & + flam_rhum_low, flam_rhum_up, flam_sm_low, flam_sm_up, & + flam_rain_const, flam_sm_func, & !Point Intent(INOUT) flam_l) @@ -196,22 +196,22 @@ SUBROUTINE calc_flam( & ! Relative Humidity (%) sm_l, & ! The INFERNO soil moisture fraction (sthu's 1st level) - rain_l, & + !rain_l, & ! The precipitation rate (kg.m-2.s-1) fuel_l, & ! The Fuel Density (0-1) - flam_rhum_up, & + flam_rhum_up, & ! Upper boundary to the relative humidity - flam_rhum_low, & + flam_rhum_low, & ! Lower boundary to the relative humidity - flam_sm_low, & + flam_sm_low, & ! Lower boundary to the soil moisture - flam_sm_up, & + flam_sm_up, & ! Upper boundary to the soil moisture flam_rain_const ! -INTEGER, INTENT(IN) :: & +INTEGER, INTENT(IN) :: & flam_sm_func REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & @@ -240,6 +240,13 @@ SUBROUTINE calc_flam( & f_sm_l ! The factor dependence on soil moisture +REAL(KIND=real_jlslsm) :: & + rain_l + ! The precipitation rate (kg.m-2.s-1) + + +LOGICAL, PARAMETER :: l_cf_old_inferno = .TRUE. + REAL(KIND=jprb) :: zhook_handle CHARACTER(LEN=*), PARAMETER :: RoutineName = "CALC_FLAM" @@ -247,6 +254,10 @@ SUBROUTINE calc_flam( & TsbyT_l = Ts / temp_l +PRINT*,"calc_flam" +PRINT*, flam_rhum_low, flam_rhum_up, flam_sm_low, flam_sm_up, flam_rain_const, flam_sm_func +PRINT*,temp_l, rhum_l, fuel_l, sm_l, rain_l + Z_l = a * (TsbyT_l-1.0) + b * LOG10(TsbyT_l) & + c * (10.0**( d * (1.0 - TsbyT_l)) - 1.0) & + f * (10.0**( h * (TsbyT_l-1.0)) - 1.0) @@ -260,6 +271,12 @@ SUBROUTINE calc_flam( & IF (rhum_l > flam_rhum_up) f_rhum_l = 0.0 ! No fires for RH > flam_rhum_up +IF (l_cf_old_inferno) THEN + f_rhum_l = (90.0 - rhum_l) / (90.0 - 10.0) + IF (rhum_l < 10.0) f_rhum_l = 1.0 + IF (rhum_l > 90.0) f_rhum_l = 0.0 +END IF + IF (flam_sm_func == 1) THEN f_sm_l = (1 - sm_l) ! The flammability goes down linearly with soil moisture @@ -273,8 +290,17 @@ SUBROUTINE calc_flam( & f_sm_l = 1.0 END IF -flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & - * EXP( flam_rain_const * rain_l) ,1.0) ,0.0) + +IF (l_cf_old_inferno) THEN + flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & + * EXP( -2.0 * s_in_day * s_in_day * rain_l) ,1.0) ,0.0) +ELSE + flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & + * EXP( flam_rain_const * rain_l) ,1.0) ,0.0) +END IF + + +PRINT*,"calc_flam", temp_l, rhum_l, fuel_l, sm_l, rain_l, flam_l IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN @@ -410,7 +436,7 @@ SUBROUTINE calc_emitted_carbon_soil( & ! Language: Fortran 90 ! -USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & +USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & triffire_ccrpm_min, triffire_ccrpm_max USE yomhook, ONLY: lhook, dr_hook @@ -444,11 +470,18 @@ SUBROUTINE calc_emitted_carbon_soil( & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) DO l = 1,land_pts - emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (triffire_ccdpm_min + & - (triffire_ccdpm_max - triffire_ccdpm_min) * & + ! emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (triffire_ccdpm_min + & + ! (triffire_ccdpm_max - triffire_ccdpm_min) * & + ! (1.0 - sm(l)))) ,0.0) + ! emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (triffire_ccrpm_min + & + ! (triffire_ccrpm_max - triffire_ccrpm_min) * & + ! (1.0 - sm(l)))) ,0.0) + + emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (0.8 + & + (1.0 - 0.8) * & (1.0 - sm(l)))) ,0.0) - emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (triffire_ccrpm_min + & - (triffire_ccrpm_max - triffire_ccrpm_min) * & + emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (0.0 + & + (0.2 - 0.0) * & (1.0 - sm(l)))) ,0.0) END DO diff --git a/src/science/vegetation/soilcarb_jls.F90 b/src/science/vegetation/soilcarb_jls.F90 index 5419f873..0812fd2c 100644 --- a/src/science/vegetation/soilcarb_jls.F90 +++ b/src/science/vegetation/soilcarb_jls.F90 @@ -348,12 +348,20 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & DO t = 1,trif_pts l = trif_index(t) burnt_carbon_dpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,1) * (triffire_ccdpm_min + & - (triffire_ccdpm_max - triffire_ccdpm_min) & + (cs(l,1,1) * (triffire_ccdpm_min + & + (triffire_ccdpm_max - triffire_ccdpm_min) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) burnt_carbon_rpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,2) * (triffire_ccrpm_min + & - (triffire_ccrpm_max - triffire_ccrpm_min) & + (cs(l,1,2) * (triffire_ccrpm_min + & + (triffire_ccrpm_max - triffire_ccrpm_min) & + * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) + burnt_carbon_dpm(l) = MAX(g_burn_gb(l) * & + (cs(l,1,1) * (0.8 + & + (1.0 - 0.8) & + * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) + burnt_carbon_rpm(l) = MAX(g_burn_gb(l) * & + (cs(l,1,2) * (0.0 + & + (0.2 - 0.0) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) cs(l,1,1) = cs(l,1,1) - burnt_carbon_dpm(l) / r_gamma cs(l,1,2) = cs(l,1,2) - burnt_carbon_rpm(l) / r_gamma diff --git a/src/science/vegetation/soilcarb_layers_jls_mod.F90 b/src/science/vegetation/soilcarb_layers_jls_mod.F90 index f4b94872..272f88f4 100644 --- a/src/science/vegetation/soilcarb_layers_jls_mod.F90 +++ b/src/science/vegetation/soilcarb_layers_jls_mod.F90 @@ -42,7 +42,7 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & USE soilcarb_tracer_age_mod, ONLY: soilcarb_tracer_age USE jules_vegetation_mod, ONLY: l_nitrogen -USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & +USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & triffire_ccrpm_min, triffire_ccrpm_max USE jules_soil_mod, ONLY: cs_min, dzsoil, sm_levels @@ -513,12 +513,12 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & END IF burnt_carbon_layer_dpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & - (cs(l,n,1) * (triffire_ccdpm_min + & - (triffire_ccdpm_max - triffire_ccdpm_min) & + (cs(l,n,1) * (triffire_ccdpm_min + & + (triffire_ccdpm_max - triffire_ccdpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) burnt_carbon_layer_rpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & (cs(l,n,2) * (triffire_ccrpm_min + & - (triffire_ccrpm_max - triffire_ccrpm_min) & + (triffire_ccrpm_max - triffire_ccrpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) ! Need to introduce a check because it is updated before updating soil C burnt_carbon_layer_dpm(l,n) = MAX(MIN(burnt_carbon_layer_dpm(l,n), & From 9d5ad044551f85898f7918e56daea5960cd07767 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:33:52 +0100 Subject: [PATCH 04/20] re-resolving conflicts --- CONTRIBUTORS.md | 1 + doc/source/namelists/fire.nml.rst | 8 +- .../HEAD/rose-meta.conf | 32 +- .../jules-vegetation/HEAD/rose-meta.conf | 1 - .../jules-standalone/HEAD/rose-meta.conf | 2 +- rose-meta/jules-um/HEAD/rose-meta.conf | 2 +- src/control/shared/jules_inferno_mod.F90 | 388 ++++++++++-------- .../shared/jules_soil_biogeochem_mod.F90 | 4 +- .../standalone/init_inferno_mod.F90 | 118 +----- src/science/vegetation/soilcarb_jls.F90 | 4 +- .../vegetation/soilcarb_layers_jls_mod.F90 | 5 +- 11 files changed, 267 insertions(+), 298 deletions(-) rename rose-meta/jules-shared/{jules-fire => jules-inferno}/HEAD/rose-meta.conf (94%) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index db1cc110..5c9e382f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -5,3 +5,4 @@ | yaswant | Yaswant Pradhan | Met Office | 2026-06-30 | | doucla | Douglas Clark | UKCEH | 2026-07-03 | | james-bruten-mo | James Bruten | Met Office | 2026-07-09 | +| eleanorgb | Eleanor Burke | Met Office | 2026-08-24 | diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index 7a4cfccd..7c8aa5fe 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -1,8 +1,7 @@ ``fire.nml`` =================== -This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that contains switches used to calculate the different fire weather indices available. -. The second namelist is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` +This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that sets time-invariant parameters for performing wildfire-related calculations. The second namelist is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` ``FIRE_SWITCHES`` namelist members ----------------------------------- @@ -127,6 +126,10 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :permitted: 1, 2 :default: 1 + Parameter controlling the relationship between soil moisture and flammability. + 1 a linear relatonship which has a flammability of 0 at 1 and 1 at 0. + 2 an exponential relationship controlled by :nml:mem:`flam_sm_low` and :nml:mem:`flam_sm_up` + .. nml:member:: flam_sm_low :type: real @@ -139,7 +142,6 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :type: real :default: 2.4 - Only used if :nml:mem:`flam_sm_func` = 2. .. nml:member:: flam_rhum_low diff --git a/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf similarity index 94% rename from rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf rename to rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index f8c12874..62dc7f0c 100644 --- a/rose-meta/jules-shared/jules-fire/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -2,14 +2,14 @@ compulsory=true description=Options for inferno fire parametrisations ns=namelist/JULES Science Settings/jules_inferno -sort-key=Section-A12g +sort-key=Section-A12p title=Fire options url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html [namelist:jules_inferno=l_inferno] compulsory=true description=Use the INFERNO interactive fire and diagnostic emissions model -sort-key=Panel-I16 +sort-key=Panel-J01 trigger=namelist:jules_inferno=ignition_method: .true.; =namelist:jules_inferno=l_trif_fire: .true.; =namelist:jules_pftparm=avg_ba_io: .true.; @@ -38,7 +38,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Use interactive fire linked to INFERNO including interactive fire emissions. fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); -sort-key=Panel-I1 +sort-key=Panel-J02 trigger=namelist:jules_pftparm=fire_mort_io: .true. type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_trif_fire @@ -46,7 +46,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=ignition_method] compulsory=true description=The method to use for ignitions -sort-key=Panel-I16a +sort-key=Panel-J02 url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ignition_method value-titles=(1) constant human and natural ignition sources, =(2) constant human varying natural ignition sources, @@ -58,7 +58,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Maximum burn depth for soil - soil carbon is burned above this level range=0.0:10.0 -sort-key=b2 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::z_burn_max @@ -74,7 +74,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Maximum fraction of DPM consumed by fire range=0.0:1.0 -sort-key=b4 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccdpm_max @@ -82,7 +82,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Minimum fraction of RPM consumed by fire range=0.0:1.0 -sort-key=b5 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccrpm_min @@ -90,7 +90,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Maximum fraction of RPM consumed by fire range=0.0:1.0 -sort-key=b6 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccrpm_max @@ -98,7 +98,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Lower relative humidity threshold for flammability range=0.0:1.0 -sort-key=b7 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_low @@ -106,7 +106,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Upper relative humidity threshold for flammability range=0.0:1.0 -sort-key=b8 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_up @@ -114,7 +114,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Lower soil moisture threshold for flammability range=0.0:1.0 -sort-key=b9 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_low @@ -122,7 +122,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Upper soil moisture threshold for flammability range=0.0:10.0 -sort-key=b10 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_up @@ -130,7 +130,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Lower fuel load threshold for flammability range=0.0:1.0 -sort-key=b11 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_low @@ -138,21 +138,21 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU compulsory=true description=Upper fuel load threshold for flammability range=0.0:1.0 -sort-key=b12 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_up [namelist:jules_inferno=flam_rain_const] compulsory=true description=Rainfall flammability scaling constant -sort-key=b13 +sort-key=Panel-J02 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rain_const [namelist:jules_inferno=flam_sm_func] compulsory=true description=Soil moisture flammability function selector -sort-key=b14 +sort-key=Panel-J02 value-titles=(1) linear, =(2) exponential values=1,2 diff --git a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf index 4967a536..9d386e24 100644 --- a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf @@ -31,7 +31,6 @@ type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_bvoc_emis - [namelist:jules_vegetation=l_limit_canhc] compulsory=true description=Logical for capping vegetation canopy areal thermal heat capacity diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index d1760351..d1cce4d1 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -1,6 +1,6 @@ # Please see jules:wiki:SharingJULESmetadata -import=jules-shared/jules-fire/HEAD +import=jules-shared/jules-inferno/HEAD =jules-shared/jules-hydrology/HEAD =jules-shared/jules-model-environment/HEAD =jules-shared/jules-nvegparm/HEAD diff --git a/rose-meta/jules-um/HEAD/rose-meta.conf b/rose-meta/jules-um/HEAD/rose-meta.conf index 6f27795a..1c665640 100644 --- a/rose-meta/jules-um/HEAD/rose-meta.conf +++ b/rose-meta/jules-um/HEAD/rose-meta.conf @@ -8,7 +8,7 @@ # Please see jules:wiki:SharingJULESmetadata ############################################################################### -import=jules-shared/jules-fire/HEAD +import=jules-shared/jules-inferno/HEAD =jules-shared/jules-hydrology/HEAD =jules-shared/jules-model-environment/HEAD =jules-shared/jules-nvegparm/HEAD diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index 66b7c67b..8237c4f3 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -6,113 +6,87 @@ MODULE jules_inferno_mod -USE missing_data_mod, ONLY: rmdi, imdi - -!----------------------------------------------------------------------------- +! ----------------------------------------------------------------------------- ! Description: -! Contains inferno and l_trif_fire options and a namelist for setting them +! Contains switches and other inputs for l_inferno and l_trif_fire options ! ! Code Owner: Please refer to ModuleLeaders.txt ! This file belongs in TECHNICAL -! -! Code Description: -! Language: Fortran 90. -! This code is written to JULES coding standards v1. -!----------------------------------------------------------------------------- +! ----------------------------------------------------------------------------- -USE um_types, ONLY: real_jlslsm +USE um_types, ONLY: real_jlslsm +USE missing_data_mod, ONLY: rmdi, imdi IMPLICIT NONE -!----------------------------------------------------------------------------- -! Module constants -!----------------------------------------------------------------------------- - -!----------------------------------------------------------------------------- -! Module variables -!----------------------------------------------------------------------------- +LOGICAL :: & + l_inferno = .FALSE., & + ! Switch used to control whether inferno fire scheme is used to calculate + ! flammability and burnt area + l_trif_fire = .FALSE. + ! Switch used to control whether fire is part of the carbon cycle + ! T => if l_inferno is also true, g_burn is calculated in INFERNO + ! passed to TRIFFID to calculate emissions and vegetation dynamics + ! T => if l_inferno is false, interactive fire is calculated via + ! ancillary if provided, and is 0 if not provided + ! F => g_burn is calculated via ancillary if provided, and is 0 if + ! not provided -! Items set in namelist jules_inferno. INTEGER :: & ignition_method = imdi, & ! Switch for the calculation method of INFERNO fire ignitions - ! IGNITION_METHOD=1:Constant (1.67 per km2 per s) - ! IGNITION_METHOD=2:Constant (Human - 1.5 per km2 per s) - ! Varying (Lightning - see Pechony and Shindell,2009) - ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony and Shindell,2009) + ! IGNITION_METHOD=1:Constant (1.67 per km2 per s) + ! IGNITION_METHOD=2:Constant (Human - 1.5 per km2 per s) + ! Varying (Lightning - see Pechony & Shindell,2009) + ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony & Shindell,2009) flam_sm_func = 1 ! Switch for the calculation method of INFERNO fire flammability - ! FLAM_SM_FUNC=1:Linear - ! FLAM_SM_FUNC=2:Exponential + ! FLAM_SM_FUNC=1:Linear (old - doesnt require flam_sm_low / flam_sm_up) + ! FLAM_SM_FUNC=2:Exponential (newer) -LOGICAL :: & - l_inferno = .FALSE., & - ! Switch used to control whether the Interactive fire scheme is used - l_trif_fire = .FALSE. - ! Switch used to control whether interactive fire is used - ! T => if l_inferno is also true, g_burn is calculated in INFERNO -! and passed to TRIFFID to calculate emissions and vegetation - ! dynamics - ! T => if l_inferno is false, interactive fire is calculated via -! ancillary if provided, and is 0 if not provided - ! F => g_burn is calculated via ancillary if provided, and is 0 if -! not provided - -INTEGER, PARAMETER :: ignition_constant = 1 -INTEGER, PARAMETER :: ignition_vary_natural = 2 -INTEGER, PARAMETER :: ignition_vary_natural_human = 3 - - -INTEGER :: errcode ! error code to pass to ereport. - REAL(KIND=real_jlslsm) :: & flam_sm_low = rmdi, & - ! Lower boundary to the soil moisture + ! Lower boundary to soil moisture for flammability calc (flam_sm_func=2) + ! UNITS flam_sm_up = rmdi, & - ! Upper boundary to the soil moisture + ! Upper boundary to soil moisture for flammability calc (flam_sm_func=2) + ! UNITS flam_rhum_low = rmdi, & - ! Lower boundary to the relative humidity + ! Lower boundary to the relative humidity (%, between 0 and 100 %) flam_rhum_up = rmdi, & - ! Upper boundary to the relative humidity + ! Lower boundary to the relative humidity (%, between 0 and 100 %) flam_rain_const = rmdi, & ! Precipitation factor (-2(day/mm)*(kg/m2/s)) flam_fuel_low = rmdi, & - ! Lower boundary to the fuel density + ! Lower boundary to the fuel density (UNITS) flam_fuel_up = rmdi, & - ! Upper boundary to the fuel density + ! Upper boundary to the fuel density (UNITS) triffire_ccdpm_min = rmdi, & - ! Minimum decomposable plant material burn fraction + ! Minimum decomposable plant material burn fraction (0 <= fraction <= 1) triffire_ccdpm_max = rmdi, & - ! Decomposable Plant Material burns between 80 to 100 % + ! Decomposable Plant Material burn fraction (0 <= fraction <= 1) triffire_ccrpm_min = rmdi, & - ! Minimum resistant plant material burn fraction + ! Minimum resistant plant material urn fraction (0 <= fraction <= 1) triffire_ccrpm_max = rmdi, & - ! Resistant Plant Material burns between 0 to 20 % + ! Resistant Plant Material burn fraction (0 <= fraction <= 1) z_burn_max = rmdi - ! Parameter setting maximum depth of burn + ! Parameter setting maximum depth of burn (m) -!----------------------------------------------------------------------------- -! Single namelist definition for UM and standalone -!----------------------------------------------------------------------------- +INTEGER, PARAMETER :: ignition_constant = 1 +INTEGER, PARAMETER :: ignition_vary_natural = 2 +INTEGER, PARAMETER :: ignition_vary_natural_human = 3 + +!----------------------------------------------------------------------- +! Set up a namelist to allow switches to be set. +!----------------------------------------------------------------------- NAMELIST / jules_inferno/ & - l_trif_fire, & - l_inferno, & - ignition_method, & - flam_sm_func, & - flam_sm_low, & - flam_sm_up, & - flam_rhum_low, & - flam_rhum_up, & - flam_rain_const, & - flam_fuel_low, & - flam_fuel_up, & - triffire_ccdpm_min, & - triffire_ccdpm_max, & - triffire_ccrpm_min, & - triffire_ccrpm_max, & - z_burn_max + l_trif_fire, l_inferno, ignition_method, flam_sm_func, & + flam_sm_low, flam_sm_up, flam_rhum_low, flam_rhum_up, & + flam_rain_const, flam_fuel_low, flam_fuel_up, & + triffire_ccdpm_min,triffire_ccdpm_max, triffire_ccrpm_min, & + triffire_ccrpm_max, z_burn_max CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='JULES_INFERNO_MOD' @@ -120,9 +94,7 @@ MODULE jules_inferno_mod SUBROUTINE check_jules_inferno() -USE ereport_mod, ONLY: ereport -USE jules_print_mgr, ONLY: jules_message !----------------------------------------------------------------------------- ! Description: ! Checks JULES_INFERNO namelist for consistency and calculates some @@ -130,22 +102,22 @@ SUBROUTINE check_jules_inferno() ! ! Code Owner: Please refer to ModuleLeaders.txt ! This file belongs in TECHNICAL -! -! Code Description: -! Language: Fortran 90. -! This code is written to JULES coding standards v1. !----------------------------------------------------------------------------- +USE ereport_mod, ONLY: ereport +USE jules_print_mgr, ONLY: jules_print, jules_message + +USE logging_mod, ONLY: log_info + IMPLICIT NONE -! Local scalar parameters. INTEGER :: errorstatus -CHARACTER(LEN=*), PARAMETER :: & - RoutineName = 'CHECK_JULES_INFERNO' ! Name of this procedure. -! Set error status to show a fatal error for all checks. -errorstatus = 101 +CHARACTER(LEN=*), PARAMETER :: RoutineName='CHECK_JULES_INFERNO' + +!ejb delete USE jules_surface_types_mod, ONLY: npft +!ejb delete USE jules_soil_biogeochem_mod, ONLY: l_layeredc !ejb check that it is set or move this trap ! Check options that depend on TRIFFID if it is not enabled !if l_triffie @@ -169,9 +141,24 @@ SUBROUTINE check_jules_inferno() ELSE IF ( flam_sm_up < flam_sm_low ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & "flam_sm_up must be >= flam_sm_low") -ELSE IF ( flam_sm_up > 1.0 ) THEN +ELSE IF ( flam_sm_up > 10.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_sm_up must be <= 1.0.") + "flam_sm_up must be <= 10.0.") +END IF + +IF ( l_inferno ) THEN + CALL log_info(RoutineName, & + "Interactive fires and emissions (INFERNO) will be diagnosed") + IF (ignition_method == ignition_constant ) THEN + CALL log_info(RoutineName, & + "Constant or ubiquitous ignitions (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural ) THEN + CALL log_info(RoutineName, & + "Constant human ignitions, varying lightning (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural_human ) THEN + CALL log_info(RoutineName, & + "Fully prescribed ignitions (INFERNO)") + END IF END IF IF ( ABS(flam_rhum_low - rmdi) < EPSILON(rmdi) ) THEN @@ -212,58 +199,62 @@ SUBROUTINE check_jules_inferno() "flam_fuel_up must be <= 1.0.") END IF -IF ( ABS(triffire_ccdpm_min - rmdi) < EPSILON(rmdi) ) THEN +IF ( ABS(flam_rain_const - rmdi) < EPSILON(rmdi) ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_min needs to be specified.") -ELSE IF ( triffire_ccdpm_min < 0.0 ) THEN + "flam_rain_const needs to be specified.") +ELSE IF ( flam_rain_const > 0.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_min must be >= 0.0.") + "flam_rain_const must be <= 0.0.") END IF -IF ( ABS(triffire_ccdpm_max - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_max needs to be specified.") -ELSE IF ( triffire_ccdpm_max < triffire_ccdpm_min ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_max must be >= triffire_ccdpm_min") -ELSE IF ( triffire_ccdpm_max > 1.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_max must be < 1.0.") -END IF -IF ( ABS(triffire_ccrpm_min - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_min needs to be specified.") -ELSE IF ( triffire_ccrpm_min < 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_min must be >= 0.0.") +IF ( l_trif_fire ) THEN + IF ( ABS(triffire_ccdpm_min - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_min needs to be specified.") + ELSE IF ( triffire_ccdpm_min < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_min must be >= 0.0.") + END IF + + IF ( ABS(triffire_ccdpm_max - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_max needs to be specified.") + ELSE IF ( triffire_ccdpm_max < triffire_ccdpm_min ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_max must be >= triffire_ccdpm_min") + ELSE IF ( triffire_ccdpm_max > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccdpm_max must be < 1.0.") + END IF + + IF ( ABS(triffire_ccrpm_min - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_min needs to be specified.") + ELSE IF ( triffire_ccrpm_min < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_min must be >= 0.0.") + END IF + + IF ( ABS(triffire_ccrpm_max - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_max needs to be specified.") + ELSE IF ( triffire_ccrpm_max < triffire_ccrpm_min ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_max must be >= triffire_ccrpm_min") + ELSE IF ( triffire_ccrpm_max > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "triffire_ccrpm_max must be < 1.0.") + END IF END IF -IF ( ABS(triffire_ccrpm_max - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_max needs to be specified.") -ELSE IF ( triffire_ccrpm_max < triffire_ccrpm_min ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_max must be >= triffire_ccrpm_min") -ELSE IF ( triffire_ccrpm_max > 1.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_max must be < 1.0.") -END IF - -IF ( ABS(flam_rain_const - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rain_const needs to be specified.") -ELSE IF ( flam_rain_const < 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rain_const must be >= 0.0.") -END IF ! Check a suitable ignition_method was given IF ( ignition_method /= ignition_constant .AND. & ignition_method /= ignition_vary_natural .AND. & ignition_method /= ignition_vary_natural_human ) THEN - errcode = 101 - CALL ereport("check_jules_vegetation", errcode, & + errorstatus = 101 + CALL ereport("check_jules_vegetation", errorstatus, & 'ignition_method must be 1, 2 or 3') END IF @@ -277,19 +268,19 @@ SUBROUTINE check_jules_inferno() ! END IF !END IF - END SUBROUTINE check_jules_inferno + SUBROUTINE print_nlist_jules_inferno() USE jules_print_mgr, ONLY: jules_print -USE jules_surface_types_mod, ONLY: npft -! USE jules_soil_biogeochem_mod, ONLY: l_layeredc !ejb check that it is set or move this trap IMPLICIT NONE CHARACTER(LEN=50000) :: lineBuffer +CALL jules_print('jules_inferno', 'Contents of namelist jules_inferno') + CALL jules_print('jules_inferno_mod', & 'Contents of namelist jules_inferno') @@ -299,44 +290,54 @@ SUBROUTINE print_nlist_jules_inferno() WRITE(lineBuffer,*)' l_inferno = ',l_inferno CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' ignition_method = ',ignition_method -CALL jules_print('jules_inferno_mod',lineBuffer) +IF ( l_inferno ) THEN + WRITE(lineBuffer,*)' ignition_method = ',ignition_method + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' flam_sm_low = ',flam_sm_low -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_sm_func = ',flam_sm_func + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' flam_sm_up = ',flam_sm_up -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_sm_low = ',flam_sm_low + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' flam_rhum_low = ',flam_rhum_low -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_sm_up = ',flam_sm_up + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' flam_rhum_up = ',flam_rhum_up -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_rhum_low = ',flam_rhum_low + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' flam_rain_const = ',flam_rain_const -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_rhum_up = ',flam_rhum_up + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' flam_fuel_low = ',flam_fuel_low -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_rain_const = ',flam_rain_const + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' flam_fuel_up = ',flam_fuel_up -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_fuel_low = ',flam_fuel_low + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' triffire_ccdpm_min = ',triffire_ccdpm_min -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' flam_fuel_up = ',flam_fuel_up + CALL jules_print('jules_inferno_mod',lineBuffer) +END IF -WRITE(lineBuffer,*)' triffire_ccdpm_max = ',triffire_ccdpm_max -CALL jules_print('jules_inferno_mod',lineBuffer) +IF ( l_trif_fire ) THEN + WRITE(lineBuffer,*)' triffire_ccdpm_min = ',triffire_ccdpm_min + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' triffire_ccrpm_min = ',triffire_ccrpm_min -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' triffire_ccdpm_max = ',triffire_ccdpm_max + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer,*)' triffire_ccrpm_max = ',triffire_ccrpm_max -CALL jules_print('jules_inferno_mod',lineBuffer) + WRITE(lineBuffer,*)' triffire_ccrpm_min = ',triffire_ccrpm_min + CALL jules_print('jules_inferno_mod',lineBuffer) -WRITE(lineBuffer, *) ' z_burn_max = ', z_burn_max -CALL jules_print('jules_soil_biogeochem_mod', lineBuffer) + WRITE(lineBuffer,*)' triffire_ccrpm_max = ',triffire_ccrpm_max + CALL jules_print('jules_inferno_mod',lineBuffer) + + WRITE(lineBuffer, *) ' z_burn_max = ', z_burn_max + CALL jules_print('jules_inferno_mod', lineBuffer) +END IF + +CALL jules_print('jules_inferno_mod', & + '- - - - - - end of namelist - - - - - -') END SUBROUTINE print_nlist_jules_inferno @@ -363,24 +364,21 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) INTEGER :: mpl_nml_type INTEGER :: ErrorStatus INTEGER :: icode +CHARACTER(LEN=errormessagelength) :: iomessage REAL(KIND=jprb) :: zhook_handle -CHARACTER(LEN=*), PARAMETER :: RoutineName='READ_NML_JULES_INFERNO' +CHARACTER(LEN=*), PARAMETER :: RoutineName='READ_NML_JULES_INFERNO' INTEGER(KIND=jpim), PARAMETER :: zhook_in = 0 INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 -CHARACTER(LEN=errormessagelength) :: iomessage - ! set number of each type of variable in my_namelist type INTEGER, PARAMETER :: no_of_types = 3 INTEGER, PARAMETER :: n_int = 2 -INTEGER, PARAMETER :: n_real = 11 +INTEGER, PARAMETER :: n_real = 12 INTEGER, PARAMETER :: n_log = 2 TYPE :: my_namelist SEQUENCE - INTEGER :: ignition_method - INTEGER :: flam_sm_func REAL(KIND=real_jlslsm) :: flam_sm_low REAL(KIND=real_jlslsm) :: flam_sm_up REAL(KIND=real_jlslsm) :: flam_rhum_low @@ -395,6 +393,8 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) REAL(KIND=real_jlslsm) :: z_burn_max LOGICAL :: l_trif_fire LOGICAL :: l_inferno + INTEGER :: ignition_method + INTEGER :: flam_sm_func END TYPE my_namelist TYPE (my_namelist) :: my_nml @@ -413,7 +413,7 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) CALL check_iostat(errorstatus, "namelist jules_inferno", iomessage) my_nml % ignition_method = ignition_method - my_nml % flam_sm_func = flam_sm_func + my_nml % flam_sm_func = flam_sm_func my_nml % l_trif_fire = l_trif_fire my_nml % l_inferno = l_inferno my_nml % flam_sm_low = flam_sm_low @@ -427,7 +427,7 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) my_nml % triffire_ccdpm_max = triffire_ccdpm_max my_nml % triffire_ccrpm_min = triffire_ccrpm_min my_nml % triffire_ccrpm_max = triffire_ccrpm_max - my_nml % z_burn_max = z_burn_max + my_nml % z_burn_max = z_burn_max END IF CALL mpl_bcast(my_nml,1,mpl_nml_type,0,my_comm,icode) @@ -449,7 +449,7 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) triffire_ccdpm_max = my_nml % triffire_ccdpm_max triffire_ccrpm_min = my_nml % triffire_ccrpm_min triffire_ccrpm_max = my_nml % triffire_ccrpm_max - z_burn_max = my_nml % z_burn_max + z_burn_max = my_nml % z_burn_max END IF CALL mpl_type_free(mpl_nml_type,icode) @@ -459,4 +459,62 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) END SUBROUTINE read_nml_jules_inferno #endif +#if !defined(UM_JULES) +SUBROUTINE read_nml_jules_inferno(nml_dir) + +!----------------------------------------------------------------------------- +! Description: +! Read the JULES_INFERNO namelist (standalone) +! +! Code Owner: Please refer to ModuleLeaders.txt +! This file belongs in TECHNICAL +!----------------------------------------------------------------------------- + +USE io_constants, ONLY: namelist_unit + +USE string_utils_mod, ONLY: to_string + +USE logging_mod, ONLY: log_info, log_fatal + +USE errormessagelength_mod, ONLY: errormessagelength + +IMPLICIT NONE + +! Arguments +CHARACTER(LEN=*), INTENT(IN) :: nml_dir ! The directory containing the + ! namelists + +INTEGER :: ERROR ! Error indicator +CHARACTER(LEN=errormessagelength) :: iomessage + +! Open the fire namelist file +OPEN(namelist_unit, FILE=(TRIM(nml_dir) // '/' // 'fire.nml'), & + STATUS='old', POSITION='rewind', ACTION='read', IOSTAT = ERROR, & + IOMSG = iomessage) +IF ( ERROR /= 0 ) & + CALL log_fatal("init_inferno", "Error opening namelist file fire.nml " // & + "Error opening namelist file inferno.nml " // & + "(IOSTAT=" // TRIM(to_string(ERROR)) // " IOMSG=" // & + TRIM(iomessage) // ")") + +! There is one namelist to read from this file for jules inferno +CALL log_info("init_inferno", "Reading JULES_INFERNO namelist...") +READ(namelist_unit, NML = jules_inferno, IOSTAT = ERROR, IOMSG = iomessage) +IF ( ERROR /= 0 ) & + CALL log_fatal("init_inferno", & + "Error reading namelist JULES_INFERNO " // & + "(IOSTAT=" // TRIM(to_string(ERROR)) // " IOMSG=" // & + TRIM(iomessage) // ")") + +! Close the namelist file +CLOSE(namelist_unit, IOSTAT = ERROR, IOMSG = iomessage) +IF ( ERROR /= 0 ) & + CALL log_fatal("init_inferno", & + "Error closing namelist file fire.nml " // & + "(IOSTAT=" // TRIM(to_string(ERROR)) // " IOMSG=" // & + TRIM(iomessage) // ")") + +END SUBROUTINE read_nml_jules_inferno +#endif + END MODULE jules_inferno_mod diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index 0c964877..aa4f0ef8 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -276,7 +276,7 @@ SUBROUTINE check_jules_soil_biogeochem() ! imported scalars l_triffid, l_nitrogen -USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire +USE jules_inferno_mod, ONLY: l_trif_fire USE ereport_mod, ONLY: ereport @@ -859,7 +859,7 @@ SUBROUTINE read_nml_jules_soil_biogeochem (unitnumber) ! set number of each type of variable in my_namelist type INTEGER, PARAMETER :: no_of_types = 3 INTEGER, PARAMETER :: n_int = 3 -INTEGER, PARAMETER :: n_real = 30 + 4 +INTEGER, PARAMETER :: n_real = 29 + 4 INTEGER, PARAMETER :: n_log = 8 TYPE :: my_namelist diff --git a/src/initialisation/standalone/init_inferno_mod.F90 b/src/initialisation/standalone/init_inferno_mod.F90 index 88240ff9..f3b9e883 100644 --- a/src/initialisation/standalone/init_inferno_mod.F90 +++ b/src/initialisation/standalone/init_inferno_mod.F90 @@ -4,15 +4,25 @@ ! For further details please refer to the file COPYRIGHT.txt ! which you should have received as part of this distribution. ! *****************************COPYRIGHT************************************** + MODULE init_inferno_mod IMPLICIT NONE CONTAINS +SUBROUTINE init_inferno(nml_dir) + +USE jules_inferno_mod, ONLY: read_nml_jules_inferno, & + print_nlist_jules_inferno, & + check_jules_inferno, & + l_inferno, l_trif_fire + +IMPLICIT NONE + !----------------------------------------------------------------------------- ! Description: -! Reads in the inferno fire namelist items and checks them for consistency +! Initialises the inferno fire model parameters and properties ! ! Code Owner: Please refer to ModuleLeaders.txt ! This file belongs in TECHNICAL @@ -21,117 +31,17 @@ MODULE init_inferno_mod ! Language: Fortran 90. ! This code is written to JULES coding standards v1. !----------------------------------------------------------------------------- -SUBROUTINE init_inferno(nml_dir) - -USE jules_inferno_mod, ONLY: print_nlist_jules_inferno, check_jules_inferno, & - l_inferno, l_trif_fire, flam_sm_up, flam_sm_low, flam_sm_func, flam_rhum_up, & - flam_rhum_low, flam_fuel_up, flam_fuel_low, flam_rain_const, & - triffire_ccdpm_max, triffire_ccdpm_min, triffire_ccrpm_max, & - triffire_ccrpm_min, z_burn_max, ignition_method, ignition_constant, & - ignition_vary_natural, ignition_vary_natural_human - -USE io_constants, ONLY: namelist_unit - -USE string_utils_mod, ONLY: to_string - -USE logging_mod, ONLY: log_info,log_fatal - -USE fire_mod, ONLY: fire_cntl, l_fire_weather_index - -USE fire_allocate_mod,ONLY: fire_allocate - -USE fire_init_mod, ONLY: fire_init - -USE metstats_mod, ONLY: l_metstats - - -IMPLICIT NONE -! Arguments CHARACTER(LEN=*), INTENT(IN) :: nml_dir ! The directory containing the ! namelists -INTEGER :: ERROR ! Error indicators - -CHARACTER(LEN=*), PARAMETER :: RoutineName='INIT_INFERNO' - -!----------------------------------------------------------------------------- -! Definition of the jules_inferno namelist -!----------------------------------------------------------------------------- -NAMELIST / jules_inferno/ & - l_trif_fire, & - l_inferno, & - ignition_method, & - flam_sm_low, & - flam_sm_up, & - flam_sm_func, & - flam_rhum_low, & - flam_rhum_up, & - flam_rain_const, & - flam_fuel_low, & - flam_fuel_up, & - triffire_ccdpm_min, & - triffire_ccdpm_max, & - triffire_ccrpm_min, & - triffire_ccrpm_max, & - z_burn_max -!----------------------------------------------------------------------------- - -!----------------------------------------------------------------------------- -! Read the namelist -!----------------------------------------------------------------------------- - -! Open the fire namelist file -OPEN(namelist_unit, FILE=(TRIM(nml_dir) // '/' // 'fire.nml'), & - STATUS='old', POSITION='rewind', ACTION='read', IOSTAT = ERROR) -IF ( ERROR /= 0 ) & - CALL log_fatal(RoutineName, "Error opening namelist file fire.nml " // & - "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") - - -! There is one namelist to read from this file for jules inferno -CALL log_info(RoutineName, "Reading JULES_INFERNO namelist...") -READ(namelist_unit, NML = jules_inferno, IOSTAT = ERROR) -IF ( ERROR /= 0 ) & - CALL log_fatal(RoutineName, & - "Error reading namelist jules_inferno " // & - "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") - -! Close the namelist file -CLOSE(namelist_unit, IOSTAT = ERROR) -IF ( ERROR /= 0 ) & - CALL log_fatal(RoutineName, & - "Error closing namelist file fire.nml " // & - "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") - -! CALL check_jules_inferno() +CALL read_nml_jules_inferno(nml_dir) CALL print_nlist_jules_inferno() -! If not running inferno, we can bail after namelist has been read. -IF ( .NOT. l_inferno ) RETURN - - -!----------------------------------------------------------------------------- -! Print some human friendly summary information about the selected options -! does this ahve to be ehrer? -!----------------------------------------------------------------------------- - -IF ( l_inferno ) THEN - CALL log_info(RoutineName, & - "Interactive fires and emissions (INFERNO) will be diagnosed") - IF (ignition_method == ignition_constant ) THEN - CALL log_info(RoutineName, & - "Constant or ubiquitous ignitions (INFERNO)") - ELSE IF (ignition_method == ignition_vary_natural ) THEN - CALL log_info(RoutineName, & - "Constant human ignitions, varying lightning (INFERNO)") - ELSE IF (ignition_method == ignition_vary_natural_human ) THEN - CALL log_info(RoutineName, & - "Fully prescribed ignitions (INFERNO)") - END IF -END IF +IF ( .NOT. l_inferno .AND. .NOT. l_trif_fire ) RETURN +CALL check_jules_inferno() RETURN diff --git a/src/science/vegetation/soilcarb_jls.F90 b/src/science/vegetation/soilcarb_jls.F90 index 0812fd2c..d33e9224 100644 --- a/src/science/vegetation/soilcarb_jls.F90 +++ b/src/science/vegetation/soilcarb_jls.F90 @@ -45,8 +45,8 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & USE jules_soil_mod, ONLY: cs_min, sm_levels USE ancil_info, ONLY: dim_cslayer, nsoilt, dim_cs1 -USE jules_inferno_mod, ONLY: l_trif_fire, triffire_ccdpm_min, triffire_ccdpm_max, & - triffire_ccrpm_min, triffire_ccrpm_max +USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & + triffire_ccrpm_min, triffire_ccrpm_max, l_trif_fire USE dpm_rpm_mod, ONLY: dpm_rpm USE decay_mod, ONLY: decay diff --git a/src/science/vegetation/soilcarb_layers_jls_mod.F90 b/src/science/vegetation/soilcarb_layers_jls_mod.F90 index 272f88f4..ac7d019c 100644 --- a/src/science/vegetation/soilcarb_layers_jls_mod.F90 +++ b/src/science/vegetation/soilcarb_layers_jls_mod.F90 @@ -38,18 +38,17 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & USE jules_surface_types_mod, ONLY: npft USE jules_soil_biogeochem_mod, ONLY: bio_hum_cn, tau_lit, l_label_frac_cs -USE jules_inferno_mod, ONLY: z_burn_max USE soilcarb_tracer_age_mod, ONLY: soilcarb_tracer_age USE jules_vegetation_mod, ONLY: l_nitrogen USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & - triffire_ccrpm_min, triffire_ccrpm_max + triffire_ccrpm_min, triffire_ccrpm_max, z_burn_max, & + l_trif_fire USE jules_soil_mod, ONLY: cs_min, dzsoil, sm_levels USE veg_param, ONLY: litc_norm USE pftparm, ONLY: rootd_ft USE ancil_info, ONLY: dim_cslayer, nsoilt, dim_cs1 -USE jules_inferno_mod, ONLY: l_trif_fire USE root_frac_mod, ONLY: root_frac USE soilcarb_mix_mod, ONLY: soilcarb_mix USE dpm_rpm_mod, ONLY: dpm_rpm From f013d0561616025afe3ab8dc02aafccd1cded518 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Thu, 27 Aug 2026 07:08:38 +0100 Subject: [PATCH 05/20] adding replacement for fire_ratio --- doc/source/namelists/fire.nml.rst | 100 ++++--- doc/source/namelists/pft_params.nml.rst | 14 + .../jules-inferno/HEAD/rose-meta.conf | 187 ++++++------ .../jules-pftparm/HEAD/rose-meta.conf | 13 + .../jules-vegetation/HEAD/rose-meta.conf | 1 - rose-meta/jules-standalone/versions.py | 19 +- src/control/shared/jules_inferno_mod.F90 | 278 ++++++++---------- .../shared/jules_soil_biogeochem_mod.F90 | 12 +- .../standalone/init_inferno_mod.F90 | 31 +- src/science/fire/inferno_mod.F90 | 31 +- src/science/params/pftparm_io_mod.F90 | 9 +- src/science/params/pftparm_mod.F90 | 12 +- src/science/vegetation/soilcarb_jls.F90 | 12 +- .../vegetation/soilcarb_layers_jls_mod.F90 | 12 +- src/science/vegetation/triffid_jls.F90 | 7 +- 15 files changed, 407 insertions(+), 331 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index 7c8aa5fe..eab02478 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -113,89 +113,91 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` FALSE Burnt area is zero unless prescribed via an ancillary file. - .. nml:member:: z_burn_max +.. nml:member:: z_burn_max - :type: real - :default: 0.2 + :type: real + :default: 0.2 + + Parameter controlling the depth to which fire burns soil litter carbon in metres. At depths shallower than this value, the fire can burn soil carbon in the two litter pools (dpm and rpm). If z_burn_max falls within a layer only a proportion of the soil carbon is burnt. Only used with layered soil carbon scheme (:nml:mem:`JULES_SOIL_BIOGEOCHEM::l_layeredc` = TRUE) and fire (either :nml:mem:`JULES_INFERNO::l_trif_fire` or :nml:mem:`JULES_INFERNO::l_inferno` or both). In reality the burn depth varies so please check whether the default value of 0.2 is suitable for your application. - Parameter controlling the depth to which fire burns soil litter carbon in metres. At depths shallower than this value, the fire can burn soil carbon in the two litter pools (dpm and rpm). If z_burn_max falls within a layer only a proportion of the soil carbon is burnt. Only used with layered soil carbon scheme (:nml:mem:`JULES_SOIL_BIOGEOCHEM::l_layeredc` = TRUE) and fire (either :nml:mem:`JULES_INFERNO::l_trif_fire` or :nml:mem:`JULES_INFERNO::l_inferno` or both). In reality the burn depth varies so please check whether the default value of 0.2 is suitable for your application. +.. nml:member:: flam_sm_func + + :type: integer + :permitted: 1, 2 + :default: 1 - .. nml:member:: flam_sm_func + Switch used to define the function used to parameterise the relationship between soil moisture and flammability - :type: integer - :permitted: 1, 2 - :default: 1 + 1. A linear relationship which has a flammability of 0 at saturation and 1 when soil is completely dry. - Parameter controlling the relationship between soil moisture and flammability. - 1 a linear relatonship which has a flammability of 0 at 1 and 1 at 0. - 2 an exponential relationship controlled by :nml:mem:`flam_sm_low` and :nml:mem:`flam_sm_up` + 2. An exponential relationship controlled by :nml:mem:`flam_sm_low` and :nml:mem:`flam_sm_up` .. nml:member:: flam_sm_low - :type: real - :default: 0.0 + :type: real + :default: 0.0 - Only used if :nml:mem:`flam_sm_func` = 2. + Soil moisture below which flammability is 1.0. Expressed as a fraction of saturation. Only used if :nml:mem:`flam_sm_func` = 2. - .. nml:member:: flam_sm_up +.. nml:member:: flam_sm_up - :type: real - :default: 2.4 + :type: real + :default: 2.4 - Only used if :nml:mem:`flam_sm_func` = 2. + Exponential decay parameter for relationship between soil moisture and flammability. Only used if :nml:mem:`flam_sm_func` = 2. - .. nml:member:: flam_rhum_low +.. nml:member:: flam_rhum_low - :type: real - :default: 0.1 + :type: real + :default: 10.0 - .. nml:member:: flam_rhum_up +.. nml:member:: flam_rhum_up - :type: real - :default: 0.9 + :type: real + :default: 90.0 - .. nml:member:: flam_rain_const +.. nml:member:: flam_rain_const - :type: real - :default: -14929920000.0 + :type: real + :default: -14929920000.0 buggy - .. nml:member:: flam_fuel_low +.. nml:member:: flam_fuel_low - :type: real - :default: 0.02 + :type: real + :default: 0.02 - .. nml:member:: flam_fuel_up - :type: real - :default: 0.2 +.. nml:member:: flam_fuel_up + :type: real + :default: 0.2 - .. nml:member:: triffire_ccdpm_min +.. nml:member:: ccdpm_min - :type: real - :default: 0.8 + :type: real + :default: 0.8 - Minimum DPM soil carbon pool combustion completness fraction. + Minimum DPM soil carbon pool combustion completness fraction. - .. nml:member:: triffire_ccdpm_max +.. nml:member:: ccdpm_max - :type: real - :default: 1.0 + :type: real + :default: 1.0 - Maximum DPM soil carbon pool combustion completness fraction. + Maximum DPM soil carbon pool combustion completness fraction. - .. nml:member:: triffire_ccrpm_min +.. nml:member:: ccrpm_min - :type: real - :default: 0.0 + :type: real + :default: 0.0 - Minimum RPM soil carbon pool combustion completness fraction. + Minimum RPM soil carbon pool combustion completness fraction. - .. nml:member:: triffire_ccrpm_max +.. nml:member:: ccrpm_max - :type: real - :default: 0.2 + :type: real + :default: 0.2 - Maximum RPM soil carbon pool combustion completness fraction. + Maximum RPM soil carbon pool combustion completness fraction. diff --git a/doc/source/namelists/pft_params.nml.rst b/doc/source/namelists/pft_params.nml.rst index 4219bf84..d596cc57 100644 --- a/doc/source/namelists/pft_params.nml.rst +++ b/doc/source/namelists/pft_params.nml.rst @@ -936,6 +936,20 @@ ease the direct links to these documents are: land surfaces with radiation for relating remote sensing products to climate models, J. Geophys. Res., 111, D02116, https://doi.org/10.1029/2005JD005952. +.. nml:member:: fireveg_c_to_atmos + + :type: real(npft) + :default: None + + Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. + Based on mean whole-plant mortality factor from Li et al (2012) table 2. + + .. seealso:: + References: + + * Li, F., Zeng, X. D., and Levis, S.: A process-based fire parameterization + of intermediate complexity in a Dynamic Global Vegetation Model, Biogeosciences, + 9, 2761-2780, https://doi.org/10.5194/bg-9-2761-2012, 2012. .. nml:group:: Only used with the Farquhar model of leaf photosynthesis (:nml:mem:`JULES_VEGETATION::photo_model` = 2). A value is required for each PFT, but only those for C\ :sub:`3` plants are used (since only C\ :sub:`3` plants use the Farquhar model). Below, J\ :sub:`max` is the potential rate of electron transport, and V\ :sub:`cmax` is the maximum rate of carboxylation of Rubisco. diff --git a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index 62dc7f0c..99a44e5f 100644 --- a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -6,12 +6,87 @@ sort-key=Section-A12p title=Fire options url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html +[namelist:jules_inferno=flam_fuel_low] +compulsory=true +description=Lower fuel load threshold for flammability +range=0.0: +sort-key=Panel-J12 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_low + +[namelist:jules_inferno=flam_fuel_up] +compulsory=true +description=Upper fuel load threshold for flammability +range=0.0: +sort-key=Panel-J13 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_up + +[namelist:jules_inferno=flam_rain_const] +compulsory=true +description=Rainfall flammability scaling constant +sort-key=Panel-J14 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rain_const + +[namelist:jules_inferno=flam_rhum_low] +compulsory=true +description=Lower relative humidity threshold for flammability +range=0.0:100.0 +sort-key=Panel-J09 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_low + +[namelist:jules_inferno=flam_rhum_up] +compulsory=true +description=Upper relative humidity threshold for flammability +range=0.0:100.0 +sort-key=Panel-J10 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_up + +[namelist:jules_inferno=flam_sm_func] +compulsory=true +description=Lower soil moisture threshold for flammability +range=0.0:1.0 +sort-key=Panel-J11a +trigger=namelist:jules_inferno=flam_sm_low: 2; + =namelist:jules_inferno=flam_sm_up: 2; + =[namelist:jules_inferno=flam_sm_low] +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_low +value-titles=(1) linear, + =(2) exponential +values=1,2 + +[namelist:jules_inferno=flam_sm_up] +compulsory=true +description=Upper soil moisture threshold for flammability +range=0.0:10.0 +sort-key=Panel-J11b +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_up + +[namelist:jules_inferno=ignition_method] +compulsory=true +description=The method to use for ignitions +sort-key=Panel-J03 +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ignition_method +value-titles=(1) constant human and natural ignition sources, + =(2) constant human varying natural ignition sources, + =(3) varying human and natural ignition sources +values=1,2,3 + [namelist:jules_inferno=l_inferno] compulsory=true description=Use the INFERNO interactive fire and diagnostic emissions model sort-key=Panel-J01 trigger=namelist:jules_inferno=ignition_method: .true.; =namelist:jules_inferno=l_trif_fire: .true.; + =namelist:jules_inferno=ccdpm_min: .true.; + =namelist:jules_inferno=ccdpm_max: .true.; + =namelist:jules_inferno=ccrpm_min: .true.; + =namelist:jules_inferno=ccrpm_max: .true.; =namelist:jules_pftparm=avg_ba_io: .true.; =namelist:jules_pftparm=ccleaf_min_io: .true.; =namelist:jules_pftparm=ccleaf_max_io: .true.; @@ -40,120 +115,46 @@ description=Use interactive fire linked to INFERNO including interactive fire em fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); sort-key=Panel-J02 trigger=namelist:jules_pftparm=fire_mort_io: .true. + =namelist:jules_pftparm=ffire_veg_io: .true. type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_trif_fire -[namelist:jules_inferno=ignition_method] -compulsory=true -description=The method to use for ignitions -sort-key=Panel-J02 -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ignition_method -value-titles=(1) constant human and natural ignition sources, - =(2) constant human varying natural ignition sources, - =(3) varying human and natural ignition sources -values=1,2,3 -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ignition_method - -[namelist:jules_inferno=z_burn_max] -compulsory=true -description=Maximum burn depth for soil - soil carbon is burned above this level -range=0.0:10.0 -sort-key=Panel-J02 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::z_burn_max - -[namelist:jules_inferno=triffire_ccdpm_min] -compulsory=true -description=Minimum fraction of DPM consumed by fire -range=0.0:1.0 -sort-key=b3 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccdpm_min - -[namelist:jules_inferno=triffire_ccdpm_max] +[namelist:jules_inferno=ccdpm_max] compulsory=true description=Maximum fraction of DPM consumed by fire range=0.0:1.0 -sort-key=Panel-J02 +sort-key=Panel-J06 type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccdpm_max +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccdpm_max -[namelist:jules_inferno=triffire_ccrpm_min] +[namelist:jules_inferno=ccdpm_min] compulsory=true -description=Minimum fraction of RPM consumed by fire +description=Minimum fraction of DPM consumed by fire range=0.0:1.0 -sort-key=Panel-J02 +sort-key=Panel-J05 type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccrpm_min +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccdpm_min -[namelist:jules_inferno=triffire_ccrpm_max] +[namelist:jules_inferno=ccrpm_max] compulsory=true description=Maximum fraction of RPM consumed by fire range=0.0:1.0 -sort-key=Panel-J02 +sort-key=Panel-J08 type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::triffire_ccrpm_max +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccrpm_max -[namelist:jules_inferno=flam_rhum_low] +[namelist:jules_inferno=ccrpm_min] compulsory=true -description=Lower relative humidity threshold for flammability -range=0.0:1.0 -sort-key=Panel-J02 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_low - -[namelist:jules_inferno=flam_rhum_up] -compulsory=true -description=Upper relative humidity threshold for flammability -range=0.0:1.0 -sort-key=Panel-J02 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rhum_up - -[namelist:jules_inferno=flam_sm_low] -compulsory=true -description=Lower soil moisture threshold for flammability +description=Minimum fraction of RPM consumed by fire range=0.0:1.0 -sort-key=Panel-J02 +sort-key=Panel-J07 type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_low +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccrpm_min -[namelist:jules_inferno=flam_sm_up] +[namelist:jules_inferno=z_burn_max] compulsory=true -description=Upper soil moisture threshold for flammability +description=Maximum burn depth for soil - soil carbon is burned above this level range=0.0:10.0 -sort-key=Panel-J02 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_up - -[namelist:jules_inferno=flam_fuel_low] -compulsory=true -description=Lower fuel load threshold for flammability -range=0.0:1.0 -sort-key=Panel-J02 +sort-key=Panel-J04 type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_low - -[namelist:jules_inferno=flam_fuel_up] -compulsory=true -description=Upper fuel load threshold for flammability -range=0.0:1.0 -sort-key=Panel-J02 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_up - -[namelist:jules_inferno=flam_rain_const] -compulsory=true -description=Rainfall flammability scaling constant -sort-key=Panel-J02 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rain_const - -[namelist:jules_inferno=flam_sm_func] -compulsory=true -description=Soil moisture flammability function selector -sort-key=Panel-J02 -value-titles=(1) linear, - =(2) exponential -values=1,2 -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_func +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::z_burn_max diff --git a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf index cb18e53a..785af417 100644 --- a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf @@ -99,6 +99,8 @@ sort-key=Panel-HR03 type=real url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES_PFTPARM::albsnf_maxl_io + + [namelist:jules_pftparm=albsnf_maxu_io] compulsory=true description=Upper limit on albsnf_max_io @@ -590,6 +592,17 @@ sort-key=Panel-HO16 type=real url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES_PFTPARM::fire_mort_io +[namelist:jules_pftparm=fireveg_c_to_atmos_io] +compulsory=true +description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. Based on mean whole-plant mortality factor from Li et al (2012) table 2. +fail-if=len(this) != namelist:jules_surface_types=npft +ns=namelist/JULES Science Settings/jules_pftparm/Other parameters +range=0:1 +sort-key=Panel-HO16 +type=real +url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES_PFTPARM::fireveg_c_to_atmos_io + + [namelist:jules_pftparm=fl_o3_ct_io] compulsory=true fail-if=len(this) != namelist:jules_surface_types=npft diff --git a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf index 9d386e24..627c159f 100644 --- a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf @@ -30,7 +30,6 @@ trigger=namelist:jules_pftparm=ief_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_bvoc_emis - [namelist:jules_vegetation=l_limit_canhc] compulsory=true description=Logical for capping vegetation canopy areal thermal heat capacity diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 7a815569..823fc951 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -90,10 +90,10 @@ def upgrade(self, config, meta_config=None): ["namelist:jules_inferno", "z_burn_max"], z_burn_max) self.remove_setting(config, ["namelist:jules_soil_biogeochem", "z_burn_max"]) - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_min"], "0.8") - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccdpm_max"], "1.0") - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_min"], "0.0") - self.add_setting(config, ["namelist:jules_inferno", "triffire_ccrpm_max"], "0.2") + self.add_setting(config, ["namelist:jules_inferno", "ccdpm_min"], "0.8") + self.add_setting(config, ["namelist:jules_inferno", "ccdpm_max"], "1.0") + self.add_setting(config, ["namelist:jules_inferno", "ccrpm_min"], "0.0") + self.add_setting(config, ["namelist:jules_inferno", "ccrpm_max"], "0.2") self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_low"], "0.1") self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_up"], "0.9") @@ -104,4 +104,15 @@ def upgrade(self, config, meta_config=None): self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], "-14929920000.0") self.add_setting(config, ["namelist:jules_inferno", "flam_sm_func"], "1") + npft = int( + self.get_setting_value(config, ["namelist:jules_surface_types", "npft"]) + ) + self.add_setting( + config, + ["namelist:jules_pftparm", "fireveg_c_to_atmos_io"], + ",".join(["0.13"] * npft), + False, + ) + + return config, self.reports diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index 8237c4f3..3627f409 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -41,35 +41,36 @@ MODULE jules_inferno_mod ! Varying (Lightning - see Pechony & Shindell,2009) ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony & Shindell,2009) flam_sm_func = 1 - ! Switch for the calculation method of INFERNO fire flammability - ! FLAM_SM_FUNC=1:Linear (old - doesnt require flam_sm_low / flam_sm_up) - ! FLAM_SM_FUNC=2:Exponential (newer) + ! Switch for relationship between INFERNO fire + ! flammability and soil moisture + ! FLAM_SM_FUNC=1:Linear (doesnt require flam_sm_low / flam_sm_up) + ! FLAM_SM_FUNC=2:Exponential REAL(KIND=real_jlslsm) :: & flam_sm_low = rmdi, & - ! Lower boundary to soil moisture for flammability calc (flam_sm_func=2) - ! UNITS + ! Below this soil moisture, flammability is 1.0 (flam_sm_func=2) + ! Expressed as a fraction of saturation (between 0 and 1) flam_sm_up = rmdi, & - ! Upper boundary to soil moisture for flammability calc (flam_sm_func=2) - ! UNITS + ! Exponential decay parameter for relationship between soil moisture + ! and flammability (flam_sm_func=2) flam_rhum_low = rmdi, & ! Lower boundary to the relative humidity (%, between 0 and 100 %) flam_rhum_up = rmdi, & - ! Lower boundary to the relative humidity (%, between 0 and 100 %) + ! Upper boundary to the relative humidity (%, between 0 and 100 %) flam_rain_const = rmdi, & ! Precipitation factor (-2(day/mm)*(kg/m2/s)) flam_fuel_low = rmdi, & ! Lower boundary to the fuel density (UNITS) flam_fuel_up = rmdi, & ! Upper boundary to the fuel density (UNITS) - triffire_ccdpm_min = rmdi, & + ccdpm_min = rmdi, & ! Minimum decomposable plant material burn fraction (0 <= fraction <= 1) - triffire_ccdpm_max = rmdi, & + ccdpm_max = rmdi, & ! Decomposable Plant Material burn fraction (0 <= fraction <= 1) - triffire_ccrpm_min = rmdi, & + ccrpm_min = rmdi, & ! Minimum resistant plant material urn fraction (0 <= fraction <= 1) - triffire_ccrpm_max = rmdi, & + ccrpm_max = rmdi, & ! Resistant Plant Material burn fraction (0 <= fraction <= 1) z_burn_max = rmdi ! Parameter setting maximum depth of burn (m) @@ -85,8 +86,7 @@ MODULE jules_inferno_mod l_trif_fire, l_inferno, ignition_method, flam_sm_func, & flam_sm_low, flam_sm_up, flam_rhum_low, flam_rhum_up, & flam_rain_const, flam_fuel_low, flam_fuel_up, & - triffire_ccdpm_min,triffire_ccdpm_max, triffire_ccrpm_min, & - triffire_ccrpm_max, z_burn_max + ccdpm_min, ccdpm_max, ccrpm_min, ccrpm_max, z_burn_max CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='JULES_INFERNO_MOD' @@ -116,157 +116,123 @@ SUBROUTINE check_jules_inferno() CHARACTER(LEN=*), PARAMETER :: RoutineName='CHECK_JULES_INFERNO' -!ejb delete USE jules_surface_types_mod, ONLY: npft -!ejb delete USE jules_soil_biogeochem_mod, ONLY: l_layeredc !ejb check that it is set or move this trap - -! Check options that depend on TRIFFID if it is not enabled -!if l_triffie - -IF ( .NOT. l_inferno .AND. .NOT. l_trif_fire ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "l_inferno needs to be specified if l_trif_fire is true.") -END IF - -IF ( ABS(flam_sm_low - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_sm_low needs to be specified.") -ELSE IF ( flam_sm_low < 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_sm_low must be >= 0.0.") -END IF - -IF ( ABS(flam_sm_up - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_sm_up needs to be specified.") -ELSE IF ( flam_sm_up < flam_sm_low ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_sm_up must be >= flam_sm_low") -ELSE IF ( flam_sm_up > 10.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_sm_up must be <= 10.0.") -END IF - IF ( l_inferno ) THEN - CALL log_info(RoutineName, & - "Interactive fires and emissions (INFERNO) will be diagnosed") - IF (ignition_method == ignition_constant ) THEN - CALL log_info(RoutineName, & - "Constant or ubiquitous ignitions (INFERNO)") - ELSE IF (ignition_method == ignition_vary_natural ) THEN - CALL log_info(RoutineName, & - "Constant human ignitions, varying lightning (INFERNO)") - ELSE IF (ignition_method == ignition_vary_natural_human ) THEN - CALL log_info(RoutineName, & - "Fully prescribed ignitions (INFERNO)") + ! Check a suitable ignition_method was given + IF ( ignition_method /= ignition_constant .AND. & + ignition_method /= ignition_vary_natural .AND. & + ignition_method /= ignition_vary_natural_human ) THEN + errorstatus = 101 + CALL ereport("check_jules_vegetation", errorstatus, & + 'ignition_method must be 1, 2 or 3') END IF -END IF -IF ( ABS(flam_rhum_low - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rhum_low needs to be specified.") -ELSE IF ( flam_rhum_low < 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rhum_low must be >= 0.0.") -END IF + IF ( flam_sm_func == 2 ) THEN + IF ( ABS(flam_sm_low - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_low needs to be specified.") + ELSE IF ( flam_sm_low < 0.0 .OR. flam_sm_low > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_low must be >= 0.0 and <= 1.0.") + END IF + + IF ( ABS(flam_sm_up - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_up needs to be specified.") + ELSE IF ( flam_sm_up < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_sm_up must be >= 0.0") + END IF + END IF -IF ( ABS(flam_rhum_up - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rhum_up needs to be specified.") -ELSE IF ( flam_rhum_up < flam_rhum_low ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rhum_up must be >= flam_rhum_low") -ELSE IF ( flam_rhum_up > 1.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rhum_up must be <= 1.0.") -END IF + IF ( ABS(flam_rhum_low - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_low needs to be specified.") + ELSE IF ( flam_rhum_low < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_low must be >= 0.0.") + END IF -IF ( ABS(flam_fuel_low - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_fuel_low needs to be specified.") -ELSE IF ( flam_fuel_low < 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_fuel_low must be >= 0.0.") -END IF + IF ( ABS(flam_rhum_up - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_up needs to be specified.") + ELSE IF ( flam_rhum_up <= flam_rhum_low ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_up must be >= flam_rhum_low") + ELSE IF ( flam_rhum_up > 100.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rhum_up must be <= 100.0.") + END IF -IF ( ABS(flam_fuel_up - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_fuel_up needs to be specified.") -ELSE IF ( flam_fuel_up < flam_fuel_low ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_fuel_up must be >= flam_fuel_low") -ELSE IF ( flam_fuel_up > 1.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_fuel_up must be <= 1.0.") -END IF + IF ( ABS(flam_fuel_low - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_low needs to be specified.") + ELSE IF ( flam_fuel_low < 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_low must be >= 0.0.") + END IF -IF ( ABS(flam_rain_const - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rain_const needs to be specified.") -ELSE IF ( flam_rain_const > 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rain_const must be <= 0.0.") -END IF + IF ( ABS(flam_fuel_up - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_up needs to be specified.") + ELSE IF ( flam_fuel_up < flam_fuel_low ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_up must be >= flam_fuel_low") + ELSE IF ( flam_fuel_up > 1.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_fuel_up must be <= 1.0.") + END IF + + IF ( ABS(flam_rain_const - rmdi) < EPSILON(rmdi) ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rain_const needs to be specified.") + ELSE IF ( flam_rain_const > 0.0 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + "flam_rain_const must be <= 0.0.") + END IF +END IF ! end of l_inferno check IF ( l_trif_fire ) THEN - IF ( ABS(triffire_ccdpm_min - rmdi) < EPSILON(rmdi) ) THEN + IF ( ABS(ccdpm_min - rmdi) < EPSILON(rmdi) ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_min needs to be specified.") - ELSE IF ( triffire_ccdpm_min < 0.0 ) THEN + "ccdpm_min needs to be specified.") + ELSE IF ( ccdpm_min < 0.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_min must be >= 0.0.") + "ccdpm_min must be >= 0.0.") END IF - IF ( ABS(triffire_ccdpm_max - rmdi) < EPSILON(rmdi) ) THEN + IF ( ABS(ccdpm_max - rmdi) < EPSILON(rmdi) ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_max needs to be specified.") - ELSE IF ( triffire_ccdpm_max < triffire_ccdpm_min ) THEN + "ccdpm_max needs to be specified.") + ELSE IF ( ccdpm_max < ccdpm_min ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_max must be >= triffire_ccdpm_min") - ELSE IF ( triffire_ccdpm_max > 1.0 ) THEN + "ccdpm_max must be >= ccdpm_min") + ELSE IF ( ccdpm_max > 1.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccdpm_max must be < 1.0.") + "ccdpm_max must be < 1.0.") END IF - IF ( ABS(triffire_ccrpm_min - rmdi) < EPSILON(rmdi) ) THEN + IF ( ABS(ccrpm_min - rmdi) < EPSILON(rmdi) ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_min needs to be specified.") - ELSE IF ( triffire_ccrpm_min < 0.0 ) THEN + "ccrpm_min needs to be specified.") + ELSE IF ( ccrpm_min < 0.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_min must be >= 0.0.") + "ccrpm_min must be >= 0.0.") END IF - IF ( ABS(triffire_ccrpm_max - rmdi) < EPSILON(rmdi) ) THEN + IF ( ABS(ccrpm_max - rmdi) < EPSILON(rmdi) ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_max needs to be specified.") - ELSE IF ( triffire_ccrpm_max < triffire_ccrpm_min ) THEN + "ccrpm_max needs to be specified.") + ELSE IF ( ccrpm_max < ccrpm_min ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_max must be >= triffire_ccrpm_min") - ELSE IF ( triffire_ccrpm_max > 1.0 ) THEN + "ccrpm_max must be >= ccrpm_min") + ELSE IF ( ccrpm_max > 1.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "triffire_ccrpm_max must be < 1.0.") + "ccrpm_max must be < 1.0.") END IF -END IF - -! Check a suitable ignition_method was given -IF ( ignition_method /= ignition_constant .AND. & - ignition_method /= ignition_vary_natural .AND. & - ignition_method /= ignition_vary_natural_human ) THEN - errorstatus = 101 - CALL ereport("check_jules_vegetation", errorstatus, & - 'ignition_method must be 1, 2 or 3') -END IF +END IF ! end of l_trif_fire check -! check value of z_burn_max with l_layeredc -!IF ( l_layeredc ) THEN -!! IF ( ABS( z_burn_max - rmdi ) > EPSILON(1.0) ) THEN - ! IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN - ! CALL ereport(RoutineName, errorstatus, & - ! "z_burn_max must be positive & less than 10 meters") - ! END IF - ! END IF -!END IF END SUBROUTINE check_jules_inferno @@ -294,6 +260,14 @@ SUBROUTINE print_nlist_jules_inferno() WRITE(lineBuffer,*)' ignition_method = ',ignition_method CALL jules_print('jules_inferno_mod',lineBuffer) + IF (ignition_method == ignition_constant ) THEN + WRITE(lineBuffer,*)'Constant or ubiquitous ignitions (l_inferno=T)' + ELSE IF (ignition_method == ignition_vary_natural ) THEN + WRITE(lineBuffer,*)'Constant human ignitions, varying lightning (l_inferno=T)' + ELSE IF (ignition_method == ignition_vary_natural_human ) THEN + WRITE(lineBuffer,*)'Fully prescribed ignitions (l_inferno=T)' + END IF + WRITE(lineBuffer,*)' flam_sm_func = ',flam_sm_func CALL jules_print('jules_inferno_mod',lineBuffer) @@ -320,16 +294,16 @@ SUBROUTINE print_nlist_jules_inferno() END IF IF ( l_trif_fire ) THEN - WRITE(lineBuffer,*)' triffire_ccdpm_min = ',triffire_ccdpm_min + WRITE(lineBuffer,*)' ccdpm_min = ',ccdpm_min CALL jules_print('jules_inferno_mod',lineBuffer) - WRITE(lineBuffer,*)' triffire_ccdpm_max = ',triffire_ccdpm_max + WRITE(lineBuffer,*)' ccdpm_max = ',ccdpm_max CALL jules_print('jules_inferno_mod',lineBuffer) - WRITE(lineBuffer,*)' triffire_ccrpm_min = ',triffire_ccrpm_min + WRITE(lineBuffer,*)' ccrpm_min = ',ccrpm_min CALL jules_print('jules_inferno_mod',lineBuffer) - WRITE(lineBuffer,*)' triffire_ccrpm_max = ',triffire_ccrpm_max + WRITE(lineBuffer,*)' ccrpm_max = ',ccrpm_max CALL jules_print('jules_inferno_mod',lineBuffer) WRITE(lineBuffer, *) ' z_burn_max = ', z_burn_max @@ -386,10 +360,10 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) REAL(KIND=real_jlslsm) :: flam_rain_const REAL(KIND=real_jlslsm) :: flam_fuel_low REAL(KIND=real_jlslsm) :: flam_fuel_up - REAL(KIND=real_jlslsm) :: triffire_ccdpm_min - REAL(KIND=real_jlslsm) :: triffire_ccdpm_max - REAL(KIND=real_jlslsm) :: triffire_ccrpm_min - REAL(KIND=real_jlslsm) :: triffire_ccrpm_max + REAL(KIND=real_jlslsm) :: ccdpm_min + REAL(KIND=real_jlslsm) :: ccdpm_max + REAL(KIND=real_jlslsm) :: ccrpm_min + REAL(KIND=real_jlslsm) :: ccrpm_max REAL(KIND=real_jlslsm) :: z_burn_max LOGICAL :: l_trif_fire LOGICAL :: l_inferno @@ -423,10 +397,10 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) my_nml % flam_rain_const = flam_rain_const my_nml % flam_fuel_low = flam_fuel_low my_nml % flam_fuel_up = flam_fuel_up - my_nml % triffire_ccdpm_min = triffire_ccdpm_min - my_nml % triffire_ccdpm_max = triffire_ccdpm_max - my_nml % triffire_ccrpm_min = triffire_ccrpm_min - my_nml % triffire_ccrpm_max = triffire_ccrpm_max + my_nml % ccdpm_min = ccdpm_min + my_nml % ccdpm_max = ccdpm_max + my_nml % ccrpm_min = ccrpm_min + my_nml % ccrpm_max = ccrpm_max my_nml % z_burn_max = z_burn_max END IF @@ -445,10 +419,10 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) flam_rain_const = my_nml % flam_rain_const flam_fuel_low = my_nml % flam_fuel_low flam_fuel_up = my_nml % flam_fuel_up - triffire_ccdpm_min = my_nml % triffire_ccdpm_min - triffire_ccdpm_max = my_nml % triffire_ccdpm_max - triffire_ccrpm_min = my_nml % triffire_ccrpm_min - triffire_ccrpm_max = my_nml % triffire_ccrpm_max + ccdpm_min = my_nml % ccdpm_min + ccdpm_max = my_nml % ccdpm_max + ccrpm_min = my_nml % ccrpm_min + ccrpm_max = my_nml % ccrpm_max z_burn_max = my_nml % z_burn_max END IF diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index aa4f0ef8..99c8bc34 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -276,7 +276,7 @@ SUBROUTINE check_jules_soil_biogeochem() ! imported scalars l_triffid, l_nitrogen -USE jules_inferno_mod, ONLY: l_trif_fire +USE jules_inferno_mod, ONLY: l_trif_fire, l_inferno, z_burn_max USE ereport_mod, ONLY: ereport @@ -520,6 +520,16 @@ SUBROUTINE check_jules_soil_biogeochem() END IF END IF +! check value of z_burn_max with l_layeredc +IF ( ( l_layeredc .AND. l_trif_fire ) .OR. & + ( l_layeredc .AND. l_inferno ) ) THEN + IF ( ABS( z_burn_max - rmdi ) > EPSILON(1.0) ) THEN + IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN + CALL ereport(RoutineName, errorstatus, & + "z_burn_max must be positive & less than 10 meters") + END IF + END IF +END IF ! methane q10's - these are always set IF ( ABS( q10_ch4_cs - rmdi ) < EPSILON(1.0) ) THEN diff --git a/src/initialisation/standalone/init_inferno_mod.F90 b/src/initialisation/standalone/init_inferno_mod.F90 index f3b9e883..c34e23eb 100644 --- a/src/initialisation/standalone/init_inferno_mod.F90 +++ b/src/initialisation/standalone/init_inferno_mod.F90 @@ -16,7 +16,9 @@ SUBROUTINE init_inferno(nml_dir) USE jules_inferno_mod, ONLY: read_nml_jules_inferno, & print_nlist_jules_inferno, & check_jules_inferno, & - l_inferno, l_trif_fire + l_inferno, l_trif_fire, ignition_method + +USE logging_mod, ONLY: log_info IMPLICIT NONE @@ -32,6 +34,10 @@ SUBROUTINE init_inferno(nml_dir) ! This code is written to JULES coding standards v1. !----------------------------------------------------------------------------- +INTEGER, PARAMETER :: ignition_constant = 1 +INTEGER, PARAMETER :: ignition_vary_natural = 2 +INTEGER, PARAMETER :: ignition_vary_natural_human = 3 + CHARACTER(LEN=*), INTENT(IN) :: nml_dir ! The directory containing the ! namelists @@ -43,6 +49,29 @@ SUBROUTINE init_inferno(nml_dir) CALL check_jules_inferno() +!----------------------------------------------------------------------------- +! Print some human friendly summary information about the selected options. +!----------------------------------------------------------------------------- +IF ( l_inferno ) THEN + CALL log_info("init_inferno", & + "Interactive fires and emissions (INFERNO) will be diagnosed") + IF (ignition_method == ignition_constant ) THEN + CALL log_info("init_inferno", & + "Constant or ubiquitous ignitions (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural ) THEN + CALL log_info("init_inferno", & + "Constant human ignitions, varying lightning (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural_human ) THEN + CALL log_info("init_inferno", & + "Fully prescribed ignitions (INFERNO)") + END IF +END IF + +IF ( l_trif_fire ) THEN + CALL log_info("init_inferno", & + "Fires will interact with the carbon cycle in triffid") +END IF + RETURN END SUBROUTINE init_inferno diff --git a/src/science/fire/inferno_mod.F90 b/src/science/fire/inferno_mod.F90 index 78114fff..e5c9e58c 100644 --- a/src/science/fire/inferno_mod.F90 +++ b/src/science/fire/inferno_mod.F90 @@ -205,14 +205,20 @@ SUBROUTINE calc_flam( & flam_rhum_low, & ! Lower boundary to the relative humidity flam_sm_low, & - ! Lower boundary to the soil moisture + ! Below this soil moisture, flammability is 1.0 + ! Expressed as a fraction of saturation (between 0 and 1) (flam_sm_func=2) flam_sm_up, & - ! Upper boundary to the soil moisture + ! Exponential decay parameter for relationship between soil moisture + ! and flammability (> 0.0) (flam_sm_func=2) flam_rain_const ! INTEGER, INTENT(IN) :: & flam_sm_func + ! The function used to parameterise the + ! relationship between soil moisture and flammability + ! 1 = linear, + ! 2 = exponential REAL(KIND=real_jlslsm), INTENT(IN OUT) :: & flam_l @@ -262,7 +268,7 @@ SUBROUTINE calc_flam( & + c * (10.0**( d * (1.0 - TsbyT_l)) - 1.0) & + f * (10.0**( h * (TsbyT_l-1.0)) - 1.0) -f_rhum_l = (flam_rhum_up - rhum_l/100.0) / (flam_rhum_up - flam_rhum_low) +f_rhum_l = (flam_rhum_up - rhum_l) / (flam_rhum_up - flam_rhum_low) ! Create boundary limits ! First for relative humidity @@ -277,11 +283,12 @@ SUBROUTINE calc_flam( & IF (rhum_l > 90.0) f_rhum_l = 0.0 END IF -IF (flam_sm_func == 1) THEN +IF ( flam_sm_func == 1 ) THEN f_sm_l = (1 - sm_l) - ! The flammability goes down linearly with soil moisture -ELSE IF ( flam_sm_func == 2) THEN + ! The flammability goes down linearly with increasing soil moisture +ELSE IF ( flam_sm_func == 2 ) THEN f_sm_l = EXP(-flam_sm_up * (sm_l - flam_sm_low) ) + ! EJB check this bottom bit ! Flammability goes down exponentially with soil moisture END IF IF (f_sm_l < 0.0) THEN @@ -436,8 +443,8 @@ SUBROUTINE calc_emitted_carbon_soil( & ! Language: Fortran 90 ! -USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & - triffire_ccrpm_min, triffire_ccrpm_max +USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & + ccrpm_min, ccrpm_max USE yomhook, ONLY: lhook, dr_hook USE parkind1, ONLY: jprb @@ -470,11 +477,11 @@ SUBROUTINE calc_emitted_carbon_soil( & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) DO l = 1,land_pts - ! emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (triffire_ccdpm_min + & - ! (triffire_ccdpm_max - triffire_ccdpm_min) * & + ! emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (ccdpm_min + & + ! (ccdpm_max - ccdpm_min) * & ! (1.0 - sm(l)))) ,0.0) - ! emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (triffire_ccrpm_min + & - ! (triffire_ccrpm_max - triffire_ccrpm_min) * & + ! emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (ccrpm_min + & + ! (ccrpm_max - ccrpm_min) * & ! (1.0 - sm(l)))) ,0.0) emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (0.8 + & diff --git a/src/science/params/pftparm_io_mod.F90 b/src/science/params/pftparm_io_mod.F90 index c2786e96..ea4f2213 100644 --- a/src/science/params/pftparm_io_mod.F90 +++ b/src/science/params/pftparm_io_mod.F90 @@ -99,6 +99,7 @@ MODULE pftparm_io fef_so2_io(npft_max) = rmdi, & fd_io(npft_max) = rmdi, & fire_mort_io(npft_max) = rmdi, & + fireveg_c_to_atmos_io(npft_max) = rmdi, & fl_o3_ct_io(npft_max) = rmdi, & fsmc_of_io(npft_max) = rmdi, & fsmc_p0_io(npft_max) = rmdi, & @@ -195,7 +196,7 @@ MODULE pftparm_io tlow_io, tupp_io, vint_io, & vsl_io, sug_yg_io, z0hm_pft_io, & z0hm_classic_pft_io, z0v_io, sox_a_io, & - sox_p50_io, sox_rp_min_io + sox_p50_io, sox_rp_min_io, fireveg_c_to_atmos_io CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='PFTPARM_IO' @@ -295,6 +296,7 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) REAL(KIND=real_jlslsm) :: fef_nh3_io(npft_max) REAL(KIND=real_jlslsm) :: fef_dms_io(npft_max) REAL(KIND=real_jlslsm) :: fire_mort_io(npft_max) + REAL(KIND=real_jlslsm) :: fireveg_c_to_atmos_io(npft_max) REAL(KIND=real_jlslsm) :: fl_o3_ct_io(npft_max) REAL(KIND=real_jlslsm) :: fsmc_of_io(npft_max) REAL(KIND=real_jlslsm) :: fsmc_p0_io(npft_max) @@ -422,6 +424,7 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) my_nml % fef_nh3_io = fef_nh3_io my_nml % fef_dms_io = fef_dms_io my_nml % fire_mort_io = fire_mort_io + my_nml % fireveg_c_to_atmos_io = fireveg_c_to_atmos_io my_nml % fl_o3_ct_io = fl_o3_ct_io my_nml % fsmc_of_io = fsmc_of_io my_nml % fsmc_p0_io = fsmc_p0_io @@ -539,6 +542,7 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) fef_nh3_io = my_nml % fef_nh3_io fef_dms_io = my_nml % fef_dms_io fire_mort_io = my_nml % fire_mort_io + fireveg_c_to_atmos_io = my_nml % fireveg_c_to_atmos_io fl_o3_ct_io = my_nml % fl_o3_ct_io fsmc_of_io = my_nml % fsmc_of_io fsmc_p0_io = my_nml % fsmc_p0_io @@ -632,7 +636,7 @@ SUBROUTINE init_pftparm_allocated() fef_oc, fef_so2, fef_c2h4, & fef_c2h6, fef_c3h8, fef_hcho, & fef_mecho, fef_nh3, & - fef_dms, fire_mort, & + fef_dms, fire_mort, fireveg_c_to_atmos, & fl_o3_ct, fsmc_of, fsmc_p0, & sug_g0, g1_stomata, g_leaf_0, & glmin, gpp_st, sug_grec, & @@ -782,6 +786,7 @@ SUBROUTINE init_pftparm_allocated() ccwood_max(:) = ccwood_max_io(1:npft) ccwood_min(:) = ccwood_min_io(1:npft) fire_mort(:) = fire_mort_io(1:npft) +fireveg_c_to_atmos(:) = fireveg_c_to_atmos_io(1:npft) ! INFERNO emission parameters fef_bc(:) = fef_bc_io(1:npft) diff --git a/src/science/params/pftparm_mod.F90 b/src/science/params/pftparm_mod.F90 index 53abcf38..d67e01e5 100644 --- a/src/science/params/pftparm_mod.F90 +++ b/src/science/params/pftparm_mod.F90 @@ -311,8 +311,10 @@ MODULE pftparm ! Wood (or Stem) minimum combustion completeness (kg/kg) ,ccwood_max(:) & ! Wood (or Stem) maximum combustion completeness (kg/kg) -,fire_mort(:) +,fire_mort(:) & ! Fire mortality per PFT +,fireveg_c_to_atmos(:) + ! Burnt vegetation carbon to atmosphere per PFT !----------------------------------------------------------------------------- ! Parameters for INFERNO emissions @@ -601,6 +603,7 @@ SUBROUTINE pftparm_alloc(npft) ALLOCATE( ccwood_min(npft)) ALLOCATE( ccwood_max(npft)) ALLOCATE( fire_mort(npft)) +ALLOCATE( fireveg_c_to_atmos(npft)) avg_ba(:) = rmdi ccleaf_min(:) = rmdi @@ -608,6 +611,7 @@ SUBROUTINE pftparm_alloc(npft) ccwood_min(:) = rmdi ccwood_max(:) = rmdi fire_mort(:) = rmdi +fireveg_c_to_atmos(:) = rmdi ! INFERNO emission parameters ALLOCATE( fef_bc(npft)) @@ -788,6 +792,8 @@ SUBROUTINE print_nlist_jules_pftparm() CALL jules_print('pftparm',lineBuffer) WRITE(lineBuffer,*)' fire_mort = ',fire_mort CALL jules_print('pftparm',lineBuffer) +WRITE(lineBuffer,*)' fireveg_c_to_atmos = ',fireveg_c_to_atmos +CALL jules_print('pftparm',lineBuffer) WRITE(lineBuffer,*)' fl_o3_ct = ',fl_o3_ct CALL jules_print('pftparm',lineBuffer) WRITE(lineBuffer,*)' fsmc_of = ',fsmc_of @@ -1406,6 +1412,10 @@ SUBROUTINE check_jules_pftparm(npft,nnpft) ERROR = 1 CALL jules_print(routinename, "No value for fire_mort") END IF + IF ( ANY( ABS( fireveg_c_to_atmos(:) - rmdi ) < EPSILON(1.0) ) ) THEN + ERROR = 1 + CALL jules_print(routinename, "No value for fireveg_c_to_atmos") + END IF END IF IF ( l_o3_damage ) THEN diff --git a/src/science/vegetation/soilcarb_jls.F90 b/src/science/vegetation/soilcarb_jls.F90 index d33e9224..d0ab6929 100644 --- a/src/science/vegetation/soilcarb_jls.F90 +++ b/src/science/vegetation/soilcarb_jls.F90 @@ -45,8 +45,8 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & USE jules_soil_mod, ONLY: cs_min, sm_levels USE ancil_info, ONLY: dim_cslayer, nsoilt, dim_cs1 -USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & - triffire_ccrpm_min, triffire_ccrpm_max, l_trif_fire +USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & + ccrpm_min, ccrpm_max, l_trif_fire USE dpm_rpm_mod, ONLY: dpm_rpm USE decay_mod, ONLY: decay @@ -348,12 +348,12 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & DO t = 1,trif_pts l = trif_index(t) burnt_carbon_dpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,1) * (triffire_ccdpm_min + & - (triffire_ccdpm_max - triffire_ccdpm_min) & + (cs(l,1,1) * (ccdpm_min + & + (ccdpm_max - ccdpm_min) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) burnt_carbon_rpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,2) * (triffire_ccrpm_min + & - (triffire_ccrpm_max - triffire_ccrpm_min) & + (cs(l,1,2) * (ccrpm_min + & + (ccrpm_max - ccrpm_min) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) burnt_carbon_dpm(l) = MAX(g_burn_gb(l) * & (cs(l,1,1) * (0.8 + & diff --git a/src/science/vegetation/soilcarb_layers_jls_mod.F90 b/src/science/vegetation/soilcarb_layers_jls_mod.F90 index ac7d019c..67db636f 100644 --- a/src/science/vegetation/soilcarb_layers_jls_mod.F90 +++ b/src/science/vegetation/soilcarb_layers_jls_mod.F90 @@ -41,8 +41,8 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & USE soilcarb_tracer_age_mod, ONLY: soilcarb_tracer_age USE jules_vegetation_mod, ONLY: l_nitrogen -USE jules_inferno_mod, ONLY: triffire_ccdpm_min, triffire_ccdpm_max, & - triffire_ccrpm_min, triffire_ccrpm_max, z_burn_max, & +USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & + ccrpm_min, ccrpm_max, z_burn_max, & l_trif_fire USE jules_soil_mod, ONLY: cs_min, dzsoil, sm_levels @@ -512,12 +512,12 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & END IF burnt_carbon_layer_dpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & - (cs(l,n,1) * (triffire_ccdpm_min + & - (triffire_ccdpm_max - triffire_ccdpm_min) & + (cs(l,n,1) * (ccdpm_min + & + (ccdpm_max - ccdpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) burnt_carbon_layer_rpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & - (cs(l,n,2) * (triffire_ccrpm_min + & - (triffire_ccrpm_max - triffire_ccrpm_min) & + (cs(l,n,2) * (ccrpm_min + & + (ccrpm_max - ccrpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) ! Need to introduce a check because it is updated before updating soil C burnt_carbon_layer_dpm(l,n) = MAX(MIN(burnt_carbon_layer_dpm(l,n), & diff --git a/src/science/vegetation/triffid_jls.F90 b/src/science/vegetation/triffid_jls.F90 index 5fcf3a61..896f3e6e 100644 --- a/src/science/vegetation/triffid_jls.F90 +++ b/src/science/vegetation/triffid_jls.F90 @@ -128,7 +128,7 @@ SUBROUTINE triffid (land_pts, trif_pts, trif_index, forw, r_gamma, & USE jules_surface_mod, ONLY: cmass -USE pftparm, ONLY: a_wl, a_ws, b_wl, eta_sl, lma, sigl +USE pftparm, ONLY: a_wl, a_ws, b_wl, eta_sl, lma, sigl, fireveg_c_to_atmos USE trif, ONLY: crop, harvest_freq, harvest_ht, harvest_type, lai_min @@ -404,7 +404,7 @@ SUBROUTINE triffid (land_pts, trif_pts, trif_index, forw, r_gamma, & ! Fraction of litter diverted as harvest. ! This fraction ends up in the product pools instead of in the soil. -REAL(KIND=real_jlslsm), PARAMETER :: fire_ratio = 0.13 +! REAL(KIND=real_jlslsm), PARAMETER :: fire_ratio = 0.13 ! Fraction of burnt carbon that goes to the atmosphere as CO2 instead ! of in the soil. Based on mean whole-plant mortality factor from ! Li et al (2012) table 2. @@ -1169,7 +1169,8 @@ SUBROUTINE triffid (land_pts, trif_pts, trif_index, forw, r_gamma, & lit_n_fire_pft(l,n) = 0.0 END IF - veg_c_fire_emission_pft(l,n) = lit_c_fire_pft(l,n) * fire_ratio + ! veg_c_fire_emission_pft(l,n) = lit_c_fire_pft(l,n) * fire_ratio + veg_c_fire_emission_pft(l,n) = lit_c_fire_pft(l,n) * fireveg_c_to_atmos(n) veg_c_fire_emission_gb(l) = veg_c_fire_emission_gb(l) + & veg_c_fire_emission_pft(l,n) From 120c495fbca0e56e88940b703c5d3c3ad27f07ce Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:11:41 +0100 Subject: [PATCH 06/20] passing tests - still some bits of new code deactivated --- doc/source/namelists/fire.nml.rst | 4 ++ rose-meta/jules-lfric/HEAD/rose-meta.conf | 4 ++ .../jules-inferno/HEAD/rose-meta.conf | 33 ++++++---- .../HEAD/rose-meta.conf | 1 + .../jules-pftparm/HEAD/rose-meta.conf | 2 +- .../jules-standalone/HEAD/rose-meta.conf | 3 + rose-meta/jules-standalone/versions.py | 10 +-- rose-meta/jules-um/HEAD/rose-meta.conf | 4 ++ src/control/shared/jules_inferno_mod.F90 | 40 ++++++------ .../standalone/init_inferno_mod.F90 | 10 +-- src/science/fire/inferno_io_mod.F90 | 14 ++-- src/science/fire/inferno_mod.F90 | 65 ++++++------------- src/science/vegetation/soilcarb_jls.F90 | 14 +--- .../vegetation/soilcarb_layers_jls_mod.F90 | 10 ++- 14 files changed, 100 insertions(+), 114 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index eab02478..e746079f 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -151,11 +151,15 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :type: real :default: 10.0 + Lower relative humidity threshold for relationship between relative humidity and flammability below which value of function is 1.0. Expressed as a percentage. + .. nml:member:: flam_rhum_up :type: real :default: 90.0 + Upper relative humidity threshold for relationship between relative humidity and flammability above which value of function is 0.0. Expressed as a percentage. + .. nml:member:: flam_rain_const :type: real diff --git a/rose-meta/jules-lfric/HEAD/rose-meta.conf b/rose-meta/jules-lfric/HEAD/rose-meta.conf index be744372..8632bc7c 100644 --- a/rose-meta/jules-lfric/HEAD/rose-meta.conf +++ b/rose-meta/jules-lfric/HEAD/rose-meta.conf @@ -295,6 +295,10 @@ fail-if= fail-if= !ns= +[namelist:jules_pftparm=fireveg_c_to_atmos_io] +fail-if= +!ns= + [namelist:jules_pftparm=fl_o3_ct_io] fail-if= !ns= diff --git a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index 99a44e5f..e82be8f4 100644 --- a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -31,7 +31,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_rhum_low] compulsory=true -description=Lower relative humidity threshold for flammability +description=Lower relative humidity threshold for relationship between relative humidity and flammability range=0.0:100.0 sort-key=Panel-J09 type=real @@ -39,7 +39,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_rhum_up] compulsory=true -description=Upper relative humidity threshold for flammability +description=Upper relative humidity threshold for relationship between relative humidity and flammability range=0.0:100.0 sort-key=Panel-J10 type=real @@ -48,23 +48,28 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_sm_func] compulsory=true description=Lower soil moisture threshold for flammability -range=0.0:1.0 -sort-key=Panel-J11a +sort-key=Panel-J11 trigger=namelist:jules_inferno=flam_sm_low: 2; =namelist:jules_inferno=flam_sm_up: 2; - =[namelist:jules_inferno=flam_sm_low] -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_low +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_func value-titles=(1) linear, =(2) exponential values=1,2 -[namelist:jules_inferno=flam_sm_up] +[namelist:jules_inferno=flam_sm_low] compulsory=true -description=Upper soil moisture threshold for flammability +description=Soil moisture below which flammability is 1.0 range=0.0:10.0 sort-key=Panel-J11b type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_low + +[namelist:jules_inferno=flam_sm_up] +compulsory=true +description=Exponential decay parameter for relationship between soil moisture and flammability +range=0.0:10.0 +sort-key=Panel-J11c +type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_up [namelist:jules_inferno=ignition_method] @@ -87,6 +92,12 @@ trigger=namelist:jules_inferno=ignition_method: .true.; =namelist:jules_inferno=ccdpm_max: .true.; =namelist:jules_inferno=ccrpm_min: .true.; =namelist:jules_inferno=ccrpm_max: .true.; + =namelist:jules_inferno=flam_fuel_low: .true.; + =namelist:jules_inferno=flam_fuel_up: .true.; + =namelist:jules_inferno=flam_rhum_low: .true.; + =namelist:jules_inferno=flam_rhum_up: .true.; + =namelist:jules_inferno=flam_sm_func: .true.; + =namelist:jules_inferno=flam_rain_const: .true.; =namelist:jules_pftparm=avg_ba_io: .true.; =namelist:jules_pftparm=ccleaf_min_io: .true.; =namelist:jules_pftparm=ccleaf_max_io: .true.; @@ -114,8 +125,8 @@ compulsory=true description=Use interactive fire linked to INFERNO including interactive fire emissions. fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); sort-key=Panel-J02 -trigger=namelist:jules_pftparm=fire_mort_io: .true. - =namelist:jules_pftparm=ffire_veg_io: .true. +trigger=namelist:jules_pftparm=fire_mort_io: .true.; + =namelist:jules_pftparm=fireveg_c_to_atmos_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_trif_fire diff --git a/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf index adc29f7c..27225012 100644 --- a/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf @@ -130,6 +130,7 @@ trigger=namelist:jules_pftparm: 1; =namelist:jules_pftparm=fef_nh3_io: 1; =namelist:jules_pftparm=fef_dms_io: 1; =namelist:jules_pftparm=fire_mort_io: 1; + =namelist:jules_pftparm=fireveg_c_to_atmos_io: 1; =namelist:jules_pftparm=fl_o3_ct_io: 1; =namelist:jules_pftparm=fsmc_of_io: 1; =namelist:jules_pftparm=fsmc_p0_io: 1; diff --git a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf index 785af417..6d51c57f 100644 --- a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf @@ -594,7 +594,7 @@ url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES [namelist:jules_pftparm=fireveg_c_to_atmos_io] compulsory=true -description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. Based on mean whole-plant mortality factor from Li et al (2012) table 2. +description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. fail-if=len(this) != namelist:jules_surface_types=npft ns=namelist/JULES Science Settings/jules_pftparm/Other parameters range=0:1 diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index d1cce4d1..0a42ff3e 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -3458,6 +3458,9 @@ length=: [namelist:jules_pftparm=fire_mort_io] length=: +[namelist:jules_pftparm=fireveg_c_to_atmos_io] +length=: + [namelist:jules_pftparm=fl_o3_ct_io] length=: diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 823fc951..0eaed57d 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -104,15 +104,9 @@ def upgrade(self, config, meta_config=None): self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], "-14929920000.0") self.add_setting(config, ["namelist:jules_inferno", "flam_sm_func"], "1") - npft = int( - self.get_setting_value(config, ["namelist:jules_surface_types", "npft"]) - ) + npft = int(self.get_setting_value(config, ["namelist:jules_surface_types", "npft"])) self.add_setting( - config, - ["namelist:jules_pftparm", "fireveg_c_to_atmos_io"], - ",".join(["0.13"] * npft), - False, - ) + config, ["namelist:jules_pftparm", "fireveg_c_to_atmos_io"], ",".join(["0.13"] * npft)) return config, self.reports diff --git a/rose-meta/jules-um/HEAD/rose-meta.conf b/rose-meta/jules-um/HEAD/rose-meta.conf index 1c665640..8c3a1eea 100644 --- a/rose-meta/jules-um/HEAD/rose-meta.conf +++ b/rose-meta/jules-um/HEAD/rose-meta.conf @@ -101,6 +101,7 @@ trigger=namelist:jules_pftparm: 1; =namelist:jules_pftparm=fef_nh3_io: 1; =namelist:jules_pftparm=fef_dms_io: 1; =namelist:jules_pftparm=fire_mort_io: 1; + =namelist:jules_pftparm=fireveg_c_to_atmos_io: 1; =namelist:jules_pftparm=fl_o3_ct_io: 1; =namelist:jules_pftparm=fsmc_of_io: 1; =namelist:jules_pftparm=fsmc_p0_io: 1; @@ -361,6 +362,9 @@ length=: [namelist:jules_pftparm=fire_mort_io] length=: +[namelist:jules_pftparm=fireveg_c_to_atmos_io] +length=: + [namelist:jules_pftparm=fl_o3_ct_io] length=: diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index 3627f409..ac509392 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -41,7 +41,7 @@ MODULE jules_inferno_mod ! Varying (Lightning - see Pechony & Shindell,2009) ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony & Shindell,2009) flam_sm_func = 1 - ! Switch for relationship between INFERNO fire + ! Switch for relationship between INFERNO fire ! flammability and soil moisture ! FLAM_SM_FUNC=1:Linear (doesnt require flam_sm_low / flam_sm_up) ! FLAM_SM_FUNC=2:Exponential @@ -52,7 +52,7 @@ MODULE jules_inferno_mod ! Below this soil moisture, flammability is 1.0 (flam_sm_func=2) ! Expressed as a fraction of saturation (between 0 and 1) flam_sm_up = rmdi, & - ! Exponential decay parameter for relationship between soil moisture + ! Exponential decay parameter for relationship between soil moisture ! and flammability (flam_sm_func=2) flam_rhum_low = rmdi, & ! Lower boundary to the relative humidity (%, between 0 and 100 %) @@ -66,11 +66,11 @@ MODULE jules_inferno_mod ! Upper boundary to the fuel density (UNITS) ccdpm_min = rmdi, & ! Minimum decomposable plant material burn fraction (0 <= fraction <= 1) - ccdpm_max = rmdi, & + ccdpm_max = rmdi, & ! Decomposable Plant Material burn fraction (0 <= fraction <= 1) - ccrpm_min = rmdi, & + ccrpm_min = rmdi, & ! Minimum resistant plant material urn fraction (0 <= fraction <= 1) - ccrpm_max = rmdi, & + ccrpm_max = rmdi, & ! Resistant Plant Material burn fraction (0 <= fraction <= 1) z_burn_max = rmdi ! Parameter setting maximum depth of burn (m) @@ -118,11 +118,11 @@ SUBROUTINE check_jules_inferno() IF ( l_inferno ) THEN ! Check a suitable ignition_method was given - IF ( ignition_method /= ignition_constant .AND. & - ignition_method /= ignition_vary_natural .AND. & + IF ( ignition_method /= ignition_constant .AND. & + ignition_method /= ignition_vary_natural .AND. & ignition_method /= ignition_vary_natural_human ) THEN errorstatus = 101 - CALL ereport("check_jules_vegetation", errorstatus, & + CALL ereport("check_jules_vegetation", errorstatus, & 'ignition_method must be 1, 2 or 3') END IF @@ -145,48 +145,48 @@ SUBROUTINE check_jules_inferno() END IF IF ( ABS(flam_rhum_low - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rhum_low needs to be specified.") ELSE IF ( flam_rhum_low < 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rhum_low must be >= 0.0.") END IF IF ( ABS(flam_rhum_up - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rhum_up needs to be specified.") ELSE IF ( flam_rhum_up <= flam_rhum_low ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rhum_up must be >= flam_rhum_low") ELSE IF ( flam_rhum_up > 100.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rhum_up must be <= 100.0.") END IF IF ( ABS(flam_fuel_low - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_fuel_low needs to be specified.") ELSE IF ( flam_fuel_low < 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_fuel_low must be >= 0.0.") END IF IF ( ABS(flam_fuel_up - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_fuel_up needs to be specified.") ELSE IF ( flam_fuel_up < flam_fuel_low ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_fuel_up must be >= flam_fuel_low") ELSE IF ( flam_fuel_up > 1.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_fuel_up must be <= 1.0.") END IF IF ( ABS(flam_rain_const - rmdi) < EPSILON(rmdi) ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rain_const needs to be specified.") ELSE IF ( flam_rain_const > 0.0 ) THEN - CALL ereport( TRIM(RoutineName), errorstatus, & + CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rain_const must be <= 0.0.") END IF END IF ! end of l_inferno check diff --git a/src/initialisation/standalone/init_inferno_mod.F90 b/src/initialisation/standalone/init_inferno_mod.F90 index c34e23eb..e30eaca4 100644 --- a/src/initialisation/standalone/init_inferno_mod.F90 +++ b/src/initialisation/standalone/init_inferno_mod.F90 @@ -53,22 +53,22 @@ SUBROUTINE init_inferno(nml_dir) ! Print some human friendly summary information about the selected options. !----------------------------------------------------------------------------- IF ( l_inferno ) THEN - CALL log_info("init_inferno", & + CALL log_info("init_inferno", & "Interactive fires and emissions (INFERNO) will be diagnosed") IF (ignition_method == ignition_constant ) THEN - CALL log_info("init_inferno", & + CALL log_info("init_inferno", & "Constant or ubiquitous ignitions (INFERNO)") ELSE IF (ignition_method == ignition_vary_natural ) THEN - CALL log_info("init_inferno", & + CALL log_info("init_inferno", & "Constant human ignitions, varying lightning (INFERNO)") ELSE IF (ignition_method == ignition_vary_natural_human ) THEN - CALL log_info("init_inferno", & + CALL log_info("init_inferno", & "Fully prescribed ignitions (INFERNO)") END IF END IF IF ( l_trif_fire ) THEN - CALL log_info("init_inferno", & + CALL log_info("init_inferno", & "Fires will interact with the carbon cycle in triffid") END IF diff --git a/src/science/fire/inferno_io_mod.F90 b/src/science/fire/inferno_io_mod.F90 index d22c1792..9dc2cb9f 100644 --- a/src/science/fire/inferno_io_mod.F90 +++ b/src/science/fire/inferno_io_mod.F90 @@ -54,15 +54,14 @@ SUBROUTINE inferno_io( & ! Average Burned Area per PFT, and fire mortality rate USE jules_inferno_mod, ONLY: & -flam_rhum_low, flam_rhum_up, & -flam_sm_low, flam_sm_up, flam_fuel_low, & + l_trif_fire, flam_rhum_low, flam_rhum_up, & + flam_sm_low, flam_sm_up, flam_fuel_low, & flam_fuel_up, flam_rain_const, flam_sm_func USE qsat_mod, ONLY: qsat_wat USE jules_surface_types_mod, ONLY: npft USE parkind1, ONLY: jprb -USE jules_inferno_mod, ONLY: l_trif_fire USE timestep_mod, ONLY: timestep USE calc_c_comps_triffid_mod, ONLY: calc_c_comps_triffid @@ -165,7 +164,7 @@ SUBROUTINE inferno_io( & fef_c3h8_rpm = 0.0 , fef_hcho_rpm = 0.0, & fef_mecho_rpm = 0.0, & fef_nh3_rpm = 0.0 , fef_dms_rpm = 0.0, & - ! HARDCODED Emission factors for DPM in g kg-1 + ! HARDCODED Emission factors for DPM and RPM in g kg-1 pmtofuel = 0.7 ! Plant Material that is available as fuel (on the surface) @@ -315,9 +314,10 @@ SUBROUTINE inferno_io( & DO i = 1, npft ! Calculate the fuel density ! We use normalised Leaf Carbon + the available DPM - inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & - /(flam_fuel_up - flam_fuel_low) - + !inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & + ! /(flam_fuel_up - flam_fuel_low) + inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - 0.02) & + /(0.2 - 0.02) WHERE (inferno_fuel < 0.0) inferno_fuel = 0.0 WHERE (inferno_fuel > 1.0) inferno_fuel = 1.0 diff --git a/src/science/fire/inferno_mod.F90 b/src/science/fire/inferno_mod.F90 index e5c9e58c..7e9705c9 100644 --- a/src/science/fire/inferno_mod.F90 +++ b/src/science/fire/inferno_mod.F90 @@ -196,8 +196,8 @@ SUBROUTINE calc_flam( & ! Relative Humidity (%) sm_l, & ! The INFERNO soil moisture fraction (sthu's 1st level) - !rain_l, & - ! The precipitation rate (kg.m-2.s-1) + rain_l, & + ! The rain rate (kg.m-2.s-1) fuel_l, & ! The Fuel Density (0-1) flam_rhum_up, & @@ -215,7 +215,7 @@ SUBROUTINE calc_flam( & INTEGER, INTENT(IN) :: & flam_sm_func - ! The function used to parameterise the + ! The function used to parameterise the ! relationship between soil moisture and flammability ! 1 = linear, ! 2 = exponential @@ -233,8 +233,10 @@ SUBROUTINE calc_flam( & b = 5.02808, & f = 8.1328e-03, & h=-3.49149, & - Ts = 373.16 + Ts = 373.16, & ! Water saturation temperature + cr=-2.0 * s_in_day + ! Precipitation factor (-2(day/mm)*(kg/m2/s)) REAL(KIND=real_jlslsm) :: & Z_l, & @@ -243,13 +245,9 @@ SUBROUTINE calc_flam( & ! Reciprocal of the temperature times ts f_rhum_l, & ! The factor dependence on relative humidity - f_sm_l + f_sm_l, & ! The factor dependence on soil moisture - -REAL(KIND=real_jlslsm) :: & - rain_l - ! The precipitation rate (kg.m-2.s-1) - + rain_rate LOGICAL, PARAMETER :: l_cf_old_inferno = .TRUE. @@ -260,10 +258,6 @@ SUBROUTINE calc_flam( & TsbyT_l = Ts / temp_l -PRINT*,"calc_flam" -PRINT*, flam_rhum_low, flam_rhum_up, flam_sm_low, flam_sm_up, flam_rain_const, flam_sm_func -PRINT*,temp_l, rhum_l, fuel_l, sm_l, rain_l - Z_l = a * (TsbyT_l-1.0) + b * LOG10(TsbyT_l) & + c * (10.0**( d * (1.0 - TsbyT_l)) - 1.0) & + f * (10.0**( h * (TsbyT_l-1.0)) - 1.0) @@ -283,32 +277,24 @@ SUBROUTINE calc_flam( & IF (rhum_l > 90.0) f_rhum_l = 0.0 END IF -IF ( flam_sm_func == 1 ) THEN +IF ( flam_sm_func == 1 ) THEN ! linear f_sm_l = (1 - sm_l) - ! The flammability goes down linearly with increasing soil moisture -ELSE IF ( flam_sm_func == 2 ) THEN +ELSE IF ( flam_sm_func == 2 ) THEN ! exponential f_sm_l = EXP(-flam_sm_up * (sm_l - flam_sm_low) ) - ! EJB check this bottom bit - ! Flammability goes down exponentially with soil moisture + f_sm_l = MAX(MIN(f_sm_l, 1.0), 0.0) END IF -IF (f_sm_l < 0.0) THEN - f_sm_l = 0.0 -ELSE IF (f_sm_l > 1.0) THEN - f_sm_l = 1.0 -END IF - IF (l_cf_old_inferno) THEN + rain_rate = rain_l * s_in_day + ! convert rain rate from kg/m2/s to mm/day flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & - * EXP( -2.0 * s_in_day * s_in_day * rain_l) ,1.0) ,0.0) + * EXP( cr * rain_rate) ,1.0) ,0.0) ELSE flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & - * EXP( flam_rain_const * rain_l) ,1.0) ,0.0) + * EXP( -flam_rain_const * rain_l) ,1.0) ,0.0) + ! EJB add units here for rain or add rain as a separate function - make flam_rain > 0 END IF - -PRINT*,"calc_flam", temp_l, rhum_l, fuel_l, sm_l, rain_l, flam_l - IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN END SUBROUTINE calc_flam @@ -443,7 +429,7 @@ SUBROUTINE calc_emitted_carbon_soil( & ! Language: Fortran 90 ! -USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & +USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & ccrpm_min, ccrpm_max USE yomhook, ONLY: lhook, dr_hook @@ -477,19 +463,10 @@ SUBROUTINE calc_emitted_carbon_soil( & IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_in,zhook_handle) DO l = 1,land_pts - ! emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (ccdpm_min + & - ! (ccdpm_max - ccdpm_min) * & - ! (1.0 - sm(l)))) ,0.0) - ! emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (ccrpm_min + & - ! (ccrpm_max - ccrpm_min) * & - ! (1.0 - sm(l)))) ,0.0) - - emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (0.8 + & - (1.0 - 0.8) * & - (1.0 - sm(l)))) ,0.0) - emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (0.0 + & - (0.2 - 0.0) * & - (1.0 - sm(l)))) ,0.0) + emitted_carbon_DPM(l) = MAX(burnt_area(l) * ( dpm_fuel(l) * (ccdpm_min + & + (ccdpm_max - ccdpm_min) * (1.0 - sm(l)))) ,0.0) + emitted_carbon_RPM(l) = MAX(burnt_area(l) * ( rpm_fuel(l) * (ccrpm_min + & + (ccrpm_max - ccrpm_min) * (1.0 - sm(l)))) ,0.0) END DO IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) diff --git a/src/science/vegetation/soilcarb_jls.F90 b/src/science/vegetation/soilcarb_jls.F90 index d0ab6929..ec399fd6 100644 --- a/src/science/vegetation/soilcarb_jls.F90 +++ b/src/science/vegetation/soilcarb_jls.F90 @@ -348,20 +348,10 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & DO t = 1,trif_pts l = trif_index(t) burnt_carbon_dpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,1) * (ccdpm_min + & - (ccdpm_max - ccdpm_min) & + (cs(l,1,1) * (ccdpm_min + (ccdpm_max - ccdpm_min) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) burnt_carbon_rpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,2) * (ccrpm_min + & - (ccrpm_max - ccrpm_min) & - * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) - burnt_carbon_dpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,1) * (0.8 + & - (1.0 - 0.8) & - * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) - burnt_carbon_rpm(l) = MAX(g_burn_gb(l) * & - (cs(l,1,2) * (0.0 + & - (0.2 - 0.0) & + (cs(l,1,2) * (ccrpm_min + (ccrpm_max - ccrpm_min) & * (1.0 - (sthu_soilt(l,1,1))))) ,0.0) cs(l,1,1) = cs(l,1,1) - burnt_carbon_dpm(l) / r_gamma cs(l,1,2) = cs(l,1,2) - burnt_carbon_rpm(l) / r_gamma diff --git a/src/science/vegetation/soilcarb_layers_jls_mod.F90 b/src/science/vegetation/soilcarb_layers_jls_mod.F90 index 67db636f..d924160b 100644 --- a/src/science/vegetation/soilcarb_layers_jls_mod.F90 +++ b/src/science/vegetation/soilcarb_layers_jls_mod.F90 @@ -41,8 +41,8 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & USE soilcarb_tracer_age_mod, ONLY: soilcarb_tracer_age USE jules_vegetation_mod, ONLY: l_nitrogen -USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & - ccrpm_min, ccrpm_max, z_burn_max, & +USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & + ccrpm_min, ccrpm_max, z_burn_max, & l_trif_fire USE jules_soil_mod, ONLY: cs_min, dzsoil, sm_levels @@ -512,12 +512,10 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & END IF burnt_carbon_layer_dpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & - (cs(l,n,1) * (ccdpm_min + & - (ccdpm_max - ccdpm_min) & + (cs(l,n,1) * (ccdpm_min + (ccdpm_max - ccdpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) burnt_carbon_layer_rpm(l,n) = prop_cs_burnt * g_burn_gb(l) * & - (cs(l,n,2) * (ccrpm_min + & - (ccrpm_max - ccrpm_min) & + (cs(l,n,2) * (ccrpm_min + (ccrpm_max - ccrpm_min) & * (1.0 - (sthu_soilt(l,1,n))))) ! Need to introduce a check because it is updated before updating soil C burnt_carbon_layer_dpm(l,n) = MAX(MIN(burnt_carbon_layer_dpm(l,n), & From a596231746d321e3ccf66fea51e46db10ede316c Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Fri, 28 Aug 2026 14:01:56 +0100 Subject: [PATCH 07/20] passing all stem tests but parameters not passed --- doc/source/namelists/fire.nml.rst | 13 ++++++++-- .../jules-inferno/HEAD/rose-meta.conf | 1 + rose-meta/jules-standalone/versions.py | 6 ++--- src/control/shared/jules_inferno_mod.F90 | 25 ++++++++++++------- src/science/fire/inferno_mod.F90 | 8 +++--- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index e746079f..90f25808 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -163,10 +163,19 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` .. nml:member:: flam_rain_const :type: real - :default: -14929920000.0 + :default: 14929920000.0 + An exponential decay factor that defines the relationship between flammability and rainfall. + In order to recreate the relationship hardwired into jules version 8.2 and lower this value + should be set to 14929920000.0. However, this isnt the relationship that + was documented by Mangeon et al. (2016). If you want the Mangeon et al. relationship + then this value should be 172800.0. + If you want to remove the dependence of flammability on rainfall then this value should be set to 0.0. -buggy + .. seealso:: + References: + + * Mangeon, S., Voulgarakis, A., Gilham, R., Harper, A., Sitch, S., and Folberth, G.: INFERNO: a fire and emissions scheme for the UK Met Office’s Unified Model, Geosci. Model Dev., 9, 2685-2700, https://doi.org/10.5194/gmd-9-2685-2016, 2016. .. nml:member:: flam_fuel_low diff --git a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index e82be8f4..cc4b9763 100644 --- a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -25,6 +25,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_rain_const] compulsory=true description=Rainfall flammability scaling constant +range=0.0: sort-key=Panel-J14 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rain_const diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 0eaed57d..7ffdb2fb 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -95,13 +95,13 @@ def upgrade(self, config, meta_config=None): self.add_setting(config, ["namelist:jules_inferno", "ccrpm_min"], "0.0") self.add_setting(config, ["namelist:jules_inferno", "ccrpm_max"], "0.2") - self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_low"], "0.1") - self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_up"], "0.9") + self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_low"], "10.0") + self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_up"], "90.0") self.add_setting(config, ["namelist:jules_inferno", "flam_sm_low"], "0.0") self.add_setting(config, ["namelist:jules_inferno", "flam_sm_up"], "2.4") self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_low"], "0.02") self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_up"], "0.2") - self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], "-14929920000.0") + self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], "14929920000.0") self.add_setting(config, ["namelist:jules_inferno", "flam_sm_func"], "1") npft = int(self.get_setting_value(config, ["namelist:jules_surface_types", "npft"])) diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index ac509392..68b09560 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -59,7 +59,7 @@ MODULE jules_inferno_mod flam_rhum_up = rmdi, & ! Upper boundary to the relative humidity (%, between 0 and 100 %) flam_rain_const = rmdi, & - ! Precipitation factor (-2(day/mm)*(kg/m2/s)) + ! Precipitation factor (2(day/mm)*(kg/m2/s) WRONG UNITS) flam_fuel_low = rmdi, & ! Lower boundary to the fuel density (UNITS) flam_fuel_up = rmdi, & @@ -116,14 +116,21 @@ SUBROUTINE check_jules_inferno() CHARACTER(LEN=*), PARAMETER :: RoutineName='CHECK_JULES_INFERNO' +errorstatus = 101 + IF ( l_inferno ) THEN ! Check a suitable ignition_method was given IF ( ignition_method /= ignition_constant .AND. & ignition_method /= ignition_vary_natural .AND. & ignition_method /= ignition_vary_natural_human ) THEN - errorstatus = 101 - CALL ereport("check_jules_vegetation", errorstatus, & - 'ignition_method must be 1, 2 or 3') + CALL ereport( TRIM(RoutineName), errorstatus, & + 'ignition_method must be 1, 2 or 3') + END IF + + ! Check a suitable flam_sm_func was given + IF ( flam_sm_func /= 1 .AND. flam_sm_func /= 2 ) THEN + CALL ereport( TRIM(RoutineName), errorstatus, & + 'flam_sm_func must be 1 or 2') END IF IF ( flam_sm_func == 2 ) THEN @@ -176,7 +183,7 @@ SUBROUTINE check_jules_inferno() "flam_fuel_up needs to be specified.") ELSE IF ( flam_fuel_up < flam_fuel_low ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_fuel_up must be >= flam_fuel_low") + "flam_fuel_up must be > flam_fuel_low") ELSE IF ( flam_fuel_up > 1.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & "flam_fuel_up must be <= 1.0.") @@ -185,9 +192,9 @@ SUBROUTINE check_jules_inferno() IF ( ABS(flam_rain_const - rmdi) < EPSILON(rmdi) ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & "flam_rain_const needs to be specified.") - ELSE IF ( flam_rain_const > 0.0 ) THEN + ELSE IF ( flam_rain_const < 0.0 ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & - "flam_rain_const must be <= 0.0.") + "flam_rain_const must be >= 0.0.") END IF END IF ! end of l_inferno check @@ -336,7 +343,7 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) INTEGER, INTENT(IN) :: unitnumber INTEGER :: my_comm INTEGER :: mpl_nml_type -INTEGER :: ErrorStatus +INTEGER :: errorstatus INTEGER :: icode CHARACTER(LEN=errormessagelength) :: iomessage REAL(KIND=jprb) :: zhook_handle @@ -467,7 +474,7 @@ SUBROUTINE read_nml_jules_inferno(nml_dir) IOMSG = iomessage) IF ( ERROR /= 0 ) & CALL log_fatal("init_inferno", "Error opening namelist file fire.nml " // & - "Error opening namelist file inferno.nml " // & + "Error opening namelist file fire.nml " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // " IOMSG=" // & TRIM(iomessage) // ")") diff --git a/src/science/fire/inferno_mod.F90 b/src/science/fire/inferno_mod.F90 index 7e9705c9..11a74a99 100644 --- a/src/science/fire/inferno_mod.F90 +++ b/src/science/fire/inferno_mod.F90 @@ -289,11 +289,11 @@ SUBROUTINE calc_flam( & ! convert rain rate from kg/m2/s to mm/day flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & * EXP( cr * rain_rate) ,1.0) ,0.0) -ELSE - flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & - * EXP( -flam_rain_const * rain_l) ,1.0) ,0.0) - ! EJB add units here for rain or add rain as a separate function - make flam_rain > 0 END IF +! flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & +! * EXP( -flam_rain_const * rain_l) ,1.0) ,0.0) + ! EJB add units here for rain or add rain as a separate function - make flam_rain > 0 + IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN From f2e7682cc8f33fc0fdb9a974fc432bf36c678caf Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:07:03 +0100 Subject: [PATCH 08/20] flam_rhum bit compares --- src/science/fire/inferno_mod.F90 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/science/fire/inferno_mod.F90 b/src/science/fire/inferno_mod.F90 index 11a74a99..2aca7258 100644 --- a/src/science/fire/inferno_mod.F90 +++ b/src/science/fire/inferno_mod.F90 @@ -271,12 +271,6 @@ SUBROUTINE calc_flam( & IF (rhum_l > flam_rhum_up) f_rhum_l = 0.0 ! No fires for RH > flam_rhum_up -IF (l_cf_old_inferno) THEN - f_rhum_l = (90.0 - rhum_l) / (90.0 - 10.0) - IF (rhum_l < 10.0) f_rhum_l = 1.0 - IF (rhum_l > 90.0) f_rhum_l = 0.0 -END IF - IF ( flam_sm_func == 1 ) THEN ! linear f_sm_l = (1 - sm_l) ELSE IF ( flam_sm_func == 2 ) THEN ! exponential From ade67dc8bdb61b1aaf7f2fc7800a2b90447af31c Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Fri, 28 Aug 2026 17:25:49 +0100 Subject: [PATCH 09/20] still passing tests --- src/science/fire/inferno_io_mod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/science/fire/inferno_io_mod.F90 b/src/science/fire/inferno_io_mod.F90 index 9dc2cb9f..37ba4d25 100644 --- a/src/science/fire/inferno_io_mod.F90 +++ b/src/science/fire/inferno_io_mod.F90 @@ -314,10 +314,10 @@ SUBROUTINE inferno_io( & DO i = 1, npft ! Calculate the fuel density ! We use normalised Leaf Carbon + the available DPM - !inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & - ! /(flam_fuel_up - flam_fuel_low) - inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - 0.02) & - /(0.2 - 0.02) + inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & + /(flam_fuel_up - flam_fuel_low) + !inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - 0.02) & + ! /(0.2 - 0.02) WHERE (inferno_fuel < 0.0) inferno_fuel = 0.0 WHERE (inferno_fuel > 1.0) inferno_fuel = 1.0 From 2bbfb36c4373a94be77bc20ff8354a396df5ebdb Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Tue, 1 Sep 2026 17:06:21 +0100 Subject: [PATCH 10/20] minor updates --- doc/source/namelists/fire.nml.rst | 2 +- etc/fcm-make/make-river.cfg | 2 +- .../jules-inferno/HEAD/rose-meta.conf | 64 +++++++++---------- .../jules-pftparm/HEAD/rose-meta.conf | 3 - rose-meta/jules-standalone/versions.py | 9 +-- .../fire/{ => inferno}/inferno_io_mod.F90 | 0 .../fire/{ => inferno}/inferno_mod.F90 | 0 7 files changed, 35 insertions(+), 45 deletions(-) rename src/science/fire/{ => inferno}/inferno_io_mod.F90 (100%) rename src/science/fire/{ => inferno}/inferno_mod.F90 (100%) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index 90f25808..fddeffb9 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -1,7 +1,7 @@ ``fire.nml`` =================== -This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that sets time-invariant parameters for performing wildfire-related calculations. The second namelist is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` +This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that contains switches used to calculate the different fire weather indices available. The second namelist is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` ``FIRE_SWITCHES`` namelist members ----------------------------------- diff --git a/etc/fcm-make/make-river.cfg b/etc/fcm-make/make-river.cfg index eba8dd77..68c43e11 100644 --- a/etc/fcm-make/make-river.cfg +++ b/etc/fcm-make/make-river.cfg @@ -160,7 +160,7 @@ extract.path-incl[river] = $extract_path_incl \ src/control/imogen/imgn_vars_mod.F90 \ src/control/shared/jules_radiation_mod.F90 \ src/params/imogen/imogen_constants.F90 \ - src/science/fire/fire_weather_index/fire_mod.F90 \ + src/science/fire/fire_mod.F90 \ src/util/shared/metstats/metstats_mod.F90 \ #............................................................................... # and allocate_river_arrays diff --git a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index cc4b9763..7532c3e7 100644 --- a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -6,6 +6,38 @@ sort-key=Section-A12p title=Fire options url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html +[namelist:jules_inferno=ccdpm_max] +compulsory=true +description=Maximum fraction of DPM consumed by fire +range=0.0:1.0 +sort-key=Panel-J06 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccdpm_max + +[namelist:jules_inferno=ccdpm_min] +compulsory=true +description=Minimum fraction of DPM consumed by fire +range=0.0:1.0 +sort-key=Panel-J05 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccdpm_min + +[namelist:jules_inferno=ccrpm_max] +compulsory=true +description=Maximum fraction of RPM consumed by fire +range=0.0:1.0 +sort-key=Panel-J08 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccrpm_max + +[namelist:jules_inferno=ccrpm_min] +compulsory=true +description=Minimum fraction of RPM consumed by fire +range=0.0:1.0 +sort-key=Panel-J07 +type=real +url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccrpm_min + [namelist:jules_inferno=flam_fuel_low] compulsory=true description=Lower fuel load threshold for flammability @@ -131,38 +163,6 @@ trigger=namelist:jules_pftparm=fire_mort_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_trif_fire -[namelist:jules_inferno=ccdpm_max] -compulsory=true -description=Maximum fraction of DPM consumed by fire -range=0.0:1.0 -sort-key=Panel-J06 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccdpm_max - -[namelist:jules_inferno=ccdpm_min] -compulsory=true -description=Minimum fraction of DPM consumed by fire -range=0.0:1.0 -sort-key=Panel-J05 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccdpm_min - -[namelist:jules_inferno=ccrpm_max] -compulsory=true -description=Maximum fraction of RPM consumed by fire -range=0.0:1.0 -sort-key=Panel-J08 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccrpm_max - -[namelist:jules_inferno=ccrpm_min] -compulsory=true -description=Minimum fraction of RPM consumed by fire -range=0.0:1.0 -sort-key=Panel-J07 -type=real -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ccrpm_min - [namelist:jules_inferno=z_burn_max] compulsory=true description=Maximum burn depth for soil - soil carbon is burned above this level diff --git a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf index 6d51c57f..ab6ca09d 100644 --- a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf @@ -99,8 +99,6 @@ sort-key=Panel-HR03 type=real url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES_PFTPARM::albsnf_maxl_io - - [namelist:jules_pftparm=albsnf_maxu_io] compulsory=true description=Upper limit on albsnf_max_io @@ -602,7 +600,6 @@ sort-key=Panel-HO16 type=real url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES_PFTPARM::fireveg_c_to_atmos_io - [namelist:jules_pftparm=fl_o3_ct_io] compulsory=true fail-if=len(this) != namelist:jules_surface_types=npft diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 7ffdb2fb..2ec66d41 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -56,18 +56,11 @@ class vn82_t61(MacroUpgrade): def upgrade(self, config, meta_config=None): """Upgrade a JULES runtime app configuration.""" - self.rename_setting(config, ["namelist:fire_switches"], - ["namelist:jules_fire_weather_index"]) - self.rename_setting(config, ["namelist:jules_fire_weather_index", - "l_fire"], - ["namelist:jules_fire_weather_index", - "l_fire_weather_index"]) - self.add_setting(config, ["namelist:jules_inferno"]) source = self.get_setting_value(config, ["file:fire.nml","source"]) source = source.replace("namelist:fire_switches", - "namelist:jules_fire_weather_index namelist:jules_inferno") + "namelist:fire_switches namelist:jules_inferno") self.change_setting_value(config, ["file:fire.nml","source"], source) l_inferno = self.get_setting_value(config, ["namelist:jules_vegetation", "l_inferno"]) diff --git a/src/science/fire/inferno_io_mod.F90 b/src/science/fire/inferno/inferno_io_mod.F90 similarity index 100% rename from src/science/fire/inferno_io_mod.F90 rename to src/science/fire/inferno/inferno_io_mod.F90 diff --git a/src/science/fire/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 similarity index 100% rename from src/science/fire/inferno_mod.F90 rename to src/science/fire/inferno/inferno_mod.F90 From 558b1ba8a3878d1bb534d4d19215f2c29670b087 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Wed, 2 Sep 2026 09:54:43 +0100 Subject: [PATCH 11/20] this version bit compares --- doc/source/namelists/fire.nml.rst | 4 ++-- .../jules-inferno/HEAD/rose-meta.conf | 4 ++-- src/control/shared/jules_inferno_mod.F90 | 3 +-- src/control/shared/jules_soil_biogeochem_mod.F90 | 3 ++- src/control/shared/jules_vegetation_mod.F90 | 2 +- src/initialisation/standalone/init.F90 | 2 +- .../um/surf_couple_read_namelists_mod.F90 | 4 +++- src/science/fire/inferno/inferno_io_mod.F90 | 3 +-- src/science/fire/inferno/inferno_mod.F90 | 16 +++++++--------- 9 files changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index fddeffb9..e96200d2 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -3,10 +3,10 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that contains switches used to calculate the different fire weather indices available. The second namelist is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` -``FIRE_SWITCHES`` namelist members +``JULES_FIRE_WEATHER_INDEX`` namelist members ----------------------------------- -.. nml:namelist:: FIRE_SWITCHES +.. nml:namelist:: JULES_FIRE_WEATHER_INDEX .. nml:member:: l_fire diff --git a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index 7532c3e7..3666326f 100644 --- a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -80,7 +80,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_sm_func] compulsory=true -description=Lower soil moisture threshold for flammability +description=Function relating soil moisture to flammability 1=linear, 2=exponential sort-key=Panel-J11 trigger=namelist:jules_inferno=flam_sm_low: 2; =namelist:jules_inferno=flam_sm_up: 2; @@ -92,7 +92,7 @@ values=1,2 [namelist:jules_inferno=flam_sm_low] compulsory=true description=Soil moisture below which flammability is 1.0 -range=0.0:10.0 +range=0.0:1.0 sort-key=Panel-J11b type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_low diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index 68b09560..fd33abd9 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -71,7 +71,7 @@ MODULE jules_inferno_mod ccrpm_min = rmdi, & ! Minimum resistant plant material urn fraction (0 <= fraction <= 1) ccrpm_max = rmdi, & - ! Resistant Plant Material burn fraction (0 <= fraction <= 1) + ! Maximum resistant Plant Material burn fraction (0 <= fraction <= 1) z_burn_max = rmdi ! Parameter setting maximum depth of burn (m) @@ -474,7 +474,6 @@ SUBROUTINE read_nml_jules_inferno(nml_dir) IOMSG = iomessage) IF ( ERROR /= 0 ) & CALL log_fatal("init_inferno", "Error opening namelist file fire.nml " // & - "Error opening namelist file fire.nml " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // " IOMSG=" // & TRIM(iomessage) // ")") diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index 99c8bc34..373dfd47 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -524,7 +524,8 @@ SUBROUTINE check_jules_soil_biogeochem() IF ( ( l_layeredc .AND. l_trif_fire ) .OR. & ( l_layeredc .AND. l_inferno ) ) THEN IF ( ABS( z_burn_max - rmdi ) > EPSILON(1.0) ) THEN - IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN + CALL ereport(RoutineName, errorstatus, "z_burn_max not found") + ELSE IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN CALL ereport(RoutineName, errorstatus, & "z_burn_max must be positive & less than 10 meters") END IF diff --git a/src/control/shared/jules_vegetation_mod.F90 b/src/control/shared/jules_vegetation_mod.F90 index ace45d15..38411381 100644 --- a/src/control/shared/jules_vegetation_mod.F90 +++ b/src/control/shared/jules_vegetation_mod.F90 @@ -985,7 +985,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) ! set number of each type of variable in my_namelist type INTEGER, PARAMETER :: no_of_types = 3 -INTEGER, PARAMETER :: n_int = 11 +INTEGER, PARAMETER :: n_int = 10 INTEGER, PARAMETER :: n_real = 11 + (n_photo_coef * 5) INTEGER, PARAMETER :: n_log = 27 + npft_max diff --git a/src/initialisation/standalone/init.F90 b/src/initialisation/standalone/init.F90 index ab9c0d80..6d2ed2cf 100644 --- a/src/initialisation/standalone/init.F90 +++ b/src/initialisation/standalone/init.F90 @@ -274,7 +274,7 @@ SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & ! Must be called after init_soil to check soil tiling flags CALL init_vegetation(nml_dir) -! initialase inferno options +! Initialise inferno options CALL init_inferno(nml_dir) ! Initialise irrigation options diff --git a/src/initialisation/um/surf_couple_read_namelists_mod.F90 b/src/initialisation/um/surf_couple_read_namelists_mod.F90 index cb2ed184..83813e6d 100644 --- a/src/initialisation/um/surf_couple_read_namelists_mod.F90 +++ b/src/initialisation/um/surf_couple_read_namelists_mod.F90 @@ -37,7 +37,8 @@ SUBROUTINE surf_couple_read_namelists(call_type, shared_unit, atmoscntl_unit) read_jules_soil_biogeochem, read_jules_surface, & read_jules_model_environment, read_jules_water_resources, & read_jules_irrigation, read_jules_red, & - read_jules_deposition, read_jules_deposition_species + read_jules_deposition, read_jules_deposition_species, & + read_jules_inferno USE jules_deposition_mod, ONLY: l_deposition @@ -75,6 +76,7 @@ SUBROUTINE surf_couple_read_namelists(call_type, shared_unit, atmoscntl_unit) CALL read_jules_sea_seaice(shared_unit) CALL read_jules_soil(shared_unit) CALL read_jules_vegetation(shared_unit) +CALL read_jules_inferno(shared_unit) CALL read_jules_irrigation(shared_unit) CALL read_jules_soil_biogeochem(shared_unit) CALL read_jules_snow(shared_unit) diff --git a/src/science/fire/inferno/inferno_io_mod.F90 b/src/science/fire/inferno/inferno_io_mod.F90 index 37ba4d25..39f3c8af 100644 --- a/src/science/fire/inferno/inferno_io_mod.F90 +++ b/src/science/fire/inferno/inferno_io_mod.F90 @@ -316,8 +316,7 @@ SUBROUTINE inferno_io( & ! We use normalised Leaf Carbon + the available DPM inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - flam_fuel_low) & /(flam_fuel_up - flam_fuel_low) - !inferno_fuel(:) = (leaf_inf(:,i) + dpm_fuel - 0.02) & - ! /(0.2 - 0.02) + WHERE (inferno_fuel < 0.0) inferno_fuel = 0.0 WHERE (inferno_fuel > 1.0) inferno_fuel = 1.0 diff --git a/src/science/fire/inferno/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 2aca7258..38e0da73 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/inferno_mod.F90 @@ -249,8 +249,6 @@ SUBROUTINE calc_flam( & ! The factor dependence on soil moisture rain_rate -LOGICAL, PARAMETER :: l_cf_old_inferno = .TRUE. - REAL(KIND=jprb) :: zhook_handle CHARACTER(LEN=*), PARAMETER :: RoutineName = "CALC_FLAM" @@ -278,15 +276,15 @@ SUBROUTINE calc_flam( & f_sm_l = MAX(MIN(f_sm_l, 1.0), 0.0) END IF -IF (l_cf_old_inferno) THEN - rain_rate = rain_l * s_in_day + +rain_rate = rain_l * s_in_day ! convert rain rate from kg/m2/s to mm/day - flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & + +flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & * EXP( cr * rain_rate) ,1.0) ,0.0) -END IF -! flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & -! * EXP( -flam_rain_const * rain_l) ,1.0) ,0.0) - ! EJB add units here for rain or add rain as a separate function - make flam_rain > 0 +!flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & +! * EXP( cr * s_in_day * rain_l), 1.0), 0.0) +! EJB add units here for rain or add rain as a separate function - make flam_rain > 0 IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) From 6c3c6fcfc9ad884ec0972feb2a04c626afd93a21 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Wed, 2 Sep 2026 10:11:35 +0100 Subject: [PATCH 12/20] fixing not comiling in soil_biogechem --- src/control/shared/jules_soil_biogeochem_mod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index 373dfd47..3c6d8dff 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -526,9 +526,8 @@ SUBROUTINE check_jules_soil_biogeochem() IF ( ABS( z_burn_max - rmdi ) > EPSILON(1.0) ) THEN CALL ereport(RoutineName, errorstatus, "z_burn_max not found") ELSE IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN - CALL ereport(RoutineName, errorstatus, & + CALL ereport(RoutineName, errorstatus, & "z_burn_max must be positive & less than 10 meters") - END IF END IF END IF From 9fd48a52e23b2e39d17a7e3fa0c5ed6336ffd582 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Wed, 2 Sep 2026 11:19:56 +0100 Subject: [PATCH 13/20] fixing z_burn_max check --- doc/source/namelists/fire.nml.rst | 14 +++++++------- src/control/shared/jules_inferno_mod.F90 | 2 -- src/control/shared/jules_soil_biogeochem_mod.F90 | 2 +- src/initialisation/standalone/init_inferno_mod.F90 | 8 +++----- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index e96200d2..259d1a28 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -64,7 +64,7 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` .. nml:namelist:: JULES_INFERNO - .. nml:member:: l_inferno +.. nml:member:: l_inferno :type: boolean :default: F @@ -166,8 +166,8 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :default: 14929920000.0 An exponential decay factor that defines the relationship between flammability and rainfall. - In order to recreate the relationship hardwired into jules version 8.2 and lower this value - should be set to 14929920000.0. However, this isnt the relationship that + In order to recreate the relationship hardwired into JULES version 8.2 and lower this value + should be set to 14929920000.0. However, this is not the relationship that was documented by Mangeon et al. (2016). If you want the Mangeon et al. relationship then this value should be 172800.0. If you want to remove the dependence of flammability on rainfall then this value should be set to 0.0. @@ -191,21 +191,21 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :type: real :default: 0.8 - Minimum DPM soil carbon pool combustion completness fraction. + Minimum DPM soil carbon pool combustion completeness fraction. .. nml:member:: ccdpm_max :type: real :default: 1.0 - Maximum DPM soil carbon pool combustion completness fraction. + Maximum DPM soil carbon pool combustion completeness fraction. .. nml:member:: ccrpm_min :type: real :default: 0.0 - Minimum RPM soil carbon pool combustion completness fraction. + Minimum RPM soil carbon pool combustion completeness fraction. .. nml:member:: ccrpm_max @@ -213,4 +213,4 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :type: real :default: 0.2 - Maximum RPM soil carbon pool combustion completness fraction. + Maximum RPM soil carbon pool combustion completeness fraction. diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index fd33abd9..4368f38a 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -107,8 +107,6 @@ SUBROUTINE check_jules_inferno() USE ereport_mod, ONLY: ereport USE jules_print_mgr, ONLY: jules_print, jules_message -USE logging_mod, ONLY: log_info - IMPLICIT NONE INTEGER :: errorstatus diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index 3c6d8dff..bcdfebcf 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -523,7 +523,7 @@ SUBROUTINE check_jules_soil_biogeochem() ! check value of z_burn_max with l_layeredc IF ( ( l_layeredc .AND. l_trif_fire ) .OR. & ( l_layeredc .AND. l_inferno ) ) THEN - IF ( ABS( z_burn_max - rmdi ) > EPSILON(1.0) ) THEN + IF ( ABS( z_burn_max - rmdi ) < EPSILON(1.0) ) THEN CALL ereport(RoutineName, errorstatus, "z_burn_max not found") ELSE IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN CALL ereport(RoutineName, errorstatus, & diff --git a/src/initialisation/standalone/init_inferno_mod.F90 b/src/initialisation/standalone/init_inferno_mod.F90 index e30eaca4..0327488c 100644 --- a/src/initialisation/standalone/init_inferno_mod.F90 +++ b/src/initialisation/standalone/init_inferno_mod.F90 @@ -16,7 +16,9 @@ SUBROUTINE init_inferno(nml_dir) USE jules_inferno_mod, ONLY: read_nml_jules_inferno, & print_nlist_jules_inferno, & check_jules_inferno, & - l_inferno, l_trif_fire, ignition_method + l_inferno, l_trif_fire, ignition_method, & + ignition_constant, ignition_vary_natural, & + ignition_vary_natural_human USE logging_mod, ONLY: log_info @@ -34,10 +36,6 @@ SUBROUTINE init_inferno(nml_dir) ! This code is written to JULES coding standards v1. !----------------------------------------------------------------------------- -INTEGER, PARAMETER :: ignition_constant = 1 -INTEGER, PARAMETER :: ignition_vary_natural = 2 -INTEGER, PARAMETER :: ignition_vary_natural_human = 3 - CHARACTER(LEN=*), INTENT(IN) :: nml_dir ! The directory containing the ! namelists From 20fee0facf0d857263cff742ac9f01c382164361 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:33:51 +0100 Subject: [PATCH 14/20] minor change --- src/science/params/pftparm_io_mod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/science/params/pftparm_io_mod.F90 b/src/science/params/pftparm_io_mod.F90 index ea4f2213..497305b4 100644 --- a/src/science/params/pftparm_io_mod.F90 +++ b/src/science/params/pftparm_io_mod.F90 @@ -232,7 +232,7 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) ! set number of each type of variable in my_namelist type INTEGER, PARAMETER :: no_of_types = 2 INTEGER, PARAMETER :: n_int = 3 * npft_max -INTEGER, PARAMETER :: n_real = 108 * npft_max +INTEGER, PARAMETER :: n_real = 109 * npft_max TYPE :: my_namelist SEQUENCE From 9de2153873056ab5b4c61d477c7ceac91cfeb5e2 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:05:39 +0100 Subject: [PATCH 15/20] returning params back to jules_vegetation --- doc/source/namelists/fire.nml.rst | 51 --------------- doc/source/namelists/jules_vegetation.nml.rst | 49 +++++++++++++++ doc/source/namelists/pft_params.nml.rst | 14 ----- doc/source/namelists/triffid_params.nml.rst | 16 +++++ rose-meta/jules-lfric/HEAD/rose-meta.conf | 4 -- .../jules-inferno/HEAD/rose-meta.conf | 62 +------------------ .../HEAD/rose-meta.conf | 1 - .../jules-pftparm/HEAD/rose-meta.conf | 10 --- .../jules-vegetation/HEAD/rose-meta.conf | 37 +++++++++++ .../jules-standalone/HEAD/rose-meta.conf | 16 +++-- rose-meta/jules-standalone/versions.py | 23 ++----- rose-meta/jules-um/HEAD/rose-meta.conf | 4 -- src/control/shared/jules_inferno_mod.F90 | 55 ++++------------ .../shared/jules_soil_biogeochem_mod.F90 | 4 +- src/control/shared/jules_vegetation_mod.F90 | 56 ++++++++++++++--- src/control/shared/surf_couple_extra_mod.F90 | 5 +- src/control/um/diagnostics_hyd.F90 | 2 +- .../shared/check_compatible_options_mod.F90 | 3 +- .../standalone/init_inferno_mod.F90 | 5 +- .../standalone/init_jules_sf_diags_mod.F90 | 5 +- .../standalone/init_vegetation.F90 | 22 ++++++- src/science/fire/inferno/inferno_io_mod.F90 | 3 +- src/science/fire/inferno/inferno_mod.F90 | 2 +- src/science/params/pftparm_io_mod.F90 | 11 +--- src/science/params/pftparm_mod.F90 | 18 +----- src/science/params/trif_io_mod.F90 | 12 ++-- src/science/params/trif_mod.F90 | 8 ++- src/science/vegetation/soilcarb_jls.F90 | 3 +- .../vegetation/soilcarb_layers_jls_mod.F90 | 5 +- src/science/vegetation/triffid_jls.F90 | 10 +-- src/science/vegetation/veg-veg2a_jls_mod.F90 | 4 +- 31 files changed, 245 insertions(+), 275 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index 259d1a28..dc81522b 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -62,57 +62,6 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` ``JULES_INFERNO`` namelist members ----------------------------------- -.. nml:namelist:: JULES_INFERNO - -.. nml:member:: l_inferno - - :type: boolean - :default: F - - Switch that determines whether interactive fires (INFERNO) is - used. This allows for the diagnostic of burnt area, burnt carbon - and a variety of fire emissions. - - TRUE - INFERNO is used to provide diagnostic fire variables - - FALSE - INFERNO is not used. - -.. nml:member:: ignition_method - - :type: integer - :permitted: 1, 2, 3 - :default: 1 - - Switch to determine the type of ignition used (ubiquitous or prescribed with population and lightning) - - 1. INFERNO uses ubiquitous (constant) ignitions, of 1.67 fires km\ - :sup:`-2` s\ :sup:`-1` (1.5 from humans, 0.17 from lightning). - - 2. INFERNO uses prescribed lightning ignitions, either from an ancillary or the UM. - Meanwhile humans are assumed to ignite 1.5 fires km\ :sup:`-2` s\ :sup:`-1`. - - 3. INFERNO uses prescribed ignition using Population Density and Lightning Frequency (Cloud-to-Ground). - These must be provided as prescribed data to the JULES run. - -.. nml:member:: l_trif_fire - - :type: boolean - :default: F - - Switch that determines whether interactive fire is used. This allows for burnt area to link with dynamic - vegetation. - - Only used if :nml:mem:`JULES_VEGETATION::l_triffid` = TRUE. - - TRUE - Burnt area is calculated in INFERNO and passed to TRIFFID to - calculate vegetation dynamics. Carbon is also removed from DPM - and RPM pools in SOILCARB. - FALSE - Burnt area is zero unless prescribed via an ancillary file. - .. nml:member:: z_burn_max :type: real diff --git a/doc/source/namelists/jules_vegetation.nml.rst b/doc/source/namelists/jules_vegetation.nml.rst index d4092a1f..ccdf9aa2 100644 --- a/doc/source/namelists/jules_vegetation.nml.rst +++ b/doc/source/namelists/jules_vegetation.nml.rst @@ -586,6 +586,55 @@ This file sets the vegetation options. It contains one namelist called :nml:lst: See Hadley Centre Technical Note 24, Eq.3. +.. nml:member:: l_inferno + + :type: logical + :default: F + + Switch that determines whether interactive fires (INFERNO) is + used. This allows for the diagnostic of burnt area, burnt carbon + and a variety of fire emissions. + + TRUE + INFERNO is used to provide diagnostic fire variables + + FALSE + INFERNO is not used. + +.. nml:member:: ignition_method + + :type: integer + :permitted: 1, 2, 3 + :default: 1 + + Switch to determine the type of ignition used (ubiquitous or prescribed with population and lightning) + + 1. INFERNO uses ubiquitous (constant) ignitions, of 1.67 fires km\ + :sup:`-2` s\ :sup:`-1` (1.5 from humans, 0.17 from lightning). + + 2. INFERNO uses prescribed lightning ignitions, either from an ancillary or the UM. + Meanwhile humans are assumed to ignite 1.5 fires km\ :sup:`-2` s\ :sup:`-1`. + + 3. INFERNO uses prescribed ignition using Population Density and Lightning Frequency (Cloud-to-Ground). + These must be provided as prescribed data to the JULES run. + +.. nml:member:: l_trif_fire + + :type: logical + :default: F + + Switch that determines whether interactive fire is used. This allows for burnt area to link with dynamic + vegetation. + + Only used if :nml:mem:`l_triffid` = TRUE. + + TRUE + Burnt area is calculated in INFERNO and passed to TRIFFID to + calculate vegetation dynamics. Carbon is also removed from DPM + and RPM pools in SOILCARB. + FALSE + Burnt area is zero unless prescribed via an ancillary file. + .. nml:member:: l_vegdrag_pft :type: logical(npft) diff --git a/doc/source/namelists/pft_params.nml.rst b/doc/source/namelists/pft_params.nml.rst index d596cc57..4219bf84 100644 --- a/doc/source/namelists/pft_params.nml.rst +++ b/doc/source/namelists/pft_params.nml.rst @@ -936,20 +936,6 @@ ease the direct links to these documents are: land surfaces with radiation for relating remote sensing products to climate models, J. Geophys. Res., 111, D02116, https://doi.org/10.1029/2005JD005952. -.. nml:member:: fireveg_c_to_atmos - - :type: real(npft) - :default: None - - Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. - Based on mean whole-plant mortality factor from Li et al (2012) table 2. - - .. seealso:: - References: - - * Li, F., Zeng, X. D., and Levis, S.: A process-based fire parameterization - of intermediate complexity in a Dynamic Global Vegetation Model, Biogeosciences, - 9, 2761-2780, https://doi.org/10.5194/bg-9-2761-2012, 2012. .. nml:group:: Only used with the Farquhar model of leaf photosynthesis (:nml:mem:`JULES_VEGETATION::photo_model` = 2). A value is required for each PFT, but only those for C\ :sub:`3` plants are used (since only C\ :sub:`3` plants use the Farquhar model). Below, J\ :sub:`max` is the potential rate of electron transport, and V\ :sub:`cmax` is the maximum rate of carboxylation of Rubisco. diff --git a/doc/source/namelists/triffid_params.nml.rst b/doc/source/namelists/triffid_params.nml.rst index 48b18cc4..2d605044 100644 --- a/doc/source/namelists/triffid_params.nml.rst +++ b/doc/source/namelists/triffid_params.nml.rst @@ -178,3 +178,19 @@ This namelist is used to read PFT parameters that are only needed by the dynamic .. note:: :nml:mem:`lai_min_io` must be set such that PFT height at :nml:mem:`lai_min_io` <= :nml:mem:`harvest_ht_io`, otherwise JULES will not start (the required value will be shown in error output). +.. nml:member:: fireveg_c_to_atmos_io + + :type: real(npft) + :default: None + + Only used if :nml:mem:`JULES_INFERNO::l_trif_fire` = TRUE. + + Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. + Based on mean whole-plant mortality factor from Li et al (2012) table 2. + + .. seealso:: + References: + + * Li, F., Zeng, X. D., and Levis, S.: A process-based fire parameterization + of intermediate complexity in a Dynamic Global Vegetation Model, Biogeosciences, + 9, 2761-2780, https://doi.org/10.5194/bg-9-2761-2012, 2012. diff --git a/rose-meta/jules-lfric/HEAD/rose-meta.conf b/rose-meta/jules-lfric/HEAD/rose-meta.conf index 8632bc7c..be744372 100644 --- a/rose-meta/jules-lfric/HEAD/rose-meta.conf +++ b/rose-meta/jules-lfric/HEAD/rose-meta.conf @@ -295,10 +295,6 @@ fail-if= fail-if= !ns= -[namelist:jules_pftparm=fireveg_c_to_atmos_io] -fail-if= -!ns= - [namelist:jules_pftparm=fl_o3_ct_io] fail-if= !ns= diff --git a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index 3666326f..4ca533e6 100644 --- a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -49,7 +49,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_fuel_up] compulsory=true description=Upper fuel load threshold for flammability -range=0.0: +range=0.0:1.0 sort-key=Panel-J13 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_fuel_up @@ -57,7 +57,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_rain_const] compulsory=true description=Rainfall flammability scaling constant -range=0.0: +range=0.0:1.0 sort-key=Panel-J14 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rain_const @@ -105,64 +105,6 @@ sort-key=Panel-J11c type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_sm_up -[namelist:jules_inferno=ignition_method] -compulsory=true -description=The method to use for ignitions -sort-key=Panel-J03 -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::ignition_method -value-titles=(1) constant human and natural ignition sources, - =(2) constant human varying natural ignition sources, - =(3) varying human and natural ignition sources -values=1,2,3 - -[namelist:jules_inferno=l_inferno] -compulsory=true -description=Use the INFERNO interactive fire and diagnostic emissions model -sort-key=Panel-J01 -trigger=namelist:jules_inferno=ignition_method: .true.; - =namelist:jules_inferno=l_trif_fire: .true.; - =namelist:jules_inferno=ccdpm_min: .true.; - =namelist:jules_inferno=ccdpm_max: .true.; - =namelist:jules_inferno=ccrpm_min: .true.; - =namelist:jules_inferno=ccrpm_max: .true.; - =namelist:jules_inferno=flam_fuel_low: .true.; - =namelist:jules_inferno=flam_fuel_up: .true.; - =namelist:jules_inferno=flam_rhum_low: .true.; - =namelist:jules_inferno=flam_rhum_up: .true.; - =namelist:jules_inferno=flam_sm_func: .true.; - =namelist:jules_inferno=flam_rain_const: .true.; - =namelist:jules_pftparm=avg_ba_io: .true.; - =namelist:jules_pftparm=ccleaf_min_io: .true.; - =namelist:jules_pftparm=ccleaf_max_io: .true.; - =namelist:jules_pftparm=ccwood_min_io: .true.; - =namelist:jules_pftparm=ccwood_max_io: .true.; - =namelist:jules_pftparm=fef_bc_io: .true.; - =namelist:jules_pftparm=fef_ch4_io: .true.; - =namelist:jules_pftparm=fef_co2_io: .true.; - =namelist:jules_pftparm=fef_co_io: .true.; - =namelist:jules_pftparm=fef_nox_io: .true.; - =namelist:jules_pftparm=fef_oc_io: .true.; - =namelist:jules_pftparm=fef_so2_io: .true.; - =namelist:jules_pftparm=fef_c2h4_io: .true.; - =namelist:jules_pftparm=fef_c2h6_io: .true.; - =namelist:jules_pftparm=fef_c3h8_io: .true.; - =namelist:jules_pftparm=fef_hcho_io: .true.; - =namelist:jules_pftparm=fef_mecho_io: .true.; - =namelist:jules_pftparm=fef_nh3_io: .true.; - =namelist:jules_pftparm=fef_dms_io: .true.; -type=logical -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_inferno - -[namelist:jules_inferno=l_trif_fire] -compulsory=true -description=Use interactive fire linked to INFERNO including interactive fire emissions. -fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); -sort-key=Panel-J02 -trigger=namelist:jules_pftparm=fire_mort_io: .true.; - =namelist:jules_pftparm=fireveg_c_to_atmos_io: .true.; -type=logical -url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::l_trif_fire - [namelist:jules_inferno=z_burn_max] compulsory=true description=Maximum burn depth for soil - soil carbon is burned above this level diff --git a/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf index 27225012..adc29f7c 100644 --- a/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-model-environment/HEAD/rose-meta.conf @@ -130,7 +130,6 @@ trigger=namelist:jules_pftparm: 1; =namelist:jules_pftparm=fef_nh3_io: 1; =namelist:jules_pftparm=fef_dms_io: 1; =namelist:jules_pftparm=fire_mort_io: 1; - =namelist:jules_pftparm=fireveg_c_to_atmos_io: 1; =namelist:jules_pftparm=fl_o3_ct_io: 1; =namelist:jules_pftparm=fsmc_of_io: 1; =namelist:jules_pftparm=fsmc_p0_io: 1; diff --git a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf index ab6ca09d..cb18e53a 100644 --- a/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-pftparm/HEAD/rose-meta.conf @@ -590,16 +590,6 @@ sort-key=Panel-HO16 type=real url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES_PFTPARM::fire_mort_io -[namelist:jules_pftparm=fireveg_c_to_atmos_io] -compulsory=true -description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. -fail-if=len(this) != namelist:jules_surface_types=npft -ns=namelist/JULES Science Settings/jules_pftparm/Other parameters -range=0:1 -sort-key=Panel-HO16 -type=real -url=https://metoffice.github.io/jules/latest/namelists/pft_params.nml.html#JULES_PFTPARM::fireveg_c_to_atmos_io - [namelist:jules_pftparm=fl_o3_ct_io] compulsory=true fail-if=len(this) != namelist:jules_surface_types=npft diff --git a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf index 627c159f..5c8f7f03 100644 --- a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf @@ -30,6 +30,34 @@ trigger=namelist:jules_pftparm=ief_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_bvoc_emis +[namelist:jules_vegetation=l_inferno] +compulsory=true +description=Use the INFERNO interactive fire and diagnostic emissions model +sort-key=Panel-I16 +trigger=namelist:jules_vegetation=ignition_method: .true.; + =namelist:jules_vegetation=l_trif_fire: .true.; + =namelist:jules_pftparm=avg_ba_io: .true.; + =namelist:jules_pftparm=ccleaf_min_io: .true.; + =namelist:jules_pftparm=ccleaf_max_io: .true.; + =namelist:jules_pftparm=ccwood_min_io: .true.; + =namelist:jules_pftparm=ccwood_max_io: .true.; + =namelist:jules_pftparm=fef_bc_io: .true.; + =namelist:jules_pftparm=fef_ch4_io: .true.; + =namelist:jules_pftparm=fef_co2_io: .true.; + =namelist:jules_pftparm=fef_co_io: .true.; + =namelist:jules_pftparm=fef_nox_io: .true.; + =namelist:jules_pftparm=fef_oc_io: .true.; + =namelist:jules_pftparm=fef_so2_io: .true.; + =namelist:jules_pftparm=fef_c2h4_io: .true.; + =namelist:jules_pftparm=fef_c2h6_io: .true.; + =namelist:jules_pftparm=fef_c3h8_io: .true.; + =namelist:jules_pftparm=fef_hcho_io: .true.; + =namelist:jules_pftparm=fef_mecho_io: .true.; + =namelist:jules_pftparm=fef_nh3_io: .true.; + =namelist:jules_pftparm=fef_dms_io: .true.; +type=logical +url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_inferno + [namelist:jules_vegetation=l_limit_canhc] compulsory=true description=Logical for capping vegetation canopy areal thermal heat capacity @@ -68,6 +96,15 @@ trigger=namelist:jules_pftparm=sug_g0_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_sugar +[namelist:jules_vegetation=l_trif_fire] +compulsory=true +description=Use interactive fire linked to INFERNO including interactive fire emissions. +fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); +sort-key=Panel-I02c +trigger=namelist:jules_pftparm=fire_mort_io: .true. +type=logical +url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_trif_fire + [namelist:jules_vegetation=l_use_pft_psi] compulsory=true description=Use psi_open_io and psi_close_io to calculate the soil moisture stress function on vegetation. diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index 0a42ff3e..fc631e73 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -3458,9 +3458,6 @@ length=: [namelist:jules_pftparm=fire_mort_io] length=: -[namelist:jules_pftparm=fireveg_c_to_atmos_io] -length=: - [namelist:jules_pftparm=fl_o3_ct_io] length=: @@ -6261,6 +6258,17 @@ length=: type=real url=https://metoffice.github.io/jules/latest/namelists/triffid_params.nml.html#JULES_TRIFFID::g_root_io +[namelist:jules_triffid=fireveg_c_to_atmos_io] +compulsory=true +description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. +fail-if=len(this) != namelist:jules_surface_types=npft +ns=namelist/JULES Science Settings/jules_pftparm/Other parameters +range=0:1 +sort-key=Panel-HO16 +type=real +url=https://metoffice.github.io/jules/latest/namelists/triffid_params.nml.html#JULES_TRIFFID::fireveg_c_to_atmos_io + + [namelist:jules_triffid=g_wood_io] compulsory=true description=Turnover rate for woody biomass (/360days) @@ -6684,7 +6692,7 @@ trigger=namelist:jules_vegetation=l_nrun_mid_trif: .true.; =namelist:jules_vegetation=l_nitrogen: .true.; =namelist:jules_vegetation=l_red: .true.; =namelist:jules_vegetation=l_trif_crop: .true.; - =namelist:jules_inferno=l_trif_fire: .true.; + =namelist:jules_vegetation=l_trif_fire: .true.; =namelist:jules_vegetation=l_trif_init_accum: .true.; =namelist:jules_vegetation=frac_min: .true.; =namelist:jules_vegetation=frac_seed: .true.; diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 2ec66d41..595a3161 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -63,31 +63,16 @@ def upgrade(self, config, meta_config=None): "namelist:fire_switches namelist:jules_inferno") self.change_setting_value(config, ["file:fire.nml","source"], source) - l_inferno = self.get_setting_value(config, ["namelist:jules_vegetation", "l_inferno"]) - self.add_setting(config, - ["namelist:jules_inferno", "l_inferno"], l_inferno) - self.remove_setting(config, ["namelist:jules_vegetation", "l_inferno"]) - - l_trif_fire = self.get_setting_value(config, ["namelist:jules_vegetation", "l_trif_fire"]) - self.add_setting(config, - ["namelist:jules_inferno", "l_trif_fire"], l_trif_fire) - self.remove_setting(config, ["namelist:jules_vegetation", "l_trif_fire"]) - - ignition_method = self.get_setting_value(config, ["namelist:jules_vegetation", "ignition_method"]) - self.add_setting(config, - ["namelist:jules_inferno", "ignition_method"], ignition_method) - self.remove_setting(config, ["namelist:jules_vegetation", "ignition_method"]) - z_burn_max = self.get_setting_value(config, ["namelist:jules_soil_biogeochem", "z_burn_max"]) self.add_setting(config, ["namelist:jules_inferno", "z_burn_max"], z_burn_max) self.remove_setting(config, ["namelist:jules_soil_biogeochem", "z_burn_max"]) - + self.add_setting(config, ["namelist:jules_inferno", "ccdpm_min"], "0.8") self.add_setting(config, ["namelist:jules_inferno", "ccdpm_max"], "1.0") self.add_setting(config, ["namelist:jules_inferno", "ccrpm_min"], "0.0") self.add_setting(config, ["namelist:jules_inferno", "ccrpm_max"], "0.2") - + self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_low"], "10.0") self.add_setting(config, ["namelist:jules_inferno", "flam_rhum_up"], "90.0") self.add_setting(config, ["namelist:jules_inferno", "flam_sm_low"], "0.0") @@ -96,10 +81,10 @@ def upgrade(self, config, meta_config=None): self.add_setting(config, ["namelist:jules_inferno", "flam_fuel_up"], "0.2") self.add_setting(config, ["namelist:jules_inferno", "flam_rain_const"], "14929920000.0") self.add_setting(config, ["namelist:jules_inferno", "flam_sm_func"], "1") - + npft = int(self.get_setting_value(config, ["namelist:jules_surface_types", "npft"])) self.add_setting( - config, ["namelist:jules_pftparm", "fireveg_c_to_atmos_io"], ",".join(["0.13"] * npft)) + config, ["namelist:jules_triffid", "fireveg_c_to_atmos_io"], ",".join(["0.13"] * npft)) return config, self.reports diff --git a/rose-meta/jules-um/HEAD/rose-meta.conf b/rose-meta/jules-um/HEAD/rose-meta.conf index 8c3a1eea..1c665640 100644 --- a/rose-meta/jules-um/HEAD/rose-meta.conf +++ b/rose-meta/jules-um/HEAD/rose-meta.conf @@ -101,7 +101,6 @@ trigger=namelist:jules_pftparm: 1; =namelist:jules_pftparm=fef_nh3_io: 1; =namelist:jules_pftparm=fef_dms_io: 1; =namelist:jules_pftparm=fire_mort_io: 1; - =namelist:jules_pftparm=fireveg_c_to_atmos_io: 1; =namelist:jules_pftparm=fl_o3_ct_io: 1; =namelist:jules_pftparm=fsmc_of_io: 1; =namelist:jules_pftparm=fsmc_p0_io: 1; @@ -362,9 +361,6 @@ length=: [namelist:jules_pftparm=fire_mort_io] length=: -[namelist:jules_pftparm=fireveg_c_to_atmos_io] -length=: - [namelist:jules_pftparm=fl_o3_ct_io] length=: diff --git a/src/control/shared/jules_inferno_mod.F90 b/src/control/shared/jules_inferno_mod.F90 index 4368f38a..e8d746dd 100644 --- a/src/control/shared/jules_inferno_mod.F90 +++ b/src/control/shared/jules_inferno_mod.F90 @@ -8,7 +8,9 @@ MODULE jules_inferno_mod ! ----------------------------------------------------------------------------- ! Description: -! Contains switches and other inputs for l_inferno and l_trif_fire options +! Contains switches and other parameters for l_inferno and l_trif_fire +! In the future will also contain l_inferno, l_trif_fire and +! ignition_method ! ! Code Owner: Please refer to ModuleLeaders.txt ! This file belongs in TECHNICAL @@ -19,27 +21,7 @@ MODULE jules_inferno_mod IMPLICIT NONE -LOGICAL :: & - l_inferno = .FALSE., & - ! Switch used to control whether inferno fire scheme is used to calculate - ! flammability and burnt area - l_trif_fire = .FALSE. - ! Switch used to control whether fire is part of the carbon cycle - ! T => if l_inferno is also true, g_burn is calculated in INFERNO - ! passed to TRIFFID to calculate emissions and vegetation dynamics - ! T => if l_inferno is false, interactive fire is calculated via - ! ancillary if provided, and is 0 if not provided - ! F => g_burn is calculated via ancillary if provided, and is 0 if - ! not provided - - INTEGER :: & - ignition_method = imdi, & - ! Switch for the calculation method of INFERNO fire ignitions - ! IGNITION_METHOD=1:Constant (1.67 per km2 per s) - ! IGNITION_METHOD=2:Constant (Human - 1.5 per km2 per s) - ! Varying (Lightning - see Pechony & Shindell,2009) - ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony & Shindell,2009) flam_sm_func = 1 ! Switch for relationship between INFERNO fire ! flammability and soil moisture @@ -83,8 +65,7 @@ MODULE jules_inferno_mod ! Set up a namelist to allow switches to be set. !----------------------------------------------------------------------- NAMELIST / jules_inferno/ & - l_trif_fire, l_inferno, ignition_method, flam_sm_func, & - flam_sm_low, flam_sm_up, flam_rhum_low, flam_rhum_up, & + flam_sm_func,flam_sm_low, flam_sm_up, flam_rhum_low, flam_rhum_up, & flam_rain_const, flam_fuel_low, flam_fuel_up, & ccdpm_min, ccdpm_max, ccrpm_min, ccrpm_max, z_burn_max @@ -104,6 +85,8 @@ SUBROUTINE check_jules_inferno() ! This file belongs in TECHNICAL !----------------------------------------------------------------------------- +USE jules_vegetation_mod, ONLY: l_inferno, l_trif_fire, ignition_method + USE ereport_mod, ONLY: ereport USE jules_print_mgr, ONLY: jules_print, jules_message @@ -197,7 +180,7 @@ SUBROUTINE check_jules_inferno() END IF ! end of l_inferno check -IF ( l_trif_fire ) THEN +IF ( l_trif_fire .OR. l_inferno ) THEN IF ( ABS(ccdpm_min - rmdi) < EPSILON(rmdi) ) THEN CALL ereport( TRIM(RoutineName), errorstatus, & "ccdpm_min needs to be specified.") @@ -244,6 +227,8 @@ END SUBROUTINE check_jules_inferno SUBROUTINE print_nlist_jules_inferno() +USE jules_vegetation_mod, ONLY: l_inferno, l_trif_fire, ignition_method + USE jules_print_mgr, ONLY: jules_print IMPLICIT NONE @@ -255,12 +240,6 @@ SUBROUTINE print_nlist_jules_inferno() CALL jules_print('jules_inferno_mod', & 'Contents of namelist jules_inferno') -WRITE(lineBuffer,*)' l_trif_fire = ',l_trif_fire -CALL jules_print('jules_inferno_mod',lineBuffer) - -WRITE(lineBuffer,*)' l_inferno = ',l_inferno -CALL jules_print('jules_inferno_mod',lineBuffer) - IF ( l_inferno ) THEN WRITE(lineBuffer,*)' ignition_method = ',ignition_method CALL jules_print('jules_inferno_mod',lineBuffer) @@ -351,10 +330,9 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) INTEGER(KIND=jpim), PARAMETER :: zhook_out = 1 ! set number of each type of variable in my_namelist type -INTEGER, PARAMETER :: no_of_types = 3 -INTEGER, PARAMETER :: n_int = 2 +INTEGER, PARAMETER :: no_of_types = 2 +INTEGER, PARAMETER :: n_int = 1 INTEGER, PARAMETER :: n_real = 12 -INTEGER, PARAMETER :: n_log = 2 TYPE :: my_namelist SEQUENCE @@ -370,9 +348,6 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) REAL(KIND=real_jlslsm) :: ccrpm_min REAL(KIND=real_jlslsm) :: ccrpm_max REAL(KIND=real_jlslsm) :: z_burn_max - LOGICAL :: l_trif_fire - LOGICAL :: l_inferno - INTEGER :: ignition_method INTEGER :: flam_sm_func END TYPE my_namelist @@ -383,7 +358,7 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) CALL gc_get_communicator(my_comm, icode) CALL setup_nml_type(no_of_types, mpl_nml_type, n_int_in = n_int, & - n_real_in = n_real, n_log_in = n_log) + n_real_in = n_real) IF (mype == 0) THEN @@ -391,10 +366,7 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) IOMSG = iomessage) CALL check_iostat(errorstatus, "namelist jules_inferno", iomessage) - my_nml % ignition_method = ignition_method my_nml % flam_sm_func = flam_sm_func - my_nml % l_trif_fire = l_trif_fire - my_nml % l_inferno = l_inferno my_nml % flam_sm_low = flam_sm_low my_nml % flam_sm_up = flam_sm_up my_nml % flam_rhum_low = flam_rhum_low @@ -413,10 +385,7 @@ SUBROUTINE read_nml_jules_inferno (unitnumber) IF (mype /= 0) THEN - ignition_method = my_nml % ignition_method flam_sm_func = my_nml % flam_sm_func - l_trif_fire = my_nml % l_trif_fire - l_inferno = my_nml % l_inferno flam_sm_low = my_nml % flam_sm_low flam_sm_up = my_nml % flam_sm_up flam_rhum_low = my_nml % flam_rhum_low diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index bcdfebcf..8343ca23 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -274,9 +274,9 @@ SUBROUTINE check_jules_soil_biogeochem() USE jules_vegetation_mod, ONLY: & ! imported scalars - l_triffid, l_nitrogen + l_triffid, l_trif_fire, l_nitrogen, l_inferno -USE jules_inferno_mod, ONLY: l_trif_fire, l_inferno, z_burn_max +USE jules_inferno_mod, ONLY: z_burn_max USE ereport_mod, ONLY: ereport diff --git a/src/control/shared/jules_vegetation_mod.F90 b/src/control/shared/jules_vegetation_mod.F90 index 38411381..bf222c07 100644 --- a/src/control/shared/jules_vegetation_mod.F90 +++ b/src/control/shared/jules_vegetation_mod.F90 @@ -152,6 +152,17 @@ MODULE jules_vegetation_mod ! switch to prevent crop and natural PFTs competing l_trif_biocrop = .FALSE., & ! Switch to enable periodic harvesting of bioenergy crop PFTs + l_inferno = .FALSE., & + ! Switch used to control whether the Interactive fire scheme is used + l_trif_fire = .FALSE., & + ! Switch used to control whether interactive fire is used + ! T => if l_inferno is also true, g_burn is calculated in INFERNO +! and passed to TRIFFID to calculate emissions and vegetation + ! dynamics + ! T => if l_inferno is false, interactive fire is calculated via +! ancillary if provided, and is 0 if not provided + ! F => g_burn is calculated via ancillary if provided, and is 0 if +! not provided l_use_pft_psi = .FALSE., & ! Switch used to control what parameters are used in the calculation ! of the soil moisture stress factor @@ -222,6 +233,12 @@ MODULE jules_vegetation_mod ! Number of layers for canopy radiation model INTEGER :: & + ignition_method = 1, & + ! Switch for the calculation method of INFERNO fire ignitions + ! IGNITION_METHOD=1:Constant (1.67 per km2 per s) + ! IGNITION_METHOD=2:Constant (Human - 1.5 per km2 per s) + ! Varying (Lightning - see Pechony and Shindell,2009) + ! IGNITION_METHOD=3:Vary Human and Lightning (Pechony and Shindell,2009) fsmc_shape = 0, & ! shape of the soil moisture stress function fsmc ! 0: piece-wise linear in vol. soil moisture. @@ -239,6 +256,10 @@ MODULE jules_vegetation_mod stomata_model = imdi ! Chosen model of stomatal conductance. +INTEGER, PARAMETER :: ignition_constant = 1 +INTEGER, PARAMETER :: ignition_vary_natural = 2 +INTEGER, PARAMETER :: ignition_vary_natural_human = 3 + INTEGER :: & phenol_period = imdi, & ! Update frequency for leaf phenology (days) @@ -322,8 +343,8 @@ MODULE jules_vegetation_mod phenol_period, triffid_period, l_trait_phys, l_ht_compete, & l_bvoc_emis, l_o3_damage, can_model, can_rad_mod, ilayers, & frac_min, frac_seed, pow, l_landuse, l_leaf_n_resp_fix, l_stem_resp_fix, & - l_nitrogen, l_vegcan_soilfx, l_trif_crop, & - l_vegdrag_pft, l_rsl_scalar, & + l_nitrogen, l_vegcan_soilfx, l_trif_crop, l_trif_fire, & + l_inferno, ignition_method, l_vegdrag_pft, l_rsl_scalar, & cd_leaf, c1_usuh, c2_usuh, c3_usuh, dsj_coef, dsv_coef, jv25_coef, & act_j_coef, act_v_coef, & n_alloc_jmax, n_alloc_vcmax, n_day_photo_acclim, & @@ -412,14 +433,15 @@ SUBROUTINE check_jules_vegetation() ! Check options that depend on TRIFFID if it is not enabled IF ( .NOT. l_triffid .AND. ANY( [ l_veg_compete, l_trif_eq, l_landuse, & - l_ht_compete, l_nitrogen, l_trif_crop, l_trif_biocrop, & + l_ht_compete, l_nitrogen, l_trif_crop, l_trif_fire, l_trif_biocrop, & l_ag_expand ] ) ) THEN errcode = 101 WRITE(jules_message,'(A,8(1x,L1))') & 'These should be false when l_triffid = F: l_veg_compete, ' // & 'l_trif_eq, l_landuse, l_ht_compete, l_nitrogen, l_trif_crop, ' // & - 'l_trif_biocrop, l_ag_expand = ', l_veg_compete, l_trif_eq, & - l_landuse, l_ht_compete, l_nitrogen, l_trif_crop, l_trif_biocrop, l_ag_expand + 'l_trif_fire, l_trif_biocrop, l_ag_expand = ', l_veg_compete, l_trif_eq, & + l_landuse, l_ht_compete, l_nitrogen, l_trif_crop, l_trif_fire, & + l_trif_biocrop, l_ag_expand CALL ereport( "check_jules_vegetation", errcode, jules_message ) END IF @@ -753,6 +775,14 @@ SUBROUTINE check_jules_vegetation() 'prescribed fractions and crop model to be active') END IF +! Check a suitable ignition_method was given +IF ( ignition_method /= ignition_constant .AND. & + ignition_method /= ignition_vary_natural .AND. & + ignition_method /= ignition_vary_natural_human ) THEN + errcode = 101 + CALL ereport("check_jules_vegetation", errcode, & + 'ignition_method must be 1, 2 or 3') +END IF IF ( fsmc_shape == 1 .AND. .NOT. l_use_pft_psi ) THEN errcode = 101 @@ -825,6 +855,9 @@ SUBROUTINE print_nlist_jules_vegetation() WRITE(lineBuffer,*)' l_trif_biocrop = ',l_trif_biocrop CALL jules_print('jules_vegetation_mod',lineBuffer) +WRITE(lineBuffer,*)' l_trif_fire = ',l_trif_fire +CALL jules_print('jules_vegetation_mod',lineBuffer) + WRITE(lineBuffer,*)' l_trait_phys = ',l_trait_phys CALL jules_print('jules_vegetation_mod',lineBuffer) @@ -985,9 +1018,9 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) ! set number of each type of variable in my_namelist type INTEGER, PARAMETER :: no_of_types = 3 -INTEGER, PARAMETER :: n_int = 10 +INTEGER, PARAMETER :: n_int = 11 INTEGER, PARAMETER :: n_real = 11 + (n_photo_coef * 5) -INTEGER, PARAMETER :: n_log = 27 + npft_max +INTEGER, PARAMETER :: n_log = 29 + npft_max TYPE :: my_namelist SEQUENCE @@ -996,6 +1029,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) INTEGER :: can_model INTEGER :: can_rad_mod INTEGER :: ilayers + INTEGER :: ignition_method INTEGER :: photo_acclim_model INTEGER :: photo_act_model INTEGER :: photo_jv_model @@ -1032,6 +1066,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) LOGICAL :: l_trif_crop LOGICAL :: l_trif_biocrop LOGICAL :: l_ag_expand + LOGICAL :: l_trif_fire LOGICAL :: l_landuse LOGICAL :: l_nitrogen LOGICAL :: l_recon @@ -1039,6 +1074,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) LOGICAL :: l_stem_resp_fix LOGICAL :: l_scale_resp_pm LOGICAL :: l_vegcan_soilfx + LOGICAL :: l_inferno LOGICAL :: l_vegdrag_pft(npft_max) LOGICAL :: l_rsl_scalar LOGICAL :: l_spec_veg_z0 @@ -1067,6 +1103,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) my_nml % can_model = can_model my_nml % can_rad_mod = can_rad_mod my_nml % ilayers = ilayers + my_nml % ignition_method = ignition_method my_nml % photo_acclim_model = photo_acclim_model my_nml % photo_act_model = photo_act_model my_nml % photo_jv_model = photo_jv_model @@ -1103,6 +1140,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) my_nml % l_trif_crop = l_trif_crop my_nml % l_trif_biocrop = l_trif_biocrop my_nml % l_ag_expand = l_ag_expand + my_nml % l_trif_fire = l_trif_fire my_nml % l_landuse = l_landuse my_nml % l_nitrogen = l_nitrogen my_nml % l_recon = l_recon @@ -1110,6 +1148,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) my_nml % l_stem_resp_fix = l_stem_resp_fix my_nml % l_scale_resp_pm = l_scale_resp_pm my_nml % l_vegcan_soilfx = l_vegcan_soilfx + my_nml % l_inferno = l_inferno my_nml % l_vegdrag_pft = l_vegdrag_pft my_nml % l_rsl_scalar = l_rsl_scalar my_nml % l_spec_veg_z0 = l_spec_veg_z0 @@ -1127,6 +1166,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) can_model = my_nml % can_model can_rad_mod = my_nml % can_rad_mod ilayers = my_nml % ilayers + ignition_method = my_nml % ignition_method photo_acclim_model = my_nml % photo_acclim_model photo_act_model = my_nml % photo_act_model photo_jv_model = my_nml % photo_jv_model @@ -1163,6 +1203,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) l_trif_crop = my_nml % l_trif_crop l_trif_biocrop = my_nml % l_trif_biocrop l_ag_expand = my_nml % l_ag_expand + l_trif_fire = my_nml % l_trif_fire l_landuse = my_nml % l_landuse l_nitrogen = my_nml % l_nitrogen l_recon = my_nml % l_recon @@ -1170,6 +1211,7 @@ SUBROUTINE read_nml_jules_vegetation (unitnumber) l_stem_resp_fix = my_nml % l_stem_resp_fix l_scale_resp_pm = my_nml % l_scale_resp_pm l_vegcan_soilfx = my_nml % l_vegcan_soilfx + l_inferno = my_nml % l_inferno l_vegdrag_pft = my_nml % l_vegdrag_pft l_rsl_scalar = my_nml % l_rsl_scalar l_spec_veg_z0 = my_nml % l_spec_veg_z0 diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index 84edeb97..4b52d3c1 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -213,11 +213,10 @@ SUBROUTINE surf_couple_extra( & l_crop, l_fao_ref_evapotranspiration, & #endif l_triffid, l_trif_eq, l_phenol, phenol_period, triffid_period, & + l_inferno, ignition_method, & + ignition_vary_natural, ignition_vary_natural_human, & l_acclim, n_day_photo_acclim, l_red -USE jules_inferno_mod, ONLY: l_inferno, ignition_method, & - ignition_vary_natural, ignition_vary_natural_human - USE jules_irrig_mod, ONLY: l_irrig_dmd USE jules_water_tracers_mod, ONLY: n_wtrac_jls diff --git a/src/control/um/diagnostics_hyd.F90 b/src/control/um/diagnostics_hyd.F90 index f756cfb2..a3086b03 100644 --- a/src/control/um/diagnostics_hyd.F90 +++ b/src/control/um/diagnostics_hyd.F90 @@ -129,7 +129,7 @@ SUBROUTINE diagnostics_hyd( & ! INFERNO diagnostics USE jules_surface_types_mod, ONLY: npft -USE jules_inferno_mod, ONLY: l_inferno +USE jules_vegetation_mod, ONLY: l_inferno USE set_levels_list_mod, ONLY: set_levels_list USE set_pseudo_list_mod, ONLY: set_pseudo_list diff --git a/src/initialisation/shared/check_compatible_options_mod.F90 b/src/initialisation/shared/check_compatible_options_mod.F90 index 6db64700..12ef09fe 100644 --- a/src/initialisation/shared/check_compatible_options_mod.F90 +++ b/src/initialisation/shared/check_compatible_options_mod.F90 @@ -39,8 +39,7 @@ SUBROUTINE check_compatible_options(call_type) USE jules_surface_mod, ONLY: l_flake_model, l_aggregate USE jules_surface_types_mod, ONLY: urban_roof, npft, nnvg, ntype USE jules_urban_mod, ONLY: l_moruses_storage -USE jules_vegetation_mod, ONLY: l_triffid -USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire +USE jules_vegetation_mod, ONLY: l_triffid, l_inferno, l_trif_fire USE jules_water_resources_mod, ONLY: l_water_environment, & l_water_irrigation, l_water_resources,& l_water_transfers diff --git a/src/initialisation/standalone/init_inferno_mod.F90 b/src/initialisation/standalone/init_inferno_mod.F90 index 0327488c..3b2d24d4 100644 --- a/src/initialisation/standalone/init_inferno_mod.F90 +++ b/src/initialisation/standalone/init_inferno_mod.F90 @@ -15,8 +15,9 @@ SUBROUTINE init_inferno(nml_dir) USE jules_inferno_mod, ONLY: read_nml_jules_inferno, & print_nlist_jules_inferno, & - check_jules_inferno, & - l_inferno, l_trif_fire, ignition_method, & + check_jules_inferno + +USE jules_vegetation_mod, ONLY:l_inferno, l_trif_fire, ignition_method, & ignition_constant, ignition_vary_natural, & ignition_vary_natural_human diff --git a/src/initialisation/standalone/init_jules_sf_diags_mod.F90 b/src/initialisation/standalone/init_jules_sf_diags_mod.F90 index 713662f9..fcf8b5bf 100644 --- a/src/initialisation/standalone/init_jules_sf_diags_mod.F90 +++ b/src/initialisation/standalone/init_jules_sf_diags_mod.F90 @@ -40,9 +40,8 @@ SUBROUTINE set_sf_diag_switches USE jules_radiation_mod, ONLY: i_sea_alb_method -USE jules_vegetation_mod, ONLY: l_crop, l_fao_ref_evapotranspiration - -USE jules_inferno_mod, ONLY: l_inferno +USE jules_vegetation_mod, ONLY: l_crop, l_fao_ref_evapotranspiration, & + l_inferno USE sf_diags_mod, ONLY: sf_diag diff --git a/src/initialisation/standalone/init_vegetation.F90 b/src/initialisation/standalone/init_vegetation.F90 index 1b6a1b6e..a37df63b 100644 --- a/src/initialisation/standalone/init_vegetation.F90 +++ b/src/initialisation/standalone/init_vegetation.F90 @@ -36,8 +36,10 @@ SUBROUTINE init_vegetation(nml_dir) photo_act_pft, photo_act_gb, photo_jv_model, & jv_scale, jv_ntotal, stomata_model, & stomata_jacobs, stomata_medlyn, stomata_sox, & - l_trif_eq, triffid_period, & - check_jules_vegetation + l_inferno, l_trif_eq, triffid_period, & + ignition_method, check_jules_vegetation, & + ignition_constant, ignition_vary_natural, & + ignition_vary_natural_human USE logging_mod, ONLY: log_info, log_error, log_fatal @@ -174,6 +176,22 @@ SUBROUTINE init_vegetation(nml_dir) "Using the SOX model of stomatal conductance.") END SELECT +IF ( l_inferno ) THEN + CALL log_info("init_vegetation", & + "Interactive fires and emissions (INFERNO) will be diagnosed") + IF (ignition_method == ignition_constant ) THEN + CALL log_info("init_vegetation", & + "Constant or ubiquitous ignitions (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural ) THEN + CALL log_info("init_vegetation", & + "Constant human ignitions, varying lightning (INFERNO)") + ELSE IF (ignition_method == ignition_vary_natural_human ) THEN + CALL log_info("init_vegetation", & + "Fully prescribed ignitions (INFERNO)") + END IF +END IF + + ! Check that TRIFFID timestep (the coupling period) seems sensible ! In equilibrium mode, the coupling period should be sufficient to average ! out seasonal (and ideally interannual) variability, so a period >= 1yr diff --git a/src/science/fire/inferno/inferno_io_mod.F90 b/src/science/fire/inferno/inferno_io_mod.F90 index 39f3c8af..7ac99677 100644 --- a/src/science/fire/inferno/inferno_io_mod.F90 +++ b/src/science/fire/inferno/inferno_io_mod.F90 @@ -54,7 +54,7 @@ SUBROUTINE inferno_io( & ! Average Burned Area per PFT, and fire mortality rate USE jules_inferno_mod, ONLY: & - l_trif_fire, flam_rhum_low, flam_rhum_up, & + flam_rhum_low, flam_rhum_up, & flam_sm_low, flam_sm_up, flam_fuel_low, & flam_fuel_up, flam_rain_const, flam_sm_func @@ -62,6 +62,7 @@ SUBROUTINE inferno_io( & USE jules_surface_types_mod, ONLY: npft USE parkind1, ONLY: jprb +USE jules_vegetation_mod, ONLY: l_trif_fire USE timestep_mod, ONLY: timestep USE calc_c_comps_triffid_mod, ONLY: calc_c_comps_triffid diff --git a/src/science/fire/inferno/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 38e0da73..e985cf8f 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/inferno_mod.F90 @@ -81,7 +81,7 @@ SUBROUTINE calc_ignitions( & USE yomhook, ONLY: lhook, dr_hook USE parkind1, ONLY: jprb -USE jules_inferno_mod, ONLY: ignition_constant, ignition_vary_natural, & +USE jules_vegetation_mod, ONLY: ignition_constant, ignition_vary_natural, & ignition_vary_natural_human IMPLICIT NONE diff --git a/src/science/params/pftparm_io_mod.F90 b/src/science/params/pftparm_io_mod.F90 index 497305b4..c2786e96 100644 --- a/src/science/params/pftparm_io_mod.F90 +++ b/src/science/params/pftparm_io_mod.F90 @@ -99,7 +99,6 @@ MODULE pftparm_io fef_so2_io(npft_max) = rmdi, & fd_io(npft_max) = rmdi, & fire_mort_io(npft_max) = rmdi, & - fireveg_c_to_atmos_io(npft_max) = rmdi, & fl_o3_ct_io(npft_max) = rmdi, & fsmc_of_io(npft_max) = rmdi, & fsmc_p0_io(npft_max) = rmdi, & @@ -196,7 +195,7 @@ MODULE pftparm_io tlow_io, tupp_io, vint_io, & vsl_io, sug_yg_io, z0hm_pft_io, & z0hm_classic_pft_io, z0v_io, sox_a_io, & - sox_p50_io, sox_rp_min_io, fireveg_c_to_atmos_io + sox_p50_io, sox_rp_min_io CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='PFTPARM_IO' @@ -232,7 +231,7 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) ! set number of each type of variable in my_namelist type INTEGER, PARAMETER :: no_of_types = 2 INTEGER, PARAMETER :: n_int = 3 * npft_max -INTEGER, PARAMETER :: n_real = 109 * npft_max +INTEGER, PARAMETER :: n_real = 108 * npft_max TYPE :: my_namelist SEQUENCE @@ -296,7 +295,6 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) REAL(KIND=real_jlslsm) :: fef_nh3_io(npft_max) REAL(KIND=real_jlslsm) :: fef_dms_io(npft_max) REAL(KIND=real_jlslsm) :: fire_mort_io(npft_max) - REAL(KIND=real_jlslsm) :: fireveg_c_to_atmos_io(npft_max) REAL(KIND=real_jlslsm) :: fl_o3_ct_io(npft_max) REAL(KIND=real_jlslsm) :: fsmc_of_io(npft_max) REAL(KIND=real_jlslsm) :: fsmc_p0_io(npft_max) @@ -424,7 +422,6 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) my_nml % fef_nh3_io = fef_nh3_io my_nml % fef_dms_io = fef_dms_io my_nml % fire_mort_io = fire_mort_io - my_nml % fireveg_c_to_atmos_io = fireveg_c_to_atmos_io my_nml % fl_o3_ct_io = fl_o3_ct_io my_nml % fsmc_of_io = fsmc_of_io my_nml % fsmc_p0_io = fsmc_p0_io @@ -542,7 +539,6 @@ SUBROUTINE read_nml_jules_pftparm (unitnumber) fef_nh3_io = my_nml % fef_nh3_io fef_dms_io = my_nml % fef_dms_io fire_mort_io = my_nml % fire_mort_io - fireveg_c_to_atmos_io = my_nml % fireveg_c_to_atmos_io fl_o3_ct_io = my_nml % fl_o3_ct_io fsmc_of_io = my_nml % fsmc_of_io fsmc_p0_io = my_nml % fsmc_p0_io @@ -636,7 +632,7 @@ SUBROUTINE init_pftparm_allocated() fef_oc, fef_so2, fef_c2h4, & fef_c2h6, fef_c3h8, fef_hcho, & fef_mecho, fef_nh3, & - fef_dms, fire_mort, fireveg_c_to_atmos, & + fef_dms, fire_mort, & fl_o3_ct, fsmc_of, fsmc_p0, & sug_g0, g1_stomata, g_leaf_0, & glmin, gpp_st, sug_grec, & @@ -786,7 +782,6 @@ SUBROUTINE init_pftparm_allocated() ccwood_max(:) = ccwood_max_io(1:npft) ccwood_min(:) = ccwood_min_io(1:npft) fire_mort(:) = fire_mort_io(1:npft) -fireveg_c_to_atmos(:) = fireveg_c_to_atmos_io(1:npft) ! INFERNO emission parameters fef_bc(:) = fef_bc_io(1:npft) diff --git a/src/science/params/pftparm_mod.F90 b/src/science/params/pftparm_mod.F90 index d67e01e5..68978848 100644 --- a/src/science/params/pftparm_mod.F90 +++ b/src/science/params/pftparm_mod.F90 @@ -311,10 +311,8 @@ MODULE pftparm ! Wood (or Stem) minimum combustion completeness (kg/kg) ,ccwood_max(:) & ! Wood (or Stem) maximum combustion completeness (kg/kg) -,fire_mort(:) & +,fire_mort(:) ! Fire mortality per PFT -,fireveg_c_to_atmos(:) - ! Burnt vegetation carbon to atmosphere per PFT !----------------------------------------------------------------------------- ! Parameters for INFERNO emissions @@ -603,7 +601,6 @@ SUBROUTINE pftparm_alloc(npft) ALLOCATE( ccwood_min(npft)) ALLOCATE( ccwood_max(npft)) ALLOCATE( fire_mort(npft)) -ALLOCATE( fireveg_c_to_atmos(npft)) avg_ba(:) = rmdi ccleaf_min(:) = rmdi @@ -611,7 +608,6 @@ SUBROUTINE pftparm_alloc(npft) ccwood_min(:) = rmdi ccwood_max(:) = rmdi fire_mort(:) = rmdi -fireveg_c_to_atmos(:) = rmdi ! INFERNO emission parameters ALLOCATE( fef_bc(npft)) @@ -792,8 +788,6 @@ SUBROUTINE print_nlist_jules_pftparm() CALL jules_print('pftparm',lineBuffer) WRITE(lineBuffer,*)' fire_mort = ',fire_mort CALL jules_print('pftparm',lineBuffer) -WRITE(lineBuffer,*)' fireveg_c_to_atmos = ',fireveg_c_to_atmos -CALL jules_print('pftparm',lineBuffer) WRITE(lineBuffer,*)' fl_o3_ct = ',fl_o3_ct CALL jules_print('pftparm',lineBuffer) WRITE(lineBuffer,*)' fsmc_of = ',fsmc_of @@ -899,16 +893,14 @@ SUBROUTINE check_jules_pftparm(npft,nnpft) soil_model_4pool USE jules_vegetation_mod, ONLY: can_rad_mod, l_crop, l_trait_phys, & - l_use_pft_psi, l_bvoc_emis, & - l_o3_damage, photo_acclim_model, & + l_use_pft_psi, l_bvoc_emis, l_inferno, & + l_o3_damage, l_trif_fire, photo_acclim_model, & photo_act_model, photo_act_pft, & photo_farquhar, photo_model, & stomata_jacobs, stomata_medlyn, stomata_sox, & stomata_model, l_spec_veg_z0, l_sugar, & l_scale_resp_pm -USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire - USE jules_radiation_mod, ONLY: l_spec_albedo, l_albedo_obs, l_snow_albedo USE missing_data_mod, ONLY: rmdi @@ -1412,10 +1404,6 @@ SUBROUTINE check_jules_pftparm(npft,nnpft) ERROR = 1 CALL jules_print(routinename, "No value for fire_mort") END IF - IF ( ANY( ABS( fireveg_c_to_atmos(:) - rmdi ) < EPSILON(1.0) ) ) THEN - ERROR = 1 - CALL jules_print(routinename, "No value for fireveg_c_to_atmos") - END IF END IF IF ( l_o3_damage ) THEN diff --git a/src/science/params/trif_io_mod.F90 b/src/science/params/trif_io_mod.F90 index b11744b3..5a6a3ceb 100644 --- a/src/science/params/trif_io_mod.F90 +++ b/src/science/params/trif_io_mod.F90 @@ -33,6 +33,7 @@ MODULE trif_io ag_expand_io(npft_max) = imdi REAL(KIND=real_jlslsm) :: & + fireveg_c_to_atmos_io(npft_max) = rmdi, & g_area_io(npft_max) = rmdi, & g_grow_io(npft_max) = rmdi, & g_root_io(npft_max) = rmdi, & @@ -55,7 +56,7 @@ MODULE trif_io g_wood_io,lai_max_io,lai_min_io, & alloc_fast_io,alloc_med_io,alloc_slow_io, & dpm_rpm_ratio_io,retran_l_io,retran_r_io, & - harvest_ht_io + harvest_ht_io, fireveg_c_to_atmos_io CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='TRIF_IO' @@ -100,8 +101,8 @@ SUBROUTINE print_nlist_jules_triffid() CALL jules_print('trif_io',lineBuffer) WRITE(lineBuffer,*)' ag_expand_io = ',ag_expand_io CALL jules_print('trif_io',lineBuffer) -WRITE(lineBuffer,*)' harvest_ht_io = ',harvest_ht_io -CALL jules_print('harvest_ht_io',lineBuffer) + WRITE(lineBuffer,*)' harvest_ht_io = ',harvest_ht_io + CALL jules_print('harvest_ht_io',lineBuffer) CALL jules_print('trif_io', & '- - - - - - end of namelist - - - - - -') @@ -140,7 +141,7 @@ SUBROUTINE read_nml_jules_triffid (unitnumber) ! set number of each type of variable in my_namelist type INTEGER, PARAMETER :: no_of_types = 2 INTEGER, PARAMETER :: n_int = 4 * npft_max -INTEGER, PARAMETER :: n_real = 13 * npft_max +INTEGER, PARAMETER :: n_real = 14 * npft_max TYPE :: my_namelist SEQUENCE @@ -153,6 +154,7 @@ SUBROUTINE read_nml_jules_triffid (unitnumber) REAL(KIND=real_jlslsm) :: g_grow_io(npft_max) REAL(KIND=real_jlslsm) :: g_root_io(npft_max) REAL(KIND=real_jlslsm) :: g_wood_io(npft_max) + REAL(KIND=real_jlslsm) :: fireveg_c_to_atmos_io(npft_max) REAL(KIND=real_jlslsm) :: lai_max_io(npft_max) REAL(KIND=real_jlslsm) :: lai_min_io(npft_max) REAL(KIND=real_jlslsm) :: alloc_fast_io(npft_max) @@ -187,6 +189,7 @@ SUBROUTINE read_nml_jules_triffid (unitnumber) my_nml % g_grow_io = g_grow_io my_nml % g_root_io = g_root_io my_nml % g_wood_io = g_wood_io + my_nml % fireveg_c_to_atmos_io = fireveg_c_to_atmos_io my_nml % lai_max_io = lai_max_io my_nml % lai_min_io = lai_min_io my_nml % alloc_fast_io = alloc_fast_io @@ -210,6 +213,7 @@ SUBROUTINE read_nml_jules_triffid (unitnumber) g_grow_io = my_nml % g_grow_io g_root_io = my_nml % g_root_io g_wood_io = my_nml % g_wood_io + fireveg_c_to_atmos_io = my_nml % fireveg_c_to_atmos_io lai_max_io = my_nml % lai_max_io lai_min_io = my_nml % lai_min_io alloc_fast_io = my_nml % alloc_fast_io diff --git a/src/science/params/trif_mod.F90 b/src/science/params/trif_mod.F90 index 666b1728..131cc202 100644 --- a/src/science/params/trif_mod.F90 +++ b/src/science/params/trif_mod.F90 @@ -37,7 +37,11 @@ MODULE trif ! 0 = no (default) , 1 = yes . Used only if l_ag_expand=T REAL(KIND=real_jlslsm), ALLOCATABLE :: & - g_area(:) & + fireveg_c_to_atmos(:) & + ! Fraction of burnt carbon that goes to the atmosphere as CO2 instead + ! of in the soil. Based on mean whole-plant mortality factor from + ! Li et al (2012) table 2. +,g_area(:) & ! Disturbance rate (/360days). ,g_grow(:) & ! Rate of leaf growth (/360days) @@ -104,6 +108,7 @@ SUBROUTINE trif_alloc(npft, & ALLOCATE( harvest_freq(npft)) ALLOCATE( harvest_type(npft)) ALLOCATE( ag_expand(npft)) + ALLOCATE( fireveg_c_to_atmos(npft)) ALLOCATE( g_area(npft)) ALLOCATE( g_grow(npft)) ALLOCATE( g_root(npft)) @@ -121,6 +126,7 @@ SUBROUTINE trif_alloc(npft, & harvest_freq(:) = 0 harvest_type(:) = 0 ag_expand(:) = 0 + fireveg_c_to_atmos(:) = 0 g_area(:) = 0.0 g_grow(:) = 0.0 g_root(:) = 0.0 diff --git a/src/science/vegetation/soilcarb_jls.F90 b/src/science/vegetation/soilcarb_jls.F90 index ec399fd6..4946d6c3 100644 --- a/src/science/vegetation/soilcarb_jls.F90 +++ b/src/science/vegetation/soilcarb_jls.F90 @@ -45,8 +45,9 @@ SUBROUTINE soilcarb (land_pts, trif_pts, trif_index, & USE jules_soil_mod, ONLY: cs_min, sm_levels USE ancil_info, ONLY: dim_cslayer, nsoilt, dim_cs1 +USE jules_vegetation_mod, ONLY: l_trif_fire USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & - ccrpm_min, ccrpm_max, l_trif_fire + ccrpm_min, ccrpm_max USE dpm_rpm_mod, ONLY: dpm_rpm USE decay_mod, ONLY: decay diff --git a/src/science/vegetation/soilcarb_layers_jls_mod.F90 b/src/science/vegetation/soilcarb_layers_jls_mod.F90 index d924160b..5d057ced 100644 --- a/src/science/vegetation/soilcarb_layers_jls_mod.F90 +++ b/src/science/vegetation/soilcarb_layers_jls_mod.F90 @@ -42,13 +42,12 @@ SUBROUTINE soilcarb_layers (land_pts, trif_pts, trif_index, forw, r_gamma, & USE jules_vegetation_mod, ONLY: l_nitrogen USE jules_inferno_mod, ONLY: ccdpm_min, ccdpm_max, & - ccrpm_min, ccrpm_max, z_burn_max, & - l_trif_fire - + ccrpm_min, ccrpm_max, z_burn_max USE jules_soil_mod, ONLY: cs_min, dzsoil, sm_levels USE veg_param, ONLY: litc_norm USE pftparm, ONLY: rootd_ft USE ancil_info, ONLY: dim_cslayer, nsoilt, dim_cs1 +USE jules_vegetation_mod, ONLY: l_trif_fire USE root_frac_mod, ONLY: root_frac USE soilcarb_mix_mod, ONLY: soilcarb_mix USE dpm_rpm_mod, ONLY: dpm_rpm diff --git a/src/science/vegetation/triffid_jls.F90 b/src/science/vegetation/triffid_jls.F90 index 896f3e6e..2bb4bda6 100644 --- a/src/science/vegetation/triffid_jls.F90 +++ b/src/science/vegetation/triffid_jls.F90 @@ -128,9 +128,10 @@ SUBROUTINE triffid (land_pts, trif_pts, trif_index, forw, r_gamma, & USE jules_surface_mod, ONLY: cmass -USE pftparm, ONLY: a_wl, a_ws, b_wl, eta_sl, lma, sigl, fireveg_c_to_atmos +USE pftparm, ONLY: a_wl, a_ws, b_wl, eta_sl, lma, sigl -USE trif, ONLY: crop, harvest_freq, harvest_ht, harvest_type, lai_min +USE trif, ONLY: crop, harvest_freq, harvest_ht, harvest_type, lai_min, & + fireveg_c_to_atmos USE jules_soil_biogeochem_mod, ONLY: & ! imported scalar parameters @@ -404,10 +405,6 @@ SUBROUTINE triffid (land_pts, trif_pts, trif_index, forw, r_gamma, & ! Fraction of litter diverted as harvest. ! This fraction ends up in the product pools instead of in the soil. -! REAL(KIND=real_jlslsm), PARAMETER :: fire_ratio = 0.13 - ! Fraction of burnt carbon that goes to the atmosphere as CO2 instead - ! of in the soil. Based on mean whole-plant mortality factor from - ! Li et al (2012) table 2. !----------------------------------------------------------------------------- ! Local scalar variables. @@ -1169,7 +1166,6 @@ SUBROUTINE triffid (land_pts, trif_pts, trif_index, forw, r_gamma, & lit_n_fire_pft(l,n) = 0.0 END IF - ! veg_c_fire_emission_pft(l,n) = lit_c_fire_pft(l,n) * fire_ratio veg_c_fire_emission_pft(l,n) = lit_c_fire_pft(l,n) * fireveg_c_to_atmos(n) veg_c_fire_emission_gb(l) = veg_c_fire_emission_gb(l) + & diff --git a/src/science/vegetation/veg-veg2a_jls_mod.F90 b/src/science/vegetation/veg-veg2a_jls_mod.F90 index 6f384b7c..07b9670c 100644 --- a/src/science/vegetation/veg-veg2a_jls_mod.F90 +++ b/src/science/vegetation/veg-veg2a_jls_mod.F90 @@ -66,8 +66,8 @@ SUBROUTINE veg2( & USE jules_surface_types_mod, ONLY: npft, nnpft, ncpft, ntype USE jules_vegetation_mod, ONLY: frac_min, l_crop, & - l_trif_crop, can_model -USE jules_inferno_mod, ONLY: l_inferno, l_trif_fire + l_trif_crop, can_model, & + l_inferno, l_trif_fire USE veg_param, ONLY: litc_norm, agric From c76bcf83f378cd0d0e9d3b658dc6927954ca3e06 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Mon, 7 Sep 2026 07:32:47 +0100 Subject: [PATCH 16/20] fix metadata and g_burn --- .../jules-shared/jules-inferno/HEAD/rose-meta.conf | 2 +- rose-meta/jules-standalone/HEAD/rose-meta.conf | 11 +++++++++++ rose-meta/jules-standalone/versions.py | 1 - src/control/shared/jules_soil_biogeochem_mod.F90 | 4 ++-- .../standalone/params/init_triffid.inc | 5 +++-- src/initialisation/um/surf_couple_allocate_mod.F90 | 5 +++-- src/io/model_interface/populate_var.inc | 2 +- src/science/fire/inferno/inferno_mod.F90 | 2 +- src/science/params/trif_io_mod.F90 | 12 +++++++----- src/science/params/trif_mod.F90 | 4 ++-- 10 files changed, 31 insertions(+), 17 deletions(-) diff --git a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf index 4ca533e6..dab62cc0 100644 --- a/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-inferno/HEAD/rose-meta.conf @@ -57,7 +57,7 @@ url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JU [namelist:jules_inferno=flam_rain_const] compulsory=true description=Rainfall flammability scaling constant -range=0.0:1.0 +range=0.0: sort-key=Panel-J14 type=real url=https://metoffice.github.io/jules/latest/namelists/jules_inferno.nml.html#JULES_INFERNO::flam_rain_const diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index fc631e73..452fff6e 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -6262,6 +6262,7 @@ url=https://metoffice.github.io/jules/latest/namelists/triffid_params.nml.html#J compulsory=true description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. fail-if=len(this) != namelist:jules_surface_types=npft +length=: ns=namelist/JULES Science Settings/jules_pftparm/Other parameters range=0:1 sort-key=Panel-HO16 @@ -6471,6 +6472,16 @@ value-titles=Piece-wise linear in volumetric soil moisture, Piece-wise linear in values=0,1 widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget +[namelist:jules_vegetation=ignition_method] +compulsory=true +description=The method to use for ignitions +sort-key=Panel-I16a +url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::ignition_method +value-titles=(1) constant human and natural ignition sources, + =(2) constant human varying natural ignition sources, + =(3) varying human and natural ignition sources +values=1,2,3 + [namelist:jules_vegetation=ilayers] compulsory=true description=Number of layers for canopy radiation model diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 595a3161..11dc43f1 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -86,5 +86,4 @@ def upgrade(self, config, meta_config=None): self.add_setting( config, ["namelist:jules_triffid", "fireveg_c_to_atmos_io"], ",".join(["0.13"] * npft)) - return config, self.reports diff --git a/src/control/shared/jules_soil_biogeochem_mod.F90 b/src/control/shared/jules_soil_biogeochem_mod.F90 index 8343ca23..23bdc2ce 100644 --- a/src/control/shared/jules_soil_biogeochem_mod.F90 +++ b/src/control/shared/jules_soil_biogeochem_mod.F90 @@ -526,8 +526,8 @@ SUBROUTINE check_jules_soil_biogeochem() IF ( ABS( z_burn_max - rmdi ) < EPSILON(1.0) ) THEN CALL ereport(RoutineName, errorstatus, "z_burn_max not found") ELSE IF ( z_burn_max <= 0.0 .OR. z_burn_max > 10.0 ) THEN - CALL ereport(RoutineName, errorstatus, & - "z_burn_max must be positive & less than 10 meters") + CALL ereport(RoutineName, errorstatus, & + "z_burn_max must be positive & less than 10 meters") END IF END IF diff --git a/src/initialisation/standalone/params/init_triffid.inc b/src/initialisation/standalone/params/init_triffid.inc index 4627501c..7864d5cf 100644 --- a/src/initialisation/standalone/params/init_triffid.inc +++ b/src/initialisation/standalone/params/init_triffid.inc @@ -24,7 +24,7 @@ USE jules_vegetation_mod, ONLY: l_triffid, l_phenol, l_trif_crop, l_ag_expand, & USE trif, ONLY: crop, harvest_type, harvest_freq, ag_expand, & g_area, g_grow, g_root, g_wood, lai_max, lai_min, & alloc_fast, alloc_med, alloc_slow, dpm_rpm_ratio, & - retran_r, retran_l, harvest_ht + retran_r, retran_l, harvest_ht, fireveg_c_to_atmos USE trif_io, ONLY: jules_triffid, & crop_io, harvest_type_io, harvest_freq_io, & @@ -32,7 +32,7 @@ USE trif_io, ONLY: jules_triffid, & g_wood_io,lai_max_io,lai_min_io, & alloc_fast_io,alloc_med_io,alloc_slow_io, & dpm_rpm_ratio_io,retran_l_io,retran_r_io, & - harvest_ht_io + harvest_ht_io, fireveg_c_to_atmos_io USE errormessagelength_mod, ONLY: errormessagelength @@ -106,6 +106,7 @@ crop(:) = crop_io(1:npft) harvest_freq(:) = harvest_freq_io(1:npft) harvest_type(:) = harvest_type_io(1:npft) ag_expand(:) = ag_expand_io(1:npft) +fireveg_c_to_atmos(:) = fireveg_c_to_atmos_io(1:npft) g_area(:) = g_area_io(1:npft) g_grow(:) = g_grow_io(1:npft) g_root(:) = g_root_io(1:npft) diff --git a/src/initialisation/um/surf_couple_allocate_mod.F90 b/src/initialisation/um/surf_couple_allocate_mod.F90 index 56174ac5..0497b1ac 100644 --- a/src/initialisation/um/surf_couple_allocate_mod.F90 +++ b/src/initialisation/um/surf_couple_allocate_mod.F90 @@ -64,7 +64,7 @@ SUBROUTINE surf_couple_allocate (land_field, ntiles, sm_levels, & ! namelist variables: crop_io, harvest_freq_io, & harvest_type_io, ag_expand_io, & - g_area_io, g_grow_io, & + g_area_io, g_grow_io, fireveg_c_to_atmos_io, & g_root_io, g_wood_io, lai_max_io, & lai_min_io, alloc_fast_io, alloc_med_io, & alloc_slow_io, dpm_rpm_ratio_io, retran_l_io, & @@ -73,7 +73,7 @@ SUBROUTINE surf_couple_allocate (land_field, ntiles, sm_levels, & USE trif, ONLY: & crop, harvest_freq, & harvest_type, ag_expand, & - g_area, g_grow, & + g_area, g_grow, fireveg_c_to_atmos, & g_root, g_wood, lai_max, & lai_min, alloc_fast, alloc_med, & alloc_slow, dpm_rpm_ratio, retran_l, & @@ -312,6 +312,7 @@ SUBROUTINE surf_couple_allocate (land_field, ntiles, sm_levels, & harvest_freq(:) = harvest_freq_io(1:npft) harvest_type(:) = harvest_type_io(1:npft) ag_expand(:) = ag_expand_io(1:npft) + fireveg_c_to_atmos(:) = fireveg_c_to_atmos_io(1:npft) g_area(:) = g_area_io(1:npft) g_grow(:) = g_grow_io(1:npft) g_root(:) = g_root_io(1:npft) diff --git a/src/io/model_interface/populate_var.inc b/src/io/model_interface/populate_var.inc index 5b1ca8af..f4db74f5 100644 --- a/src/io/model_interface/populate_var.inc +++ b/src/io/model_interface/populate_var.inc @@ -1554,7 +1554,7 @@ CASE ( 'deposition_n' ) trif_vars%deposition_n_gb(:) = const_val END IF -CASE ( 'trif_vars%g_burn_pft' ) +CASE ( 'g_burn_pft' ) IF ( PRESENT(cube) ) THEN cube_land = map_to_land(cube) CALL cube_get_data(cube_land, trif_vars%g_burn_pft) diff --git a/src/science/fire/inferno/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index e985cf8f..3afd6246 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/inferno_mod.F90 @@ -280,7 +280,7 @@ SUBROUTINE calc_flam( & rain_rate = rain_l * s_in_day ! convert rain rate from kg/m2/s to mm/day -flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & +flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & * EXP( cr * rain_rate) ,1.0) ,0.0) !flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & ! * EXP( cr * s_in_day * rain_l), 1.0), 0.0) diff --git a/src/science/params/trif_io_mod.F90 b/src/science/params/trif_io_mod.F90 index 5a6a3ceb..027a7796 100644 --- a/src/science/params/trif_io_mod.F90 +++ b/src/science/params/trif_io_mod.F90 @@ -71,6 +71,8 @@ SUBROUTINE print_nlist_jules_triffid() WRITE(lineBuffer,*)' crop_io = ',crop_io CALL jules_print('trif_io',lineBuffer) +WRITE(lineBuffer,*)' fireveg_c_to_atmos_io = ',fireveg_c_to_atmos_io +CALL jules_print('trif_io',lineBuffer) WRITE(lineBuffer,*)' g_area_io = ',g_area_io CALL jules_print('trif_io',lineBuffer) WRITE(lineBuffer,*)' g_grow_io = ',g_grow_io @@ -101,8 +103,8 @@ SUBROUTINE print_nlist_jules_triffid() CALL jules_print('trif_io',lineBuffer) WRITE(lineBuffer,*)' ag_expand_io = ',ag_expand_io CALL jules_print('trif_io',lineBuffer) - WRITE(lineBuffer,*)' harvest_ht_io = ',harvest_ht_io - CALL jules_print('harvest_ht_io',lineBuffer) +WRITE(lineBuffer,*)' harvest_ht_io = ',harvest_ht_io +CALL jules_print('harvest_ht_io',lineBuffer) CALL jules_print('trif_io', & '- - - - - - end of namelist - - - - - -') @@ -150,11 +152,11 @@ SUBROUTINE read_nml_jules_triffid (unitnumber) INTEGER :: harvest_type_io(npft_max) INTEGER :: ag_expand_io(npft_max) REAL(KIND=real_jlslsm) :: harvest_ht_io(npft_max) + REAL(KIND=real_jlslsm) :: fireveg_c_to_atmos_io(npft_max) REAL(KIND=real_jlslsm) :: g_area_io(npft_max) REAL(KIND=real_jlslsm) :: g_grow_io(npft_max) REAL(KIND=real_jlslsm) :: g_root_io(npft_max) REAL(KIND=real_jlslsm) :: g_wood_io(npft_max) - REAL(KIND=real_jlslsm) :: fireveg_c_to_atmos_io(npft_max) REAL(KIND=real_jlslsm) :: lai_max_io(npft_max) REAL(KIND=real_jlslsm) :: lai_min_io(npft_max) REAL(KIND=real_jlslsm) :: alloc_fast_io(npft_max) @@ -185,11 +187,11 @@ SUBROUTINE read_nml_jules_triffid (unitnumber) my_nml % harvest_type_io = harvest_type_io my_nml % ag_expand_io = ag_expand_io my_nml % harvest_ht_io = harvest_ht_io + my_nml % fireveg_c_to_atmos_io = fireveg_c_to_atmos_io my_nml % g_area_io = g_area_io my_nml % g_grow_io = g_grow_io my_nml % g_root_io = g_root_io my_nml % g_wood_io = g_wood_io - my_nml % fireveg_c_to_atmos_io = fireveg_c_to_atmos_io my_nml % lai_max_io = lai_max_io my_nml % lai_min_io = lai_min_io my_nml % alloc_fast_io = alloc_fast_io @@ -209,11 +211,11 @@ SUBROUTINE read_nml_jules_triffid (unitnumber) harvest_type_io = my_nml % harvest_type_io ag_expand_io = my_nml % ag_expand_io harvest_ht_io = my_nml % harvest_ht_io + fireveg_c_to_atmos_io = my_nml % fireveg_c_to_atmos_io g_area_io = my_nml % g_area_io g_grow_io = my_nml % g_grow_io g_root_io = my_nml % g_root_io g_wood_io = my_nml % g_wood_io - fireveg_c_to_atmos_io = my_nml % fireveg_c_to_atmos_io lai_max_io = my_nml % lai_max_io lai_min_io = my_nml % lai_min_io alloc_fast_io = my_nml % alloc_fast_io diff --git a/src/science/params/trif_mod.F90 b/src/science/params/trif_mod.F90 index 131cc202..eea78d69 100644 --- a/src/science/params/trif_mod.F90 +++ b/src/science/params/trif_mod.F90 @@ -40,7 +40,7 @@ MODULE trif fireveg_c_to_atmos(:) & ! Fraction of burnt carbon that goes to the atmosphere as CO2 instead ! of in the soil. Based on mean whole-plant mortality factor from - ! Li et al (2012) table 2. + ! Li et al (2012) table 2. ,g_area(:) & ! Disturbance rate (/360days). ,g_grow(:) & @@ -126,7 +126,7 @@ SUBROUTINE trif_alloc(npft, & harvest_freq(:) = 0 harvest_type(:) = 0 ag_expand(:) = 0 - fireveg_c_to_atmos(:) = 0 + fireveg_c_to_atmos(:) = 0.0 g_area(:) = 0.0 g_grow(:) = 0.0 g_root(:) = 0.0 From 4fe368a634c8de3e2eb4f9afab04aead5d9a34f7 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:30:55 +0100 Subject: [PATCH 17/20] passing stem tests -doc/metadata updates --- doc/source/namelists/fire.nml.rst | 2 +- doc/source/namelists/triffid_params.nml.rst | 2 +- .../jules-vegetation/HEAD/rose-meta.conf | 1 + .../jules-standalone/HEAD/rose-meta.conf | 22 +++++++++---------- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index dc81522b..b864bf3d 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -67,7 +67,7 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :type: real :default: 0.2 - Parameter controlling the depth to which fire burns soil litter carbon in metres. At depths shallower than this value, the fire can burn soil carbon in the two litter pools (dpm and rpm). If z_burn_max falls within a layer only a proportion of the soil carbon is burnt. Only used with layered soil carbon scheme (:nml:mem:`JULES_SOIL_BIOGEOCHEM::l_layeredc` = TRUE) and fire (either :nml:mem:`JULES_INFERNO::l_trif_fire` or :nml:mem:`JULES_INFERNO::l_inferno` or both). In reality the burn depth varies so please check whether the default value of 0.2 is suitable for your application. + Parameter controlling the depth to which fire burns soil litter carbon in metres. At depths shallower than this value, the fire can burn soil carbon in the two litter pools (dpm and rpm). If z_burn_max falls within a layer only a proportion of the soil carbon is burnt. Only used with layered soil carbon scheme (:nml:mem:`JULES_SOIL_BIOGEOCHEM::l_layeredc` = TRUE) and fire (either :nml:mem:`JULES_VEGETATION::l_trif_fire` or :nml:mem:`JULES_VEGETATION::l_inferno` or both). In reality the burn depth varies so please check whether the default value of 0.2 is suitable for your application. .. nml:member:: flam_sm_func diff --git a/doc/source/namelists/triffid_params.nml.rst b/doc/source/namelists/triffid_params.nml.rst index 2d605044..e348bdc3 100644 --- a/doc/source/namelists/triffid_params.nml.rst +++ b/doc/source/namelists/triffid_params.nml.rst @@ -183,7 +183,7 @@ This namelist is used to read PFT parameters that are only needed by the dynamic :type: real(npft) :default: None - Only used if :nml:mem:`JULES_INFERNO::l_trif_fire` = TRUE. + Only used if :nml:mem:`JULES_VEGETATION::l_trif_fire` = TRUE. Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. Based on mean whole-plant mortality factor from Li et al (2012) table 2. diff --git a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf index 5c8f7f03..5adbff2d 100644 --- a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf @@ -102,6 +102,7 @@ description=Use interactive fire linked to INFERNO including interactive fire em fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); sort-key=Panel-I02c trigger=namelist:jules_pftparm=fire_mort_io: .true. +trigger=namelist:jules_triffid=fireveg_c_to_atmos_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_trif_fire diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index 452fff6e..746c941e 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -6234,6 +6234,16 @@ length=: type=real url=https://metoffice.github.io/jules/latest/namelists/triffid_params.nml.htm#JULES_TRIFFID::dpm_rpm_ratio_io +[namelist:jules_triffid=fireveg_c_to_atmos_io] +compulsory=true +description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. +fail-if=len(this) != namelist:jules_surface_types=npft +length=: +ns=namelist/JULES Science Settings/jules_pftparm/Other parameters +range=0:1 +type=real +url=https://metoffice.github.io/jules/latest/namelists/triffid_params.nml.html#JULES_TRIFFID::fireveg_c_to_atmos_io + [namelist:jules_triffid=g_area_io] compulsory=true description=Disturbance rate (/360days) @@ -6258,18 +6268,6 @@ length=: type=real url=https://metoffice.github.io/jules/latest/namelists/triffid_params.nml.html#JULES_TRIFFID::g_root_io -[namelist:jules_triffid=fireveg_c_to_atmos_io] -compulsory=true -description=Fraction of burnt carbon that goes to the atmosphere as CO2 instead of in the soil. -fail-if=len(this) != namelist:jules_surface_types=npft -length=: -ns=namelist/JULES Science Settings/jules_pftparm/Other parameters -range=0:1 -sort-key=Panel-HO16 -type=real -url=https://metoffice.github.io/jules/latest/namelists/triffid_params.nml.html#JULES_TRIFFID::fireveg_c_to_atmos_io - - [namelist:jules_triffid=g_wood_io] compulsory=true description=Turnover rate for woody biomass (/360days) From aabd18766b4925b74d5165e63dd31c87b4333db6 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Mon, 14 Sep 2026 17:04:16 +0100 Subject: [PATCH 18/20] minor update --- rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf index 5adbff2d..8425ce1f 100644 --- a/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf +++ b/rose-meta/jules-shared/jules-vegetation/HEAD/rose-meta.conf @@ -101,8 +101,8 @@ compulsory=true description=Use interactive fire linked to INFERNO including interactive fire emissions. fail-if=this == '.true.' and (namelist:jules_vegetation=l_trif_eq == '.true.'); sort-key=Panel-I02c -trigger=namelist:jules_pftparm=fire_mort_io: .true. -trigger=namelist:jules_triffid=fireveg_c_to_atmos_io: .true.; +trigger=namelist:jules_pftparm=fire_mort_io: .true.; + =namelist:jules_triffid=fireveg_c_to_atmos_io: .true.; type=logical url=https://metoffice.github.io/jules/latest/namelists/jules_vegetation.nml.html#JULES_VEGETATION::l_trif_fire From b4627d752ea24e04881bd3041e0d1723bb6de756 Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Tue, 15 Sep 2026 08:36:23 +0100 Subject: [PATCH 19/20] smaller additions --- doc/source/namelists/fire.nml.rst | 4 ++-- src/science/fire/inferno/inferno_mod.F90 | 15 ++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index b864bf3d..fc8a8c05 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -3,10 +3,10 @@ This file contains two namelists one called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that contains switches used to calculate the different fire weather indices available. The second namelist is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` -``JULES_FIRE_WEATHER_INDEX`` namelist members +``FIRE_SWITCHES`` namelist members ----------------------------------- -.. nml:namelist:: JULES_FIRE_WEATHER_INDEX +.. nml:namelist:: FIRE_SWITCHES .. nml:member:: l_fire diff --git a/src/science/fire/inferno/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 3afd6246..f3597b30 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/inferno_mod.F90 @@ -211,7 +211,7 @@ SUBROUTINE calc_flam( & ! Exponential decay parameter for relationship between soil moisture ! and flammability (> 0.0) (flam_sm_func=2) flam_rain_const - ! + ! decay function for exponential relationship between rain & flammability. INTEGER, INTENT(IN) :: & flam_sm_func @@ -233,12 +233,12 @@ SUBROUTINE calc_flam( & b = 5.02808, & f = 8.1328e-03, & h=-3.49149, & - Ts = 373.16, & + Ts = 373.16 ! Water saturation temperature - cr=-2.0 * s_in_day - ! Precipitation factor (-2(day/mm)*(kg/m2/s)) REAL(KIND=real_jlslsm) :: & + cr, & + ! Precipitation factor (mm/day) Z_l, & ! Component of the Goff-Gratch saturation vapor pressure TsbyT_l, & @@ -279,13 +279,10 @@ SUBROUTINE calc_flam( & rain_rate = rain_l * s_in_day ! convert rain rate from kg/m2/s to mm/day +cr = -flam_rain_const / s_in_day flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & - * EXP( cr * rain_rate) ,1.0) ,0.0) -!flam_l = MAX(MIN(10.0**Z_l * f_rhum_l * fuel_l * f_sm_l & -! * EXP( cr * s_in_day * rain_l), 1.0), 0.0) -! EJB add units here for rain or add rain as a separate function - make flam_rain > 0 - + * EXP( cr * rain_rate) ,1.0) ,0.0) IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN From 29b0096b212eac5e63fc5ec9094fd24f1de9e1ec Mon Sep 17 00:00:00 2001 From: eleanorgb <38913404+eleanorgb@users.noreply.github.com> Date: Tue, 15 Sep 2026 09:11:35 +0100 Subject: [PATCH 20/20] reverting compiler stuff --- rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json | 4 ++-- rose-stem/app/fab_jules/bin/intel_rivers.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json b/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json index a1571c4d..9e0a567d 100644 --- a/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json +++ b/rose-stem/app/fab_jules/bin/gfortran_10_plus_rivers.json @@ -140,7 +140,7 @@ "/src/science/params/trif_mod.F90", "/src/science/params/pftparm_mod.F90", "/src/science/params/ecosse_param_mod.F90", - "/src/science/fire/fire_weather_index/fire_mod.F90", + "/src/science/fire/fire_mod.F90", "/src/science/surface/sf_diags_mod.F90", "/src/science/params/urban_param_mod.F90", "/src/params/imogen/imogen_time.F90", @@ -241,4 +241,4 @@ "-fopenmp", "-Wl,--rpath=/data/apps/spack/opt/linux-rhel9-zen2/gcc-12.2.0/netcdf-fortran-4.6.1-3bu2pvjyujppdgn446jxste4k7vq6xay/lib" ] -} \ No newline at end of file +} diff --git a/rose-stem/app/fab_jules/bin/intel_rivers.json b/rose-stem/app/fab_jules/bin/intel_rivers.json index 38180141..04d24e92 100644 --- a/rose-stem/app/fab_jules/bin/intel_rivers.json +++ b/rose-stem/app/fab_jules/bin/intel_rivers.json @@ -139,7 +139,7 @@ "/src/science/params/trif_mod.F90", "/src/science/params/pftparm_mod.F90", "/src/science/params/ecosse_param_mod.F90", - "/src/science/fire/fire_weather_index/fire_mod.F90", + "/src/science/fire/fire_mod.F90", "/src/science/surface/sf_diags_mod.F90", "/src/science/params/urban_param_mod.F90", "/src/params/imogen/imogen_time.F90",