From 771ed70ed84ae6caf769a0d3fa54a9f15c556856 Mon Sep 17 00:00:00 2001 From: Yaswant Pradhan <2984440+yaswant@users.noreply.github.com> Date: Wed, 22 Jul 2026 15:53:37 +0100 Subject: [PATCH 01/14] Update GitHub Actions workflows (#133) --- .github/pull_request_template.md | 31 +++++++------------ .github/workflows/check-cr-approved.yaml | 21 +++++++++---- .github/workflows/cla-check.yaml | 21 ++++++++++++- .github/workflows/track-review-project.yaml | 19 +++++++++--- .../workflows/trigger-project-workflow.yaml | 19 +++++++++--- .github/workflows/umdp3_fixer.yaml | 18 ++++++++--- .github/workflows/user-guide.yaml | 30 +++++++++--------- .github/zizmor.yml | 15 +++++++++ doc/pyproject.toml | 6 ++++ 9 files changed, 123 insertions(+), 57 deletions(-) create mode 100644 .github/zizmor.yml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e3f44db6..7427f114 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,5 +1,7 @@ # PR Summary + + Sci/Tech Reviewer: Code Reviewer: @@ -26,20 +28,16 @@ Code Reviewer: - [ ] I have performed a self-review of my own code - [ ] My code follows the project's style guidelines -- [ ] Comments have been included that aid undertanding and enhance the - readability of the code +- [ ] Comments have been included that aid understanding and enhance the readability of the code - [ ] My changes generate no new warnings - [ ] If editing `rose-meta/jules-shared` then have you supplied a linked UM and LFRic Apps PR? ## Testing - [ ] I have tested this change locally, using the JULES rose-stem suite -- [ ] If shared files have been modified, I have run the UM and LFRic Apps rose - stem suites -- [ ] If any tests fail (rose-stem or CI) the reason is understood and - acceptable (eg. kgo changes) -- [ ] I have added tests to cover new functionality as appropriate (eg. system - tests, unit tests, etc.) +- [ ] If shared files have been modified, I have run the UM and LFRic Apps rose stem suites +- [ ] If any tests fail (rose-stem or CI) the reason is understood and acceptable (eg. kgo changes) +- [ ] I have added tests to cover new functionality as appropriate (eg. system tests, unit tests, etc.) @@ -55,28 +53,21 @@ Code Reviewer: ## Performance Impact -- [ ] Performance of the code has been considered and, if applicable, suitable - performance measurements have been conducted +- [ ] Performance of the code has been considered and, if applicable, suitable performance measurements have been conducted ## AI Assistance and Attribution -- [ ] Some of the content of this change has been produced with the assistance - of _Generative AI tool name_ (e.g., Met Office Github Copilot Enterprise, - Github Copilot Personal, ChatGPT GPT-4, etc) and I have followed the - [Simulation Systems AI policy](https://metoffice.github.io/simulation-systems/FurtherDetails/ai.html) - (including attribution labels) +- [ ] Some of the content of this change has been produced with the assistance of _Generative AI tool name_ (e.g., Met Office Github Copilot Enterprise, Github Copilot Personal, ChatGPT GPT-4, etc) and I have followed the [Simulation Systems AI policy](https://metoffice.github.io/simulation-systems/FurtherDetails/ai.html) (including attribution labels) ## Documentation -- [ ] Where appropriate I have updated documentation related to this change and - confirmed that it builds correctly +- [ ] Where appropriate I have updated documentation related to this change and confirmed that it builds correctly ## Approvals -Please request all relevant approvals. See the CodeOwners.txt file for section -owners. +Please request all relevant approvals. See the CodeOwners.txt file for section owners. ### Technical @@ -93,7 +84,7 @@ owners. - [ ] Hydrology - [ ] Vegetation - [ ] Veg3 RED Demography -- [ ] Biogechemistry +- [ ] Biogeochemistry - [ ] Biogenic fluxes - [ ] Fire - [ ] Lakes diff --git a/.github/workflows/check-cr-approved.yaml b/.github/workflows/check-cr-approved.yaml index 9b66712a..11fdb34c 100644 --- a/.github/workflows/check-cr-approved.yaml +++ b/.github/workflows/check-cr-approved.yaml @@ -1,11 +1,20 @@ +# ----------------------------------------------------------------------------- +# (C) Crown copyright Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +# ----------------------------------------------------------------------------- + name: Check CR approved on: - pull_request_review: - types: [submitted, edited, dismissed] - workflow_dispatch: + pull_request_review: + types: [submitted, edited, dismissed] + workflow_dispatch: jobs: - check_cr_approved: - if: ${{ github.event.pull_request.number }} - uses: MetOffice/growss/.github/workflows/check-cr-approved.yaml@main + check_cr_approved: + permissions: + contents: read # Required to evaluate the event trigger metadata safely + pull-requests: read # Required to read pull request details + if: ${{ github.event.pull_request.number }} + uses: MetOffice/growss/.github/workflows/check-cr-approved.yaml@0f9ffe6a138ae9943053621916a850a075997db8 # v1.0.0 diff --git a/.github/workflows/cla-check.yaml b/.github/workflows/cla-check.yaml index 18878145..aa7e3118 100644 --- a/.github/workflows/cla-check.yaml +++ b/.github/workflows/cla-check.yaml @@ -1,10 +1,29 @@ +# ----------------------------------------------------------------------------- +# (C) Crown copyright Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +# ----------------------------------------------------------------------------- + +# Check Contributor Licence Agreement + name: Legal on: pull_request_target: +concurrency: + # Automatically cancels the workflow run instantly before the + # engine can parse empty jobs and generate notification emails + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: ${{ github.event.pull_request.head.repo.full_name != 'MetOffice/jules' }} + +permissions: {} + jobs: cla: - uses: MetOffice/growss/.github/workflows/cla-check.yaml@main + permissions: + contents: read # Required to evaluate the event trigger metadata safely + pull-requests: write # Required for the downstream engine to post status comments on the PR + uses: MetOffice/growss/.github/workflows/cla-check.yaml@0f9ffe6a138ae9943053621916a850a075997db8 # v1.0.0 with: cla-url: 'https://github.com/MetOffice/jules/blob/main/CLA.md' diff --git a/.github/workflows/track-review-project.yaml b/.github/workflows/track-review-project.yaml index 639477cd..1ab60122 100644 --- a/.github/workflows/track-review-project.yaml +++ b/.github/workflows/track-review-project.yaml @@ -1,3 +1,9 @@ +# ----------------------------------------------------------------------------- +# (C) Crown copyright Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +# ----------------------------------------------------------------------------- + name: Track Review Project on: @@ -7,11 +13,14 @@ on: - completed permissions: - actions: read - contents: read - pull-requests: write + contents: read # Required to evaluate the event trigger metadata safely jobs: track_review_project: - uses: MetOffice/growss/.github/workflows/track-review-project.yaml@main - secrets: inherit + permissions: + actions: read # Required to check out code or parse files safely + contents: read # Required to read the upstream triggered workflow run artifact status + pull-requests: write # Required for the downstream engine to add comments or update metadata on the PR + uses: MetOffice/growss/.github/workflows/track-review-project.yaml@0f9ffe6a138ae9943053621916a850a075997db8 # v1.0.0 + secrets: + PROJECT_ACTION_PAT: ${{ secrets.PROJECT_ACTION_PAT }} diff --git a/.github/workflows/trigger-project-workflow.yaml b/.github/workflows/trigger-project-workflow.yaml index ccb7a55b..69e58c93 100644 --- a/.github/workflows/trigger-project-workflow.yaml +++ b/.github/workflows/trigger-project-workflow.yaml @@ -1,3 +1,9 @@ +# ----------------------------------------------------------------------------- +# (C) Crown copyright Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +# ----------------------------------------------------------------------------- + name: Trigger Review Project on: @@ -7,11 +13,14 @@ on: pull_request_review_comment: permissions: - actions: read - contents: read - pull-requests: write + contents: read # Required to evaluate the event trigger metadata safely jobs: trigger_project_workflow: - uses: MetOffice/growss/.github/workflows/trigger-project-workflow.yaml@main - secrets: inherit + if: github.repository == 'MetOffice/jules' + + permissions: + actions: read # Required to check out code or parse files safely + contents: read # Required to read the upstream triggered workflow run artifact status + pull-requests: write # Required for the downstream engine to add comments or update metadata on the PR + uses: MetOffice/growss/.github/workflows/trigger-project-workflow.yaml@0f9ffe6a138ae9943053621916a850a075997db8 # v1.0.0 diff --git a/.github/workflows/umdp3_fixer.yaml b/.github/workflows/umdp3_fixer.yaml index 6f265be6..da2938f5 100644 --- a/.github/workflows/umdp3_fixer.yaml +++ b/.github/workflows/umdp3_fixer.yaml @@ -1,10 +1,18 @@ +# ----------------------------------------------------------------------------- +# (C) Crown copyright Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +# ----------------------------------------------------------------------------- + name: umdp3 Fixer on: - pull_request: - types: [opened, synchronize, reopened] - workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: jobs: - umdp3_fixer: - uses: MetOffice/growss/.github/workflows/umdp3_fixer.yaml@main + umdp3_fixer: + permissions: + contents: read + uses: MetOffice/growss/.github/workflows/umdp3_fixer.yaml@0f9ffe6a138ae9943053621916a850a075997db8 # v1.0.0 diff --git a/.github/workflows/user-guide.yaml b/.github/workflows/user-guide.yaml index 345965a9..4077ef2d 100644 --- a/.github/workflows/user-guide.yaml +++ b/.github/workflows/user-guide.yaml @@ -42,33 +42,33 @@ jobs: steps: - name: Check deployment conditions id: check-deploy + env: + GH_REPOSITORY: ${{ github.repository }} + GH_REF_NAME: ${{ github.ref_name }} + GH_EVENT_NAME: ${{ github.event_name }} run: | - if [[ "${{ github.repository }}" == "MetOffice/jules" && ("${{ github.ref_name }}" == "main" || "${{ github.ref_name }}" == "stable") && ("${{ github.event_name }}" == "push" || "${{ github.event_name }}" == "merge_group" || "${{ github.event_name }}" == "release" || "${{ github.event_name }}" == "workflow_dispatch") ]]; then + if [[ "$GH_REPOSITORY" == "MetOffice/jules" && ("$GH_REF_NAME" == "main" || "$GH_REF_NAME" == "stable") && ("$GH_EVENT_NAME" == "push" || "$GH_EVENT_NAME" == "merge_group" || "$GH_EVENT_NAME" == "release" || "$GH_EVENT_NAME" == "workflow_dispatch") ]]; then echo "should-deploy=true" >> $GITHUB_OUTPUT else echo "should-deploy=false" >> $GITHUB_OUTPUT fi - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: path: ${{ env.JULES_PATH }} # Get all refs to build historic versions fetch-depth: 0 + persist-credentials: false - name: Setup uv with Python ${{ env.PYTHON_VRSN }} - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 with: python-version: ${{ env.PYTHON_VRSN }} - - - name: Cache uv venv - uses: actions/cache@v4 - with: - path: ${{ env.VENV_PATH }} - key: ${{ runner.os }}-uv-${{ env.PYTHON_VRSN }}-${{ hashFiles('doc/pyproject.toml', 'doc/uv.lock') }} - restore-keys: | - ${{ runner.os }}-uv-${{ env.PYTHON_VRSN }}- - ${{ runner.os }}-uv- + enable-cache: false + cache-dependency-glob: | + doc/pyproject.toml + doc/uv.lock - name: Install dependencies working-directory: ${{ env.JULES_PATH }}/doc @@ -119,11 +119,11 @@ jobs: # -- Deploy to GitHub Pages only on push to upstream main - name: Setup GitHub Pages if: steps.check-deploy.outputs.should-deploy == 'true' - uses: actions/configure-pages@v5 + uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 - name: Upload artifact to GitHub Pages if: steps.check-deploy.outputs.should-deploy == 'true' - uses: actions/upload-pages-artifact@v4 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: name: github-pages path: ${{ env.OUTPUT_PATH }} @@ -133,4 +133,4 @@ jobs: - name: Deploy to GitHub Pages id: deployment if: steps.check-deploy.outputs.should-deploy == 'true' - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 00000000..e66c5e79 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------------------ +# (c) Crown copyright Met Office. All rights reserved. +# The file LICENCE, distributed with this code, contains details of the terms +# under which the code may be used. +# ------------------------------------------------------------------------------ + +# Rules for Zizmor GitHub workflow linter. This file is used to configure which +# rules to ignore for specific workflow files, allowing for exceptions to be +# made where necessary while still enforcing best practices across the codebase. +rules: + dangerous-triggers: + ignore: + - "cla-check.yaml" + - "track-review-project.yaml" + - "trigger-project-workflow.yaml" diff --git a/doc/pyproject.toml b/doc/pyproject.toml index 3a2acaff..66d007c5 100644 --- a/doc/pyproject.toml +++ b/doc/pyproject.toml @@ -9,5 +9,11 @@ dependencies = [ "sphinx==8.2.3", "sphinx-lint==1.0.1", ] + +[project.urls] +repository = "https://github.com/MetOffice/jules" +documentation = "https://metoffice.github.io/jules/" +discussion = "https://github.com/MetOffice/simulation-systems/discussions/categories/jules" + [tool.setuptools] packages = [] From 88a61706be66a72dc9b0ddf6c69422f4b83bf535 Mon Sep 17 00:00:00 2001 From: James Bruten <109733895+james-bruten-mo@users.noreply.github.com> Date: Thu, 13 Aug 2026 11:55:15 +0100 Subject: [PATCH 02/14] Remove bare subroutines (#135) Co-authored-by: Erica Neininger <107684099+ericaneininger@users.noreply.github.com> Co-authored-by: Pierre Siddall <43399998+Pierre-siddall@users.noreply.github.com> --- etc/fcm-make/compiler/cray_12_plus.cfg | 2 +- etc/fcm-make/make-river.cfg | 2 +- etc/fcm-make/make.cfg | 6 +----- .../{clim_calc.F90 => clim_calc_mod.F90} | 10 ++++++++- .../imogen/{day_calc.F90 => day_calc_mod.F90} | 9 ++++++++ .../{delta_temp.F90 => delta_temp_mod.F90} | 10 +++++++++ ...f_atmos_ch4.F90 => diff_atmos_ch4_mod.F90} | 11 ++++++++-- ...land_ch4.F90 => diffcarb_land_ch4_mod.F90} | 8 +++++++ ...land_co2.F90 => diffcarb_land_co2_mod.F90} | 7 +++++++ .../imogen/{drdat.F90 => drdat_mod.F90} | 7 +++++++ ...{imogen_check.F90 => imogen_check_mod.F90} | 8 +++++++ ...te_carb.F90 => imogen_update_carb_mod.F90} | 15 +++++++++++++ ...te_clim.F90 => imogen_update_clim_mod.F90} | 21 +++++++++++++++++++ .../imogen/{invert.F90 => invert_mod.F90} | 8 +++++++ .../{ocean_co2.F90 => ocean_co2_mod.F90} | 9 ++++++++ .../{gcm_anlg.F90 => pattern_scaling_mod.F90} | 7 +++++++ .../imogen/{radf_ch4.F90 => radf_ch4_mod.F90} | 10 +++++++-- .../imogen/{radf_co2.F90 => radf_co2_mod.F90} | 7 +++++++ ...{radf_non_co2.F90 => radf_non_co2_mod.F90} | 7 +++++++ .../imogen/{response.F90 => response_mod.F90} | 7 +++++++ src/control/imogen/{rndm.F90 => rndm_mod.F90} | 7 +++++++ src/control/rivers-standalone/river.F90 | 4 ++-- ...control_mod.F90 => rivers_control_mod.F90} | 12 +++++------ src/control/standalone/jules.F90 | 6 +++++- ...control.F90 => standalone_control_mod.F90} | 12 +++++++++-- .../{init_fire.F90 => init_fire_mod.F90} | 7 +++++++ .../{init_imogen.F90 => init_imogen_mod.F90} | 8 +++++++ ...irrigation.F90 => init_irrigation_mod.F90} | 6 ++++++ .../standalone/{init.F90 => init_mod.F90} | 10 +++++++++ ..._data.F90 => init_prescribed_data_mod.F90} | 6 ++++++ .../{init_urban.F90 => init_urban_mod.F90} | 6 ++++++ ...nit_vars_tmp.F90 => init_vars_tmp_mod.F90} | 7 +++++++ src/science/vegetation/crop_mod.F90 | 8 +++++++ .../{develop.F90 => develop_mod.F90} | 6 ++++++ .../vegetation/{emerge.F90 => emerge_mod.F90} | 7 +++++++ .../{partition.F90 => partition_mod.F90} | 6 ++++++ .../vegetation/{sow.F90 => sow_mod.F90} | 7 +++++++ src/util/logging_mod.F90 | 2 +- 38 files changed, 274 insertions(+), 24 deletions(-) rename src/control/imogen/{clim_calc.F90 => clim_calc_mod.F90} (98%) rename src/control/imogen/{day_calc.F90 => day_calc_mod.F90} (99%) rename src/control/imogen/{delta_temp.F90 => delta_temp_mod.F90} (98%) rename src/control/imogen/{diff_atmos_ch4.F90 => diff_atmos_ch4_mod.F90} (97%) rename src/control/imogen/{diffcarb_land_ch4.F90 => diffcarb_land_ch4_mod.F90} (97%) rename src/control/imogen/{diffcarb_land_co2.F90 => diffcarb_land_co2_mod.F90} (96%) rename src/control/imogen/{drdat.F90 => drdat_mod.F90} (98%) rename src/control/imogen/{imogen_check.F90 => imogen_check_mod.F90} (99%) rename src/control/imogen/{imogen_update_carb.F90 => imogen_update_carb_mod.F90} (97%) rename src/control/imogen/{imogen_update_clim.F90 => imogen_update_clim_mod.F90} (96%) rename src/control/imogen/{invert.F90 => invert_mod.F90} (98%) rename src/control/imogen/{ocean_co2.F90 => ocean_co2_mod.F90} (98%) rename src/control/imogen/{gcm_anlg.F90 => pattern_scaling_mod.F90} (97%) rename src/control/imogen/{radf_ch4.F90 => radf_ch4_mod.F90} (98%) rename src/control/imogen/{radf_co2.F90 => radf_co2_mod.F90} (95%) rename src/control/imogen/{radf_non_co2.F90 => radf_non_co2_mod.F90} (98%) rename src/control/imogen/{response.F90 => response_mod.F90} (97%) rename src/control/imogen/{rndm.F90 => rndm_mod.F90} (96%) rename src/control/rivers-standalone/{control_mod.F90 => rivers_control_mod.F90} (97%) rename src/control/standalone/{control.F90 => standalone_control_mod.F90} (99%) rename src/initialisation/standalone/{init_fire.F90 => init_fire_mod.F90} (98%) rename src/initialisation/standalone/{init_imogen.F90 => init_imogen_mod.F90} (99%) rename src/initialisation/standalone/{init_irrigation.F90 => init_irrigation_mod.F90} (97%) rename src/initialisation/standalone/{init.F90 => init_mod.F90} (98%) rename src/initialisation/standalone/{init_prescribed_data.F90 => init_prescribed_data_mod.F90} (99%) rename src/initialisation/standalone/{init_urban.F90 => init_urban_mod.F90} (94%) rename src/initialisation/standalone/{init_vars_tmp.F90 => init_vars_tmp_mod.F90} (99%) rename src/science/vegetation/{develop.F90 => develop_mod.F90} (97%) rename src/science/vegetation/{emerge.F90 => emerge_mod.F90} (96%) rename src/science/vegetation/{partition.F90 => partition_mod.F90} (98%) rename src/science/vegetation/{sow.F90 => sow_mod.F90} (98%) diff --git a/etc/fcm-make/compiler/cray_12_plus.cfg b/etc/fcm-make/compiler/cray_12_plus.cfg index bc8fe63b..4fb0c2a0 100644 --- a/etc/fcm-make/compiler/cray_12_plus.cfg +++ b/etc/fcm-make/compiler/cray_12_plus.cfg @@ -60,4 +60,4 @@ $SOURCE_PATH_PREFIX{?} = jules build.prop{fc.flags}[$SOURCE_PATH_PREFIX/src/io/model_interface/model_interface_mod.F90] = -O0 -Ovector0 -hfp0 -hflex_mp=strict -hipa0 # # File override to circumvent compiler bug - compiler version: cce/12.0.1 -build.prop{fc.flags}[$SOURCE_PATH_PREFIX/src/initialisation/standalone/init_prescribed_data.F90] = $fflags_common -O1 +build.prop{fc.flags}[$SOURCE_PATH_PREFIX/src/initialisation/standalone/init_prescribed_data_mod.F90] = $fflags_common -O1 diff --git a/etc/fcm-make/make-river.cfg b/etc/fcm-make/make-river.cfg index 68c43e11..81789894 100644 --- a/etc/fcm-make/make-river.cfg +++ b/etc/fcm-make/make-river.cfg @@ -89,7 +89,7 @@ extract.path-incl[river] = $extract_path_incl \ src/initialisation/standalone/init_output_mod.F90 \ src/initialisation/standalone/init_rivers.F90 \ src/initialisation/standalone/init_initial_mod.F90 \ - src/initialisation/standalone/init_prescribed_data.F90 \ + src/initialisation/standalone/init_prescribed_data_mod.F90 \ src/io/dump \ src/io/file_handling \ src/io/input/fill_variables_from_file_mod.F90 \ diff --git a/etc/fcm-make/make.cfg b/etc/fcm-make/make.cfg index cf27c477..35d88747 100644 --- a/etc/fcm-make/make.cfg +++ b/etc/fcm-make/make.cfg @@ -65,11 +65,7 @@ preprocess.prop{file-ext.h} = .inc build.target = rose-run jules.exe # Explicit dependencies that need to be defined -build.prop{ns-dep.o}[jules/src/control/standalone/jules.F90] = jules/src/initialisation/standalone \ - jules/src/science \ - jules/src/control/imogen \ - jules/utils -build.prop{dep.o}[jules/src/control/standalone/jules.F90] = control.o +build.prop{ns-dep.o}[jules/src/control/standalone/jules.F90] = jules/utils ################################################################################ diff --git a/src/control/imogen/clim_calc.F90 b/src/control/imogen/clim_calc_mod.F90 similarity index 98% rename from src/control/imogen/clim_calc.F90 rename to src/control/imogen/clim_calc_mod.F90 index 15ccd25d..a9959a0b 100644 --- a/src/control/imogen/clim_calc.F90 +++ b/src/control/imogen/clim_calc_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE clim_calc_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE clim_calc(land_pts, mm, md, nsdmax, seed_rain, imgn_drive, ainfo) USE missing_data_mod, ONLY: rmdi @@ -18,6 +24,7 @@ SUBROUTINE clim_calc(land_pts, mm, md, nsdmax, seed_rain, imgn_drive, ainfo) USE ancil_info, ONLY: ainfo_type USE theta_field_sizes, ONLY: t_i_length USE imogen_run, ONLY: l_daily_metdata_climatol +USE day_calc_mod, ONLY: day_calc IMPLICIT NONE @@ -47,7 +54,7 @@ SUBROUTINE clim_calc(land_pts, mm, md, nsdmax, seed_rain, imgn_drive, ainfo) ! Seeding number for subdaily rainfall. TYPE(imgn_drive_type), INTENT(IN OUT) :: imgn_drive -TYPE(ainfo_type), INTENT(IN OUT) :: ainfo +TYPE(ainfo_type), INTENT(IN) :: ainfo ! Create "subdaily" values of the arrays below using day_calc REAL :: & @@ -220,4 +227,5 @@ SUBROUTINE clim_calc(land_pts, mm, md, nsdmax, seed_rain, imgn_drive, ainfo) RETURN END SUBROUTINE clim_calc +END MODULE clim_calc_mod #endif diff --git a/src/control/imogen/day_calc.F90 b/src/control/imogen/day_calc_mod.F90 similarity index 99% rename from src/control/imogen/day_calc.F90 rename to src/control/imogen/day_calc_mod.F90 index 6f73081c..14457c6f 100644 --- a/src/control/imogen/day_calc.F90 +++ b/src/control/imogen/day_calc_mod.F90 @@ -8,6 +8,13 @@ ! ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** + +MODULE day_calc_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE day_calc( & land_pts, swdown_daily, precip_daily, tl1_daily, diurnal_tl1_daily, & lwdown_daily, pstar_daily, wind_daily, ql1_daily, swdown_subdaily, & @@ -24,6 +31,7 @@ SUBROUTINE day_calc( & USE model_grid_mod, ONLY: latitude, longitude USE theta_field_sizes, ONLY: t_i_length, t_j_length USE jules_fields_mod, ONLY: ainfo +USE rndm_mod, ONLY: rndm ! USE update_mod, ONLY: t_for_snow, t_for_con_rain ! ejb add trap in imogen nml to ensure they are read ! not activated in #1322 because metadata is a nightmare @@ -468,4 +476,5 @@ SUBROUTINE day_calc( & RETURN END SUBROUTINE day_calc +END MODULE day_calc_mod #endif diff --git a/src/control/imogen/delta_temp.F90 b/src/control/imogen/delta_temp_mod.F90 similarity index 98% rename from src/control/imogen/delta_temp.F90 rename to src/control/imogen/delta_temp_mod.F90 index 8a4e38e1..76c1c818 100644 --- a/src/control/imogen/delta_temp.F90 +++ b/src/control/imogen/delta_temp_mod.F90 @@ -8,9 +8,18 @@ ! ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** + +MODULE delta_temp_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE delta_temp( & n_olevs,f_ocean,kappa_o,lambda_l,lambda_o,mu,dqradf,dtemp_l,dtemp_o, dtemp_g) +USE invert_mod, ONLY: invert + USE veg_param, ONLY: secs_per_360days USE jules_print_mgr, ONLY: jules_message, jules_print @@ -204,4 +213,5 @@ SUBROUTINE delta_temp( & RETURN END SUBROUTINE delta_temp +END MODULE delta_temp_mod #endif diff --git a/src/control/imogen/diff_atmos_ch4.F90 b/src/control/imogen/diff_atmos_ch4_mod.F90 similarity index 97% rename from src/control/imogen/diff_atmos_ch4.F90 rename to src/control/imogen/diff_atmos_ch4_mod.F90 index 482ad9b0..81af95cd 100644 --- a/src/control/imogen/diff_atmos_ch4.F90 +++ b/src/control/imogen/diff_atmos_ch4_mod.F90 @@ -8,6 +8,13 @@ ! ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** + +MODULE diff_atmos_ch4_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE diff_atmos_ch4(d_land_atmos_ch4, ch4_ppbv) USE io_constants, ONLY: imogen_unit @@ -130,6 +137,6 @@ SUBROUTINE diff_atmos_ch4(d_land_atmos_ch4, ch4_ppbv) RETURN -END - +END SUBROUTINE diff_atmos_ch4 +END MODULE diff_atmos_ch4_mod #endif diff --git a/src/control/imogen/diffcarb_land_ch4.F90 b/src/control/imogen/diffcarb_land_ch4_mod.F90 similarity index 97% rename from src/control/imogen/diffcarb_land_ch4.F90 rename to src/control/imogen/diffcarb_land_ch4_mod.F90 index 870b604a..1e0482e9 100644 --- a/src/control/imogen/diffcarb_land_ch4.F90 +++ b/src/control/imogen/diffcarb_land_ch4_mod.F90 @@ -2,6 +2,13 @@ ! ********************************************************************* ! Calculates the global change in atmospheric CH4 ! ********************************************************************* + +MODULE diffcarb_land_ch4_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE diffcarb_land_ch4(land_pts, d_land_atmos_ch4, darea, dctot_ch4) USE imogen_run, ONLY: fch4_ref, yr_fch4_ref @@ -78,4 +85,5 @@ SUBROUTINE diffcarb_land_ch4(land_pts, d_land_atmos_ch4, darea, dctot_ch4) RETURN END SUBROUTINE diffcarb_land_ch4 +END MODULE diffcarb_land_ch4_mod #endif diff --git a/src/control/imogen/diffcarb_land_co2.F90 b/src/control/imogen/diffcarb_land_co2_mod.F90 similarity index 96% rename from src/control/imogen/diffcarb_land_co2.F90 rename to src/control/imogen/diffcarb_land_co2_mod.F90 index b7ddc70d..0de89113 100644 --- a/src/control/imogen/diffcarb_land_co2.F90 +++ b/src/control/imogen/diffcarb_land_co2_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE diffcarb_land_co2_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE diffcarb_land_co2(land_pts, d_land_atmos_co2, darea, dctot_co2) USE conversions_mod, ONLY: conv_gtc_to_ppm @@ -66,4 +72,5 @@ SUBROUTINE diffcarb_land_co2(land_pts, d_land_atmos_co2, darea, dctot_co2) RETURN END SUBROUTINE diffcarb_land_co2 +END MODULE diffcarb_land_co2_mod #endif diff --git a/src/control/imogen/drdat.F90 b/src/control/imogen/drdat_mod.F90 similarity index 98% rename from src/control/imogen/drdat.F90 rename to src/control/imogen/drdat_mod.F90 index 1ddd8852..f09dd436 100644 --- a/src/control/imogen/drdat.F90 +++ b/src/control/imogen/drdat_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE drdat_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE drdat(iyear) USE fill_variables_from_file_mod, ONLY: fill_variables_from_file @@ -82,4 +88,5 @@ SUBROUTINE drdat(iyear) RETURN END SUBROUTINE drdat +END MODULE drdat_mod #endif diff --git a/src/control/imogen/imogen_check.F90 b/src/control/imogen/imogen_check_mod.F90 similarity index 99% rename from src/control/imogen/imogen_check.F90 rename to src/control/imogen/imogen_check_mod.F90 index 5e73444d..fd3632b6 100644 --- a/src/control/imogen/imogen_check.F90 +++ b/src/control/imogen/imogen_check_mod.F90 @@ -8,6 +8,13 @@ ! ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** + +MODULE imogen_check_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE imogen_check( & c_emissions, include_co2, include_non_co2_radf, land_feed_co2, & land_feed_ch4, ocean_feed, change_metdata_method, l_change_metdata) @@ -284,4 +291,5 @@ SUBROUTINE imogen_check( & RETURN END SUBROUTINE imogen_check +END MODULE imogen_check_mod #endif diff --git a/src/control/imogen/imogen_update_carb.F90 b/src/control/imogen/imogen_update_carb_mod.F90 similarity index 97% rename from src/control/imogen/imogen_update_carb.F90 rename to src/control/imogen/imogen_update_carb_mod.F90 index 5c9a7a73..2381de98 100644 --- a/src/control/imogen/imogen_update_carb.F90 +++ b/src/control/imogen/imogen_update_carb_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE imogen_update_carb_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE imogen_update_carb(progs, imgn_vars) USE model_grid_mod, ONLY: grid_area_ij @@ -42,6 +48,14 @@ SUBROUTINE imogen_update_carb(progs, imgn_vars) USE imogen_io_vars, ONLY: & yr_emiss,c_emiss +USE diffcarb_land_co2_mod, ONLY: diffcarb_land_co2 + +USE ocean_co2_mod, ONLY: ocean_co2 + +USE diffcarb_land_ch4_mod, ONLY: diffcarb_land_ch4 + +USE diff_atmos_ch4_mod, ONLY: diff_atmos_ch4 + USE logging_mod, ONLY: log_fatal !TYPE definitions @@ -246,4 +260,5 @@ SUBROUTINE imogen_update_carb(progs, imgn_vars) RETURN END SUBROUTINE imogen_update_carb +END MODULE imogen_update_carb_mod #endif diff --git a/src/control/imogen/imogen_update_clim.F90 b/src/control/imogen/imogen_update_clim_mod.F90 similarity index 96% rename from src/control/imogen/imogen_update_clim.F90 rename to src/control/imogen/imogen_update_clim_mod.F90 index 67ab8a0f..75a43973 100644 --- a/src/control/imogen/imogen_update_clim.F90 +++ b/src/control/imogen/imogen_update_clim_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE imogen_update_clim_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE imogen_update_clim(progs, imgn_drive, imgn_vars, ainfo) USE model_time_mod, ONLY: current_time @@ -34,6 +40,20 @@ SUBROUTINE imogen_update_clim(progs, imgn_drive, imgn_vars, ainfo) USE imogen_constants, ONLY: n_olevs +USE radf_co2_mod, ONLY: radf_co2 + +USE radf_non_co2_mod, ONLY: radf_non_co2 + +USE radf_ch4_mod, ONLY: radf_ch4 + +USE delta_temp_mod, ONLY: delta_temp + +USE pattern_scaling_mod, ONLY: pattern_scaling + +USE drdat_mod, ONLY: drdat + +USE clim_calc_mod, ONLY: clim_calc + USE logging_mod, ONLY: log_fatal USE jules_print_mgr, ONLY: & @@ -269,4 +289,5 @@ SUBROUTINE imogen_update_clim(progs, imgn_drive, imgn_vars, ainfo) RETURN END SUBROUTINE imogen_update_clim +END MODULE imogen_update_clim_mod #endif diff --git a/src/control/imogen/invert.F90 b/src/control/imogen/invert_mod.F90 similarity index 98% rename from src/control/imogen/invert.F90 rename to src/control/imogen/invert_mod.F90 index aee39e19..d40198a9 100644 --- a/src/control/imogen/invert.F90 +++ b/src/control/imogen/invert_mod.F90 @@ -8,6 +8,13 @@ ! ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** + +MODULE invert_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE invert( & u_old,u_new,p,lambda_old,lambda_new,r1,r2,dz_top,n_olevs & ) @@ -184,4 +191,5 @@ SUBROUTINE invert( & RETURN END SUBROUTINE invert +END MODULE invert_mod #endif diff --git a/src/control/imogen/ocean_co2.F90 b/src/control/imogen/ocean_co2_mod.F90 similarity index 98% rename from src/control/imogen/ocean_co2.F90 rename to src/control/imogen/ocean_co2_mod.F90 index 2f7ba51d..f4e7326b 100644 --- a/src/control/imogen/ocean_co2.F90 +++ b/src/control/imogen/ocean_co2_mod.F90 @@ -9,12 +9,20 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE ocean_co2_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE ocean_co2( & iyear,year_co2,co2_atmos_ppmv,co2_atmos_init_ppmv,dt_ocean, & fa_ocean,ocean_area,grad_co2_atmos_ppmv,year_run, & t_ocean_init,nfarray,d_ocean_atmos & ) +USE response_mod, ONLY: response + USE jules_print_mgr, ONLY: & jules_message, & jules_print @@ -202,4 +210,5 @@ SUBROUTINE ocean_co2( & RETURN END SUBROUTINE ocean_co2 +END MODULE ocean_co2_mod #endif diff --git a/src/control/imogen/gcm_anlg.F90 b/src/control/imogen/pattern_scaling_mod.F90 similarity index 97% rename from src/control/imogen/gcm_anlg.F90 rename to src/control/imogen/pattern_scaling_mod.F90 index c31e8bb4..5e9fc227 100644 --- a/src/control/imogen/gcm_anlg.F90 +++ b/src/control/imogen/pattern_scaling_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE pattern_scaling_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE pattern_scaling(land_pts, mm, dtemp_g, imgn_drive, ainfo) USE imgn_drive_mod, ONLY: imgn_drive_type @@ -77,4 +83,5 @@ SUBROUTINE pattern_scaling(land_pts, mm, dtemp_g, imgn_drive, ainfo) RETURN END SUBROUTINE pattern_scaling +END MODULE pattern_scaling_mod #endif diff --git a/src/control/imogen/radf_ch4.F90 b/src/control/imogen/radf_ch4_mod.F90 similarity index 98% rename from src/control/imogen/radf_ch4.F90 rename to src/control/imogen/radf_ch4_mod.F90 index 4ad2600b..19eedab6 100644 --- a/src/control/imogen/radf_ch4.F90 +++ b/src/control/imogen/radf_ch4_mod.F90 @@ -8,6 +8,13 @@ ! ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** + +MODULE radf_ch4_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE radf_ch4(ch4_ppbv, q_ch4) USE io_constants, ONLY: imogen_unit @@ -124,8 +131,6 @@ SUBROUTINE calc_q_ch4(ch4_ppbv, ch4_interp_ppbv, n2o_interp_ppbv, q_ch4) ! Local parameters REAL :: & - overlap, & - ! overlap function. olap, & ! overlap fn output with modelled ch4 conc olap_interp ! overlap fn output with reference ch4 conc. @@ -169,4 +174,5 @@ FUNCTION overlap(ch4_ppbv, n2o_ppbv) RESULT(overlap_val) + (5.31e-15 * ch4_ppbv * (ch4_ppbv * n2o_ppbv)** 1.52)) END FUNCTION overlap +END MODULE radf_ch4_mod #endif diff --git a/src/control/imogen/radf_co2.F90 b/src/control/imogen/radf_co2_mod.F90 similarity index 95% rename from src/control/imogen/radf_co2.F90 rename to src/control/imogen/radf_co2_mod.F90 index 93914e9f..a2449b55 100644 --- a/src/control/imogen/radf_co2.F90 +++ b/src/control/imogen/radf_co2_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE radf_co2_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE radf_co2(co2, co2ref, q2co2, q_co2) IMPLICIT NONE @@ -41,4 +47,5 @@ SUBROUTINE radf_co2(co2, co2ref, q2co2, q_co2) RETURN END SUBROUTINE radf_co2 +END MODULE radf_co2_mod #endif diff --git a/src/control/imogen/radf_non_co2.F90 b/src/control/imogen/radf_non_co2_mod.F90 similarity index 98% rename from src/control/imogen/radf_non_co2.F90 rename to src/control/imogen/radf_non_co2_mod.F90 index 7da2c5fd..b7f8ae02 100644 --- a/src/control/imogen/radf_non_co2.F90 +++ b/src/control/imogen/radf_non_co2_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE radf_non_co2_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE radf_non_co2( & year,q,nyr_non_co2,file_non_co2_radf) @@ -110,4 +116,5 @@ SUBROUTINE radf_non_co2( & RETURN END SUBROUTINE radf_non_co2 +END MODULE radf_non_co2_mod #endif diff --git a/src/control/imogen/response.F90 b/src/control/imogen/response_mod.F90 similarity index 97% rename from src/control/imogen/response.F90 rename to src/control/imogen/response_mod.F90 index ffe2bcbe..c7fd9b61 100644 --- a/src/control/imogen/response.F90 +++ b/src/control/imogen/response_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE response_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE response(ncallyr,year_run,rs) IMPLICIT NONE @@ -60,4 +66,5 @@ SUBROUTINE response(ncallyr,year_run,rs) RETURN END SUBROUTINE response +END MODULE response_mod #endif diff --git a/src/control/imogen/rndm.F90 b/src/control/imogen/rndm_mod.F90 similarity index 96% rename from src/control/imogen/rndm.F90 rename to src/control/imogen/rndm_mod.F90 index ce0d4120..a465a117 100644 --- a/src/control/imogen/rndm.F90 +++ b/src/control/imogen/rndm_mod.F90 @@ -9,6 +9,12 @@ ! [Met Office Ref SC0237] !******************************COPYRIGHT************************************** +MODULE rndm_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE rndm(random_num,seed) IMPLICIT NONE @@ -64,4 +70,5 @@ SUBROUTINE rndm(random_num,seed) RETURN END SUBROUTINE rndm +END MODULE rndm_mod #endif diff --git a/src/control/rivers-standalone/river.F90 b/src/control/rivers-standalone/river.F90 index 55bf51b1..dcb32c86 100644 --- a/src/control/rivers-standalone/river.F90 +++ b/src/control/rivers-standalone/river.F90 @@ -33,7 +33,7 @@ PROGRAM river USE jules_print_mgr, ONLY: jules_message, jules_print -USE control_mod, ONLY: control +USE rivers_control_mod, ONLY: rivers_control !TYPE definitions USE jules_fields_mod, ONLY: psparms_data, psparms, & @@ -143,7 +143,7 @@ PROGRAM river !----------------------------------------------------------------------------- ! Call the main model science routine !----------------------------------------------------------------------------- - CALL control( & + CALL rivers_control( & !TYPES containing field data (IN OUT) psparms, ainfo, progs, fluxes, rivers, wtrac_jls ) diff --git a/src/control/rivers-standalone/control_mod.F90 b/src/control/rivers-standalone/rivers_control_mod.F90 similarity index 97% rename from src/control/rivers-standalone/control_mod.F90 rename to src/control/rivers-standalone/rivers_control_mod.F90 index 14d32fa3..b91f5257 100644 --- a/src/control/rivers-standalone/control_mod.F90 +++ b/src/control/rivers-standalone/rivers_control_mod.F90 @@ -1,4 +1,4 @@ -MODULE control_mod +MODULE rivers_control_mod ! *****************************COPYRIGHT**************************************** ! (c) Crown copyright, Met Office. All rights reserved. ! @@ -14,13 +14,13 @@ MODULE control_mod PRIVATE -PUBLIC :: control +PUBLIC :: rivers_control -CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='CONTROL_MOD' +CHARACTER(LEN=*), PARAMETER, PRIVATE :: ModuleName='RIVERS_CONTROL_MOD' CONTAINS -SUBROUTINE control ( & +SUBROUTINE rivers_control ( & !TYPES containing field data (IN OUT) psparms, ainfo, progs, fluxes, river, wtrac_jls ) @@ -185,6 +185,6 @@ SUBROUTINE control ( & CALL jules_print(RoutineName, jules_message) END SELECT -END SUBROUTINE control +END SUBROUTINE rivers_control -END MODULE control_mod +END MODULE rivers_control_mod diff --git a/src/control/standalone/jules.F90 b/src/control/standalone/jules.F90 index fd1f8ae8..72972741 100644 --- a/src/control/standalone/jules.F90 +++ b/src/control/standalone/jules.F90 @@ -10,6 +10,8 @@ PROGRAM jules !$ USE omp_lib, ONLY: omp_get_max_threads +USE standalone_control_mod, ONLY: standalone_control + USE init_mod, ONLY: init USE io_constants, ONLY: max_file_name_len @@ -72,6 +74,8 @@ PROGRAM jules work_vars_data_cbl, work_vars_cbl USE imgn_drive_mod, ONLY: imgn_drive_data, imgn_drive USE imgn_vars_mod, ONLY: imgn_vars_data, imgn_vars +USE imogen_update_clim_mod, ONLY: imogen_update_clim +USE imogen_update_carb_mod, ONLY: imogen_update_carb IMPLICIT NONE @@ -191,7 +195,7 @@ PROGRAM jules !----------------------------------------------------------------------------- ! Call the main model science routine !----------------------------------------------------------------------------- - CALL control( & + CALL standalone_control( & ! Scalar arguments (INTENT IN) timestep_number, & ! Forcing (INTENT IN) diff --git a/src/control/standalone/control.F90 b/src/control/standalone/standalone_control_mod.F90 similarity index 99% rename from src/control/standalone/control.F90 rename to src/control/standalone/standalone_control_mod.F90 index 0542a79b..97703a60 100644 --- a/src/control/standalone/control.F90 +++ b/src/control/standalone/standalone_control_mod.F90 @@ -1,5 +1,12 @@ #if !defined(UM_JULES) -SUBROUTINE control ( & + +MODULE standalone_control_mod + +IMPLICIT NONE + +CONTAINS + +SUBROUTINE standalone_control ( & ! Scalar arguments (INTENT IN) timestep_number, & u_1_ij, v_1_ij, & @@ -911,5 +918,6 @@ SUBROUTINE control ( & work_cbl & ) -END SUBROUTINE control +END SUBROUTINE standalone_control +END MODULE standalone_control_mod #endif diff --git a/src/initialisation/standalone/init_fire.F90 b/src/initialisation/standalone/init_fire_mod.F90 similarity index 98% rename from src/initialisation/standalone/init_fire.F90 rename to src/initialisation/standalone/init_fire_mod.F90 index 8681971f..c57a6c1c 100644 --- a/src/initialisation/standalone/init_fire.F90 +++ b/src/initialisation/standalone/init_fire_mod.F90 @@ -5,6 +5,12 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT************************************** +MODULE init_fire_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE init_fire(nml_dir,land_index) USE io_constants, ONLY: namelist_unit @@ -100,4 +106,5 @@ SUBROUTINE init_fire(nml_dir,land_index) RETURN END SUBROUTINE init_fire +END MODULE init_fire_mod #endif diff --git a/src/initialisation/standalone/init_imogen.F90 b/src/initialisation/standalone/init_imogen_mod.F90 similarity index 99% rename from src/initialisation/standalone/init_imogen.F90 rename to src/initialisation/standalone/init_imogen_mod.F90 index e9e3e1b2..d02ff279 100644 --- a/src/initialisation/standalone/init_imogen.F90 +++ b/src/initialisation/standalone/init_imogen_mod.F90 @@ -5,6 +5,11 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT************************************** +MODULE init_imogen_mod + +IMPLICIT NONE + +CONTAINS SUBROUTINE init_imogen(nml_dir, progs_data, trifctltype, imgn_drive, & imgn_vars, ainfo) @@ -39,6 +44,8 @@ SUBROUTINE init_imogen(nml_dir, progs_data, trifctltype, imgn_drive, & USE imogen_anlg_vals, ONLY: imogen_anlg_vals_list, file_clim, file_patt, & diff_frac_const_imogen +USE imogen_check_mod, ONLY: imogen_check + USE imogen_io_vars, ONLY: nyr_max, yr_emiss, c_emiss USE aero, ONLY: co2_mmr @@ -386,4 +393,5 @@ SUBROUTINE init_imogen(nml_dir, progs_data, trifctltype, imgn_drive, & RETURN END SUBROUTINE init_imogen +END MODULE init_imogen_mod #endif diff --git a/src/initialisation/standalone/init_irrigation.F90 b/src/initialisation/standalone/init_irrigation_mod.F90 similarity index 97% rename from src/initialisation/standalone/init_irrigation.F90 rename to src/initialisation/standalone/init_irrigation_mod.F90 index d3ab3d14..434d8c04 100644 --- a/src/initialisation/standalone/init_irrigation.F90 +++ b/src/initialisation/standalone/init_irrigation_mod.F90 @@ -5,6 +5,11 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT************************************** +MODULE init_irrigation_mod + +IMPLICIT NONE + +CONTAINS SUBROUTINE init_irrigation(nml_dir) @@ -79,4 +84,5 @@ SUBROUTINE init_irrigation(nml_dir) RETURN END SUBROUTINE init_irrigation +END MODULE init_irrigation_mod #endif diff --git a/src/initialisation/standalone/init.F90 b/src/initialisation/standalone/init_mod.F90 similarity index 98% rename from src/initialisation/standalone/init.F90 rename to src/initialisation/standalone/init_mod.F90 index f96a37ed..f94cdc16 100644 --- a/src/initialisation/standalone/init.F90 +++ b/src/initialisation/standalone/init_mod.F90 @@ -5,7 +5,11 @@ ! *****************************COPYRIGHT************************************** MODULE init_mod + +IMPLICIT NONE + CONTAINS + SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & psparms_data, psparms, & toppdm, top_pdm_data, & @@ -72,6 +76,12 @@ SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & USE check_compatible_options_mod, ONLY: check_compatible_options USE init_deposition_mod, ONLY: init_deposition USE jules_science_fixes_mod, ONLY: init_science_fixes +USE init_irrigation_mod, ONLY: init_irrigation +USE init_urban_mod, ONLY: init_urban +USE init_fire_mod, ONLY: init_fire +USE init_imogen_mod, ONLY: init_imogen +USE init_prescribed_data_mod, ONLY: init_prescribed_data +USE init_vars_tmp_mod, ONLY: init_vars_tmp ! Get fields for veg3_init USE jules_surface_types_mod, ONLY: npft, nnpft, ntype diff --git a/src/initialisation/standalone/init_prescribed_data.F90 b/src/initialisation/standalone/init_prescribed_data_mod.F90 similarity index 99% rename from src/initialisation/standalone/init_prescribed_data.F90 rename to src/initialisation/standalone/init_prescribed_data_mod.F90 index 7853b085..f6d24f4a 100644 --- a/src/initialisation/standalone/init_prescribed_data.F90 +++ b/src/initialisation/standalone/init_prescribed_data_mod.F90 @@ -5,6 +5,11 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT************************************** +MODULE init_prescribed_data_mod + +IMPLICIT NONE + +CONTAINS SUBROUTINE init_prescribed_data(nml_dir) @@ -729,4 +734,5 @@ SUBROUTINE init_prescribed_data(nml_dir) RETURN END SUBROUTINE init_prescribed_data +END MODULE init_prescribed_data_mod #endif diff --git a/src/initialisation/standalone/init_urban.F90 b/src/initialisation/standalone/init_urban_mod.F90 similarity index 94% rename from src/initialisation/standalone/init_urban.F90 rename to src/initialisation/standalone/init_urban_mod.F90 index cb6edbfb..9026af19 100644 --- a/src/initialisation/standalone/init_urban.F90 +++ b/src/initialisation/standalone/init_urban_mod.F90 @@ -5,6 +5,11 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT************************************** +MODULE init_urban_mod + +IMPLICIT NONE + +CONTAINS SUBROUTINE init_urban(nml_dir) @@ -39,4 +44,5 @@ SUBROUTINE init_urban(nml_dir) RETURN END SUBROUTINE init_urban +END MODULE init_urban_mod #endif diff --git a/src/initialisation/standalone/init_vars_tmp.F90 b/src/initialisation/standalone/init_vars_tmp_mod.F90 similarity index 99% rename from src/initialisation/standalone/init_vars_tmp.F90 rename to src/initialisation/standalone/init_vars_tmp_mod.F90 index c0dc8c05..d6a27cb8 100644 --- a/src/initialisation/standalone/init_vars_tmp.F90 +++ b/src/initialisation/standalone/init_vars_tmp_mod.F90 @@ -1,5 +1,11 @@ #if !defined(UM_JULES) +MODULE init_vars_tmp_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE init_vars_tmp(crop_vars,psparms,toppdm,ainfo,trif_vars, aerotype, & progs, trifctltype, coast, jules_vars, & !fluxes, & @@ -323,4 +329,5 @@ SUBROUTINE init_vars_tmp(crop_vars,psparms,toppdm,ainfo,trif_vars, aerotype, & RETURN END SUBROUTINE init_vars_tmp +END MODULE init_vars_tmp_mod #endif diff --git a/src/science/vegetation/crop_mod.F90 b/src/science/vegetation/crop_mod.F90 index a6269985..c688ee62 100644 --- a/src/science/vegetation/crop_mod.F90 +++ b/src/science/vegetation/crop_mod.F90 @@ -58,6 +58,14 @@ SUBROUTINE crop(p_field, land_pts, land_index, a_step, & USE ancil_info, ONLY: nsurft, nsoilt +USE sow_mod, ONLY: sow + +USE emerge_mod, ONLY: emerge + +USE develop_mod, ONLY: develop + +USE partition_mod, ONLY: partition + IMPLICIT NONE !----------------------------------------------------------------------------- diff --git a/src/science/vegetation/develop.F90 b/src/science/vegetation/develop_mod.F90 similarity index 97% rename from src/science/vegetation/develop.F90 rename to src/science/vegetation/develop_mod.F90 index b1c8ce11..21f43960 100644 --- a/src/science/vegetation/develop.F90 +++ b/src/science/vegetation/develop_mod.F90 @@ -4,6 +4,11 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT******************************* +MODULE develop_mod + +IMPLICIT NONE + +CONTAINS SUBROUTINE develop(n, t_surft, phot, tt_veg, tt_rep, dvi) @@ -92,3 +97,4 @@ SUBROUTINE develop(n, t_surft, phot, tt_veg, tt_rep, dvi) END IF END SUBROUTINE develop +END MODULE develop_mod diff --git a/src/science/vegetation/emerge.F90 b/src/science/vegetation/emerge_mod.F90 similarity index 96% rename from src/science/vegetation/emerge.F90 rename to src/science/vegetation/emerge_mod.F90 index c4e3617c..d74f70b9 100644 --- a/src/science/vegetation/emerge.F90 +++ b/src/science/vegetation/emerge_mod.F90 @@ -4,6 +4,12 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT******************************* +MODULE emerge_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE emerge(n, t_surft, dvi) USE conversions_mod, ONLY: rsec_per_day @@ -58,3 +64,4 @@ SUBROUTINE emerge(n, t_surft, dvi) dvi = dvi + ( teff / tt_emr(n) ) END SUBROUTINE emerge +END MODULE emerge_mod diff --git a/src/science/vegetation/partition.F90 b/src/science/vegetation/partition_mod.F90 similarity index 98% rename from src/science/vegetation/partition.F90 rename to src/science/vegetation/partition_mod.F90 index b543097c..a73d55aa 100644 --- a/src/science/vegetation/partition.F90 +++ b/src/science/vegetation/partition_mod.F90 @@ -4,6 +4,11 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT******************************* +MODULE partition_mod + +IMPLICIT NONE + +CONTAINS SUBROUTINE partition(n, npp_ft_acc, dvi, rootc, harvc, reservec, & nonyield_diag, stemc, leafc, harv_count, harv_trig) @@ -155,3 +160,4 @@ SUBROUTINE partition(n, npp_ft_acc, dvi, rootc, harvc, reservec, & END SUBROUTINE partition +END MODULE partition_mod diff --git a/src/science/vegetation/sow.F90 b/src/science/vegetation/sow_mod.F90 similarity index 98% rename from src/science/vegetation/sow.F90 rename to src/science/vegetation/sow_mod.F90 index b7c7b998..9964ba6d 100644 --- a/src/science/vegetation/sow.F90 +++ b/src/science/vegetation/sow_mod.F90 @@ -4,6 +4,12 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT******************************* +MODULE sow_mod + +IMPLICIT NONE + +CONTAINS + SUBROUTINE sow(n, sm_levels, t_soil, sthu, smvcst, smvccl, dphotdt, & sowdate, dvi) @@ -98,3 +104,4 @@ SUBROUTINE sow(n, sm_levels, t_soil, sthu, smvcst, smvccl, dphotdt, & END IF END SUBROUTINE sow +END MODULE sow_mod diff --git a/src/util/logging_mod.F90 b/src/util/logging_mod.F90 index eb1d0d06..c6046412 100644 --- a/src/util/logging_mod.F90 +++ b/src/util/logging_mod.F90 @@ -10,7 +10,7 @@ MODULE logging_mod USE jules_vars_mod, ONLY: mpi_local_comm -USE ISO_FORTRAN_ENV, ONLY: OUTPUT_UNIT, ERROR_UNIT +USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: OUTPUT_UNIT, ERROR_UNIT IMPLICIT NONE From 33ef7252c2b3def023fd7fb8a644c928462ef9ac Mon Sep 17 00:00:00 2001 From: Maggie Hendry Date: Wed, 19 Aug 2026 15:40:20 +0100 Subject: [PATCH 03/14] Directory structure split fire -> fire_weather_index and inferno and init_fire renamed init_fire_weather_index. --- ...e_mod.F90 => init_fire_weather_index_mod.F90} | 16 ++++++++-------- src/initialisation/standalone/init_mod.F90 | 4 ++-- .../{ => fire_weather_index}/canadian_mod.F90 | 0 .../{ => fire_weather_index}/fire_allocate.F90 | 0 .../{ => fire_weather_index}/fire_calc_daily.F90 | 0 .../fire/{ => fire_weather_index}/fire_init.F90 | 0 .../fire/{ => fire_weather_index}/fire_mod.F90 | 0 .../fire_timestep_mod.F90 | 0 .../{ => fire_weather_index}/mcarthur_mod.F90 | 0 .../{ => fire_weather_index}/nesterov_mod.F90 | 0 .../fire/{ => inferno}/inferno_io_mod.F90 | 0 src/science/fire/{ => inferno}/inferno_mod.F90 | 0 12 files changed, 10 insertions(+), 10 deletions(-) rename src/initialisation/standalone/{init_fire_mod.F90 => init_fire_weather_index_mod.F90} (88%) rename src/science/fire/{ => fire_weather_index}/canadian_mod.F90 (100%) rename src/science/fire/{ => fire_weather_index}/fire_allocate.F90 (100%) rename src/science/fire/{ => fire_weather_index}/fire_calc_daily.F90 (100%) rename src/science/fire/{ => fire_weather_index}/fire_init.F90 (100%) rename src/science/fire/{ => fire_weather_index}/fire_mod.F90 (100%) rename src/science/fire/{ => fire_weather_index}/fire_timestep_mod.F90 (100%) rename src/science/fire/{ => fire_weather_index}/mcarthur_mod.F90 (100%) rename src/science/fire/{ => fire_weather_index}/nesterov_mod.F90 (100%) rename src/science/fire/{ => inferno}/inferno_io_mod.F90 (100%) rename src/science/fire/{ => inferno}/inferno_mod.F90 (100%) diff --git a/src/initialisation/standalone/init_fire_mod.F90 b/src/initialisation/standalone/init_fire_weather_index_mod.F90 similarity index 88% rename from src/initialisation/standalone/init_fire_mod.F90 rename to src/initialisation/standalone/init_fire_weather_index_mod.F90 index c57a6c1c..84fc67f6 100644 --- a/src/initialisation/standalone/init_fire_mod.F90 +++ b/src/initialisation/standalone/init_fire_weather_index_mod.F90 @@ -5,13 +5,13 @@ ! which you should have received as part of this distribution. ! *****************************COPYRIGHT************************************** -MODULE init_fire_mod +MODULE init_fire_weather_index_mod IMPLICIT NONE CONTAINS -SUBROUTINE init_fire(nml_dir,land_index) +SUBROUTINE init_fire_weather_index(nml_dir,land_index) USE io_constants, ONLY: namelist_unit @@ -64,23 +64,23 @@ SUBROUTINE init_fire(nml_dir,land_index) OPEN(namelist_unit, FILE=(TRIM(nml_dir) // '/' // 'fire.nml'), & STATUS='old', POSITION='rewind', ACTION='read', IOSTAT = ERROR) IF ( ERROR /= 0 ) & - CALL log_fatal("init_fire", & + CALL log_fatal("init_fire_weather_index", & "Error opening namelist file fire.nml " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") ! There is one namelist to read from this file -CALL log_info("init_fire", "Reading FIRE_SWITCHES namelist...") +CALL log_info("init_fire_weather_index", "Reading FIRE_SWITCHES namelist...") READ(namelist_unit, NML = fire_switches, IOSTAT = ERROR) IF ( ERROR /= 0 ) & - CALL log_fatal("init_fire", & + CALL log_fatal("init_fire_weather_index", & "Error reading namelist fire_SWITCHES " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") ! Close the namelist file CLOSE(namelist_unit, IOSTAT = ERROR) IF ( ERROR /= 0 ) & - CALL log_fatal("init_fire", & + CALL log_fatal("init_fire_weather_index", & "Error closing namelist file fire.nml " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") @@ -105,6 +105,6 @@ SUBROUTINE init_fire(nml_dir,land_index) RETURN -END SUBROUTINE init_fire -END MODULE init_fire_mod +END SUBROUTINE init_fire_weather_index +END MODULE init_fire_weather_index_mod #endif diff --git a/src/initialisation/standalone/init_mod.F90 b/src/initialisation/standalone/init_mod.F90 index f94cdc16..b7850e9f 100644 --- a/src/initialisation/standalone/init_mod.F90 +++ b/src/initialisation/standalone/init_mod.F90 @@ -78,7 +78,7 @@ SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & USE jules_science_fixes_mod, ONLY: init_science_fixes USE init_irrigation_mod, ONLY: init_irrigation USE init_urban_mod, ONLY: init_urban -USE init_fire_mod, ONLY: init_fire +USE init_fire_weather_index_mod, ONLY: init_fire_weather_index USE init_imogen_mod, ONLY: init_imogen USE init_prescribed_data_mod, ONLY: init_prescribed_data USE init_vars_tmp_mod, ONLY: init_vars_tmp @@ -372,7 +372,7 @@ SUBROUTINE init(nml_dir, crop_vars_data, crop_vars, & CALL init_params(nml_dir,progs,land_pts,nsurft,nnpft,npft,nmasst,ntype) ! Initialise fire module -CALL init_fire(nml_dir,ainfo%land_index) +CALL init_fire_weather_index(nml_dir,ainfo%land_index) ! Contains allocation of progs_data%seed_rain - hence passing in the data type CALL init_drive(nml_dir,ainfo,progs_data) diff --git a/src/science/fire/canadian_mod.F90 b/src/science/fire/fire_weather_index/canadian_mod.F90 similarity index 100% rename from src/science/fire/canadian_mod.F90 rename to src/science/fire/fire_weather_index/canadian_mod.F90 diff --git a/src/science/fire/fire_allocate.F90 b/src/science/fire/fire_weather_index/fire_allocate.F90 similarity index 100% rename from src/science/fire/fire_allocate.F90 rename to src/science/fire/fire_weather_index/fire_allocate.F90 diff --git a/src/science/fire/fire_calc_daily.F90 b/src/science/fire/fire_weather_index/fire_calc_daily.F90 similarity index 100% rename from src/science/fire/fire_calc_daily.F90 rename to src/science/fire/fire_weather_index/fire_calc_daily.F90 diff --git a/src/science/fire/fire_init.F90 b/src/science/fire/fire_weather_index/fire_init.F90 similarity index 100% rename from src/science/fire/fire_init.F90 rename to src/science/fire/fire_weather_index/fire_init.F90 diff --git a/src/science/fire/fire_mod.F90 b/src/science/fire/fire_weather_index/fire_mod.F90 similarity index 100% rename from src/science/fire/fire_mod.F90 rename to src/science/fire/fire_weather_index/fire_mod.F90 diff --git a/src/science/fire/fire_timestep_mod.F90 b/src/science/fire/fire_weather_index/fire_timestep_mod.F90 similarity index 100% rename from src/science/fire/fire_timestep_mod.F90 rename to src/science/fire/fire_weather_index/fire_timestep_mod.F90 diff --git a/src/science/fire/mcarthur_mod.F90 b/src/science/fire/fire_weather_index/mcarthur_mod.F90 similarity index 100% rename from src/science/fire/mcarthur_mod.F90 rename to src/science/fire/fire_weather_index/mcarthur_mod.F90 diff --git a/src/science/fire/nesterov_mod.F90 b/src/science/fire/fire_weather_index/nesterov_mod.F90 similarity index 100% rename from src/science/fire/nesterov_mod.F90 rename to src/science/fire/fire_weather_index/nesterov_mod.F90 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 ed7681fd5253ed2371a78b0858d55cdd4d3116e3 Mon Sep 17 00:00:00 2001 From: Maggie Hendry Date: Wed, 19 Aug 2026 18:45:58 +0100 Subject: [PATCH 04/14] fire_switches renamed fire_weather_index & l_fire to l_fire_weather_index --- doc/source/namelists/fire.nml.rst | 8 ++-- .../jules-standalone/HEAD/rose-meta.conf | 44 +++++++++---------- rose-meta/jules-standalone/versions.py | 21 ++++++--- src/control/shared/surf_couple_extra_mod.F90 | 4 +- .../init_fire_weather_index_mod.F90 | 27 ++++++------ .../required_vars_for_configuration_mod.F90 | 4 +- .../fire/fire_weather_index/fire_init.F90 | 6 +-- .../fire/fire_weather_index/fire_mod.F90 | 2 +- 8 files changed, 64 insertions(+), 52 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index 96c8f492..ad2d7572 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -1,14 +1,14 @@ ``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 a single namelist called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that sets time-invariant parameters for performing wildfire-related calculations. -``FIRE_SWITCHES`` namelist members +``JULES_FIRE_WEATHER_INDEX`` namelist members ----------------------------------- -.. nml:namelist:: FIRE_SWITCHES +.. nml:namelist:: JULES_FIRE_WEATHER_INDEX -.. nml:member:: l_fire +.. nml:member:: l_fire_weather_index :type: logical :default: F diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index e30a27c5..3e523385 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -665,63 +665,63 @@ length=: type=integer url=https://metoffice.github.io/jules/latest/namelists/cable_surface_types.nml.html#CABLE_SURFACE_TYPES::urban_cable -[namelist:fire_switches] +[namelist:jules_fire_weather_index] compulsory=true description=Switches for controlling activation of the fire module -ns=namelist/JULES Science Settings/fire_switches +ns=namelist/JULES Science Settings/jules_fire_weather_index sort-key=16 -title=Fire options -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#namelist-FIRE_SWITCHES +title=Fire Weather Index options +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#namelist-JULES_FIRE_WEATHER_INDEX -[namelist:fire_switches=canadian_flag] +[namelist:jules_fire_weather_index=canadian_flag] compulsory=true description=Switch for Canadian Fire Weather Index (FWI) sort-key=04 -trigger=namelist:fire_switches=canadian_hemi_opt: .true.; +trigger=namelist:jules_fire_weather_index=canadian_hemi_opt: .true.; type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#FIRE_SWITCHES::canadian_flag +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::canadian_flag -[namelist:fire_switches=canadian_hemi_opt] +[namelist:jules_fire_weather_index=canadian_hemi_opt] compulsory=true description=If TRUE, apply 6-month offset to S-hemisphere month-dependent parameters sort-key=05 type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#FIRE_SWITCHES::canadian_hemi_opt +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::canadian_hemi_opt -[namelist:fire_switches=l_fire] +[namelist:jules_fire_weather_index=l_fire_weather_index] compulsory=true description=Switch to enable the fire module sort-key=01 -trigger=namelist:fire_switches=mcarthur_flag: .true.; - =namelist:fire_switches=mcarthur_opt: .true.; - =namelist:fire_switches=canadian_flag: .true.; - =namelist:fire_switches=nesterov_flag: .true.; +trigger=namelist:jules_fire_weather_index=mcarthur_flag: .true.; + =namelist:jules_fire_weather_index=mcarthur_opt: .true.; + =namelist:jules_fire_weather_index=canadian_flag: .true.; + =namelist:jules_fire_weather_index=nesterov_flag: .true.; type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#FIRE_SWITCHES::l_fire +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::l_fire_weather_index -[namelist:fire_switches=mcarthur_flag] +[namelist:jules_fire_weather_index=mcarthur_flag] compulsory=true description=Switch for McArthur Forest Fire Danger Index (FFDI) sort-key=02 -trigger=namelist:fire_switches=mcarthur_opt: .true.; +trigger=namelist:jules_fire_weather_index=mcarthur_opt: .true.; type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#FIRE_SWITCHES::mcarthur_flag +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::mcarthur_flag -[namelist:fire_switches=mcarthur_opt] +[namelist:jules_fire_weather_index=mcarthur_opt] compulsory=true description=Method for soil moisture deficit in McArthur FFDI sort-key=03 -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#FIRE_SWITCHES::mcarthur_opt +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::mcarthur_opt value-titles=Model value,Fixed at 120 mm values=1,2 widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget -[namelist:fire_switches=nesterov_flag] +[namelist:jules_fire_weather_index=nesterov_flag] compulsory=true description=Switch for Nesterov Index sort-key=06 type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#FIRE_SWITCHES::nesterov_flag +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::nesterov_flag [namelist:imogen_anlg_vals_list] compulsory=true diff --git a/rose-meta/jules-standalone/versions.py b/rose-meta/jules-standalone/versions.py index 1d4c41a9..fe0f4c7a 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -45,15 +45,26 @@ from .version81_82 import * -class vnYY_txxxx(MacroUpgrade): +class vn82_t119(MacroUpgrade): - """Upgrade macro from JULES by Author""" + """Upgrade macro from JULES by Maggie Hendry""" - BEFORE_TAG = "vnY.Y" - AFTER_TAG = "vnY.Y_txxxx" + BEFORE_TAG = "vn8.2" + AFTER_TAG = "vn8.2_t119" 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"]) + + source = self.get_setting_value(config, ["file:fire.nml","source"]) + source = source.replace("namelist:fire_switches", + "namelist:jules_fire_weather_index") + self.change_setting_value(config, ["file:fire.nml","source"], source) + return config, self.reports diff --git a/src/control/shared/surf_couple_extra_mod.F90 b/src/control/shared/surf_couple_extra_mod.F90 index 4b52d3c1..76d4d279 100644 --- a/src/control/shared/surf_couple_extra_mod.F90 +++ b/src/control/shared/surf_couple_extra_mod.F90 @@ -259,7 +259,7 @@ SUBROUTINE surf_couple_extra( & USE atm_step_local, ONLY: dim_cs1 #else !Modules specific to JULES -USE fire_mod, ONLY: fire_prog, fire_diag, l_fire +USE fire_mod, ONLY: fire_prog, fire_diag, l_fire_weather_index USE metstats_mod, ONLY: metstats_prog, l_metstats @@ -1027,7 +1027,7 @@ SUBROUTINE surf_couple_extra( & END IF !Fire (standalone only) - IF ( l_fire ) THEN + IF ( l_fire_weather_index ) THEN !Calculate the gridbox mean soil moisture smc_gb = soiltiles_to_gbm(progs%smc_soilt, ainfo) CALL fire_timestep(metstats_prog, smc_gb, fire_prog, fire_diag, & diff --git a/src/initialisation/standalone/init_fire_weather_index_mod.F90 b/src/initialisation/standalone/init_fire_weather_index_mod.F90 index 84fc67f6..7d36750d 100644 --- a/src/initialisation/standalone/init_fire_weather_index_mod.F90 +++ b/src/initialisation/standalone/init_fire_weather_index_mod.F90 @@ -19,7 +19,7 @@ SUBROUTINE init_fire_weather_index(nml_dir,land_index) USE logging_mod, ONLY: log_info,log_fatal -USE fire_mod, ONLY: fire_cntl, l_fire +USE fire_mod, ONLY: fire_cntl, l_fire_weather_index USE fire_allocate_mod,ONLY: fire_allocate @@ -48,11 +48,13 @@ SUBROUTINE init_fire_weather_index(nml_dir,land_index) LOGICAL :: canadian_hemi_opt = .FALSE. INTEGER :: mcarthur_opt = imdi +CHARACTER(LEN=*), PARAMETER :: RoutineName='INIT_FIRE_WEATHER_INDEX' + !----------------------------------------------------------------------------- -! Definition of the fire_Switches namelist +! Definition of the jules_fire_weather_index namelist !----------------------------------------------------------------------------- -NAMELIST / fire_switches/ l_fire, mcarthur_flag, mcarthur_opt, & - canadian_flag, canadian_hemi_opt, & +NAMELIST /jules_fire_weather_index/ l_fire_weather_index, mcarthur_flag, & + mcarthur_opt, canadian_flag, canadian_hemi_opt, & nesterov_flag !----------------------------------------------------------------------------- @@ -60,32 +62,31 @@ SUBROUTINE init_fire_weather_index(nml_dir,land_index) ! Read the namelist !----------------------------------------------------------------------------- - ! Open the fire namelist file +! 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("init_fire_weather_index", & - "Error opening namelist file fire.nml " // & + CALL log_fatal(RoutineName, "Error opening namelist file fire.nml " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") ! There is one namelist to read from this file -CALL log_info("init_fire_weather_index", "Reading FIRE_SWITCHES namelist...") -READ(namelist_unit, NML = fire_switches, IOSTAT = ERROR) +CALL log_info(RoutineName, "Reading JULES_FIRE_WEATHER_INDEX namelist...") +READ(namelist_unit, NML = jules_fire_weather_index, IOSTAT = ERROR) IF ( ERROR /= 0 ) & - CALL log_fatal("init_fire_weather_index", & - "Error reading namelist fire_SWITCHES " // & + CALL log_fatal(RoutineName, & + "Error reading namelist jules_fire_weather_index " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") ! Close the namelist file CLOSE(namelist_unit, IOSTAT = ERROR) IF ( ERROR /= 0 ) & - CALL log_fatal("init_fire_weather_index", & + CALL log_fatal(RoutineName, & "Error closing namelist file fire.nml " // & "(IOSTAT=" // TRIM(to_string(ERROR)) // ")") ! If not running fire, we can bail -IF ( .NOT. l_fire ) RETURN +IF ( .NOT. l_fire_weather_index ) RETURN ! Copy across namelist variables to the fire_cntl structure fire_cntl%canadian%flag = canadian_flag diff --git a/src/io/dump/required_vars_for_configuration_mod.F90 b/src/io/dump/required_vars_for_configuration_mod.F90 index 2d4b666d..2bc98a18 100644 --- a/src/io/dump/required_vars_for_configuration_mod.F90 +++ b/src/io/dump/required_vars_for_configuration_mod.F90 @@ -49,7 +49,7 @@ SUBROUTINE required_vars_for_configuration(nvars, identifiers, & USE jules_soil_mod, ONLY: l_bedrock, sm_levels, l_tile_soil -USE fire_mod, ONLY: fire_cntl, l_fire +USE fire_mod, ONLY: fire_cntl, l_fire_weather_index USE metstats_mod, ONLY: metstats_flag, l_metstats @@ -368,7 +368,7 @@ SUBROUTINE required_vars_for_configuration(nvars, identifiers, & !----------------------------------------------------------------------------- ! Add fire prognostic variables if switched on !----------------------------------------------------------------------------- -IF ( l_fire ) THEN +IF ( l_fire_weather_index ) THEN IF (fire_cntl%mcarthur%flag) THEN CALL add_to_list( 'fire_mcarthur_r_dr', nvars, identifiers ) CALL add_to_list( 'fire_mcarthur_n_dr', nvars, identifiers ) diff --git a/src/science/fire/fire_weather_index/fire_init.F90 b/src/science/fire/fire_weather_index/fire_init.F90 index 2007cb9c..0f64dab2 100644 --- a/src/science/fire/fire_weather_index/fire_init.F90 +++ b/src/science/fire/fire_weather_index/fire_init.F90 @@ -10,7 +10,7 @@ SUBROUTINE fire_init() ! < Module imports > USE metstats_mod, ONLY: metstats_flag -USE fire_mod, ONLY: fire_cntl, l_fire +USE fire_mod, ONLY: fire_cntl, l_fire_weather_index USE jules_soil_mod, ONLY: zsmc !Depth of layer for soil moisture diag (m) @@ -50,7 +50,7 @@ SUBROUTINE fire_init() ! ------------------------------------------ ! Activate the required metstats -IF (l_fire) THEN +IF (l_fire_weather_index) THEN IF (fire_cntl%mcarthur%flag .OR. fire_cntl%nesterov%flag) THEN metstats_flag%prec_tot_00h = .TRUE. @@ -89,7 +89,7 @@ SUBROUTINE fire_init() !Nothing to do for nesterov -END IF !l_fire +END IF !l_fire_weather_index IF (lhook) CALL dr_hook(ModuleName//':'//RoutineName,zhook_out,zhook_handle) RETURN diff --git a/src/science/fire/fire_weather_index/fire_mod.F90 b/src/science/fire/fire_weather_index/fire_mod.F90 index 5225c1f8..8e43f8de 100644 --- a/src/science/fire/fire_weather_index/fire_mod.F90 +++ b/src/science/fire/fire_weather_index/fire_mod.F90 @@ -40,7 +40,7 @@ MODULE fire_mod ! Module constants !Switch for if we're using the fire module -LOGICAL :: l_fire = .FALSE. +LOGICAL :: l_fire_weather_index = .FALSE. !Canadian model user defined types for prognostics, diagnotics and control TYPE :: canadian_progs From f186850846da078bd4195d7ad130397bb4cbb275 Mon Sep 17 00:00:00 2001 From: Maggie Hendry Date: Wed, 19 Aug 2026 18:47:26 +0100 Subject: [PATCH 05/14] rose config-dump applied. --- .../jules-standalone/HEAD/rose-meta.conf | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/rose-meta/jules-standalone/HEAD/rose-meta.conf b/rose-meta/jules-standalone/HEAD/rose-meta.conf index 3e523385..f93860bc 100644 --- a/rose-meta/jules-standalone/HEAD/rose-meta.conf +++ b/rose-meta/jules-standalone/HEAD/rose-meta.conf @@ -665,64 +665,6 @@ length=: type=integer url=https://metoffice.github.io/jules/latest/namelists/cable_surface_types.nml.html#CABLE_SURFACE_TYPES::urban_cable -[namelist:jules_fire_weather_index] -compulsory=true -description=Switches for controlling activation of the fire module -ns=namelist/JULES Science Settings/jules_fire_weather_index -sort-key=16 -title=Fire Weather Index options -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#namelist-JULES_FIRE_WEATHER_INDEX - -[namelist:jules_fire_weather_index=canadian_flag] -compulsory=true -description=Switch for Canadian Fire Weather Index (FWI) -sort-key=04 -trigger=namelist:jules_fire_weather_index=canadian_hemi_opt: .true.; -type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::canadian_flag - -[namelist:jules_fire_weather_index=canadian_hemi_opt] -compulsory=true -description=If TRUE, apply 6-month offset to S-hemisphere month-dependent parameters -sort-key=05 -type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::canadian_hemi_opt - -[namelist:jules_fire_weather_index=l_fire_weather_index] -compulsory=true -description=Switch to enable the fire module -sort-key=01 -trigger=namelist:jules_fire_weather_index=mcarthur_flag: .true.; - =namelist:jules_fire_weather_index=mcarthur_opt: .true.; - =namelist:jules_fire_weather_index=canadian_flag: .true.; - =namelist:jules_fire_weather_index=nesterov_flag: .true.; -type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::l_fire_weather_index - -[namelist:jules_fire_weather_index=mcarthur_flag] -compulsory=true -description=Switch for McArthur Forest Fire Danger Index (FFDI) -sort-key=02 -trigger=namelist:jules_fire_weather_index=mcarthur_opt: .true.; -type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::mcarthur_flag - -[namelist:jules_fire_weather_index=mcarthur_opt] -compulsory=true -description=Method for soil moisture deficit in McArthur FFDI -sort-key=03 -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::mcarthur_opt -value-titles=Model value,Fixed at 120 mm -values=1,2 -widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget - -[namelist:jules_fire_weather_index=nesterov_flag] -compulsory=true -description=Switch for Nesterov Index -sort-key=06 -type=logical -url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::nesterov_flag - [namelist:imogen_anlg_vals_list] compulsory=true ns=namelist/IMOGEN/GCM Analogue configuration @@ -2056,6 +1998,64 @@ sort-key=13 type=real url=https://metoffice.github.io/jules/latest/namelists/drive.nml.html#JULES_DRIVE::z1_uv_in +[namelist:jules_fire_weather_index] +compulsory=true +description=Switches for controlling activation of the fire module +ns=namelist/JULES Science Settings/jules_fire_weather_index +sort-key=16 +title=Fire Weather Index options +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#namelist-JULES_FIRE_WEATHER_INDEX + +[namelist:jules_fire_weather_index=canadian_flag] +compulsory=true +description=Switch for Canadian Fire Weather Index (FWI) +sort-key=04 +trigger=namelist:jules_fire_weather_index=canadian_hemi_opt: .true.; +type=logical +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::canadian_flag + +[namelist:jules_fire_weather_index=canadian_hemi_opt] +compulsory=true +description=If TRUE, apply 6-month offset to S-hemisphere month-dependent parameters +sort-key=05 +type=logical +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::canadian_hemi_opt + +[namelist:jules_fire_weather_index=l_fire_weather_index] +compulsory=true +description=Switch to enable the fire module +sort-key=01 +trigger=namelist:jules_fire_weather_index=mcarthur_flag: .true.; + =namelist:jules_fire_weather_index=mcarthur_opt: .true.; + =namelist:jules_fire_weather_index=canadian_flag: .true.; + =namelist:jules_fire_weather_index=nesterov_flag: .true.; +type=logical +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::l_fire_weather_index + +[namelist:jules_fire_weather_index=mcarthur_flag] +compulsory=true +description=Switch for McArthur Forest Fire Danger Index (FFDI) +sort-key=02 +trigger=namelist:jules_fire_weather_index=mcarthur_opt: .true.; +type=logical +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::mcarthur_flag + +[namelist:jules_fire_weather_index=mcarthur_opt] +compulsory=true +description=Method for soil moisture deficit in McArthur FFDI +sort-key=03 +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::mcarthur_opt +value-titles=Model value,Fixed at 120 mm +values=1,2 +widget[rose-config-edit]=cylc8_compat.ComboBoxValueWidget + +[namelist:jules_fire_weather_index=nesterov_flag] +compulsory=true +description=Switch for Nesterov Index +sort-key=06 +type=logical +url=https://metoffice.github.io/jules/latest/namelists/fire.nml.html#JULES_FIRE_WEATHER_INDEX::nesterov_flag + [namelist:jules_flake] compulsory=true description=Configuration of the FLake model, only required if l_flake_model=true From a7745c4a9924c65324f8cf304e1a77e77a7189a4 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 06/14] 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 | 45 +- 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 +- .../standalone/init_inferno_mod.F90 | 138 ++++++ .../standalone/init_jules_sf_diags_mod.F90 | 5 +- src/initialisation/standalone/init_mod.F90 | 3 + .../standalone/init_vegetation.F90 | 22 +- .../um/read_jules_namelists_mod.F90 | 31 ++ src/science/fire/inferno/inferno_io_mod.F90 | 18 +- src/science/fire/inferno/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, 943 insertions(+), 235 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 81789894..d7ee7f3e 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 f93860bc..2b5a4e84 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 fe0f4c7a..74e0414f 100644 --- a/rose-meta/jules-standalone/versions.py +++ b/rose-meta/jules-standalone/versions.py @@ -45,12 +45,13 @@ from .version81_82 import * -class vn82_t119(MacroUpgrade): - """Upgrade macro from JULES by Maggie Hendry""" +class vn82_t61(MacroUpgrade): + + """Upgrade macro from JULES by Eleanor Burke""" BEFORE_TAG = "vn8.2" - AFTER_TAG = "vn8.2_t119" + AFTER_TAG = "vn8.2_t61" def upgrade(self, config, meta_config=None): """Upgrade a JULES runtime app configuration.""" @@ -62,9 +63,45 @@ def upgrade(self, config, meta_config=None): ["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_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 76d4d279..c5611fa5 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_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_mod.F90 b/src/initialisation/standalone/init_mod.F90 index b7850e9f..3a66a99d 100644 --- a/src/initialisation/standalone/init_mod.F90 +++ b/src/initialisation/standalone/init_mod.F90 @@ -56,6 +56,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 @@ -283,6 +284,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_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/inferno_io_mod.F90 b/src/science/fire/inferno/inferno_io_mod.F90 index 1fb36dda..e6ceea03 100644 --- a/src/science/fire/inferno/inferno_io_mod.F90 +++ b/src/science/fire/inferno/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/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 3a7d18ff..3e0ecedc 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_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 abdcc51a3614a14030c25b5e4c6797bc2f2bef07 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 07/14] 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 8bae02947be554643b0a4d305edf837dea79a68e 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 08/14] passing with flammability set to old functions --- doc/source/namelists/fire.nml.rst | 141 +++++++++++++++++- .../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 +- .../standalone/init_inferno_mod.F90 | 8 +- src/initialisation/standalone/init_mod.F90 | 1 + src/science/fire/inferno/inferno_io_mod.F90 | 8 +- src/science/fire/inferno/inferno_mod.F90 | 63 ++++++-- src/science/vegetation/soilcarb_jls.F90 | 16 +- .../vegetation/soilcarb_layers_jls_mod.F90 | 8 +- 11 files changed, 222 insertions(+), 91 deletions(-) diff --git a/doc/source/namelists/fire.nml.rst b/doc/source/namelists/fire.nml.rst index ad2d7572..36fbe68b 100644 --- a/doc/source/namelists/fire.nml.rst +++ b/doc/source/namelists/fire.nml.rst @@ -1,7 +1,7 @@ ``fire.nml`` =================== -This file contains a single namelist called :nml:lst:`JULES_FIRE_WEATHER_INDEX` that sets time-invariant parameters for performing wildfire-related calculations. +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 namelsit is for parameters associated with the inferno fire model called :nml:lst:`JULES_INFERNO` ``JULES_FIRE_WEATHER_INDEX`` namelist members ----------------------------------- @@ -57,3 +57,142 @@ This file contains a single namelist called :nml:lst:`JULES_FIRE_WEATHER_INDEX` :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_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/initialisation/standalone/init_mod.F90 b/src/initialisation/standalone/init_mod.F90 index 3a66a99d..f0dbae11 100644 --- a/src/initialisation/standalone/init_mod.F90 +++ b/src/initialisation/standalone/init_mod.F90 @@ -284,6 +284,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/science/fire/inferno/inferno_io_mod.F90 b/src/science/fire/inferno/inferno_io_mod.F90 index e6ceea03..d22c1792 100644 --- a/src/science/fire/inferno/inferno_io_mod.F90 +++ b/src/science/fire/inferno/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/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 3e0ecedc..78114fff 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/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 c8eb8789e203780606fa0e558d75a198c0eaf9eb 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 09/14] rewriting namelist reading files --- CONTRIBUTORS.md | 1 + doc/source/namelists/fire.nml.rst | 7 +- .../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(+), 297 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 36fbe68b..be8b4db1 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 namelsit 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` ``JULES_FIRE_WEATHER_INDEX`` namelist members ----------------------------------- @@ -126,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 @@ -138,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 2b5a4e84..35c2ec7d 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 d24daec39182a8e497b9bf682e13e8eda1385865 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 10/14] 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/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 be8b4db1..ffb6af77 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/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 78114fff..e5c9e58c 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/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 5a926d0aa9d040e08c88d118df4e7f305997255a 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 11/14] 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/inferno_io_mod.F90 | 14 ++-- src/science/fire/inferno/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 ffb6af77..2ccbfec1 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 35c2ec7d..b60f12f0 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/inferno_io_mod.F90 b/src/science/fire/inferno/inferno_io_mod.F90 index d22c1792..9dc2cb9f 100644 --- a/src/science/fire/inferno/inferno_io_mod.F90 +++ b/src/science/fire/inferno/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/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index e5c9e58c..7e9705c9 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/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 bc6f8272866461457d6ea9d5df9abbea6d663f55 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 12/14] 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/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 2ccbfec1..a8713631 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/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 7e9705c9..11a74a99 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/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 299821605d2a99a44cbf744553e5a7aaf231fbf7 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 13/14] flam_rhum bit compares --- src/science/fire/inferno/inferno_mod.F90 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/science/fire/inferno/inferno_mod.F90 b/src/science/fire/inferno/inferno_mod.F90 index 11a74a99..2aca7258 100644 --- a/src/science/fire/inferno/inferno_mod.F90 +++ b/src/science/fire/inferno/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 7240585b2cfd82b3ed3af59f218dda52870a65ec 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 14/14] still passing tests --- src/science/fire/inferno/inferno_io_mod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/science/fire/inferno/inferno_io_mod.F90 b/src/science/fire/inferno/inferno_io_mod.F90 index 9dc2cb9f..37ba4d25 100644 --- a/src/science/fire/inferno/inferno_io_mod.F90 +++ b/src/science/fire/inferno/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