diff --git a/.gitmodules b/.gitmodules index d52b9067ba..6ff4b67f13 100644 --- a/.gitmodules +++ b/.gitmodules @@ -68,7 +68,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/mizuRoute [submodule "ccs_config"] path = ccs_config url = https://github.com/ESMCI/ccs_config_cesm.git -fxtag = ccs_config_cesm1.0.88 +fxtag = ccs_config_cesm1.0.92 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git @@ -76,7 +76,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git [submodule "cime"] path = cime url = https://github.com/ESMCI/cime -fxtag = cime6.5.5 +fxtag = cime6.5.20 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESMCI/cime @@ -84,7 +84,7 @@ fxDONOTUSEurl = https://github.com/ESMCI/cime [submodule "cmeps"] path = components/cmeps url = https://github.com/ESCOMP/CMEPS.git -fxtag = cmeps1.1.69 +fxtag = cmeps1.1.71 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git @@ -92,7 +92,7 @@ fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git [submodule "cdeps"] path = components/cdeps url = https://github.com/ESCOMP/CDEPS.git -fxtag = cdeps1.0.109 +fxtag = cdeps1.0.110 fxrequired = ToplevelRequired # Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 5409562ca6..ff6ab52de8 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -2403,9 +2403,26 @@ sub setup_logic_urban { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'building_temp_method'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'urban_hac'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'building_humidity_mode'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'urban_explicit_ac'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'urban_traffic'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'init_interp_fill_missing_urban_with_HD'); + my $building_humidity_mode = $nl->get_value('building_humidity_mode'); + if ($building_humidity_mode < 0 || $building_humidity_mode > 2) { + $log->fatal_error("building_humidity_mode must be 0, 1, or 2"); + } + if ($building_humidity_mode >= 1 && $nl->get_value('building_temp_method') != 1) { + $log->fatal_error("building_humidity_mode=1 or 2 requires building_temp_method=1"); + } + if ($building_humidity_mode == 2) { + my $urban_hac = remove_leading_and_trailing_quotes($nl->get_value('urban_hac')); + if ($urban_hac ne 'ON' && $urban_hac ne 'ON_WASTEHEAT') { + $log->fatal_error("building_humidity_mode=2 requires urban_hac to be ON or ON_WASTEHEAT"); + } + if (! value_is_true($nl->get_value('urban_explicit_ac'))) { + $log->fatal_error("building_humidity_mode=2 requires urban_explicit_ac=.true."); + } + } } #------------------------------------------------------------------------------- diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index a40a82a56b..82dced7cf1 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -235,6 +235,9 @@ attributes from the config_cache.xml file (with keys converted to upper-case). FAST NONE + +0 + .false. .true. diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index cc20e00fc2..daa0ab8ba4 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -1247,6 +1247,18 @@ Turn urban air conditioning/heating ON or OFF and add wasteheat: If TRUE, use explicit, time-varying AC adoption rate for air-conditioning flux and interior building temperature calculations. +See Li et al. (2024), doi:10.1029/2023MS004107 + + + +Select treatment of indoor building humidity: + 0 = Existing CLMU formulation without indoor humidity or air-conditioning dehumidification + 1 = Indoor humidity and latent heat exchange without air-conditioning dehumidification + 2 = Indoor humidity and latent heat exchange with air-conditioning dehumidification and condensate production +Modes 1 and 2 require building_temp_method=1 (prognostic calculation of interior building temp (clm5_0)). +Mode 2 also requires urban_hac to be ON or ON_WASTEHEAT and urban_explicit_ac=.true. +See Li et al. (2026), doi:10.1038/s44284-026-00474-4 { options=>"-envxml_dir .", + namelst=>"building_humidity_mode=-1", + phys=>"clm6_0", + }, + "building humidity mode above range" + =>{ options=>"-envxml_dir .", + namelst=>"building_humidity_mode=3", + phys=>"clm6_0", + }, + "humidity mode 1 with simple temperature" + =>{ options=>"-envxml_dir .", + namelst=>"building_humidity_mode=1,building_temp_method=0", + phys=>"clm6_0", + }, + "humidity mode 2 with simple temperature" + =>{ options=>"-envxml_dir .", + namelst=>"building_humidity_mode=2,building_temp_method=0,urban_hac='ON',urban_explicit_ac=.true.", + phys=>"clm6_0", + }, + "humidity mode 2 with AC off" + =>{ options=>"-envxml_dir .", + namelst=>"building_humidity_mode=2,building_temp_method=1,urban_hac='OFF',urban_explicit_ac=.true.", + phys=>"clm6_0", + }, + "humidity mode 2 without explicit AC" + =>{ options=>"-envxml_dir .", + namelst=>"building_humidity_mode=2,building_temp_method=1,urban_hac='ON',urban_explicit_ac=.false.", + phys=>"clm6_0", + }, "cmip7_w_issp" =>{ options=>"-envxml_dir . -use_case 1850-2100_SSP2-4.5_transient", namelst=>"", CLM_CMIP_ERA=>"cmip7", @@ -1211,10 +1241,6 @@ sub cat_and_create_namelistinfile { namelst=>"use_fates_inventory_init=.true.", phys=>"clm4_5", }, - "inventoryfileDNE" =>{ options=>"-bgc fates -envxml_dir . -no-megan", - namelst=>"use_fates_inventory_init=.true., fates_inventory_ctrl_filename='zztop'", - phys=>"clm4_5", - }, "useFATESLUH2butnotfile" =>{ options=>"--res 0.9x1.25 --bgc fates --envxml_dir . --no-megan", namelst=>"use_fates_luh=.true.", phys=>"clm4_5", @@ -1223,10 +1249,6 @@ sub cat_and_create_namelistinfile { namelst=>"use_fates_lupft=.true.", phys=>"clm4_5", }, - "useFATESLUH2fileDNE" =>{ options=>"-bgc fates -envxml_dir . -no-megan", - namelst=>"use_fates_luh=.true., fluh_timeseries='zztop'", - phys=>"clm4_5", - }, "useFATESLUH2invalidlogic" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_fates_luh=.true., fates_lu_transition_logic=0", phys=>"clm6_0", diff --git a/ccs_config b/ccs_config index 7c8bd604c8..c71cdfba50 160000 --- a/ccs_config +++ b/ccs_config @@ -1 +1 @@ -Subproject commit 7c8bd604c818e4e832dda02b8584260fb7e22efc +Subproject commit c71cdfba50aedc452a96fe3dd033f8bfdcf7c0fb diff --git a/cime b/cime index 92ae0fd813..b9e65323db 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit 92ae0fd8133a3397a95f1cfcfa40dc138562f305 +Subproject commit b9e65323db198ac14ab3a78ae162c9782ac43c09 diff --git a/cime_config/testdefs/ExpectedTestFails.xml b/cime_config/testdefs/ExpectedTestFails.xml index f7fcde5c91..fdeb1060c5 100644 --- a/cime_config/testdefs/ExpectedTestFails.xml +++ b/cime_config/testdefs/ExpectedTestFails.xml @@ -30,11 +30,17 @@ - + FAIL CDEPS/#243 and/or #2122 + + + FAIL + #4238 + + @@ -128,63 +134,6 @@ - - - FAIL - #4160 - - - - - - FAIL - #4160 - - - - - - FAIL - #4160 - - - - - - FAIL - #4160 - - - - - - FAIL - #4160 - - - - - - FAIL - #4160 - - - - - - FAIL - #4160 - - - - - - FAIL - #4160 - Does this also relate to #2619? - - - diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index 345eedc3d3..16c4aade05 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -317,6 +317,16 @@ + + + + + + + + + + @@ -2213,16 +2223,6 @@ - - - - - - - - - - @@ -2233,16 +2233,6 @@ - - - - - - - - - - @@ -2253,16 +2243,6 @@ - - - - - - - - - - @@ -5044,7 +5024,7 @@ - + @@ -5057,7 +5037,7 @@ - + diff --git a/cime_config/testdefs/testmods_dirs/clm/norESMTest/shell_commands b/cime_config/testdefs/testmods_dirs/clm/norESMTest/shell_commands new file mode 100755 index 0000000000..564c30a2a0 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/norESMTest/shell_commands @@ -0,0 +1,3 @@ +#!/bin/bash + +./xmlchange MODEL="noresm" diff --git a/components/cdeps b/components/cdeps index 23acaf245d..51ae05e65b 160000 --- a/components/cdeps +++ b/components/cdeps @@ -1 +1 @@ -Subproject commit 23acaf245d7294fba62b2784b2c937b9fc79b5d8 +Subproject commit 51ae05e65b9ddd0843663d09d52f08d5302b34a7 diff --git a/components/cmeps b/components/cmeps index a51b39fe5b..0060d41cdb 160000 --- a/components/cmeps +++ b/components/cmeps @@ -1 +1 @@ -Subproject commit a51b39fe5bfcb9e5eebc628e9ffaa751eedea73c +Subproject commit 0060d41cdbc2349e3f2ac6d19f2dd6db681f4b20 diff --git a/doc/.ChangeLog_template b/doc/.ChangeLog_template index 7dd14135c1..a5bbdbbb0a 100644 --- a/doc/.ChangeLog_template +++ b/doc/.ChangeLog_template @@ -95,7 +95,7 @@ infrastructure should be run when appropriate, as described below. derecho - - python testing (if python code has changed; see instructions in python/README.md; document testing done): + python testing (if python or CIME code has changed; see instructions in python/README.md; document testing done): derecho - diff --git a/doc/ChangeLog b/doc/ChangeLog index 4e3cd74510..dfce821863 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,298 @@ =============================================================== +Tag name: ctsm5.4.062 +Originator(s): slevis (Samuel Levis,UCAR/TSS,+1 303 497 1234) +Date: Fri Oct 2 07:23:31 AM MDT 2026 +One-line Summary: Merge b4b-dev to master + +Purpose and description of changes +---------------------------------- + +Includes these PRs +#4199 Make additional history fields active in prep. for CMIP7 +#4236 Make the Python unit-test job fail when a test fails +#4231 test(subset_data): make unit test work outside NCAR cluster, like its siblings do +#4229 Specify q10 for HR and MR +#4185 refactor(biogeophys): Rename frac_sno and frac_sno_eff to clarify albedo vs flux roles +#4225 Fix test_unit_neon_site error +#4222 Fix test_sys_plumber2_surf_wrapper.py failures +#4220 Change GLC_NCPL to 4 for DAE test to pass + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: +Resolves #4181 +Resolves #4230 Contributes to #3236 +Resolves #4196 +Resolves #822 +Resolves #4216 +Resolves #4215 +Resolves #4202 + +Notes of particular relevance for users +--------------------------------------- +Changes to documentation: Minor, as needed + +Contributors in addition to originator: +@Santoshkumarpuppala +@johnpaulalex +@wwieder +@olyson + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + Removed DAE test from ExpectedTestFails.xml. See titles of included PRs for other test-related work. + ERP_P64x2_Ld396.f10_f10_mg37.IHistClm60Bgc.derecho_intel.clm-monthly--clm-matrixcnOn_ignore_warnings passed in COMPARE_base_rest when expected to fail according to issue #2619; I recorded this in #2619 but did not remove the test from the expected fails, yet + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python or CIME code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + +Answer changes +-------------- +Changes answers relative to baseline: No, only field lists differ due to #4199 + + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/4241 and the PRs listed above + +=============================================================== +=============================================================== +Tag name: ctsm5.4.061 +Originator(s): erik (Erik Kluzek,UCAR/TSS,+1 303 497 1326) +Date: Wed Sep 30 11:22:16 PM MDT 2026 +One-line Summary: Update to cesm3_0_beta10 externals cime/ccs_config, including more ccs_config grid aliases with MOM grids + +Purpose and description of changes +---------------------------------- + +Update cime and ccs_config to latest version as in the cesm3_0_beta10 tag. Also includes changes so that CIME_MODEL can be set to noresm. + +Also include new ccs_config version that has more t233/t201 grid aliases from @slevis-lmwg + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: + Add a new test for NorESM, that currently fails. It may be a test to remove. + +Testing summary: regular + fates + ctsm_sci +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python or CIME code has changed; see instructions in python/README.md; document testing done): + + derecho - OK + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (fates-sci.1.93.1_api.46.0.0-ctsm5.4.060) + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: No b4b + +Other details +------------- + +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + cime to cime6.5.20 + ccs_config to ccs_config_cesm1.0.92 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + Update submodules as for final cesm3_0_beta10, cime and ccs_config to latest including more t233 grid aliases #4232 + +=============================================================== +=============================================================== +Tag name: ctsm5.4.060 +Originator(s): erik (Erik Kluzek,UCAR/TSS,+1 303 497 1326) +Date: Fri Sep 25 12:53:38 PM MDT 2026 +One-line Summary: Update CDEPS/CMEPS to versions with reproducible sums to fix some failing tests + +Purpose and description of changes +---------------------------------- + +Bring in use of reproducible sums in CDEPS and CMEPS so that our longer threaded tests with DGLC will now PASS. These are turned on with the CMEPS BFBFLAG which was previously not used for anything. + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + - Resolves Threaded exact restart tests that change task/thread count fail with DGLC or CISM when run to a year or more #4160 + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + The xml variable BFBFLAG now actually does something + +Contributors: + - @billsacks did the underlying CDEPS/CMEPS tags + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: + - Remove 364-day tests that were there because the longer ones weren't passing previously + - Lower wallclock for two ctsm_sci tests that didn't need to be so long + - Remove tests that now pass from expected fails + +Testing summary: regular + ctsm_sci +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: Potentially roundoff different + + Summarize any changes to answers, i.e., + - what code configurations: compset with either DGLC or CISM AND BFBFLAG==TRUE + - what platforms/compilers: all + - nature of change: roundoff + + If bitwise differences were observed, how did you show they were no worse + than roundoff? + + - The changes were just a few coupled fields and only to roundoff level + - The exact restart tests that change PE layouts, which previously failed, now PASS + - @billsacks did the evaluation for this in the CMEPS/CDEPS tags + - Since most tests were identical even with the change, this gives assurance that the change often doesn't change answers, or only does so when run long enough + +Other details +------------- + +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): cdeps and cmeps + - cmeps to cmeps1.1.71 (NOTE: this skips past cmeps1.1.70, which was b4b with changes for threading) + - cdeps to cdeps1.0.110 + +Pull Requests that document the changes (include PR ids): + Reproducible sums in CDEPS and CMEPS so that longer threaded tests will PASS #4224 + +=============================================================== +=============================================================== +Tag name: ctsm5.4.059 +Originator(s): cathyxinchangli (Cathy Xinchang Li, U of Illinois - Urbana-Champaign) +Date: Mon Sep 21 10:55:44 AM MDT 2026 +One-line Summary: Indoor humidity and A/C dehumidification + +Purpose and description of changes +---------------------------------- + + This PR adds indoor humidity and air-conditioning dehumidification to the CLMU BEM (Building Energy Model). It prognoses indoor specific humidity, calculates sensible cooling and latent dehumidification loads, and diagnoses condensate production and routes the condensate into urban runoff. The behavior is controlled by an integer CLM namelist variable, building_humidity_mode: + + 0: use the existing CLMU formulation without indoor humidity or AC dehumidification; + 1: enable indoor humidity and latent heat exchange, but no AC dehumidification (requires prognostic building temperature, building_temp_method=1); and + 2: enable indoor humidity, latent heat exchange, dehumidification load, and condensate production (requires prognostic building temperature, urban_hac to be ON or ON_WASTEHEAT and urban_explicit_ac=.true.). + + The default is set to 0 to ensure bit-for-bit reproducibility with the original scheme. + + Indoor humidity and air-conditioning dehumidification are described by Li et al. (2026), doi:10.1038/s44284-026-00474-4. + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Resolves #4162 + +Notes of particular relevance for users +--------------------------------------- +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + building_humidity_mode is added as a namelist variable + +Changes to documentation: + #4195 will address the need for new docs + +Contributors: + Lei Zhao (@Face2sea) + Zhiwen Luo + Keith Oleson (@olyson) + Yifan Cheng (@yifanc17) + Xiaoxiong Xie + Alvin C. G. Varquez + Mitsuna Sekiya + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + 6 new tests in build-namelist_test.pl + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - OK (2 expected fails) + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + +Answer changes +-------------- +Changes answers relative to baseline: No (read the caveat) + + Caveat: + - Results remain bit-for-bit under building_humidity_mode=0 (default). + - Comparing building_humidity_mode=1 with 0, two new variables are added (QBUILD, RHBUILD), and VENTILATION and EFLXBUILD changes because they now include latent heat exchanges between indoors and outdoors, and URBAN_AC and URBAN_HEAT changes slightly because of the changes in ventilation and higher heat capacity of moist air. + - Comparing building_humidity_mode=2 with 1, three more new variables (URBAN_AC_SEN, QCOND_FROM_AC, QCOND_FROM_AC_LUN) are added, and URBAN_AC increases because it now includes sensible (for cooling) and latent (for dehumidification) heat components of urban AC demand. URBAN_HEAT, VENTILATION, EFLXBUILD, WASTEHEAT changes slightly as an indirect results of the changes in AC. + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/4164 + +=============================================================== +=============================================================== Tag name: ctsm5.4.058 Originator(s): erik (Erik Kluzek,UCAR/TSS,+1 303 497 1326) Date: Fri Sep 18 02:58:26 PM MDT 2026 diff --git a/doc/ChangeSum b/doc/ChangeSum index 9d96316b25..fe55a6ff87 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,9 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.4.062 slevis 10/02/2026 Merge b4b-dev to master + ctsm5.4.061 erik 09/30/2026 Update to cesm3_0_beta10 externals cime/ccs_config, including more ccs_config grid aliases with MOM grids + ctsm5.4.060 erik 09/25/2026 Update CDEPS/CMEPS to versions with reproducible sums to fix some failing tests + ctsm5.4.059 cathyxin 09/21/2026 Indoor humidity and A/C dehumidification ctsm5.4.058 erik 09/18/2026 Merge b4b-dev to master ctsm5.4.057 erik 09/17/2026 CDEPS/CMEPS updates for CPLHIST mode and 1850 ndep from DATM ctsm5.4.056 multiple 09/10/2026 Merge the wetlands branch to master diff --git a/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst index a886a3f6ce..e57c113a24 100644 --- a/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst +++ b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst @@ -393,10 +393,13 @@ PROD10C_LOSS - loss from 10-yr wood produc PROD10N - 10-yr wood product N gN/m^2 F PROD10N_LOSS - loss from 10-yr wood product pool gN/m^2/s F PSurf - atmospheric pressure at surface (downscaled for glacier and hillslope columns) Pa F +P_AC - prescribed air-conditioning ownership rate a fraction between 0 and 1 F Q2M - 2m specific humidity kg/kg T QAF - canopy air humidity kg/kg F QBOT - atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg T QBOT_NOT_DOWNSCALED - atmospheric specific humidity (pre-downscaling) kg/kg F +QBUILD - internal urban building air specific humidity kg/kg F +QCOND_FROM_AC - Condensed water flux from AC dehumidification mm/s F QDIRECT_THROUGHFALL - direct throughfall of liquid (rain + above-canopy irrigation) mm/s F QDIRECT_THROUGHFALL_SNOW - direct throughfall of snow mm/s F QDRAI - sub-surface drainage mm/s T @@ -477,6 +480,7 @@ RH2M - 2m relative humidity RH2M_R - Rural 2m relative humidity % F RH2M_U - Urban 2m relative humidity % F RHAF - fractional humidity of canopy air fraction F +RHBUILD - Internal urban building air relative humidity % F RH_LEAF - fractional humidity at leaf surface fraction F RSCANOPY - canopy resistance s m-1 T RSSHA - shaded leaf stomatal resistance s/m T @@ -651,6 +655,7 @@ U10_ICE - 10-m wind (ice landunits on UAF - canopy air speed m/s F UM - wind speed plus stability effect m/s F URBAN_AC - urban air conditioning flux W/m^2 T +URBAN_AC_SEN - sensible heat component of urban air conditioning flux W/m^2 F URBAN_HEAT - urban heating flux W/m^2 T USTAR - aerodynamical resistance s/m F UST_LAKE - friction velocity (lakes only) m/s F diff --git a/doc/source/users_guide/setting-up-and-running-a-case/history_fields_nofates.rst b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_nofates.rst index fbb5d3a578..fad41ab213 100644 --- a/doc/source/users_guide/setting-up-and-running-a-case/history_fields_nofates.rst +++ b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_nofates.rst @@ -876,10 +876,13 @@ PSNSHADE_TO_CPOOL - C fixation from shaded cano PSNSUN - sunlit leaf photosynthesis umolCO2/m^2/s T F PSNSUN_TO_CPOOL - C fixation from sunlit canopy gC/m^2/s T F PSurf - atmospheric pressure at surface (downscaled for glacier and hillslope columns) Pa F F +P_AC - prescribed air-conditioning ownership rate a fraction between 0 and 1 F F Q2M - 2m specific humidity kg/kg T F QAF - canopy air humidity kg/kg F F QBOT - atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg T F QBOT_NOT_DOWNSCALED - atmospheric specific humidity (pre-downscaling) kg/kg F F +QBUILD - internal urban building air specific humidity kg/kg F F +QCOND_FROM_AC - Condensed water flux from AC dehumidification mm/s F F QDIRECT_THROUGHFALL - direct throughfall of liquid (rain + above-canopy irrigation) mm/s F F QDIRECT_THROUGHFALL_SNOW - direct throughfall of snow mm/s F F QDRAI - sub-surface drainage mm/s T F @@ -966,6 +969,7 @@ RH2M_U - Urban 2m relative humidity RH30 - 30-day running mean of relative humidity % F F RHAF - fractional humidity of canopy air fraction F F RHAF10 - 10 day running mean of fractional humidity of canopy air fraction F F +RHBUILD - Internal urban building air relative humidity % F F RH_LEAF - fractional humidity at leaf surface fraction F F RR - root respiration (fine root MR + total root GR) gC/m^2/s T F RSSHA - shaded leaf stomatal resistance s/m T F @@ -1195,6 +1199,7 @@ UAF - canopy air speed ULRAD - upward longwave radiation above the canopy W/m^2 F F UM - wind speed plus stability effect m/s F F URBAN_AC - urban air conditioning flux W/m^2 T F +URBAN_AC_SEN - sensible heat component of urban air conditioning flux W/m^2 F F URBAN_HEAT - urban heating flux W/m^2 T F USTAR - friction velocity m/s F F UST_LAKE - friction velocity (lakes only) m/s F F diff --git a/src/biogeophys/BalanceCheckMod.F90 b/src/biogeophys/BalanceCheckMod.F90 index 01993fd25d..525c05237d 100644 --- a/src/biogeophys/BalanceCheckMod.F90 +++ b/src/biogeophys/BalanceCheckMod.F90 @@ -36,6 +36,7 @@ module BalanceCheckMod use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall use column_varcon , only : icol_road_perv, icol_road_imperv use clm_varctl , only : use_hillslope_routing + use UrbanParamsType , only : IsACDehumidificationEnabled ! ! !PUBLIC TYPES: implicit none @@ -475,6 +476,7 @@ subroutine BalanceCheck( bounds, & real(r8) :: qflx_glcice_dyn_water_flux_grc(bounds%begg:bounds%endg) ! grid cell-level water flux needed for balance check due to glc_dyn_runoff_routing [mm H2O/s] (positive means addition of water to the system) real(r8) :: qflx_snwcp_discarded_liq_grc(bounds%begg:bounds%endg) ! grid cell-level excess liquid h2o due to snow capping, which we simply discard in order to reset the snow pack [mm H2O /s] real(r8) :: qflx_snwcp_discarded_ice_grc(bounds%begg:bounds%endg) ! grid cell-level excess solid h2o due to snow capping, which we simply discard in order to reset the snow pack [mm H2O /s] + real(r8) :: qflx_condensate_from_ac_grc(bounds%begg:bounds%endg) ! grid cell-level condensate water flux from air-conditioning [mm H2O /s] real(r8) :: errh2o_max_val ! Maximum value of error in water conservation error over all columns [mm H2O] real(r8) :: errh2osno_max_val ! Maximum value of error in h2osno conservation error over all columns [kg m-2] @@ -534,7 +536,8 @@ subroutine BalanceCheck( bounds, & qflx_sfc_irrig_col => waterflux_inst%qflx_sfc_irrig_col , & ! Input: [real(r8) (:) ] column level irrigation flux (mm H2O /s) qflx_sfc_irrig_grc => waterlnd2atm_inst%qirrig_grc , & ! Input: [real(r8) (:) ] grid cell-level irrigation flux (mm H20 /s) - qflx_glcice_dyn_water_flux_col => waterflux_inst%qflx_glcice_dyn_water_flux_col & ! Input: [real(r8) (:)] column level water flux needed for balance check due to glc_dyn_runoff_routing (mm H2O/s) (positive means addition of water to the system) + qflx_glcice_dyn_water_flux_col => waterflux_inst%qflx_glcice_dyn_water_flux_col, & ! Input: [real(r8) (:)] column level water flux needed for balance check due to glc_dyn_runoff_routing (mm H2O/s) (positive means addition of water to the system) + qflx_condensate_from_ac_col => waterflux_inst%qflx_condensate_from_ac_col & ! Input: [real(r8) (:)] column level condensate water flux from air-conditioning (mm H2O /s) ) ! Get step size and time step @@ -580,6 +583,10 @@ subroutine BalanceCheck( bounds, & - qflx_snwcp_discarded_liq_col(c) & - qflx_snwcp_discarded_ice_col(c)) * dtime + if (IsACDehumidificationEnabled()) then + errh2o_col(c) = errh2o_col(c) - qflx_condensate_from_ac_col(c) * dtime + end if + else errh2o_col(c) = 0.0_r8 @@ -614,6 +621,9 @@ subroutine BalanceCheck( bounds, & write(iulog,*)'qflx_surf = ',qflx_surf_col(indexc)*dtime write(iulog,*)'qflx_qrgwl = ',qflx_qrgwl_col(indexc)*dtime write(iulog,*)'qflx_drain = ',qflx_drain_col(indexc)*dtime + if (IsACDehumidificationEnabled()) then + write(iulog,*)'qflx_condensate_from_ac = ',qflx_condensate_from_ac_col(indexc)*dtime + end if write(iulog,*)'qflx_ice_runoff = ',qflx_ice_runoff_col(indexc)*dtime @@ -651,6 +661,12 @@ subroutine BalanceCheck( bounds, & qflx_snwcp_discarded_ice_col(bounds%begc:bounds%endc), & qflx_snwcp_discarded_ice_grc(bounds%begg:bounds%endg), & c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) + if (IsACDehumidificationEnabled()) then + call c2g( bounds, & + qflx_condensate_from_ac_col(bounds%begc:bounds%endc), & + qflx_condensate_from_ac_grc(bounds%begg:bounds%endg), & + c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) + end if do g = bounds%begg, bounds%endg errh2o_grc(g) = endwb_grc(g) - begwb_grc(g) & @@ -667,6 +683,10 @@ subroutine BalanceCheck( bounds, & - qflx_ice_runoff_grc(g) & - qflx_snwcp_discarded_liq_grc(g) & - qflx_snwcp_discarded_ice_grc(g)) * dtime + + if (IsACDehumidificationEnabled()) then + errh2o_grc(g) = errh2o_grc(g) - qflx_condensate_from_ac_grc(g) * dtime + end if end do ! add landunit level flux variable, convert from (m3/s) to (kg m-2 s-1) @@ -714,6 +734,9 @@ subroutine BalanceCheck( bounds, & write(iulog,*)'qflx_drain_perched = ',qflx_drain_perched_grc(indexg)*dtime write(iulog,*)'forc_flood = ',forc_flood_grc(indexg)*dtime write(iulog,*)'qflx_glcice_dyn_water_flux = ',qflx_glcice_dyn_water_flux_grc(indexg)*dtime + if (IsACDehumidificationEnabled()) then + write(iulog,*)'qflx_condensate_from_ac = ',qflx_condensate_from_ac_grc(indexg)*dtime + end if write(iulog,*)'CTSM is stopping' call endrun(subgrid_index=indexg, subgrid_level=subgrid_level_gridcell, msg=errmsg(sourcefile, __LINE__)) diff --git a/src/biogeophys/EnergyFluxType.F90 b/src/biogeophys/EnergyFluxType.F90 index 4bb95cf177..d677fd232c 100644 --- a/src/biogeophys/EnergyFluxType.F90 +++ b/src/biogeophys/EnergyFluxType.F90 @@ -13,6 +13,7 @@ module EnergyFluxType use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch + use UrbanParamsType, only : IsACDehumidificationEnabled ! implicit none save @@ -62,14 +63,15 @@ module EnergyFluxType real(r8), pointer :: eflx_anthro_patch (:) ! patch total anthropogenic heat flux (W/m**2) real(r8), pointer :: eflx_traffic_patch (:) ! patch traffic sensible heat flux (W/m**2) real(r8), pointer :: eflx_wasteheat_patch (:) ! patch sensible heat flux from domestic heating/cooling sources of waste heat (W/m**2) - real(r8), pointer :: eflx_ventilation_patch (:) ! patch sensible heat flux from building ventilation (W/m**2) + real(r8), pointer :: eflx_ventilation_patch (:) ! patch sensible and latent heat flux from building ventilation (W/m**2) real(r8), pointer :: eflx_heat_from_ac_patch (:) ! patch sensible heat flux put back into canyon due to removal by AC (W/m**2) real(r8), pointer :: eflx_traffic_lun (:) ! lun traffic sensible heat flux (W/m**2) real(r8), pointer :: eflx_wasteheat_lun (:) ! lun sensible heat flux from domestic heating/cooling sources of waste heat (W/m**2) - real(r8), pointer :: eflx_ventilation_lun (:) ! lun sensible heat flux from building ventilation (W/m**2) + real(r8), pointer :: eflx_ventilation_lun (:) ! lun sensible and latent heat flux from building ventilation (W/m**2) real(r8), pointer :: eflx_heat_from_ac_lun (:) ! lun sensible heat flux to be put back into canyon due to removal by AC (W/m**2) - real(r8), pointer :: eflx_building_lun (:) ! lun building heat flux from change in interior building air temperature (W/m**2) + real(r8), pointer :: eflx_building_lun (:) ! lun building heat flux from change in interior building air temperature (and humidity, if prognosed indoor humidity) (W/m**2) real(r8), pointer :: eflx_urban_ac_lun (:) ! lun urban air conditioning flux (W/m**2) + real(r8), pointer :: eflx_urban_ac_sen_lun (:) ! lun sensible heat component of air conditioning flux (W/m**2) real(r8), pointer :: eflx_urban_heat_lun (:) ! lun urban heating flux (W/m**2) ! Derivatives of energy fluxes @@ -229,6 +231,7 @@ subroutine InitAllocate(this, bounds) allocate( this%eflx_heat_from_ac_lun (begl:endl)) ; this%eflx_heat_from_ac_lun (:) = nan allocate( this%eflx_building_lun (begl:endl)) ; this%eflx_building_lun (:) = nan allocate( this%eflx_urban_ac_lun (begl:endl)) ; this%eflx_urban_ac_lun (:) = nan + allocate( this%eflx_urban_ac_sen_lun (begl:endl)) ; this%eflx_urban_ac_sen_lun (:) = nan allocate( this%eflx_urban_heat_lun (begl:endl)) ; this%eflx_urban_heat_lun (:) = nan allocate( this%eflx_traffic_lun (begl:endl)) ; this%eflx_traffic_lun (:) = nan allocate( this%eflx_wasteheat_lun (begl:endl)) ; this%eflx_wasteheat_lun (:) = nan @@ -571,7 +574,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp) else this%eflx_building_lun(begl:endl) = spval call hist_addfld1d (fname='EFLXBUILD', units='W/m^2', & - avgflag='A', long_name='building heat flux from change in interior building air temperature', & + avgflag='A', long_name='building heat flux from change in interior building air temperature (and humidity, if prognosed indoor humidity)', & ptr_lunit=this%eflx_building_lun, set_nourb=0._r8, l2g_scale_type='unity') this%eflx_urban_ac_lun(begl:endl) = spval @@ -579,6 +582,13 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp) avgflag='A', long_name='urban air conditioning flux', & ptr_lunit=this%eflx_urban_ac_lun, set_nourb=0._r8, l2g_scale_type='unity') + if (IsACDehumidificationEnabled()) then + this%eflx_urban_ac_sen_lun(begl:endl) = spval + call hist_addfld1d (fname='URBAN_AC_SEN', units='W/m^2', & + avgflag='A', long_name='sensible heat component of urban air conditioning flux', & + ptr_lunit=this%eflx_urban_ac_sen_lun, set_nourb=0._r8, l2g_scale_type='unity') + end if + this%eflx_urban_heat_lun(begl:endl) = spval call hist_addfld1d (fname='URBAN_HEAT', units='W/m^2', & avgflag='A', long_name='urban heating flux', & @@ -615,7 +625,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp) if ( is_prog_buildtemp )then this%eflx_ventilation_patch(begp:endp) = spval call hist_addfld1d (fname='VENTILATION', units='W/m^2', & - avgflag='A', long_name='sensible heat flux from building ventilation', & + avgflag='A', long_name='sensible (and latent, if prognosed indoor humidity) heat flux from building ventilation', & ptr_patch=this%eflx_ventilation_patch, set_nourb=0._r8, c2l_scale_type='urbanf') end if @@ -753,6 +763,7 @@ subroutine InitCold(this, bounds, t_grnd_col, is_simple_buildtemp, is_prog_build if ( is_prog_buildtemp )then this%eflx_building_lun(l) = 0._r8 this%eflx_urban_ac_lun(l) = 0._r8 + this%eflx_urban_ac_sen_lun(l)= 0._r8 this%eflx_urban_heat_lun(l) = 0._r8 end if @@ -766,6 +777,7 @@ subroutine InitCold(this, bounds, t_grnd_col, is_simple_buildtemp, is_prog_build if ( is_prog_buildtemp )then this%eflx_building_lun(l) = 0._r8 this%eflx_urban_ac_lun(l) = 0._r8 + this%eflx_urban_ac_sen_lun(l)= 0._r8 this%eflx_urban_heat_lun(l) = 0._r8 this%eflx_ventilation_lun(l)= 0._r8 end if @@ -864,7 +876,7 @@ subroutine Restart(this, bounds, ncid, flag, is_simple_buildtemp, is_prog_buildt end if call restartvar(ncid=ncid, flag=flag, varname='EFLX_VENTILATION', xtype=ncd_double, & dim1name='landunit', & - long_name='sensible heat flux from building ventilation', units='watt/m^2', & + long_name='sensible (and latent, if prognosed indoor humidity) heat flux from building ventilation', units='watt/m^2', & interpinic_flag='interp', readvar=readvar, data=this%eflx_ventilation_lun) if (flag=='read' .and. .not. readvar) then if (masterproc) write(iulog,*) "can't find EFLX_VENTILATION in initial file..." diff --git a/src/biogeophys/HumanIndexMod.F90 b/src/biogeophys/HumanIndexMod.F90 index c5fa5e5385..5be821bcbf 100644 --- a/src/biogeophys/HumanIndexMod.F90 +++ b/src/biogeophys/HumanIndexMod.F90 @@ -1387,4 +1387,3 @@ end subroutine QSat_2 !----------------------------------------------------------------------- end module HumanIndexMod - diff --git a/src/biogeophys/SoilFluxesMod.F90 b/src/biogeophys/SoilFluxesMod.F90 index 2c80b3378f..7269be2b4c 100644 --- a/src/biogeophys/SoilFluxesMod.F90 +++ b/src/biogeophys/SoilFluxesMod.F90 @@ -115,7 +115,7 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & htvp => energyflux_inst%htvp_col , & ! Input: [real(r8) (:) ] latent heat of vapor of water (or sublimation) [j/kg] eflx_building_heat_errsoi=> energyflux_inst%eflx_building_heat_errsoi_col , & ! Input: [real(r8) (:)] heat flux to interior surface of walls and roof for errsoi check (W m-2) eflx_wasteheat_patch => energyflux_inst%eflx_wasteheat_patch , & ! Input: [real(r8) (:) ] sensible heat flux from urban heating/cooling sources of waste heat (W/m**2) - eflx_ventilation_patch => energyflux_inst%eflx_ventilation_patch , & ! Input: [real(r8) (:) ] sensible heat flux from building ventilation (W/m**2) + eflx_ventilation_patch => energyflux_inst%eflx_ventilation_patch , & ! Input: [real(r8) (:) ] sensible and latent heat flux from building ventilation (W/m**2) eflx_heat_from_ac_patch => energyflux_inst%eflx_heat_from_ac_patch , & ! Input: [real(r8) (:) ] sensible heat flux put back into canyon due to removal by AC (W/m**2) eflx_traffic_patch => energyflux_inst%eflx_traffic_patch , & ! Input: [real(r8) (:) ] traffic sensible heat flux (W/m**2) dlrad => energyflux_inst%dlrad_patch , & ! Input: [real(r8) (:) ] downward longwave radiation below the canopy [W/m2] diff --git a/src/biogeophys/SoilHydrologyMod.F90 b/src/biogeophys/SoilHydrologyMod.F90 index 1f6c5920fd..656805fac2 100644 --- a/src/biogeophys/SoilHydrologyMod.F90 +++ b/src/biogeophys/SoilHydrologyMod.F90 @@ -33,6 +33,7 @@ module SoilHydrologyMod use LandunitType , only : lun use ColumnType , only : column_type, col use PatchType , only : patch + use UrbanParamsType , only : IsACDehumidificationEnabled ! ! !PUBLIC TYPES: @@ -497,6 +498,7 @@ subroutine TotalSurfaceRunoff(bounds, num_hydrologyc, filter_hydrologyc, & qflx_liqevap_from_top_layer => waterfluxbulk_inst%qflx_liqevap_from_top_layer_col, & ! Input: [real(r8) (:) ] rate of liquid water evaporated from top soil or snow layer (mm H2O/s) [+] qflx_floodc => waterfluxbulk_inst%qflx_floodc_col , & ! Input: [real(r8) (:) ] column flux of flood water from RTM qflx_sat_excess_surf => waterfluxbulk_inst%qflx_sat_excess_surf_col , & ! Input: [real(r8) (:) ] surface runoff due to saturated surface (mm H2O /s) + qflx_condensate_from_ac => waterfluxbulk_inst%qflx_condensate_from_ac_col, & ! Input: [real(r8) (:) ] condensate from air-conditioning (mm H2O /s) xs_urban => soilhydrology_inst%xs_urban_col , & ! Output: [real(r8) (:) ] excess soil water above urban ponding limit @@ -538,8 +540,14 @@ subroutine TotalSurfaceRunoff(bounds, num_hydrologyc, filter_hydrologyc, & pondmx_urban/dtime) qflx_surf(c) = xs_urban(c) end if - ! send flood water flux to runoff for all urban columns - qflx_surf(c) = qflx_surf(c) + qflx_floodc(c) + ! Send flood water flux and air-conditioning condensate (the latter exists only + ! when prognosed indoor humidity and AC dehumidification are enabled) + ! to runoff for all urban columns + if (IsACDehumidificationEnabled()) then + qflx_surf(c) = qflx_surf(c) + qflx_floodc(c) + qflx_condensate_from_ac(c) + else + qflx_surf(c) = qflx_surf(c) + qflx_floodc(c) + end if else if (col%itype(c) == icol_sunwall .or. col%itype(c) == icol_shadewall) then qflx_surf(c) = 0._r8 end if diff --git a/src/biogeophys/SoilTemperatureMod.F90 b/src/biogeophys/SoilTemperatureMod.F90 index 61c8a975fb..41f636dbf8 100644 --- a/src/biogeophys/SoilTemperatureMod.F90 +++ b/src/biogeophys/SoilTemperatureMod.F90 @@ -541,8 +541,10 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter if ( IsProgBuildTemp() )then call BuildingTemperature(bounds, num_urbanl, filter_urbanl, num_nolakec, filter_nolakec, & + num_urbanc, filter_urbanc, & tk(bounds%begc:bounds%endc, :), urbanparams_inst, & - temperature_inst, energyflux_inst, urbantv_inst, atm2lnd_inst) + temperature_inst, energyflux_inst, urbantv_inst, & + waterdiagnosticbulk_inst, waterfluxbulk_inst, atm2lnd_inst) end if do fc = 1,num_nolakec @@ -1632,7 +1634,7 @@ subroutine ComputeGroundHeatFluxAndDeriv(bounds, & dlrad => energyflux_inst%dlrad_patch , & ! Input: [real(r8) (:) ] downward longwave radiation blow the canopy [W/m2] eflx_traffic => energyflux_inst%eflx_traffic_lun , & ! Input: [real(r8) (:) ] traffic sensible heat flux (W/m**2) eflx_wasteheat => energyflux_inst%eflx_wasteheat_lun , & ! Input: [real(r8) (:) ] sensible heat flux from urban heating/cooling sources of waste heat (W/m**2) - eflx_ventilation => energyflux_inst%eflx_ventilation_lun , & ! Input: [real(r8) (:) ] sensible heat flux from building ventilation (W/m**2) + eflx_ventilation => energyflux_inst%eflx_ventilation_lun , & ! Input: [real(r8) (:) ] sensible and latent heat flux from building ventilation (W/m**2) eflx_heat_from_ac => energyflux_inst%eflx_heat_from_ac_lun , & ! Input: [real(r8) (:) ] sensible heat flux put back into canyon due to removal by AC (W/m**2) eflx_sh_snow => energyflux_inst%eflx_sh_snow_patch , & ! Input: [real(r8) (:) ] sensible heat flux from snow (W/m**2) [+ to atm] eflx_sh_soil => energyflux_inst%eflx_sh_soil_patch , & ! Input: [real(r8) (:) ] sensible heat flux from soil (W/m**2) [+ to atm] @@ -1640,7 +1642,7 @@ subroutine ComputeGroundHeatFluxAndDeriv(bounds, & eflx_sh_grnd => energyflux_inst%eflx_sh_grnd_patch , & ! Input: [real(r8) (:) ] sensible heat flux from ground (W/m**2) [+ to atm] eflx_lwrad_net => energyflux_inst%eflx_lwrad_net_patch , & ! Input: [real(r8) (:) ] net infrared (longwave) rad (W/m**2) [+ = to atm] eflx_wasteheat_patch => energyflux_inst%eflx_wasteheat_patch , & ! Input: [real(r8) (:) ] sensible heat flux from urban heating/cooling sources of waste heat (W/m**2) - eflx_ventilation_patch => energyflux_inst%eflx_ventilation_patch , & ! Input: [real(r8) (:) ] sensible heat flux from building ventilation (W/m**2) + eflx_ventilation_patch => energyflux_inst%eflx_ventilation_patch , & ! Input: [real(r8) (:) ] sensible and latent heat flux from building ventilation (W/m**2) eflx_heat_from_ac_patch => energyflux_inst%eflx_heat_from_ac_patch , & ! Input: [real(r8) (:) ] sensible heat flux put back into canyon due to removal by AC (W/m**2) eflx_traffic_patch => energyflux_inst%eflx_traffic_patch , & ! Input: [real(r8) (:) ] traffic sensible heat flux (W/m**2) eflx_anthro => energyflux_inst%eflx_anthro_patch , & ! Input: [real(r8) (:) ] total anthropogenic heat flux (W/m**2) diff --git a/src/biogeophys/UrbBuildTempOleson2015Mod.F90 b/src/biogeophys/UrbBuildTempOleson2015Mod.F90 index 3081948f6b..d33f4ec815 100644 --- a/src/biogeophys/UrbBuildTempOleson2015Mod.F90 +++ b/src/biogeophys/UrbBuildTempOleson2015Mod.F90 @@ -6,6 +6,10 @@ module UrbBuildTempOleson2015Mod ! !DESCRIPTION: ! Calculates internal building air temperature ! + ! Explicit air-conditioning adoption is described by Li et al. (2024), + ! doi:10.1029/2023MS004107. Indoor humidity and air-conditioning dehumidification + ! are described by Li et al. (2026), doi:10.1038/s44284-026-00474-4. + ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod , only : bounds_type, subgrid_level_landunit @@ -16,9 +20,11 @@ module UrbBuildTempOleson2015Mod use UrbanTimeVarType , only : urbantv_type use EnergyFluxType , only : energyflux_type use TemperatureType , only : temperature_type - use atm2lndType , only : atm2lnd_type + use WaterDiagnosticBulkType, only : waterdiagnosticbulk_type + use WaterFluxBulkType , only : waterfluxbulk_type use LandunitType , only : lun - use ColumnType , only : col + use ColumnType , only : col + use atm2lndType , only : atm2lnd_type ! ! !PUBLIC TYPES: implicit none @@ -28,6 +34,9 @@ module UrbBuildTempOleson2015Mod ! !PUBLIC MEMBER FUNCTIONS: public :: BuildingTemperature ! Calculation of interior building air temperature, inner ! surface temperatures of walls and roof, and floor temperature + + ! !PRIVATE PARAMETERS: + real(r8), parameter :: ac_latent_error_thresh = 1.e-5_r8 ! Error threshold for the AC latent-energy consistency check [W/m2 of urban area] character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -42,8 +51,10 @@ module UrbBuildTempOleson2015Mod ! ! !INTERFACE: subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, & - filter_nolakec, tk, urbanparams_inst, temperature_inst, & - energyflux_inst, urbantv_inst, atm2lnd_inst) + filter_nolakec, num_urbanc, filter_urbanc, & + tk, urbanparams_inst, temperature_inst, & + energyflux_inst, urbantv_inst, waterdiagnosticbulk_inst, & + waterfluxbulk_inst, atm2lnd_inst) ! ! !DESCRIPTION: ! Solve for t_building, inner surface temperatures of roof, sunw, shdw, and floor temperature @@ -54,11 +65,11 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, ! qrd_sunw + qcd_sunw + qcv_sunw = 0 ! qrd_shdw + qcd_shdw + qcv_shdw = 0 ! qrd_floor + qcd_floor + qcv_floor = 0 -! Vbld*rho_dair*cpair*(dt_building/dt) = sum(Asfc*hcv_sfc*(t_sfc - t_building) -! + Vvent*rho_dair*cpair*(taf - t_building) +! Vbld*rho_air*cp_air*(dt_building/dt) = sum(Asfc*hcv_sfc*(t_sfc - t_building) +! + Vvent*rho_air*cp_air*(taf - t_building) ! where Vlbd is volume of building air, -! rho_dair is density of dry air at t_building (kg m-3), -! cpair is specific heat of dry air (J kg-1 K-1), +! rho_air is density of indoor air at outdoor pressure and t_building (kg m-3), +! cp_air is specific heat capacity of indoor air (J kg-1 K-1), ! dt_building is change in interior building temperature (K), ! dt is timestep (s), ! Asfc is surface area of roof, sunw, shdw, floor (m2) @@ -206,18 +217,24 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, use clm_varcon , only : rair, cpair, sb, hcv_roof, hcv_roof_enhanced, & hcv_floor, hcv_floor_enhanced, hcv_sunw, hcv_shdw, & em_roof_int, em_floor_int, em_sunw_int, em_shdw_int, & - dz_floor, dens_floor, cp_floor, vent_ach + dz_floor, dens_floor, cp_floor, vent_ach, & + rh_building_max, hvap, rwat, cpwvap, secsphr, pct_to_frac use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall use clm_varctl , only : iulog use abortutils , only : endrun use clm_varpar , only : nlevurb, nlevsno, nlevmaxurbgrnd - use UrbanParamsType , only : urban_hac, urban_hac_off, urban_hac_on, urban_wasteheat_on, urban_explicit_ac + use UrbanParamsType , only : urban_hac, urban_hac_off, urban_hac_on, urban_wasteheat_on, & + urban_explicit_ac, IsBuildingHumidityEnabled, & + IsACDehumidificationEnabled + use QSatMod , only : QSat ! ! !ARGUMENTS: implicit none type(bounds_type), intent(in) :: bounds ! bounds integer , intent(in) :: num_nolakec ! number of column non-lake points in column filter integer , intent(in) :: filter_nolakec(:) ! column filter for non-lake points + integer , intent(in) :: num_urbanc ! number of column urban points in column filter + integer , intent(in) :: filter_urbanc(:) ! column filter for urban points integer , intent(in) :: num_urbanl ! number of urban landunits in clump integer , intent(in) :: filter_urbanl(:) ! urban landunit filter real(r8), intent(in) :: tk(bounds%begc: , -nlevsno+1: ) ! thermal conductivity (W m-1 K-1) [col, j] @@ -225,6 +242,8 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, type(temperature_type), intent(inout) :: temperature_inst ! temperature variables type(energyflux_type) , intent(inout) :: energyflux_inst ! energy flux variables type(urbantv_type) , intent(in) :: urbantv_inst ! urban time varying variables + type(waterdiagnosticbulk_type), intent(inout) :: waterdiagnosticbulk_inst ! water diagnostic variables + type(waterfluxbulk_type), intent(inout) :: waterfluxbulk_inst ! water flux variables type(atm2lnd_type) , intent(in) :: atm2lnd_inst ! forcing variables from atmosphere ! ! !LOCAL VARIABLES: @@ -238,7 +257,10 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, real(r8) :: t_floor_bef(bounds%begl:bounds%endl) ! floor temperature at previous time step (K) real(r8) :: t_building_bef(bounds%begl:bounds%endl) ! internal building air temperature at previous time step [K] real(r8) :: t_building_bef_hac(bounds%begl:bounds%endl)! internal building air temperature before applying HAC [K] + real(r8) :: q_building_bef(bounds%begl:bounds%endl) ! internal building air specific humidity at previous time step (kg/kg) + real(r8) :: q_building_bef_hac(bounds%begl:bounds%endl)! internal building air specific humidity before applying HAC (kg/kg) real(r8) :: eflx_urban_ac_sat(bounds%begl:bounds%endl) ! urban air conditioning flux under AC adoption saturation (W/m**2) + real(r8) :: eflx_urban_ac_sat_lat(bounds%begl:bounds%endl) ! latent heat component of urban air conditioning flux under AC adoption saturation (W/m**2) real(r8) :: hcv_roofi(bounds%begl:bounds%endl) ! roof convective heat transfer coefficient (W m-2 K-1) real(r8) :: hcv_sunwi(bounds%begl:bounds%endl) ! sunwall convective heat transfer coefficient (W m-2 K-1) real(r8) :: hcv_shdwi(bounds%begl:bounds%endl) ! shadewall convective heat transfer coefficient (W m-2 K-1) @@ -250,7 +272,8 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, real(r8) :: dz_floori(bounds%begl:bounds%endl) ! concrete floor thickness (m) real(r8) :: cp_floori(bounds%begl:bounds%endl) ! concrete floor volumetric heat capacity (J m-3 K-1) real(r8) :: cv_floori(bounds%begl:bounds%endl) ! intermediate calculation for concrete floor (W m-2 K-1) - real(r8) :: rho_dair(bounds%begl:bounds%endl) ! density of dry air at standard pressure and t_building (kg m-3) + real(r8) :: rho_air(bounds%begl:bounds%endl) ! density of indoor air at outdoor pressure and t_building (kg m-3) + real(r8) :: cp_air(bounds%begl:bounds%endl) ! specific heat capacity of indoor air (J kg-1 K-1) real(r8) :: vf_rf(bounds%begl:bounds%endl) ! view factor of roof for floor (-) real(r8) :: vf_fr(bounds%begl:bounds%endl) ! view factor of floor for roof (-) real(r8) :: vf_wf(bounds%begl:bounds%endl) ! view factor of wall for floor (-) @@ -301,6 +324,14 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, ! on exit, if info = 0, the n-by-nrhs solution matrix x integer :: info ! exit information for LAPACK routine dgesv integer :: ipiv(neq) ! the pivot indices that define the permutation matrix P + real(r8) :: q_building_max ! maximum internal building air specific humidity determined from rh_building_max (kg/kg) + real(r8) :: qsat_building_max ! maximum specific humidity/mixing ratio of saturated internal building air at indoor temperature before HAC, used to determine q_building_max from rh_building_max (kg/kg) + real(r8) :: qsat_building ! specific humidity/mixing ratio of saturated internal building air at indoor temperature, used to calculate rho_air, cp_air, and rh_building (kg/kg) + real(r8) :: esat_building ! internal building air saturated vapor pressure used to calculate p_vapor (Pa) + real(r8) :: p_vapor ! internal building air partial pressure of water vapor (Pa) + real(r8) :: qtot_condensate(bounds%begl:bounds%endl) ! total condensed water due to dehumidification per building area (kg m-2) + real(r8) :: eflx_urban_ac_lat_derived(bounds%begl:bounds%endl) ! urban air conditioning latent heat flux derived from condensate output, for error check (W m-2) + real(r8) :: err_eflx_urban_ac_lat(bounds%begl:bounds%endl) ! Difference between the dehumidification energy flux calculated from condensate and the urban AC latent heat flux for error check (W m-2) !EOP !----------------------------------------------------------------------- @@ -317,6 +348,7 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, ht_roof => lun%ht_roof , & ! Input: [real(r8) (:)] height of urban roof (m) canyon_hwr => lun%canyon_hwr , & ! Input: [real(r8) (:)] ratio of building height to street hwidth (-) wtlunit_roof => lun%wtlunit_roof , & ! Input: [real(r8) (:)] weight of roof with respect to landunit + wtroad_perv => lun%wtroad_perv , & ! Input: [real(r8) (:)] weight of pervious road column to total road (-) urbpoi => lun%urbpoi , & ! Input: [logical (:)] true => landunit is an urban point taf => temperature_inst%taf_lun , & ! Input: [real(r8) (:)] urban canopy air temperature (K) @@ -332,10 +364,18 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, t_building_max => urbantv_inst%t_building_max , & ! Input: [real(r8) (:)] maximum internal building air temperature (K) t_building_min => urbanparams_inst%t_building_min , & ! Input: [real(r8) (:)] minimum internal building air temperature (K) - eflx_building => energyflux_inst%eflx_building_lun , & ! Output: [real(r8) (:)] building heat flux from change in interior building air temperature (W/m**2) + qaf => waterdiagnosticbulk_inst%qaf_lun , & ! Input: [real(r8) (:)] urban canopy air specific humidity (kg/kg) + q_building => waterdiagnosticbulk_inst%q_building_lun,& ! InOut: [real(r8) (:)] internal building air specific humidity (kg/kg) + rh_building => waterdiagnosticbulk_inst%rh_building_lun,& ! InOut: [real(r8) (:)] internal building air relative humidity (%) + + eflx_building => energyflux_inst%eflx_building_lun , & ! Output: [real(r8) (:)] building heat flux from change in interior building air temperature (and humidity, if prognosed indoor humidity) (W/m**2) eflx_urban_ac => energyflux_inst%eflx_urban_ac_lun , & ! Output: [real(r8) (:)] urban air conditioning flux (W/m**2) + eflx_urban_ac_sen => energyflux_inst%eflx_urban_ac_sen_lun,& ! Output: [real(r8) (:)] sensible heat component of urban air conditioning flux (W/m**2) eflx_urban_heat => energyflux_inst%eflx_urban_heat_lun,& ! Output: [real(r8) (:)] urban heating flux (W/m**2) - eflx_ventilation => energyflux_inst%eflx_ventilation_lun & ! Output: [real(r8) (:)] sensible heat flux from building ventilation (W/m**2) + eflx_ventilation => energyflux_inst%eflx_ventilation_lun, & ! Output: [real(r8) (:)] sensible and latent heat flux from building ventilation (W/m**2) + + qflx_condensate_from_ac => waterfluxbulk_inst%qflx_condensate_from_ac_col, & ! Output: [real(r8) (:)] condensed water flux due to dehumidification for roof (building footprint) area (mm/s) + qflx_condensate_from_ac_lu => waterfluxbulk_inst%qflx_condensate_from_ac_lun & ! Output: [real(r8) (:)] condensed water flux due to dehumidification for urban area (mm/s) ) ! Get step size @@ -352,39 +392,53 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, do fl = 1,num_urbanl l = filter_urbanl(fl) g = lun%gridcell(l) - if (urbpoi(l)) then - t_roof_inner_bef(l) = t_roof_inner(l) - t_sunw_inner_bef(l) = t_sunw_inner(l) - t_shdw_inner_bef(l) = t_shdw_inner(l) - t_floor_bef(l) = t_floor(l) - t_building_bef(l) = t_building(l) - if (t_roof_inner_bef(l) .le. t_building_bef(l)) then - hcv_roofi(l) = hcv_roof_enhanced - else - hcv_roofi(l) = hcv_roof - end if - if (t_floor_bef(l) .ge. t_building_bef(l)) then - hcv_floori(l) = hcv_floor_enhanced - else - hcv_floori(l) = hcv_floor - end if - hcv_sunwi(l) = hcv_sunw - hcv_shdwi(l) = hcv_shdw - em_roofi(l) = em_roof_int - em_sunwi(l) = em_sunw_int - em_shdwi(l) = em_shdw_int - em_floori(l) = em_floor_int - ! Concrete floor thickness (m) - dz_floori(l) = dz_floor - ! Concrete floor volumetric heat capacity (J m-3 K-1) - cp_floori(l) = cp_floor - ! Intermediate calculation for concrete floor (W m-2 K-1) - cv_floori(l) = (dz_floori(l) * cp_floori(l)) / dtime - ! Density of dry air at surface pressure and t_building (kg m-3) - rho_dair(l) = forc_pbot(g) / (rair*t_building_bef(l)) - ! Building height to building width ratio - building_hwr(l) = canyon_hwr(l)*(1._r8-wtlunit_roof(l))/wtlunit_roof(l) + t_roof_inner_bef(l) = t_roof_inner(l) + t_sunw_inner_bef(l) = t_sunw_inner(l) + t_shdw_inner_bef(l) = t_shdw_inner(l) + t_floor_bef(l) = t_floor(l) + t_building_bef(l) = t_building(l) + if (IsBuildingHumidityEnabled()) then + q_building_bef(l) = q_building(l) + end if + if (t_roof_inner_bef(l) .le. t_building_bef(l)) then + hcv_roofi(l) = hcv_roof_enhanced + else + hcv_roofi(l) = hcv_roof + end if + if (t_floor_bef(l) .ge. t_building_bef(l)) then + hcv_floori(l) = hcv_floor_enhanced + else + hcv_floori(l) = hcv_floor + end if + hcv_sunwi(l) = hcv_sunw + hcv_shdwi(l) = hcv_shdw + em_roofi(l) = em_roof_int + em_sunwi(l) = em_sunw_int + em_shdwi(l) = em_shdw_int + em_floori(l) = em_floor_int + ! Concrete floor thickness (m) + dz_floori(l) = dz_floor + ! Concrete floor volumetric heat capacity (J m-3 K-1) + cp_floori(l) = cp_floor + ! Intermediate calculation for concrete floor (W m-2 K-1) + cv_floori(l) = (dz_floori(l) * cp_floori(l)) / dtime + if (IsBuildingHumidityEnabled()) then + ! Specific humidity (kg/kg) and vapor pressure (Pa) at saturation at current temperature and pressure + call QSat(t_building_bef(l), forc_pbot(g), qsat_building, es = esat_building) + ! Indoor vapor pressure (Pa) from saturation vapor pressure. The saturation ratio is capped at 1 (100% saturation) + ! so indoor vapor pressure does not exceed saturation vapor pressure + p_vapor = min(1._r8, q_building_bef(l) / qsat_building) * esat_building + ! Density (kg m-3) and specific heat capacity (J kg-1 K-1) of moist air at current temperature and pressure + rho_air(l) = (forc_pbot(g) - p_vapor) / (rair * t_building_bef(l)) & + + p_vapor / (rwat * t_building_bef(l)) + cp_air(l) = cpair + cpwvap * q_building_bef(l) + else + ! Density (kg m-3) and specific heat capacity (J kg-1 K-1) of dry air at current temperature and pressure + rho_air(l) = forc_pbot(g) / (rair*t_building_bef(l)) + cp_air(l) = cpair end if + ! Building height to building width ratio + building_hwr(l) = canyon_hwr(l)*(1._r8-wtlunit_roof(l))/wtlunit_roof(l) end do ! Get terms from soil temperature equations to compute conduction flux @@ -424,52 +478,48 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, ! Calculate view factors do fl = 1,num_urbanl l = filter_urbanl(fl) - if (urbpoi(l)) then - vf_rf(l) = sqrt(1._r8 + building_hwr(l)**2._r8) - building_hwr(l) - vf_fr(l) = vf_rf(l) + vf_rf(l) = sqrt(1._r8 + building_hwr(l)**2._r8) - building_hwr(l) + vf_fr(l) = vf_rf(l) - ! This view factor implicitly converts from per unit wall area to per unit floor area - vf_wf(l) = 0.5_r8*(1._r8 - vf_rf(l)) + ! This view factor implicitly converts from per unit wall area to per unit floor area + vf_wf(l) = 0.5_r8*(1._r8 - vf_rf(l)) - vf_fw(l) = vf_wf(l) + vf_fw(l) = vf_wf(l) - vf_rw(l) = vf_fw(l) + vf_rw(l) = vf_fw(l) - ! This view factor implicitly converts from per unit wall area to per unit roof area - vf_wr(l) = vf_wf(l) + ! This view factor implicitly converts from per unit wall area to per unit roof area + vf_wr(l) = vf_wf(l) - vf_ww(l) = 1._r8 - vf_rw(l) - vf_fw(l) + vf_ww(l) = 1._r8 - vf_rw(l) - vf_fw(l) - end if end do ! error check -- make sure view factor sums to one for floor, wall, and roof do fl = 1,num_urbanl l = filter_urbanl(fl) - if (urbpoi(l)) then - - sum = vf_rf(l) + 2._r8*vf_wf(l) - if (abs(sum-1._r8) > 1.e-06_r8 ) then - write (iulog,*) 'urban floor view factor error',sum - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - endif - sum = vf_rw(l) + vf_fw(l) + vf_ww(l) - if (abs(sum-1._r8) > 1.e-06_r8 ) then - write (iulog,*) 'urban wall view factor error',sum - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - endif - sum = vf_fr(l) + vf_wr(l) + vf_wr(l) - if (abs(sum-1._r8) > 1.e-06_r8 ) then - write (iulog,*) 'urban roof view factor error',sum - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - endif + sum = vf_rf(l) + 2._r8*vf_wf(l) + if (abs(sum-1._r8) > 1.e-06_r8 ) then + write (iulog,*) 'urban floor view factor error',sum + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + endif + sum = vf_rw(l) + vf_fw(l) + vf_ww(l) + if (abs(sum-1._r8) > 1.e-06_r8 ) then + write (iulog,*) 'urban wall view factor error',sum + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + endif + sum = vf_fr(l) + vf_wr(l) + vf_wr(l) + if (abs(sum-1._r8) > 1.e-06_r8 ) then + write (iulog,*) 'urban roof view factor error',sum + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) endif + end do n = neq @@ -479,485 +529,582 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, do fl = 1,num_urbanl l = filter_urbanl(fl) - if (urbpoi(l)) then - ! ROOF - a(1,1) = 0.5_r8*hcv_roofi(l) & - + 0.5_r8*tk_roof_innerl(l)/(zi_roof_innerl(l) - z_roof_innerl(l)) & - + 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8 & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l) - - a(1,2) = - 4._r8*em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) - - a(1,3) = - 4._r8*em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) - - a(1,4) = - 4._r8*em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l) - - a(1,5) = - 0.5_r8*hcv_roofi(l) - - result(1) = 0.5_r8*tk_roof_innerl(l)*t_roof_innerl(l)/(zi_roof_innerl(l) - z_roof_innerl(l)) & - - 0.5_r8*tk_roof_innerl(l)*(t_roof_inner_bef(l)-t_roof_innerl_bef(l))/(zi_roof_innerl(l) & - - z_roof_innerl(l)) & - - 3._r8*em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l) & - - 3._r8*em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l) & - - 3._r8*em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l) & - + 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8 & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) - t_building_bef(l)) - - ! SUNWALL - a(2,1) = - 4._r8*em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) - - a(2,2) = 0.5_r8*hcv_sunwi(l)*building_hwr(l) & - + 0.5_r8*tk_sunw_innerl(l)/(zi_sunw_innerl(l) - z_sunw_innerl(l))*building_hwr(l) & - + 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8 & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) - - a(2,3) = - 4._r8*em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) - - a(2,4) = - 4._r8*em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l) - a(2,5) = - 0.5_r8*hcv_sunwi(l)*building_hwr(l) - - result(2) = 0.5_r8*tk_sunw_innerl(l)*t_sunw_innerl(l)/(zi_sunw_innerl(l) - z_sunw_innerl(l))*building_hwr(l) & - - 0.5_r8*tk_sunw_innerl(l)*(t_sunw_inner_bef(l)-t_sunw_innerl_bef(l))/(zi_sunw_innerl(l) & - - z_sunw_innerl(l))*building_hwr(l) & - - 3._r8*em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & - - 3._r8*em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l) & - - 3._r8*em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & - + 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8 & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) - t_building_bef(l))*building_hwr(l) - - ! SHADEWALL - a(3,1) = - 4._r8*em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) - - a(3,2) = - 4._r8*em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) - - a(3,3) = 0.5_r8*hcv_shdwi(l)*building_hwr(l) & - + 0.5_r8*tk_shdw_innerl(l)/(zi_shdw_innerl(l) - z_shdw_innerl(l))*building_hwr(l) & - + 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8 & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) - - a(3,4) = - 4._r8*em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l) - - a(3,5) = - 0.5_r8*hcv_shdwi(l)*building_hwr(l) - - result(3) = 0.5_r8*tk_shdw_innerl(l)*t_shdw_innerl(l)/(zi_shdw_innerl(l) - z_shdw_innerl(l))*building_hwr(l) & - - 0.5_r8*tk_shdw_innerl(l)*(t_shdw_inner_bef(l)-t_shdw_innerl_bef(l))/(zi_shdw_innerl(l) & - - z_shdw_innerl(l))*building_hwr(l) & - - 3._r8*em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & - - 3._r8*em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l) & - - 3._r8*em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & - + 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8 & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) - t_building_bef(l))*building_hwr(l) - - ! FLOOR - a(4,1) = - 4._r8*em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l) - - a(4,2) = - 4._r8*em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) - - a(4,3) = - 4._r8*em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l) - - a(4,4) = (cv_floori(l) + 0.5_r8*hcv_floori(l)) & - + 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8 & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l) - - a(4,5) = - 0.5_r8*hcv_floori(l) - - result(4) = cv_floori(l)*t_floor_bef(l) & - - 3._r8*em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l) & - - 3._r8*em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l) & - - 3._r8*em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l) & - + 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8 & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l) & - - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & - - 0.5_r8*hcv_floori(l)*(t_floor_bef(l) - t_building_bef(l)) - - ! Building air temperature - a(5,1) = - 0.5_r8*hcv_roofi(l) - a(5,2) = - 0.5_r8*hcv_sunwi(l)*building_hwr(l) - - a(5,3) = - 0.5_r8*hcv_shdwi(l)*building_hwr(l) - - a(5,4) = - 0.5_r8*hcv_floori(l) - - a(5,5) = ((ht_roof(l)*rho_dair(l)*cpair)/dtime) + & - ((ht_roof(l)*vent_ach)/3600._r8)*rho_dair(l)*cpair + & - 0.5_r8*hcv_roofi(l) + & - 0.5_r8*hcv_sunwi(l)*building_hwr(l) + & - 0.5_r8*hcv_shdwi(l)*building_hwr(l) + & - 0.5_r8*hcv_floori(l) - - result(5) = (ht_roof(l)*rho_dair(l)*cpair/dtime)*t_building_bef(l) & - + ((ht_roof(l)*vent_ach)/3600._r8)*rho_dair(l)*cpair*taf(l) & - + 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) - t_building_bef(l)) & - + 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & - + 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & - + 0.5_r8*hcv_floori(l)*(t_floor_bef(l) - t_building_bef(l)) - - ! Solve equations - call dgesv(n, nrhs, a, lda, ipiv, result, ldb, info) - - ! If dgesv fails, abort - if (info /= 0) then - write(iulog,*)'fl: ',fl - write(iulog,*)'l: ',l - write(iulog,*)'dgesv info: ',info - write (iulog,*) 'dgesv error' - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - end if - ! Assign new temperatures - t_roof_inner(l) = result(1) - t_sunw_inner(l) = result(2) - t_shdw_inner(l) = result(3) - t_floor(l) = result(4) - t_building(l) = result(5) + ! ROOF + a(1,1) = 0.5_r8*hcv_roofi(l) & + + 0.5_r8*tk_roof_innerl(l)/(zi_roof_innerl(l) - z_roof_innerl(l)) & + + 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8 & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l) + + a(1,2) = - 4._r8*em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) + + a(1,3) = - 4._r8*em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) + + a(1,4) = - 4._r8*em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l) + + a(1,5) = - 0.5_r8*hcv_roofi(l) + + result(1) = 0.5_r8*tk_roof_innerl(l)*t_roof_innerl(l)/(zi_roof_innerl(l) - z_roof_innerl(l)) & + - 0.5_r8*tk_roof_innerl(l)*(t_roof_inner_bef(l)-t_roof_innerl_bef(l))/(zi_roof_innerl(l) & + - z_roof_innerl(l)) & + - 3._r8*em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l) & + - 3._r8*em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l) & + - 3._r8*em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l) & + + 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8 & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) - t_building_bef(l)) + + ! SUNWALL + a(2,1) = - 4._r8*em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) + + a(2,2) = 0.5_r8*hcv_sunwi(l)*building_hwr(l) & + + 0.5_r8*tk_sunw_innerl(l)/(zi_sunw_innerl(l) - z_sunw_innerl(l))*building_hwr(l) & + + 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8 & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) + + a(2,3) = - 4._r8*em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) + + a(2,4) = - 4._r8*em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l) + a(2,5) = - 0.5_r8*hcv_sunwi(l)*building_hwr(l) + + result(2) = 0.5_r8*tk_sunw_innerl(l)*t_sunw_innerl(l)/(zi_sunw_innerl(l) - z_sunw_innerl(l))*building_hwr(l) & + - 0.5_r8*tk_sunw_innerl(l)*(t_sunw_inner_bef(l)-t_sunw_innerl_bef(l))/(zi_sunw_innerl(l) & + - z_sunw_innerl(l))*building_hwr(l) & + - 3._r8*em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & + - 3._r8*em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l) & + - 3._r8*em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & + + 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8 & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) - t_building_bef(l))*building_hwr(l) + + ! SHADEWALL + a(3,1) = - 4._r8*em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) + + a(3,2) = - 4._r8*em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) + + a(3,3) = 0.5_r8*hcv_shdwi(l)*building_hwr(l) & + + 0.5_r8*tk_shdw_innerl(l)/(zi_shdw_innerl(l) - z_shdw_innerl(l))*building_hwr(l) & + + 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8 & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) + + a(3,4) = - 4._r8*em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l) + + a(3,5) = - 0.5_r8*hcv_shdwi(l)*building_hwr(l) + + result(3) = 0.5_r8*tk_shdw_innerl(l)*t_shdw_innerl(l)/(zi_shdw_innerl(l) - z_shdw_innerl(l))*building_hwr(l) & + - 0.5_r8*tk_shdw_innerl(l)*(t_shdw_inner_bef(l)-t_shdw_innerl_bef(l))/(zi_shdw_innerl(l) & + - z_shdw_innerl(l))*building_hwr(l) & + - 3._r8*em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & + - 3._r8*em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l) & + - 3._r8*em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & + + 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8 & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) - t_building_bef(l))*building_hwr(l) + + ! FLOOR + a(4,1) = - 4._r8*em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l) + + a(4,2) = - 4._r8*em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) + + a(4,3) = - 4._r8*em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l) + + a(4,4) = (cv_floori(l) + 0.5_r8*hcv_floori(l)) & + + 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8 & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l) + + a(4,5) = - 0.5_r8*hcv_floori(l) + + result(4) = cv_floori(l)*t_floor_bef(l) & + - 3._r8*em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l) & + - 3._r8*em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l) & + - 3._r8*em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l) & + + 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8 & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 3._r8*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l) & + - 3._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 3._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 3._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & + - 0.5_r8*hcv_floori(l)*(t_floor_bef(l) - t_building_bef(l)) + + ! Building air temperature + a(5,1) = - 0.5_r8*hcv_roofi(l) + a(5,2) = - 0.5_r8*hcv_sunwi(l)*building_hwr(l) + + a(5,3) = - 0.5_r8*hcv_shdwi(l)*building_hwr(l) + + a(5,4) = - 0.5_r8*hcv_floori(l) + + a(5,5) = ((ht_roof(l)*rho_air(l)*cp_air(l))/dtime) + & + ((ht_roof(l)*vent_ach)/secsphr)*rho_air(l)*cp_air(l) + & + 0.5_r8*hcv_roofi(l) + & + 0.5_r8*hcv_sunwi(l)*building_hwr(l) + & + 0.5_r8*hcv_shdwi(l)*building_hwr(l) + & + 0.5_r8*hcv_floori(l) + + result(5) = (ht_roof(l)*rho_air(l)*cp_air(l)/dtime)*t_building_bef(l) & + + ((ht_roof(l)*vent_ach)/secsphr)*rho_air(l)*cp_air(l)*taf(l) & + + 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) - t_building_bef(l)) & + + 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & + + 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & + + 0.5_r8*hcv_floori(l)*(t_floor_bef(l) - t_building_bef(l)) + + ! Solve equations + call dgesv(n, nrhs, a, lda, ipiv, result, ldb, info) + + ! If dgesv fails, abort + if (info /= 0) then + write(iulog,*)'fl: ',fl + write(iulog,*)'l: ',l + write(iulog,*)'dgesv info: ',info + write (iulog,*) 'dgesv error' + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) end if + ! Assign new temperatures + t_roof_inner(l) = result(1) + t_sunw_inner(l) = result(2) + t_shdw_inner(l) = result(3) + t_floor(l) = result(4) + t_building(l) = result(5) end do + ! Update indoor specific humidity assuming well-mixed indoor air + if (IsBuildingHumidityEnabled()) then + do fl = 1,num_urbanl + l = filter_urbanl(fl) + q_building(l) = qaf(l) * (vent_ach/secsphr * dtime) & + + q_building_bef(l) * (1 - vent_ach/secsphr * dtime) + end do + end if + ! Energy balance checks do fl = 1,num_urbanl l = filter_urbanl(fl) - if (urbpoi(l)) then - qrd_roof(l) = - em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l) & - - 4._r8*em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l) & - - 4._r8*em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l) & - - 4._r8*em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(t_floor(l) - t_floor_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l)*(t_floor(l) & - - t_floor_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l)*(t_floor(l) & - - t_floor_bef(l)) & - + em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8 & - + 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*(t_roof_inner(l) - t_roof_inner_bef(l)) - - qrd_sunw(l) = - em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & - - 4._r8*em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l) & - - 4._r8*em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & - - 4._r8*em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(t_floor(l) - t_floor_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_floor(l) & - - t_floor_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l)*(t_floor(l) & - - t_floor_bef(l)) & - + em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8 & - + 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*(t_sunw_inner(l) - t_sunw_inner_bef(l)) - - qrd_shdw(l) = - em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & - - 4._r8*em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l) & - - 4._r8*em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & - - 4._r8*em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(t_floor(l) - t_floor_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_floor(l) & - - t_floor_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l)*(t_floor(l) & - - t_floor_bef(l)) & - + em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8 & - + 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*(t_shdw_inner(l) - t_shdw_inner_bef(l)) - - qrd_floor(l) = - em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l) & - - 4._r8*em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l) & - - 4._r8*em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l) & - - 4._r8*em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l)*(t_floor(l) & - - t_floor_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l)*(t_floor(l) & - - t_floor_bef(l)) & - - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & - - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l)*(t_floor(l) & - - t_floor_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l)*(t_sunw_inner(l) & - - t_sunw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l)*(t_shdw_inner(l) & - - t_shdw_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & - - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l)*(t_roof_inner(l) & - - t_roof_inner_bef(l)) & - + em_floori(l)*sb*t_floor_bef(l)**4._r8 & - + 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*(t_floor(l) - t_floor_bef(l)) - - qrd_building(l) = qrd_roof(l) + qrd_sunw(l) + qrd_shdw(l) + qrd_floor(l) - - if (abs(qrd_building(l)) > .10_r8 ) then - write (iulog,*) 'urban inside building net longwave radiation balance error ',qrd_building(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - end if + qrd_roof(l) = - em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wr(l) & + - 4._r8*em_roofi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wr(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wr(l) & + - 4._r8*em_roofi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wr(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fr(l) & + - 4._r8*em_roofi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fr(l)*(t_floor(l) - t_floor_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wr(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wr(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(1._r8-em_floori(l))*vf_fr(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wr(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wr(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(1._r8-em_floori(l))*vf_fr(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wr(l)*(t_floor(l) & + - t_floor_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wr(l)*(t_floor(l) & + - t_floor_bef(l)) & + + em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8 & + + 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*(t_roof_inner(l) - t_roof_inner_bef(l)) + + qrd_sunw(l) = - em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & + - 4._r8*em_sunwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_ww(l) & + - 4._r8*em_sunwi(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_ww(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & + - 4._r8*em_sunwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(t_floor(l) - t_floor_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_shdwi(l))*vf_ww(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_shdwi(l))*vf_ww(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_floor(l) & + - t_floor_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_shdwi(l))*vf_ww(l)*(t_floor(l) & + - t_floor_bef(l)) & + + em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8 & + + 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*(t_sunw_inner(l) - t_sunw_inner_bef(l)) + + qrd_shdw(l) = - em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rw(l) & + - 4._r8*em_shdwi(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rw(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_ww(l) & + - 4._r8*em_shdwi(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_ww(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**4._r8*vf_fw(l) & + - 4._r8*em_shdwi(l)*em_floori(l)*sb*t_floor_bef(l)**3._r8*vf_fw(l)*(t_floor(l) - t_floor_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_sunwi(l))*vf_ww(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_sunwi(l))*vf_ww(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rf(l)*(1._r8-em_floori(l))*vf_fw(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fr(l)*(1._r8-em_roofi(l))*vf_rw(l)*(t_floor(l) & + - t_floor_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_sunwi(l))*vf_ww(l)*(t_floor(l) & + - t_floor_bef(l)) & + + em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8 & + + 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*(t_shdw_inner(l) - t_shdw_inner_bef(l)) + + qrd_floor(l) = - em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8*vf_rf(l) & + - 4._r8*em_floori(l)*em_roofi(l)*sb*t_roof_inner_bef(l)**3._r8*vf_rf(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8*vf_wf(l) & + - 4._r8*em_floori(l)*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3._r8*vf_wf(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8*vf_wf(l) & + - 4._r8*em_floori(l)*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3._r8*vf_wf(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fr(l)*(1._r8-em_roofi(l))*vf_rf(l)*(t_floor(l) & + - t_floor_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_sunwi(l))*vf_wf(l)*(t_floor(l) & + - t_floor_bef(l)) & + - (em_floori(l)*sb*t_floor_bef(l)**4._r8)*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & + - 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*vf_fw(l)*(1._r8-em_shdwi(l))*vf_wf(l)*(t_floor(l) & + - t_floor_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_shdwi(l))*vf_wf(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_sunwi(l)*sb*t_sunw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 4._r8*em_sunwi(l)*sb*t_sunw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l)*(t_sunw_inner(l) & + - t_sunw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_wr(l)*(1._r8-em_roofi(l))*vf_rf(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_shdwi(l)*sb*t_shdw_inner_bef(l)**4._r8)*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 4._r8*em_shdwi(l)*sb*t_shdw_inner_bef(l)**3.*vf_ww(l)*(1._r8-em_sunwi(l))*vf_wf(l)*(t_shdw_inner(l) & + - t_shdw_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_sunwi(l))*vf_wf(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + - (em_roofi(l)*sb*t_roof_inner_bef(l)**4._r8)*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l) & + - 4._r8*em_roofi(l)*sb*t_roof_inner_bef(l)**3.*vf_rw(l)*(1._r8-em_shdwi(l))*vf_wf(l)*(t_roof_inner(l) & + - t_roof_inner_bef(l)) & + + em_floori(l)*sb*t_floor_bef(l)**4._r8 & + + 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*(t_floor(l) - t_floor_bef(l)) + + qrd_building(l) = qrd_roof(l) + qrd_sunw(l) + qrd_shdw(l) + qrd_floor(l) + + if (abs(qrd_building(l)) > .10_r8 ) then + write (iulog,*) 'urban inside building net longwave radiation balance error ',qrd_building(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + end if - qcv_roof(l) = 0.5_r8*hcv_roofi(l)*(t_roof_inner(l) - t_building(l)) + 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) & - - t_building_bef(l)) - qcd_roof(l) = 0.5_r8*tk_roof_innerl(l)*(t_roof_inner(l) - t_roof_innerl(l))/(zi_roof_innerl(l) - z_roof_innerl(l)) & - + 0.5_r8*tk_roof_innerl(l)*(t_roof_inner_bef(l) - t_roof_innerl_bef(l))/(zi_roof_innerl(l) & - - z_roof_innerl(l)) - enrgy_bal_roof(l) = qrd_roof(l) + qcv_roof(l) + qcd_roof(l) - if (abs(enrgy_bal_roof(l)) > .10_r8 ) then - write (iulog,*) 'urban inside roof energy balance error ',enrgy_bal_roof(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - end if + qcv_roof(l) = 0.5_r8*hcv_roofi(l)*(t_roof_inner(l) - t_building(l)) + 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) & + - t_building_bef(l)) + qcd_roof(l) = 0.5_r8*tk_roof_innerl(l)*(t_roof_inner(l) - t_roof_innerl(l))/(zi_roof_innerl(l) - z_roof_innerl(l)) & + + 0.5_r8*tk_roof_innerl(l)*(t_roof_inner_bef(l) - t_roof_innerl_bef(l))/(zi_roof_innerl(l) & + - z_roof_innerl(l)) + enrgy_bal_roof(l) = qrd_roof(l) + qcv_roof(l) + qcd_roof(l) + if (abs(enrgy_bal_roof(l)) > .10_r8 ) then + write (iulog,*) 'urban inside roof energy balance error ',enrgy_bal_roof(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + end if - qcv_sunw(l) = 0.5_r8*hcv_sunwi(l)*(t_sunw_inner(l) - t_building(l)) + 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) & - - t_building_bef(l)) - qcd_sunw(l) = 0.5_r8*tk_sunw_innerl(l)*(t_sunw_inner(l) - t_sunw_innerl(l))/(zi_sunw_innerl(l) - z_sunw_innerl(l)) & - + 0.5_r8*tk_sunw_innerl(l)*(t_sunw_inner_bef(l) - t_sunw_innerl_bef(l))/(zi_sunw_innerl(l) & - - z_sunw_innerl(l)) - enrgy_bal_sunw(l) = qrd_sunw(l) + qcv_sunw(l)*building_hwr(l) + qcd_sunw(l)*building_hwr(l) - if (abs(enrgy_bal_sunw(l)) > .10_r8 ) then - write (iulog,*) 'urban inside sunwall energy balance error ',enrgy_bal_sunw(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - end if + qcv_sunw(l) = 0.5_r8*hcv_sunwi(l)*(t_sunw_inner(l) - t_building(l)) + 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) & + - t_building_bef(l)) + qcd_sunw(l) = 0.5_r8*tk_sunw_innerl(l)*(t_sunw_inner(l) - t_sunw_innerl(l))/(zi_sunw_innerl(l) - z_sunw_innerl(l)) & + + 0.5_r8*tk_sunw_innerl(l)*(t_sunw_inner_bef(l) - t_sunw_innerl_bef(l))/(zi_sunw_innerl(l) & + - z_sunw_innerl(l)) + enrgy_bal_sunw(l) = qrd_sunw(l) + qcv_sunw(l)*building_hwr(l) + qcd_sunw(l)*building_hwr(l) + if (abs(enrgy_bal_sunw(l)) > .10_r8 ) then + write (iulog,*) 'urban inside sunwall energy balance error ',enrgy_bal_sunw(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + end if - qcv_shdw(l) = 0.5_r8*hcv_shdwi(l)*(t_shdw_inner(l) - t_building(l)) + 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) & - - t_building_bef(l)) - qcd_shdw(l) = 0.5_r8*tk_shdw_innerl(l)*(t_shdw_inner(l) - t_shdw_innerl(l))/(zi_shdw_innerl(l) - z_shdw_innerl(l)) & - + 0.5_r8*tk_shdw_innerl(l)*(t_shdw_inner_bef(l) - t_shdw_innerl_bef(l))/(zi_shdw_innerl(l) & - - z_shdw_innerl(l)) - enrgy_bal_shdw(l) = qrd_shdw(l) + qcv_shdw(l)*building_hwr(l) + qcd_shdw(l)*building_hwr(l) - if (abs(enrgy_bal_shdw(l)) > .10_r8 ) then - write (iulog,*) 'urban inside shadewall energy balance error ',enrgy_bal_shdw(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - end if + qcv_shdw(l) = 0.5_r8*hcv_shdwi(l)*(t_shdw_inner(l) - t_building(l)) + 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) & + - t_building_bef(l)) + qcd_shdw(l) = 0.5_r8*tk_shdw_innerl(l)*(t_shdw_inner(l) - t_shdw_innerl(l))/(zi_shdw_innerl(l) - z_shdw_innerl(l)) & + + 0.5_r8*tk_shdw_innerl(l)*(t_shdw_inner_bef(l) - t_shdw_innerl_bef(l))/(zi_shdw_innerl(l) & + - z_shdw_innerl(l)) + enrgy_bal_shdw(l) = qrd_shdw(l) + qcv_shdw(l)*building_hwr(l) + qcd_shdw(l)*building_hwr(l) + if (abs(enrgy_bal_shdw(l)) > .10_r8 ) then + write (iulog,*) 'urban inside shadewall energy balance error ',enrgy_bal_shdw(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + end if - qcv_floor(l) = 0.5_r8*hcv_floori(l)*(t_floor(l) - t_building(l)) + 0.5_r8*hcv_floori(l)*(t_floor_bef(l) & - - t_building_bef(l)) - qcd_floor(l) = cv_floori(l)*(t_floor(l) - t_floor_bef(l)) - enrgy_bal_floor(l) = qrd_floor(l) + qcv_floor(l) + qcd_floor(l) - if (abs(enrgy_bal_floor(l)) > .10_r8 ) then - write (iulog,*) 'urban inside floor energy balance error ',enrgy_bal_floor(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - end if + qcv_floor(l) = 0.5_r8*hcv_floori(l)*(t_floor(l) - t_building(l)) + 0.5_r8*hcv_floori(l)*(t_floor_bef(l) & + - t_building_bef(l)) + qcd_floor(l) = cv_floori(l)*(t_floor(l) - t_floor_bef(l)) + enrgy_bal_floor(l) = qrd_floor(l) + qcv_floor(l) + qcd_floor(l) + if (abs(enrgy_bal_floor(l)) > .10_r8 ) then + write (iulog,*) 'urban inside floor energy balance error ',enrgy_bal_floor(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + end if - enrgy_bal_buildair(l) = (ht_roof(l)*rho_dair(l)*cpair/dtime)*(t_building(l) - t_building_bef(l)) & - - ht_roof(l)*(vent_ach/3600._r8)*rho_dair(l)*cpair*(taf(l) - t_building(l)) & - - 0.5_r8*hcv_roofi(l)*(t_roof_inner(l) - t_building(l)) & - - 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) - t_building_bef(l)) & - - 0.5_r8*hcv_sunwi(l)*(t_sunw_inner(l) - t_building(l))*building_hwr(l) & - - 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & - - 0.5_r8*hcv_shdwi(l)*(t_shdw_inner(l) - t_building(l))*building_hwr(l) & - - 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & - - 0.5_r8*hcv_floori(l)*(t_floor(l) - t_building(l)) & - - 0.5_r8*hcv_floori(l)*(t_floor_bef(l) - t_building_bef(l)) - if (abs(enrgy_bal_buildair(l)) > .10_r8 ) then - write (iulog,*) 'urban building air energy balance error ',enrgy_bal_buildair(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) - end if + enrgy_bal_buildair(l) = (ht_roof(l)*rho_air(l)*cp_air(l)/dtime)*(t_building(l) - t_building_bef(l)) & + - ht_roof(l)*(vent_ach/secsphr)*rho_air(l)*cp_air(l)*(taf(l) - t_building(l)) & + - 0.5_r8*hcv_roofi(l)*(t_roof_inner(l) - t_building(l)) & + - 0.5_r8*hcv_roofi(l)*(t_roof_inner_bef(l) - t_building_bef(l)) & + - 0.5_r8*hcv_sunwi(l)*(t_sunw_inner(l) - t_building(l))*building_hwr(l) & + - 0.5_r8*hcv_sunwi(l)*(t_sunw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & + - 0.5_r8*hcv_shdwi(l)*(t_shdw_inner(l) - t_building(l))*building_hwr(l) & + - 0.5_r8*hcv_shdwi(l)*(t_shdw_inner_bef(l) - t_building_bef(l))*building_hwr(l) & + - 0.5_r8*hcv_floori(l)*(t_floor(l) - t_building(l)) & + - 0.5_r8*hcv_floori(l)*(t_floor_bef(l) - t_building_bef(l)) + if (abs(enrgy_bal_buildair(l)) > .10_r8 ) then + write (iulog,*) 'urban building air energy balance error ',enrgy_bal_buildair(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + end if - ! Sensible heat flux from ventilation. It is added as a flux to the canyon floor in SoilTemperatureMod. - ! Note that we multiply it here by wtlunit_roof which converts it from W/m2 of building area to W/m2 - ! of urban area. eflx_urban_ac and eflx_urban_heat are treated similarly below. This flux is balanced - ! by an equal and opposite flux into/out of the building and so has a net effect of zero on the energy balance - ! of the urban landunit. - eflx_ventilation(l) = wtlunit_roof(l) * ( - ht_roof(l)*(vent_ach/3600._r8) & - * rho_dair(l) * cpair * (taf(l) - t_building(l)) ) + ! Sensible and latent heat flux (if indoor humidity is prognosed) from ventilation. It is added as a flux to the canyon floor in SoilTemperatureMod. + ! Note that we multiply it here by wtlunit_roof which converts it from W/m2 of building area to W/m2 + ! of urban area. eflx_urban_ac and eflx_urban_heat are treated similarly below. This flux is balanced + ! by an equal and opposite flux into/out of the building and so has a net effect of zero on the energy balance + ! of the urban landunit. + if (IsBuildingHumidityEnabled()) then + eflx_ventilation(l) = wtlunit_roof(l) * ( & + - ht_roof(l) * (vent_ach/secsphr) * rho_air(l) * cp_air(l) * (taf(l) - t_building(l)) & + - ht_roof(l) * (vent_ach/secsphr) * rho_air(l) * hvap * (qaf(l) - q_building(l)) ) + else + eflx_ventilation(l) = wtlunit_roof(l) * ( & + - ht_roof(l) * (vent_ach/secsphr) * rho_air(l) * cpair * (taf(l) - t_building(l)) ) end if end do ! Restrict internal building air temperature to between min and max + ! and restrict internal building air specific humidity to below max, when AC dehumidification is enabled. ! Calculate heating or air conditioning flux from energy required to change - ! internal building air temperature to t_building_min or t_building_max. + ! internal building air temperature to t_building_min or t_building_max + ! and internal building specific humidity to below q_building_max, when AC dehumidification is enabled. do fl = 1,num_urbanl l = filter_urbanl(fl) - if (urbpoi(l)) then - if (trim(urban_hac) == urban_hac_on .or. trim(urban_hac) == urban_wasteheat_on) then - t_building_bef_hac(l) = t_building(l) + g = lun%gridcell(l) + if_hac_on: if (trim(urban_hac) == urban_hac_on .or. trim(urban_hac) == urban_wasteheat_on) then + t_building_bef_hac(l) = t_building(l) ! rho_dair(l) = pstd / (rair*t_building(l)) + if (IsACDehumidificationEnabled()) then + q_building_bef_hac(l) = q_building(l) + ! Convert maximum indoor relative humidity to maximum specific humidity + ! at the current indoor temperature and pressure. + call QSat(t_building_bef_hac(l), forc_pbot(g), qsat_building_max) + q_building_max = rh_building_max * pct_to_frac * qsat_building_max + end if - if (t_building_bef_hac(l) > t_building_max(l)) then - if (urban_explicit_ac) then ! use explicit ac adoption rate parameterization scheme: - ! Here, t_building_max is the AC saturation setpoint - eflx_urban_ac_sat(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_max(l) & - - (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_bef_hac(l) ) - t_building(l) = t_building_max(l) + ( 1._r8 - p_ac(l) ) * eflx_urban_ac_sat(l) & - * dtime / (ht_roof(l) * rho_dair(l) * cpair * wtlunit_roof(l)) - eflx_urban_ac(l) = p_ac(l) * eflx_urban_ac_sat(l) - else - t_building(l) = t_building_max(l) - eflx_urban_ac(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building(l) & - - (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_bef_hac(l) ) - end if - - else if (t_building_bef_hac(l) < t_building_min(l)) then - t_building(l) = t_building_min(l) - eflx_urban_heat(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building(l) & - - (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_bef_hac(l) ) - else - eflx_urban_ac(l) = 0._r8 - eflx_urban_heat(l) = 0._r8 - end if - else - eflx_urban_ac(l) = 0._r8 - eflx_urban_heat(l) = 0._r8 + if_temp_control: if (t_building_bef_hac(l) > t_building_max(l)) then + if_explicit_ac: if (urban_explicit_ac) then ! use explicit ac adoption rate parameterization scheme: + + ! Sensible heat component of AC + ! Here, t_building_max is the AC saturation setpoint + eflx_urban_ac_sat(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_air(l) * cp_air(l) / dtime) * t_building_max(l) & + - (ht_roof(l) * rho_air(l) * cp_air(l) / dtime) * t_building_bef_hac(l) ) + t_building(l) = t_building_max(l) + ( 1._r8 - p_ac(l) ) * eflx_urban_ac_sat(l) & + * dtime / (ht_roof(l) * rho_air(l) * cp_air(l) * wtlunit_roof(l)) + if_dehumidification: if (IsACDehumidificationEnabled()) then + ! Save sensible AC flux at actual adoption for URBAN_AC_SEN history output + ! and the condensate/latent-energy consistency check, before adding latent demand. + eflx_urban_ac_sen(l) = p_ac(l) * eflx_urban_ac_sat(l) + ! Latent heat component of AC + if (q_building_bef_hac(l) > q_building_max) then + ! Calculate latent heat flux needed to lower indoor specific humidity to q_building_max at saturated AC adoption + eflx_urban_ac_sat_lat(l) = wtlunit_roof(l) * abs( & + (ht_roof(l) * rho_air(l) * hvap / dtime) * q_building_max & + - (ht_roof(l) * rho_air(l) * hvap / dtime) * q_building_bef_hac(l) ) + ! Add to the sensible heat component calculated previously + eflx_urban_ac_sat(l) = eflx_urban_ac_sat(l) + eflx_urban_ac_sat_lat(l) + ! Reset q_building based on actual moisture removed at the actual AC adoption rate + q_building(l) = q_building_max + (1._r8 - p_ac(l)) * eflx_urban_ac_sat_lat(l) & + * dtime / (ht_roof(l) * rho_air(l) * hvap * wtlunit_roof(l)) + end if + end if if_dehumidification + eflx_urban_ac(l) = p_ac(l) * eflx_urban_ac_sat(l) + else + t_building(l) = t_building_max(l) + eflx_urban_ac(l) = wtlunit_roof(l) * abs( & + (ht_roof(l) * rho_air(l) * cp_air(l) / dtime) * t_building(l) & + - (ht_roof(l) * rho_air(l) * cp_air(l) / dtime) * t_building_bef_hac(l) ) + end if if_explicit_ac + + else if (t_building_bef_hac(l) < t_building_min(l)) then + ! Humidification during urban heating is not implemented. + t_building(l) = t_building_min(l) + eflx_urban_heat(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_air(l) * cp_air(l) / dtime) * t_building(l) & + - (ht_roof(l) * rho_air(l) * cp_air(l) / dtime) * t_building_bef_hac(l) ) + else + eflx_urban_ac(l) = 0._r8 + eflx_urban_heat(l) = 0._r8 + if (IsACDehumidificationEnabled()) eflx_urban_ac_sen(l) = 0._r8 + end if if_temp_control + + else + eflx_urban_ac(l) = 0._r8 + eflx_urban_heat(l) = 0._r8 + if (IsACDehumidificationEnabled()) eflx_urban_ac_sen(l) = 0._r8 + end if if_hac_on + + if (IsBuildingHumidityEnabled()) then + ! Calculate sensible and latent heat flux from the change in indoor air state. + eflx_building(l) = wtlunit_roof(l) * ( & + (ht_roof(l) * rho_air(l)*cp_air(l)/dtime) * (t_building(l) - t_building_bef(l)) & + + (ht_roof(l) * rho_air(l)*hvap/dtime) * (q_building(l) - q_building_bef(l)) ) + if (IsACDehumidificationEnabled()) then + ! Convert the decrease in indoor water vapor to condensate per building footprint area. + qtot_condensate(l) = max(0._r8, (-q_building(l)+q_building_bef_hac(l))) * ht_roof(l) * rho_air(l) + qflx_condensate_from_ac_lu(l) = wtlunit_roof(l) * qtot_condensate(l) / dtime end if - eflx_building(l) = wtlunit_roof(l) * (ht_roof(l) * rho_dair(l)*cpair/dtime) * (t_building(l) - t_building_bef(l)) + ! Diagnose indoor relative humidity from the updated temperature and humidity. + call QSat(t_building(l), forc_pbot(g), qsat_building) + rh_building(l) = min(100._r8, q_building(l) / (qsat_building * pct_to_frac)) + else + eflx_building(l) = wtlunit_roof(l) * (ht_roof(l) * rho_air(l)*cpair/dtime) & + * (t_building(l) - t_building_bef(l)) end if end do + ! AC dehumidification consistency check + if (IsACDehumidificationEnabled()) then + do fl = 1,num_urbanl + l = filter_urbanl(fl) + ! Dehumidification energy flux calculated from condensate + eflx_urban_ac_lat_derived(l) = qflx_condensate_from_ac_lu(l) * hvap + ! Error between the above and the Latent heat component of AC energy flux + err_eflx_urban_ac_lat(l) = eflx_urban_ac_lat_derived(l) - (eflx_urban_ac(l) - eflx_urban_ac_sen(l)) + if (abs(err_eflx_urban_ac_lat(l)) > ac_latent_error_thresh ) then + write (iulog,*) 'dehumidification energy flux derived from condensate does not match condensate output' + write (iulog,*) 'dehumidification energy flux derived from condensate [W/m2 urban]: ',eflx_urban_ac_lat_derived(l) + write (iulog,*) 'total AC energy flux [W/m2 urban]: ',eflx_urban_ac(l) + write (iulog,*) 'sensible heat component of AC energy flux [W/m2 urban]: ',eflx_urban_ac_sen(l) + write (iulog,*) 'latent heat component of AC energy flux (total minus sensible) [W/m2 urban]: ', & + eflx_urban_ac(l) - eflx_urban_ac_sen(l) + write (iulog,*) 'error in dehumidification energy flux [W/m2 urban]: ',err_eflx_urban_ac_lat(l) + write (iulog,*) 'error tolerance [W/m2 urban]: ',ac_latent_error_thresh + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit) + end if + end do + + ! Assign condensate water flux to roof column, which then goes directly to surface runoff. + ! It is assigned to roof column rather than other columns as it is calculated per building footprint, + ! which is equivalent to roof area. + ! Set condensate water flux to zero for all other columns. + do fc = 1,num_urbanc + c = filter_urbanc(fc) + l = clandunit(c) + if (ctype(c) == icol_roof) then + qflx_condensate_from_ac(c) = qtot_condensate(l)/dtime + else + qflx_condensate_from_ac(c) = 0._r8 + end if + end do + end if + end associate end subroutine BuildingTemperature diff --git a/src/biogeophys/UrbanParamsType.F90 b/src/biogeophys/UrbanParamsType.F90 index 9fd87f82dc..b844f8806b 100644 --- a/src/biogeophys/UrbanParamsType.F90 +++ b/src/biogeophys/UrbanParamsType.F90 @@ -23,6 +23,8 @@ module UrbanParamsType public :: CheckUrban ! Check validity of urban points public :: IsSimpleBuildTemp ! If using the simple building temperature method public :: IsProgBuildTemp ! If using the prognostic building temperature method + public :: IsBuildingHumidityEnabled ! If indoor building humidity is prognosed + public :: IsACDehumidificationEnabled ! If air-conditioning dehumidification is enabled ! ! !PRIVATE TYPE type urbinp_type @@ -93,6 +95,7 @@ module UrbanParamsType contains procedure, public :: Init + procedure, public :: InitForTesting end type urbanparams_type ! @@ -101,6 +104,10 @@ module UrbanParamsType character(len= *), parameter, public :: urban_hac_on = 'ON' character(len= *), parameter, public :: urban_wasteheat_on = 'ON_WASTEHEAT' character(len= 16), public :: urban_hac = urban_hac_off + integer, parameter, public :: BUILDING_HUMIDITY_MODE_OFF = 0 + integer, parameter, public :: BUILDING_HUMIDITY_MODE_ON = 1 + integer, parameter, public :: BUILDING_HUMIDITY_MODE_DEHUMIDIFY = 2 + integer, public :: building_humidity_mode = BUILDING_HUMIDITY_MODE_OFF logical, public :: urban_explicit_ac = .true. ! whether to use explicit, time-varying AC adoption rate logical, public :: urban_traffic = .false. ! urban traffic fluxes @@ -363,6 +370,34 @@ subroutine Init(this, bounds) end subroutine Init + !----------------------------------------------------------------------- + subroutine InitForTesting(this, bounds) + ! + ! !DESCRIPTION: + ! Version of Init routine just for unit tests + ! + ! This version sets building_humidity_mode and then calls Init + ! + ! !ARGUMENTS: + class(urbanparams_type) , intent(inout) :: this + type(bounds_type) , intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + + character(len=*), parameter :: subname = 'InitForTesting' + !----------------------------------------------------------------------- + + ! Default setting (prognostic indoor humidity and dehumidification off) + building_humidity_mode = BUILDING_HUMIDITY_MODE_OFF + + ! We set this to .true. to enable the IsBuildingHumidityEnabled and + ! IsACDehumidificationEnabled functions to be used for unit testing + ReadNamelist = .true. + + call Init(this, bounds = bounds) + + end subroutine InitForTesting + !----------------------------------------------------------------------- subroutine UrbanInput(begg, endg, mode) ! @@ -851,7 +886,7 @@ subroutine UrbanReadNML ( NLFilename ) integer :: unitn ! unit for namelist file character(len=32) :: subname = 'UrbanReadNML' ! subroutine name - namelist / clmu_inparm / urban_hac, urban_explicit_ac, urban_traffic, building_temp_method + namelist / clmu_inparm / urban_hac, building_humidity_mode, urban_explicit_ac, urban_traffic, building_temp_method !EOP !----------------------------------------------------------------------- @@ -879,6 +914,7 @@ subroutine UrbanReadNML ( NLFilename ) ! Broadcast namelist variables read in call shr_mpi_bcast(urban_hac, mpicom) + call shr_mpi_bcast(building_humidity_mode, mpicom) call shr_mpi_bcast(urban_explicit_ac, mpicom) call shr_mpi_bcast(urban_traffic, mpicom) call shr_mpi_bcast(building_temp_method, mpicom) @@ -888,9 +924,28 @@ subroutine UrbanReadNML ( NLFilename ) write(iulog,*)'Urban traffic fluxes are not implemented currently' call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if (building_humidity_mode < BUILDING_HUMIDITY_MODE_OFF .or. & + building_humidity_mode > BUILDING_HUMIDITY_MODE_DEHUMIDIFY) then + call endrun(msg='building_humidity_mode must be 0, 1, or 2'//errmsg(sourcefile, __LINE__)) + end if + if (building_humidity_mode >= BUILDING_HUMIDITY_MODE_ON .and. & + building_temp_method /= BUILDING_TEMP_METHOD_PROG) then + call endrun(msg='building_humidity_mode=1 or 2 requires the prognostic building temperature method'// & + errmsg(sourcefile, __LINE__)) + end if + if (building_humidity_mode == BUILDING_HUMIDITY_MODE_DEHUMIDIFY) then + if (trim(urban_hac) /= urban_hac_on .and. trim(urban_hac) /= urban_wasteheat_on) then + call endrun(msg='building_humidity_mode=2 requires urban_hac to be ON or ON_WASTEHEAT'// & + errmsg(sourcefile, __LINE__)) + end if + if (.not. urban_explicit_ac) then + call endrun(msg='building_humidity_mode=2 requires urban_explicit_ac=.true.'//errmsg(sourcefile, __LINE__)) + end if + end if ! if ( masterproc )then write(iulog,*) ' urban air conditioning/heating and wasteheat = ', urban_hac + write(iulog,*) ' urban building humidity mode = ', building_humidity_mode write(iulog,*) ' urban explicit air-conditioning adoption rate = ', urban_explicit_ac write(iulog,*) ' urban traffic flux = ', urban_traffic end if @@ -957,4 +1012,60 @@ end function IsProgBuildTemp !----------------------------------------------------------------------- + !----------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: IsBuildingHumidityEnabled + ! + ! !INTERFACE: + ! + logical function IsBuildingHumidityEnabled( ) + ! + ! !DESCRIPTION: + ! + ! If indoor building humidity is being simulated + ! + ! !USES: + implicit none + !EOP + !----------------------------------------------------------------------- + + if ( .not. ReadNamelist )then + write(iulog,*)'IsBuildingHumidityEnabled called before urban namelist was read in' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + IsBuildingHumidityEnabled = building_humidity_mode >= BUILDING_HUMIDITY_MODE_ON + + end function IsBuildingHumidityEnabled + + !----------------------------------------------------------------------- + + !----------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: IsACDehumidificationEnabled + ! + ! !INTERFACE: + ! + logical function IsACDehumidificationEnabled( ) + ! + ! !DESCRIPTION: + ! + ! If air-conditioning dehumidification is enabled + ! + ! !USES: + implicit none + !EOP + !----------------------------------------------------------------------- + + if ( .not. ReadNamelist )then + write(iulog,*)'IsACDehumidificationEnabled called before urban namelist was read in' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + IsACDehumidificationEnabled = building_humidity_mode == BUILDING_HUMIDITY_MODE_DEHUMIDIFY + + end function IsACDehumidificationEnabled + + !----------------------------------------------------------------------- + end module UrbanParamsType diff --git a/src/biogeophys/WaterDiagnosticBulkType.F90 b/src/biogeophys/WaterDiagnosticBulkType.F90 index 696435bd1e..4310c71ed9 100644 --- a/src/biogeophys/WaterDiagnosticBulkType.F90 +++ b/src/biogeophys/WaterDiagnosticBulkType.F90 @@ -28,6 +28,7 @@ module WaterDiagnosticBulkType use WaterStateType, only : waterstate_type use WaterStateBulkType, only : waterstatebulk_type use WaterFluxType, only : waterflux_type + use UrbanParamsType, only : IsBuildingHumidityEnabled ! implicit none save @@ -63,6 +64,7 @@ module WaterDiagnosticBulkType real(r8), pointer :: rh_ref2m_patch (:) ! patch 2 m height surface relative humidity (%) real(r8), pointer :: rh_ref2m_r_patch (:) ! patch 2 m height surface relative humidity - rural (%) real(r8), pointer :: rh_ref2m_u_patch (:) ! patch 2 m height surface relative humidity - urban (%) + real(r8), pointer :: rh_building_lun (:) ! lun internal building air relative humidity (%) real(r8), pointer :: rh_af_patch (:) ! patch fractional humidity of canopy air (dimensionless) ! private real(r8), pointer :: rh10_af_patch (:) ! 10-day mean patch fractional humidity of canopy air (dimensionless) real(r8), pointer :: dqgdT_col (:) ! col d(qg)/dT @@ -154,7 +156,7 @@ subroutine InitBulk(this, bounds, info, vars, & real(r8) , intent(in) :: h2osno_input_col(bounds%begc:) ! Initial total snow water (mm H2O) - call this%Init(bounds, info, vars) + call this%Init(bounds, info, vars, IsBuildingHumidityEnabled()) call this%InitBulkAllocate(bounds) @@ -219,6 +221,7 @@ subroutine InitBulkAllocate(this, bounds) allocate(this%rh_ref2m_patch (begp:endp)) ; this%rh_ref2m_patch (:) = nan allocate(this%rh_ref2m_u_patch (begp:endp)) ; this%rh_ref2m_u_patch (:) = nan allocate(this%rh_ref2m_r_patch (begp:endp)) ; this%rh_ref2m_r_patch (:) = nan + allocate(this%rh_building_lun (begl:endl)) ; this%rh_building_lun (:) = nan allocate(this%rh_af_patch (begp:endp)) ; this%rh_af_patch (:) = nan allocate(this%rh10_af_patch (begp:endp)) ; this%rh10_af_patch (:) = spval @@ -357,6 +360,16 @@ subroutine InitBulkHistory(this, bounds) long_name=this%info%lname('Urban 2m relative humidity'), & ptr_patch=this%rh_ref2m_u_patch, set_nourb=spval) + if (IsBuildingHumidityEnabled()) then + this%rh_building_lun(begl:endl) = spval + call hist_addfld1d ( & + fname=this%info%fname('RHBUILD'), & + units='%', & + avgflag='A', & + long_name=this%info%lname('Internal urban building air relative humidity'), & + ptr_lunit=this%rh_building_lun, set_nourb=spval) + end if + this%rh_af_patch(begp:endp) = spval ! Commented out failing fields (see https://github.com/ESCOMP/CTSM/issues/3661) to allow all_outputs test to catch new problems as they arise ! call hist_addfld1d ( & @@ -815,7 +828,7 @@ subroutine RestartBulk(this, bounds, ncid, flag, writing_finidat_interp_dest_fil !------------------------------------------------------------------------ - call this%Restart(bounds, ncid, flag=flag) + call this%Restart(bounds, ncid, flag=flag, is_prog_buildhumidity=IsBuildingHumidityEnabled()) if(use_luna)then call restartvar(ncid=ncid, flag=flag, & diff --git a/src/biogeophys/WaterDiagnosticType.F90 b/src/biogeophys/WaterDiagnosticType.F90 index 57be0e62af..fc4b609a84 100644 --- a/src/biogeophys/WaterDiagnosticType.F90 +++ b/src/biogeophys/WaterDiagnosticType.F90 @@ -49,6 +49,7 @@ module WaterDiagnosticType real(r8), pointer :: qg_h2osfc_col (:) ! col ground specific humidity [kg/kg] real(r8), pointer :: qg_col (:) ! col ground specific humidity [kg/kg] real(r8), pointer :: qaf_lun (:) ! lun urban canopy air specific humidity (kg/kg) + real(r8), pointer :: q_building_lun (:) ! lun internal building air specific humidity (kg/kg) contains @@ -69,20 +70,21 @@ module WaterDiagnosticType contains !------------------------------------------------------------------------ - subroutine Init(this, bounds, info, tracer_vars) + subroutine Init(this, bounds, info, tracer_vars, is_prog_buildhumidity) class(waterdiagnostic_type), intent(inout) :: this type(bounds_type) , intent(in) :: bounds class(water_info_base_type), intent(in), target :: info type(water_tracer_container_type), intent(inout) :: tracer_vars + logical, intent(in) :: is_prog_buildhumidity ! Prognostic building humidity is being used this%info => info call this%InitAllocate(bounds, tracer_vars) - call this%InitHistory(bounds) + call this%InitHistory(bounds, is_prog_buildhumidity) - call this%InitCold(bounds) + call this%InitCold(bounds, is_prog_buildhumidity) end subroutine Init @@ -138,11 +140,14 @@ subroutine InitAllocate(this, bounds, tracer_vars) call AllocateVar1d(var = this%q_ref2m_patch, name = 'q_ref2m_patch', & container = tracer_vars, & bounds = bounds, subgrid_level = subgrid_level_patch) + call AllocateVar1d(var = this%q_building_lun, name = 'q_building_lun', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_landunit) end subroutine InitAllocate !------------------------------------------------------------------------ - subroutine InitHistory(this, bounds) + subroutine InitHistory(this, bounds, is_prog_buildhumidity) ! ! !DESCRIPTION: ! Initialize module data structure @@ -153,15 +158,18 @@ subroutine InitHistory(this, bounds) ! !ARGUMENTS: class(waterdiagnostic_type), intent(in) :: this type(bounds_type), intent(in) :: bounds + logical, intent(in) :: is_prog_buildhumidity ! Prognostic building humidity is being used ! ! !LOCAL VARIABLES: integer :: begp, endp integer :: begc, endc + integer :: begl, endl integer :: begg, endg !------------------------------------------------------------------------ begp = bounds%begp; endp= bounds%endp begc = bounds%begc; endc= bounds%endc + begl = bounds%begl; endl= bounds%endl begg = bounds%begg; endg= bounds%endg @@ -241,12 +249,21 @@ subroutine InitHistory(this, bounds) long_name=this%info%lname('snow ice (ice landunits only)'), & ptr_col=this%snowice_col, c2l_scale_type='urbanf', l2g_scale_type='ice', & default='inactive') - + + if ( is_prog_buildhumidity ) then + this%q_building_lun(begl:endl) = spval + call hist_addfld1d ( & + fname=this%info%fname('QBUILD'), & + units='kg/kg', & + avgflag='A', & + long_name=this%info%lname('internal urban building air specific humidity'), & + ptr_lunit=this%q_building_lun, l2g_scale_type='unity', set_nourb=spval) + end if end subroutine InitHistory !----------------------------------------------------------------------- - subroutine InitCold(this, bounds) + subroutine InitCold(this, bounds, is_prog_buildhumidity) ! ! !DESCRIPTION: ! Initialize time constant variables and cold start conditions @@ -257,6 +274,7 @@ subroutine InitCold(this, bounds) ! !ARGUMENTS: class(waterdiagnostic_type), intent(in) :: this type(bounds_type) , intent(in) :: bounds + logical , intent(in) :: is_prog_buildhumidity ! Prognostic building humidity is being used ! ! !LOCAL VARIABLES: integer :: l @@ -286,10 +304,19 @@ subroutine InitCold(this, bounds) end if end do + ! Initialize internal building specific humidity (following example above and t_building_max in TemperatureType.F90) + if ( is_prog_buildhumidity ) then + do l = bounds%begl, bounds%endl + if (lun%urbpoi(l)) then + this%q_building_lun(l) = this%qaf_lun(l) ! set to urban canopy specific humidity + end if + end do + end if + end subroutine InitCold !------------------------------------------------------------------------ - subroutine Restart(this, bounds, ncid, flag) + subroutine Restart(this, bounds, ncid, flag, is_prog_buildhumidity) ! ! !DESCRIPTION: ! Read/Write module information to/from restart file. @@ -297,14 +324,16 @@ subroutine Restart(this, bounds, ncid, flag) ! !USES: use clm_varcon , only : nameg, namec use ncdio_pio , only : file_desc_t, ncd_double - use clm_varctl , only : use_fates_planthydro + use clm_varctl , only : use_fates_planthydro, iulog use restUtilMod + use spmdMod , only : masterproc ! ! !ARGUMENTS: class(waterdiagnostic_type), intent(in) :: this type(bounds_type), intent(in) :: bounds type(file_desc_t), intent(inout) :: ncid ! netcdf id character(len=*) , intent(in) :: flag ! 'read' or 'write' + logical , intent(in) :: is_prog_buildhumidity ! Prognostic building humidity is being used ! ! !LOCAL VARIABLES: integer :: c,l,j @@ -340,6 +369,21 @@ subroutine Restart(this, bounds, ncid, flag) interpinic_flag='interp', readvar=readvar, data=this%total_plant_stored_h2o_col) end if + if ( is_prog_buildhumidity ) then + ! landunit type physical state variable - q_building + call restartvar(ncid=ncid, flag=flag, & + varname=this%info%fname('q_building'), & + xtype=ncd_double, dim1name='landunit', & + long_name=this%info%lname('internal building air specific humidity'), & + units='kg/kg', & + interpinic_flag='interp', readvar=readvar, data=this%q_building_lun) + if (flag=='read' .and. .not. readvar) then + if (masterproc) write(iulog,*) "can't find q_building in initial file..." + if (masterproc) write(iulog,*) "Initialize q_building to qaf" + this%q_building_lun(bounds%begl:bounds%endl) = this%qaf_lun(bounds%begl:bounds%endl) + end if + end if + end subroutine Restart !----------------------------------------------------------------------- diff --git a/src/biogeophys/WaterFluxType.F90 b/src/biogeophys/WaterFluxType.F90 index 561a658c21..4e516b555e 100644 --- a/src/biogeophys/WaterFluxType.F90 +++ b/src/biogeophys/WaterFluxType.F90 @@ -16,6 +16,7 @@ module WaterFluxType use WaterInfoBaseType, only : water_info_base_type use WaterTracerContainerType, only : water_tracer_container_type use WaterTracerUtils, only : AllocateVar1d, AllocateVar2d + use UrbanParamsType, only : IsACDehumidificationEnabled ! implicit none private @@ -49,7 +50,9 @@ module WaterFluxType real(r8), pointer :: qflx_evap_tot_col (:) ! col col_qflx_evap_soi + col_qflx_evap_veg + qflx_tran_veg real(r8), pointer :: qflx_liqevap_from_top_layer_patch(:) ! patch rate of liquid water evaporated from top soil or snow layer (mm H2O/s) [+] real(r8), pointer :: qflx_liqevap_from_top_layer_col(:) ! col rate of liquid water evaporated from top soil or snow layer (mm H2O/s) [+] - + real(r8), pointer :: qflx_condensate_from_ac_col(:) ! col condensate due to dehumidification from air-conditioning (mm H2O/S) [+] + real(r8), pointer :: qflx_condensate_from_ac_lun(:) ! lun condensate due to dehumidification from air-conditioning (mm H2O/S) [+] + ! In the snow capping parametrization excess mass above h2osno_max is removed. A breakdown of mass into liquid ! and solid fluxes is done, these are represented by qflx_snwcp_liq_col and qflx_snwcp_ice_col. real(r8), pointer :: qflx_snwcp_liq_col (:) ! col excess liquid h2o due to snow capping (outgoing) (mm H2O /s) @@ -263,6 +266,14 @@ subroutine InitAllocate(this, bounds, tracer_vars) call AllocateVar1d(var = this%qflx_liqevap_from_top_layer_patch, name = 'qflx_liqevap_from_top_layer_patch', & container = tracer_vars, & bounds = bounds, subgrid_level = subgrid_level_patch) + ! The following two vars are initialized as 0.0_r8 rather than spval + ! to prevent nan from occurring during spatial aggregation + call AllocateVar1d(var = this%qflx_condensate_from_ac_col, name = 'qflx_condensate_from_ac_col', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_column, ival = 0.0_r8) + call AllocateVar1d(var = this%qflx_condensate_from_ac_lun, name = 'qflx_condensate_from_ac_lun', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_landunit, ival = 0.0_r8) call AllocateVar1d(var = this%qflx_infl_col, name = 'qflx_infl_col', & container = tracer_vars, & @@ -574,6 +585,16 @@ subroutine InitHistory(this, bounds) long_name=this%info%lname('Rural total runoff'), & ptr_col=this%qflx_runoff_r_col, set_spec=spval, default='inactive') + if (IsACDehumidificationEnabled()) then + this%qflx_condensate_from_ac_col(begc:endc) = 0.0_r8 + call hist_addfld1d ( & + fname=this%info%fname('QCOND_FROM_AC'), & + units='mm/s', & + avgflag='A', & + long_name=this%info%lname('Condensed water flux from AC dehumidification'), & + ptr_col=this%qflx_condensate_from_ac_col, set_nourb=0.0_r8, c2l_scale_type='urbanf') + end if + this%qflx_snomelt_col(begc:endc) = spval call hist_addfld1d ( & fname=this%info%fname('QSNOMELT'), & diff --git a/src/biogeophys/WaterType.F90 b/src/biogeophys/WaterType.F90 index 9a4884ce8c..f0745acc9d 100644 --- a/src/biogeophys/WaterType.F90 +++ b/src/biogeophys/WaterType.F90 @@ -78,6 +78,7 @@ module WaterType use Wateratm2lndBulkType , only : wateratm2lndbulk_type use WaterTracerContainerType , only : water_tracer_container_type use WaterTracerUtils , only : CompareBulkToTracer, SetTracerToBulkTimesRatio + use UrbanParamsType , only : IsBuildingHumidityEnabled implicit none private @@ -394,7 +395,8 @@ subroutine DoInit(this, bounds, & call this%bulk_and_tracers(i)%waterdiagnostic_inst%Init(bounds, & this%bulk_and_tracers(i)%info, & - this%bulk_and_tracers(i)%vars) + this%bulk_and_tracers(i)%vars, & + IsBuildingHumidityEnabled()) call this%bulk_and_tracers(i)%waterbalance_inst%Init(bounds, & this%bulk_and_tracers(i)%info, & @@ -733,7 +735,7 @@ end subroutine UpdateAccVars !----------------------------------------------------------------------- subroutine Restart(this, bounds, ncid, flag, writing_finidat_interp_dest_file, & - watsat_col, t_soisno_col, altmax_lastyear_indx) + watsat_col, t_soisno_col, altmax_lastyear_indx, is_prog_buildhumidity) ! ! !DESCRIPTION: ! Read/write information to/from restart file for all water variables @@ -747,6 +749,7 @@ subroutine Restart(this, bounds, ncid, flag, writing_finidat_interp_dest_file, & real(r8) , intent(in) :: watsat_col (bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) real(r8) , intent(in) :: t_soisno_col(bounds%begc:, -nlevsno+1:) ! col soil temperature (Kelvin) integer , intent(in) :: altmax_lastyear_indx(bounds%begc:) !col active layer index last year + logical , intent(in) :: is_prog_buildhumidity ! Prognostic building humidity is being used ! ! !LOCAL VARIABLES: integer :: i @@ -776,7 +779,8 @@ subroutine Restart(this, bounds, ncid, flag, writing_finidat_interp_dest_file, & t_soisno_col=t_soisno_col(bounds%begc:, -nlevsno+1:), & altmax_lastyear_indx=altmax_lastyear_indx(bounds%begc:)) - call this%bulk_and_tracers(i)%waterdiagnostic_inst%Restart(bounds, ncid, flag=flag) + call this%bulk_and_tracers(i)%waterdiagnostic_inst%Restart(bounds, ncid, flag=flag, & + is_prog_buildhumidity=is_prog_buildhumidity) end do diff --git a/src/biogeophys/test/Irrigation_test/test_irrigation.pf b/src/biogeophys/test/Irrigation_test/test_irrigation.pf index d83fc94329..8257180af2 100644 --- a/src/biogeophys/test/Irrigation_test/test_irrigation.pf +++ b/src/biogeophys/test/Irrigation_test/test_irrigation.pf @@ -22,6 +22,7 @@ module test_irrigation use ColumnType , only : col use GridcellType , only : grc use pftconMod , only : pftcon + use UrbanParamsType, only : urbanparams_type use unittestWaterTypeFactory, only : unittest_water_type_factory_type use unittestSimpleSubgridSetupsMod, only : setup_single_veg_patch, setup_n_veg_patches use unittestFilterBuilderMod, only : filter_from_range @@ -37,6 +38,7 @@ module test_irrigation type, extends(irrigation_type) :: irrigation_test_type real(r8) :: gw_frac_from_con ! Fraction of groundwater irrigation taken from confined aquifer (same for all columns) real(r8), allocatable :: gw_frac_from_uncon(:) ! Fraction of groundwater irrigation taken from unconfined aquifer in various layers (same for all columns) + type(urbanparams_type) :: urbanparams_inst contains procedure, public :: InitForTesting ! Call the main irrigation InitForTesting, and also initialize IrrigationTestType's test-specific data to reasonable values procedure, public :: SetGwFractions ! Set fraction of groundwater from various sources @@ -417,6 +419,8 @@ contains ! ! !ARGUMENTS: class(TestIrrigation), intent(in) :: this + type(urbanparams_type) :: urbanparams_inst + integer, intent(in) :: maxpft ! max pft type that needs to be supported ! Irrigation method (drip by default); just set for the module-level pft_type parameter @@ -437,6 +441,10 @@ contains allocate(pftcon%irrigated(0:maxpft), source=1.0_r8) + ! Reguired so that the IsBuildingHumidityEnabled and IsACDehumidificationEnabled + ! namelist functions can be used + call urbanparams_inst%InitForTesting(bounds) + ! In the production code, irrig_method goes cft_lb:cft_ub; but it's safe to allocate ! more space than we really need here. allocate(irrig_method(bounds%begg:bounds%endg, 0:maxpft)) diff --git a/src/biogeophys/test/WaterType_test/test_water_type.pf b/src/biogeophys/test/WaterType_test/test_water_type.pf index f3edc731a3..3367047bf2 100644 --- a/src/biogeophys/test/WaterType_test/test_water_type.pf +++ b/src/biogeophys/test/WaterType_test/test_water_type.pf @@ -5,6 +5,7 @@ module test_water_type use funit use WaterType use shr_kind_mod , only : r8 => shr_kind_r8 + use UrbanParamsType, only : urbanparams_type use unittestSubgridMod, only : bounds, unittest_subgrid_teardown use unittestSimpleSubgridSetupsMod, only : setup_single_veg_patch use unittestUtils, only : endrun_msg @@ -15,6 +16,7 @@ module test_water_type @TestCase type, extends(TestCase) :: TestWaterType type(water_type) :: water_inst + type(urbanparams_type) :: urbanparams_inst type(unittest_water_type_factory_type) :: factory contains procedure :: setUp @@ -49,6 +51,11 @@ contains class(TestWaterType), intent(inout) :: this call setup_single_veg_patch(pft_type=1) + + ! Reguired so that the IsBuildingHumidityEnabled and IsACDehumidificationEnabled + ! namelist functions can be used + call this%urbanparams_inst%InitForTesting(bounds) + call this%factory%setup_after_subgrid(snl = 0, dz = 1._r8) call this%factory%create_water_type(this%water_inst, & enable_consistency_checks = .true., & diff --git a/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf b/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf index 98e678fb2c..7ba9e19b8e 100644 --- a/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf +++ b/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf @@ -30,9 +30,9 @@ module test_dyn_cons_biogeophys type(unittest_water_type_factory_type) :: water_type_factory type(soilstate_type) :: soilstate_inst type(temperature_type) :: temperature_inst - type(urbanparams_type) :: urbanparams_inst type(lakestate_type) :: lakestate_inst type(water_type) :: water_inst + type(urbanparams_type) :: urbanparams_inst contains procedure :: setUp procedure :: tearDown @@ -203,6 +203,10 @@ contains ! Arbitrary value, not important here this%urbanparams_inst%nlev_improad(bounds%begl:bounds%endl) = 3 + ! Reguired so that the IsBuildingHumidityEnabled and IsACDehumidificationEnabled + ! namelist functions can be used + call this%urbanparams_inst%InitForTesting(bounds) + ! Initialize water_inst ! (snl and dz are totally arbitrary here: these are unimportant for this test) call this%water_type_factory%setup_after_subgrid(snl = -2, dz = 0.05_r8) diff --git a/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf b/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf index 79ec506f90..6b474ed261 100644 --- a/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf +++ b/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf @@ -15,6 +15,7 @@ module test_init_columns use shr_kind_mod , only : r8 => shr_kind_r8 use TemperatureType , only : temperature_type use WaterType , only : water_type + use UrbanParamsType, only : urbanparams_type use unittestWaterTypeFactory, only : unittest_water_type_factory_type use WaterstateType , only : waterstate_type use dynColumnTemplateMod, only : TEMPLATE_NONE_FOUND @@ -29,6 +30,7 @@ module test_init_columns integer :: l2 ! index of the landunit with landunit type 2 type(temperature_type) :: temperature_inst type(water_type) :: water_inst + type(urbanparams_type) :: urbanparams_inst type(unittest_water_type_factory_type) :: water_factory contains procedure :: setUp @@ -87,6 +89,10 @@ contains call unittest_subgrid_setup_end() + ! Reguired so that the IsBuildingHumidityEnabled and IsACDehumidificationEnabled + ! namelist functions can be used + call this%urbanparams_inst%InitForTesting(bounds) + call this%water_factory%setup_after_subgrid(snl = 0, dz = 1._r8) call this%water_factory%create_water_type(this%water_inst, & enable_isotopes = .true.) diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index 271ccf84f4..7b2c0d9529 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -517,7 +517,7 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) ! ! !USES: use ncdio_pio , only : file_desc_t - use UrbanParamsType , only : IsSimpleBuildTemp, IsProgBuildTemp + use UrbanParamsType , only : IsSimpleBuildTemp, IsProgBuildTemp, IsBuildingHumidityEnabled use decompMod , only : get_proc_bounds, get_proc_clumps, get_clump_bounds use clm_varpar , only : nlevsno @@ -567,8 +567,9 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) call water_inst%restart(bounds, ncid, flag=flag, & writing_finidat_interp_dest_file = writing_finidat_interp_dest_file, & watsat_col = soilstate_inst%watsat_col(bounds%begc:bounds%endc,:), & - t_soisno_col=temperature_inst%t_soisno_col(bounds%begc:bounds%endc, -nlevsno+1:), & - altmax_lastyear_indx=active_layer_inst%altmax_lastyear_indx_col(bounds%begc:bounds%endc)) + t_soisno_col=temperature_inst%t_soisno_col(bounds%begc:bounds%endc, -nlevsno+1:), & + altmax_lastyear_indx=active_layer_inst%altmax_lastyear_indx_col(bounds%begc:bounds%endc), & + is_prog_buildhumidity = IsBuildingHumidityEnabled()) call irrigation_inst%restart (bounds, ncid, flag=flag) diff --git a/src/main/clm_varcon.F90 b/src/main/clm_varcon.F90 index 234b89c797..751145ce97 100644 --- a/src/main/clm_varcon.F90 +++ b/src/main/clm_varcon.F90 @@ -13,7 +13,8 @@ module clm_varcon SHR_CONST_RHOICE,SHR_CONST_TKFRZ,SHR_CONST_REARTH, & SHR_CONST_PDB, SHR_CONST_PI, SHR_CONST_CDAY, & SHR_CONST_RGAS, SHR_CONST_PSTD, & - SHR_CONST_MWDAIR, SHR_CONST_MWWV, SHR_CONST_CPFW + SHR_CONST_MWDAIR, SHR_CONST_MWWV, SHR_CONST_CPFW, & + SHR_CONST_CPWV use clm_varpar , only: numrad, nlevgrnd, nlevlak, nlevdecomp_full use clm_varpar , only: ngases use clm_varpar , only: nlayer @@ -56,6 +57,7 @@ module clm_varcon real(r8), public :: cpliq = SHR_CONST_CPFW ! Specific heat of water [J/kg-K] real(r8), public :: cpice = SHR_CONST_CPICE ! Specific heat of ice [J/kg-K] real(r8), public :: cpair = SHR_CONST_CPDAIR ! specific heat of dry air [J/kg/K] + real(r8), public :: cpwvap = SHR_CONST_CPWV ! specific heat of water vapor [J/kg/K] real(r8), public :: hvap = SHR_CONST_LATVAP ! Latent heat of evap for water [J/kg] real(r8), public :: hsub = SHR_CONST_LATSUB ! Latent heat of sublimation [J/kg] real(r8), public :: hfus = SHR_CONST_LATICE ! Latent heat of fusion for ice [J/kg] @@ -188,6 +190,7 @@ module clm_varcon real(r8), public, parameter :: sh_floor = 880._r8 ! specific heat of floor - concrete (Salmanca et al. 2010, TAC) (J kg-1 K-1) real(r8), public :: cp_floor = dens_floor*sh_floor ! volumetric heat capacity of floor - concrete (Salmanca et al. 2010, TAC) (J m-3 K-1) real(r8), public :: vent_ach = 0.3_r8 ! ventilation rate (air exchanges per hour) + real(r8), public :: rh_building_max = 65._r8 ! maximum internal building air relative humidity (Li et al. 2026, Nat Cities, which follows ASHRAE Standards 62.1-2022 and 62.1-2013) (%) real(r8), public :: wasteheat_limit = 100._r8 ! limit on wasteheat (W/m2) diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index 99f4688766..321758d1f5 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -496,7 +496,7 @@ subroutine hist_printflds() allhistfldlist(nf)%field%type2d, & allhistfldlist(nf)%field%long_name, & allhistfldlist(nf)%field%units, & - allhistfldlist(nf)%actflag(1,:) + allhistfldlist(nf)%actflag(1,max_split_files:1:-1) end do ! Table footer, same as header diff --git a/src/unit_test_shr/unittestDustEmisInputs.F90 b/src/unit_test_shr/unittestDustEmisInputs.F90 index 08ad677ed4..316794e6f7 100644 --- a/src/unit_test_shr/unittestDustEmisInputs.F90 +++ b/src/unit_test_shr/unittestDustEmisInputs.F90 @@ -9,6 +9,7 @@ module unittestDustEmisInputs use shr_kind_mod , only : r8 => shr_kind_r8 use unittestFilterBuilderMod, only : filter_from_range use atm2lndType, only : atm2lnd_type, atm2lnd_params_type + use UrbanParamsType, only : urbanparams_type use SoilStateType, only : soilstate_type use CanopyStateType, only : canopystate_type use TemperatureType, only : temperature_type @@ -32,6 +33,7 @@ module unittestDustEmisInputs type(unittest_water_type_factory_type), private :: water_factory type(water_type) :: water_inst type(frictionvel_type) :: frictionvel_inst + type(urbanparams_type) :: urbanparams_inst contains procedure, public :: setUp procedure, public :: tearDown @@ -86,6 +88,11 @@ subroutine setUp(this) ) call this%atm2lnd_inst%InitForTesting(bounds, atm2lnd_params) + + ! Reguired so that the IsBuildingHumidityEnabled and IsACDehumidificationEnabled + ! namelist functions can be used + call this%urbanparams_inst%InitForTesting(bounds) + ! Water and soil state -- after the subgrid setup call this%water_factory%setup_after_subgrid(snl = snl) call this%setupSoilState( ) ! This needs to happen before the water_type object creation @@ -271,4 +278,4 @@ end subroutine print_values !----------------------------------------------------------------------- -end module unittestDustEmisInputs \ No newline at end of file +end module unittestDustEmisInputs