diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index c00226b7dd..9b7cb3c036 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -12,3 +12,4 @@ b771971e3299c4fa56534b93421f7a2b9c7282fd 8bc4688e52ea23ef688e283698f70a44388373eb # Ran SystemTests and python/ctsm through black python formatter 5364ad66eaceb55dde2d3d598fe4ce37ac83a93c +8056ae649c1b37f5e10aaaac79005d6e3a8b2380 diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index 438b48e918..3759fa84c3 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -16,6 +16,22 @@ jobs: # Use options and version identical to the conda environment # Using pyproject.toml makes sure this testing is consistent with our python directory testing options: "--check --config python/pyproject.toml" - src: "./python" + src: "./python" # Version should be coordinated with the ctsm_pylib conda environment under the python directory version: "22.3.0" + # Actions identical to above for each directory and source file we need to check (arrays aren't allowed for src: field) + - uses: psf/black@stable + with: + options: "--check --config python/pyproject.toml" + src: "./cime_config/SystemTests" + version: "22.3.0" + - uses: psf/black@stable + with: + options: "--check --config python/pyproject.toml" + src: "./cime_config/buildlib" + version: "22.3.0" + - uses: psf/black@stable + with: + options: "--check --config python/pyproject.toml" + src: "./cime_config/buildnml" + version: "22.3.0" diff --git a/Externals_CLM.cfg b/Externals_CLM.cfg index 7f405e593f..c540fe8b0c 100644 --- a/Externals_CLM.cfg +++ b/Externals_CLM.cfg @@ -2,7 +2,7 @@ local_path = src/fates protocol = git repo_url = https://github.com/NGEET/fates -tag = sci.1.67.1_api.26.0.0 +tag = sci.1.67.1_api.27.0.0 required = True [externals_description] diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index 69b3a8c3dc..493313be19 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -91,11 +91,13 @@ OPTIONS This toggles off the namelist variable: use_cn bgc = Carbon Nitrogen with methane, nitrification, vertical soil C, CENTURY or MIMICS decomposition - This toggles on the namelist variables: + This toggles on the namelist variables: use_cn, use_lch4, use_nitrif_denitrif - fates = FATES/Ecosystem Demography with below ground BGC - This toggles on the namelist variables: - use_fates + fates = FATES/Ecosystem Demography with below ground BGC + CENTURY or MIMICS decomposition + This toggles on the namelist variables: + use_fates. use_lch4 and use_nitrif_denitrif are optional + (Only for CLM4.5/CLM5.0) -[no-]chk_res Also check [do NOT check] to make sure the resolution and land-mask is valid. @@ -763,26 +765,12 @@ sub setup_cmdl_fates_mode { } } - # The following variables may be set by the user and are compatible with use_fates - # no need to set defaults, covered in a different routine - my @list = ( "use_lch4" ); - foreach my $var ( @list ) { - if ( defined($nl->get_value($var)) ) { - $nl_flags->{$var} = $nl->get_value($var); - $val = $nl_flags->{$var}; - my $group = $definition->get_group_name($var); - $nl->set_variable_value($group, $var, $val); - if ( ! $definition->is_valid_value( $var, $val ) ) { - my @valid_values = $definition->get_valid_values( $var ); - $log->fatal_error("$var has a value ($val) that is NOT valid. Valid values are: @valid_values"); - } - } - } } else { # dis-allow fates specific namelist items with non-fates runs my @list = ( "fates_spitfire_mode", "use_fates_planthydro", "use_fates_ed_st3", "use_fates_ed_prescribed_phys", - "use_fates_cohort_age_tracking", - "use_fates_inventory_init","use_fates_fixed_biogeog","use_fates_nocomp","use_fates_sp","fates_inventory_ctrl_filename","use_fates_logging","fates_parteh_mode","use_fates_tree_damage" ); + "use_fates_cohort_age_tracking","use_fates_inventory_init","use_fates_fixed_biogeog", + "use_fates_nocomp","use_fates_sp","fates_inventory_ctrl_filename","use_fates_logging", + "fates_parteh_mode","use_fates_tree_damage" ); # dis-allow fates specific namelist items with non-fates runs foreach my $var ( @list ) { if ( defined($nl->get_value($var)) ) { @@ -2990,24 +2978,30 @@ sub setup_logic_supplemental_nitrogen { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; if ( $nl_flags->{'bgc_mode'} ne "sp" && $nl_flags->{'bgc_mode'} ne "fates" && &value_is_true($nl_flags->{'use_crop'}) ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, - 'suplnitro', 'use_cn'=>$nl_flags->{'use_cn'}, 'use_crop'=>$nl_flags->{'use_crop'}); - } + # If this is non-fates, non-sp and crop is active + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, + 'suplnitro', 'use_cn'=>$nl_flags->{'use_cn'}, 'use_crop'=>$nl_flags->{'use_crop'}); + } elsif ( $nl_flags->{'bgc_mode'} eq "fates" && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + # Or... if its fates but not fates-sp + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, + 'suplnitro', 'use_fates'=>$nl_flags->{'use_fates'}); + } + # # Error checking for suplnitro # my $suplnitro = $nl->get_value('suplnitro'); if ( defined($suplnitro) ) { if ( $nl_flags->{'bgc_mode'} eq "sp" ) { - $log->fatal_error("supplemental Nitrogen (suplnitro) is set, but neither CN nor CNDV is active!"); + $log->fatal_error("supplemental Nitrogen (suplnitro) is set, but neither CN nor CNDV nor FATES is active!"); } if ( ! &value_is_true($nl_flags->{'use_crop'}) && $suplnitro =~ /PROG_CROP_ONLY/i ) { $log->fatal_error("supplemental Nitrogen is set to run over prognostic crops, but prognostic crop is NOT active!"); } if ( $suplnitro =~ /ALL/i ) { - if ( $nl_flags->{'bgc_spinup'} eq "on" ) { + if ( $nl_flags->{'bgc_spinup'} eq "on" && $nl_flags->{'bgc_mode'} ne "fates" ) { $log->warning("There is no need to use a bgc_spinup mode when supplemental Nitrogen is on for all PFT's, as these modes spinup Nitrogen" ); } } @@ -3324,6 +3318,12 @@ sub setup_logic_luna { 'use_cn'=>$nl_flags->{'use_cn'} ); } $nl_flags->{'use_luna'} = $nl->get_value('use_luna'); + + # LUNA can NOT be on with FATES + if ( &value_is_true( $nl_flags->{'use_luna'} ) && &value_is_true( $nl_flags->{'use_fates'} )) { + $log->fatal_error("Cannot turn use_luna to true when bgc=fates" ); + } + my $vcmax_opt= $nl->get_value('vcmax_opt'); # lnc_opt only applies if luna is on or for vcmax_opt=3/4 if ( &value_is_true( $nl_flags->{'use_luna'} ) || $vcmax_opt == 3 || $vcmax_opt == 4 ) { @@ -3490,18 +3490,18 @@ sub setup_logic_nitrogen_deposition { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; # - # Nitrogen deposition for bgc=CN + # Nitrogen deposition for bgc=CN or fates # - if ( $nl_flags->{'bgc_mode'} =~/bgc/ ) { + if ( ($nl_flags->{'bgc_mode'} =~/bgc/) ) { # or ($nl_flags->{'bgc_mode'} =~/fates/) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'ndepmapalgo', 'phys'=>$nl_flags->{'phys'}, 'use_cn'=>$nl_flags->{'use_cn'}, 'hgrid'=>$nl_flags->{'res'}, 'clm_accelerated_spinup'=>$nl_flags->{'clm_accelerated_spinup'} ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'ndep_taxmode', 'phys'=>$nl_flags->{'phys'}, - 'use_cn'=>$nl_flags->{'use_cn'}, - 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); + 'use_cn'=>$nl_flags->{'use_cn'}, + 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'ndep_varlist', 'phys'=>$nl_flags->{'phys'}, - 'use_cn'=>$nl_flags->{'use_cn'}, - 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); + 'use_cn'=>$nl_flags->{'use_cn'}, + 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_first_ndep', 'phys'=>$nl_flags->{'phys'}, 'use_cn'=>$nl_flags->{'use_cn'}, 'sim_year'=>$nl_flags->{'sim_year'}, 'sim_year_range'=>$nl_flags->{'sim_year_range'}); @@ -4278,6 +4278,13 @@ sub setup_logic_fates { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'use_fates'=>$nl_flags->{'use_fates'}, 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); } + my $suplnitro = $nl->get_value('suplnitro'); + my $parteh_mode = $nl->get_value('fates_parteh_mode'); + if ( ($parteh_mode == 1) && ($suplnitro !~ /ALL/) && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + $log->fatal_error("supplemental Nitrogen (suplnitro) is NOT set to ALL, FATES is on, " . + "but and FATES-SP is not active, but fates_parteh_mode is 1, so Nitrogen is not active" . + "Change suplnitro back to ALL"); + } # # For FATES SP mode make sure no-competetiion, and fixed-biogeography are also set # And also check for other settings that can't be trigged on as well diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 1d895524e6..0819b8dd29 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -146,7 +146,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). NONE -NONE +ALL 0.50,0.30 @@ -510,6 +510,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. .false. .false. +.false. .true. diff --git a/bld/unit_testers/build-namelist_test.pl b/bld/unit_testers/build-namelist_test.pl index 82a178bf03..bbf991a7a7 100755 --- a/bld/unit_testers/build-namelist_test.pl +++ b/bld/unit_testers/build-namelist_test.pl @@ -164,6 +164,7 @@ sub cat_and_create_namelistinfile { # Figure out number of tests that will run # my $ntests = 1992; + if ( defined($opts{'compare'}) ) { $ntests += 1353; } @@ -1015,6 +1016,21 @@ sub cat_and_create_namelistinfile { GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_1", }, + "useFATESWluna" =>{ options=>"--bgc fates --envxml_dir . --no-megan", + namelst=>"use_luna=TRUE", + GLC_TWO_WAY_COUPLING=>"FALSE", + phys=>"clm5_1", + }, + "useFATESWfun" =>{ options=>"--bgc fates --envxml_dir . --no-megan", + namelst=>"use_fun=TRUE", + GLC_TWO_WAY_COUPLING=>"FALSE", + phys=>"clm5_1", + }, + "useFATESWOsuplnitro" =>{ options=>"--bgc fates --envxml_dir . --no-megan", + namelst=>"suplnitro='NONE'", + GLC_TWO_WAY_COUPLING=>"FALSE", + phys=>"clm5_1", + }, "FireNoneButBGCfireon" =>{ options=>"-bgc bgc -envxml_dir . -light_res none", namelst=>"fire_method='li2021gswpfrc'", GLC_TWO_WAY_COUPLING=>"FALSE", diff --git a/cime_config/SystemTests/rxcropmaturity.py b/cime_config/SystemTests/rxcropmaturity.py index 4fd812b84a..15f524dfce 100644 --- a/cime_config/SystemTests/rxcropmaturity.py +++ b/cime_config/SystemTests/rxcropmaturity.py @@ -353,7 +353,7 @@ def _run_generate_gdds(self, case_gddgen): f"--sdates-file {sdates_file}", f"--hdates-file {hdates_file}", f"--output-dir generate_gdds_out", - f"--skip-crops miscanthus,irrigated_miscanthus" + f"--skip-crops miscanthus,irrigated_miscanthus", ] ) stu.run_python_script( diff --git a/doc/ChangeLog b/doc/ChangeLog index e65560d5c3..43a19a6644 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,85 @@ =============================================================== +Tag name: ctsm5.1.dev134 +Originator(s): rgknox (Ryan Knox,LBNL EESA), erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Wed Aug 16 17:20:27 MDT 2023 +One-line Summary: Migration of FATES to share normal soil BGC call sequence and functionality + +Purpose and description of changes +---------------------------------- + +This set of changes enables the normal soil biogeochemistry that is used for CN, to be used for FATES as well. FATES had been using a simplified subset of soil biogeochemistry in its own module. This change required coordination of litter flux and methane boundary conditions from FATES to CLM. CNVEG datastructures were given trivial allocation (of size one on index zero) to prevent inappropriate use of CNVEG datastructures while FATES is active. Note that now the carbon balance checking for the soil is now active when FATES is active. Various accomodations have also been put in place to enable nitrogen cycling between the two models. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +Surprisingly, nvhpc tests are now working, but it may just be coincidental. All existing aux_clm tests are passing. Tests without FATES are b4b, with roundoff differences in just TOTCOLC and TOTCOLN. + +CTSM issues fixed (include CTSM Issue #): + We think #1879 -- "AD spinup issues for FATES", is fixed but haven't proved it + #2112 -- black check on SystemTest file + +Notes of particular relevance for users +--------------------------------------- +A CLM-FATES simulation will turn on nitrogen supplementation, this enables sufficient immobilization and decomposition. Until FATES and CLM can handle fully coupled nitrogen exchange, which would include root uptake of the mineralized aqueous forms (NH4 and NO3), N limitations in the soil are meaningless when FATES is on. + +Caveats for users (e.g., need to interpolate initial conditions): + FATES MUST have suplnitro='ALL' now (was NONE). When fates_parteh_mode>=1 other settings are allowed. + More checking for use_luna and suplnitro is added for FATES in the build-namelist + +Changes made to namelist defaults (e.g., changed parameter values): FATES runs now supplement N + suplnitro set to ALL for FATES + use_luna set to .false. for FATES and clm4_5 physics + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + We should update defaults for suplnitro, when Nitrogen nutrients are allowed in FATES + The black checdk github action has to duplicate actions for each source file or directory + We should move to using the Makefile in the python directory when we figure it out + +Testing summary: +---------------- + +aux_clm test run on cheyenne and izumi. See: + +izumi: OK /scratch/cluster/rgknox/tests_0814-095624iz +cheyenne: OK /glade/scratch/rgknox/tests_0814-134713ch + + +Answer changes +-------------- + +Changes answers relative to baseline: Two diganostic fields (TOTCOLC and TOTCOLN) + +Baseline changes will be reported for many tests, all tests were combed to identify RMS diffs, all non-FATES tests had at most, roundoff level (= secspyear) then - end_of_year(c) = .true. - cnveg_state_inst%annsum_counter_col(c) = 0._r8 - else - end_of_year(c) = .false. + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) + if(.not.col%is_fates(c))then + cnveg_state_inst%annsum_counter_col(c) = cnveg_state_inst%annsum_counter_col(c) + dt + if (cnveg_state_inst%annsum_counter_col(c) >= secspyear) then + end_of_year(c) = .true. + cnveg_state_inst%annsum_counter_col(c) = 0._r8 + else + end_of_year(c) = .false. + end if end if end do + - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) c = patch%column(p) - if (end_of_year(c)) then + if (end_of_year(c) .and. .not.col%is_fates(c)) then ! update annual plant ndemand accumulator cnveg_state_inst%annsum_potential_gpp_patch(p) = cnveg_state_inst%tempsum_potential_gpp_patch(p) @@ -94,20 +98,22 @@ subroutine CNAnnualUpdate(bounds, num_soilc, filter_soilc, num_soilp, filter_soi end do ! Get column-level averages, just for the columns that have reached their personal end-of-year - filter_endofyear_c = col_filter_from_filter_and_logical_array( & - bounds = bounds, & - num_orig = num_soilc, & - filter_orig = filter_soilc, & - logical_col = end_of_year(bounds%begc:bounds%endc)) - - call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & - cnveg_carbonflux_inst%annsum_npp_patch(bounds%begp:bounds%endp), & - cnveg_carbonflux_inst%annsum_npp_col(bounds%begc:bounds%endc)) - - call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & - cnveg_state_inst%annavg_t2m_patch(bounds%begp:bounds%endp), & - cnveg_state_inst%annavg_t2m_col(bounds%begc:bounds%endc)) - + if(num_bgc_vegp>0)then + filter_endofyear_c = col_filter_from_filter_and_logical_array( & + bounds = bounds, & + num_orig = num_bgc_soilc, & + filter_orig = filter_bgc_soilc, & + logical_col = end_of_year(bounds%begc:bounds%endc)) + + call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & + cnveg_carbonflux_inst%annsum_npp_patch(bounds%begp:bounds%endp), & + cnveg_carbonflux_inst%annsum_npp_col(bounds%begc:bounds%endc)) + + call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & + cnveg_state_inst%annavg_t2m_patch(bounds%begp:bounds%endp), & + cnveg_state_inst%annavg_t2m_col(bounds%begc:bounds%endc)) + end if + end subroutine CNAnnualUpdate end module CNAnnualUpdateMod diff --git a/src/biogeochem/CNBalanceCheckMod.F90 b/src/biogeochem/CNBalanceCheckMod.F90 index 014a55d7b1..35efd2e9aa 100644 --- a/src/biogeochem/CNBalanceCheckMod.F90 +++ b/src/biogeochem/CNBalanceCheckMod.F90 @@ -10,19 +10,23 @@ module CNBalanceCheckMod use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type, subgrid_level_gridcell, subgrid_level_column use abortutils , only : endrun - use clm_varctl , only : iulog, use_nitrif_denitrif + use clm_varctl , only : iulog, use_nitrif_denitrif, use_fates_bgc use clm_time_manager , only : get_step_size_real use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type use CNVegNitrogenStateType , only : cnveg_nitrogenstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use CNVegCarbonStateType , only : cnveg_carbonstate_type + use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type + use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use SoilBiogeochemNitrogenfluxType , only : soilbiogeochem_nitrogenflux_type use SoilBiogeochemCarbonfluxType , only : soilbiogeochem_carbonflux_type use CNProductsMod , only : cn_products_type use ColumnType , only : col use GridcellType , only : grc use CNSharedParamsMod , only : use_fun - + use CLMFatesInterfaceMod , only : hlm_fates_interface_type + use clm_varpar , only : nlevdecomp + ! implicit none private @@ -100,7 +104,7 @@ end subroutine InitAllocate !----------------------------------------------------------------------- subroutine BeginCNGridcellBalance(this, bounds, cnveg_carbonflux_inst, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst, & c_products_inst, n_products_inst) ! ! !DESCRIPTION: @@ -113,13 +117,13 @@ subroutine BeginCNGridcellBalance(this, bounds, cnveg_carbonflux_inst, & ! !USES: ! ! !ARGUMENTS: - class(cn_balance_type) , intent(inout) :: this - type(bounds_type) , intent(in) :: bounds - type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst - type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst - type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst - type(cn_products_type) , intent(in) :: c_products_inst - type(cn_products_type) , intent(in) :: n_products_inst + class(cn_balance_type) , intent(inout) :: this + type(bounds_type) , intent(in) :: bounds + type(soilbiogeochem_carbonstate_type), intent(in) :: soilbiogeochem_carbonstate_inst + type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst + type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst + type(cn_products_type) , intent(in) :: c_products_inst + type(cn_products_type) , intent(in) :: n_products_inst ! ! !LOCAL VARIABLES: integer :: g @@ -132,8 +136,8 @@ subroutine BeginCNGridcellBalance(this, bounds, cnveg_carbonflux_inst, & associate( & begcb => this%begcb_grc , & ! Output: [real(r8) (:)] (gC/m2) gridcell carbon mass, beginning of time step begnb => this%begnb_grc , & ! Output: [real(r8) (:)] (gN/m2) gridcell nitrogen mass, beginning of time step - totc => cnveg_carbonstate_inst%totc_grc , & ! Input: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool - totn => cnveg_nitrogenstate_inst%totn_grc, & ! Input: [real(r8) (:)] (gN/m2) total gridcell nitrogen, incl veg + totc => soilbiogeochem_carbonstate_inst%totc_grc , & ! Input: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool + totn => soilbiogeochem_nitrogenstate_inst%totn_grc, & ! Input: [real(r8) (:)] (gN/m2) total gridcell nitrogen, incl veg c_cropprod1 => c_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gC/m2) carbon in crop products n_cropprod1 => n_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gC/m2) nitrogen in crop products c_tot_woodprod => c_products_inst%tot_woodprod_grc , & ! Input: [real(r8) (:)] (gC/m2) total carbon in wood products @@ -141,13 +145,19 @@ subroutine BeginCNGridcellBalance(this, bounds, cnveg_carbonflux_inst, & ) begg = bounds%begg; endg = bounds%endg - - call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_beg( & + + if(.not.use_fates_bgc)then + call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_beg( & bounds, hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg)) - call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_beg( & - bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) - call cnveg_carbonflux_inst%gru_conv_cflux_dribbler%get_amount_left_to_dribble_beg( & - bounds, gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_beg( & + bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%gru_conv_cflux_dribbler%get_amount_left_to_dribble_beg( & + bounds, gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + else + hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg) = 0._r8 + dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) = 0._r8 + gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) = 0._r8 + end if do g = begg, endg begcb(g) = totc(g) + c_tot_woodprod(g) + c_cropprod1(g) + & @@ -163,7 +173,7 @@ end subroutine BeginCNGridcellBalance !----------------------------------------------------------------------- subroutine BeginCNColumnBalance(this, bounds, num_soilc, filter_soilc, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) + soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) ! ! !DESCRIPTION: ! Calculate beginning column-level carbon/nitrogen balance, for mass conservation check @@ -177,8 +187,8 @@ subroutine BeginCNColumnBalance(this, bounds, num_soilc, filter_soilc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_soilc ! number of soil columns filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns - type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst - type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst + type(soilbiogeochem_carbonstate_type), intent(in) :: soilbiogeochem_carbonstate_inst + type(soilbiogeochem_nitrogenstate_type), intent(in) :: soilbiogeochem_nitrogenstate_inst ! ! !LOCAL VARIABLES: integer :: fc,c @@ -187,14 +197,16 @@ subroutine BeginCNColumnBalance(this, bounds, num_soilc, filter_soilc, & associate( & col_begcb => this%begcb_col , & ! Output: [real(r8) (:)] (gC/m2) column carbon mass, beginning of time step col_begnb => this%begnb_col , & ! Output: [real(r8) (:)] (gN/m2) column nitrogen mass, beginning of time step - totcolc => cnveg_carbonstate_inst%totc_col , & ! Input: [real(r8) (:)] (gC/m2) total column carbon, incl veg and cpool - totcoln => cnveg_nitrogenstate_inst%totn_col & ! Input: [real(r8) (:)] (gN/m2) total column nitrogen, incl veg + totcolc => soilbiogeochem_carbonstate_inst%totc_col , & ! Input: [real(r8) (:)] (gC/m2) total column carbon, incl veg and cpool + totcoln => soilbiogeochem_nitrogenstate_inst%totn_col & ! Input: [real(r8) (:)] (gN/m2) total column nitrogen, incl veg ) do fc = 1,num_soilc c = filter_soilc(fc) + col_begcb(c) = totcolc(c) col_begnb(c) = totcoln(c) + end do end associate @@ -203,14 +215,20 @@ end subroutine BeginCNColumnBalance !----------------------------------------------------------------------- subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & - soilbiogeochem_carbonflux_inst, cnveg_carbonflux_inst, & - cnveg_carbonstate_inst, c_products_inst) + soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, c_products_inst, & + clm_fates) ! ! !USES: use subgridAveMod, only: c2g + ! ! !DESCRIPTION: ! Perform carbon mass conservation check for column and patch + ! + ! Note on FATES: On fates colums, there is no vegetation biomass + ! and no gpp flux. There is a litter input flux. + ! ! !ARGUMENTS: class(cn_balance_type) , intent(inout) :: this @@ -218,13 +236,18 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns type(soilbiogeochem_carbonflux_type) , intent(in) :: soilbiogeochem_carbonflux_inst + type(soilbiogeochem_carbonstate_type), intent(inout) :: soilbiogeochem_carbonstate_inst type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cn_products_type) , intent(in) :: c_products_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + ! ! !LOCAL VARIABLES: - integer :: c, g, err_index ! indices + integer :: c, g, err_index ! indices + integer :: s ! fates site index (follows c) integer :: fc ! lake filter indices + integer :: ic ! index of the current clump logical :: err_found ! error flag real(r8) :: dt ! radiation time step (seconds) real(r8) :: col_cinputs, grc_cinputs @@ -235,12 +258,14 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & real(r8) :: hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg) real(r8) :: gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) real(r8) :: dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) + real(r8) :: fates_woodproduct_flux ! Total carbon wood products flux from FATES to CLM [gC/m2/s] + !----------------------------------------------------------------------- associate( & grc_begcb => this%begcb_grc , & ! Input: [real(r8) (:) ] (gC/m2) gridcell-level carbon mass, beginning of time step grc_endcb => this%endcb_grc , & ! Output: [real(r8) (:) ] (gC/m2) gridcell-level carbon mass, end of time step - totgrcc => cnveg_carbonstate_inst%totc_grc , & ! Input: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool + totgrcc => soilbiogeochem_carbonstate_inst%totc_grc , & ! Output: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool nbp_grc => cnveg_carbonflux_inst%nbp_grc , & ! Input: [real(r8) (:) ] (gC/m2/s) net biome production (positive for sink) cropprod1_grc => c_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gC/m2) carbon in crop products tot_woodprod_grc => c_products_inst%tot_woodprod_grc , & ! Input: [real(r8) (:)] (gC/m2) total carbon in wood products @@ -256,39 +281,67 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & er => cnveg_carbonflux_inst%er_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total ecosystem respiration, autotrophic + heterotrophic col_fire_closs => cnveg_carbonflux_inst%fire_closs_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total column-level fire C loss col_hrv_xsmrpool_to_atm => cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_col , & ! Input: [real(r8) (:) ] (gC/m2/s) excess MR pool harvest mortality - col_xsmrpool_to_atm => cnveg_carbonflux_inst%xsmrpool_to_atm_col , & ! Input: [real(r8) (:) ] (gC/m2/s) excess MR pool crop harvest loss to atm + col_xsmrpool_to_atm => cnveg_carbonflux_inst%xsmrpool_to_atm_col , & ! Input: [real(r8) (:) ] (gC/m2/s) excess MR pool crop harvest loss to atm som_c_leached => soilbiogeochem_carbonflux_inst%som_c_leached_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total SOM C loss from vertical transport - totcolc => cnveg_carbonstate_inst%totc_col & ! Input: [real(r8) (:) ] (gC/m2) total column carbon, incl veg and cpool + totcolc => soilbiogeochem_carbonstate_inst%totc_col , & ! Input: [real(r8) (:) ] (gC/m2) total column carbon, incl veg and cpool + fates_litter_flux => soilbiogeochem_carbonflux_inst%fates_litter_flux & ! Total carbon litter flux from FATES to CLM [gC/m2/s] ) ! set time steps dt = get_step_size_real() + ! clump index + ic = bounds%clump_index + err_found = .false. do fc = 1,num_soilc c = filter_soilc(fc) ! calculate the total column-level carbon storage, for mass conservation check + ! for bigleaf, totcolc includes soil and all of the veg c pools including cpool, xfer, etc + ! for fates, totcolc only includes soil and non-fates litter carbon, + ! see soibiogeochem_carbonstate_inst%summary for calculations col_endcb(c) = totcolc(c) + + + if( col%is_fates(c) ) then + + s = clm_fates%f2hmap(ic)%hsites(c) + + + fates_woodproduct_flux = clm_fates%fates(ic)%bc_out(s)%hrv_deadstemc_to_prod10c + & + clm_fates%fates(ic)%bc_out(s)%hrv_deadstemc_to_prod100c + + col_cinputs = fates_litter_flux(c) + fates_woodproduct_flux + + ! calculate total column-level outputs + ! fates has already exported burn losses and fluxes to the atm + ! So they are irrelevant here + ! (gC/m2/s) total heterotrophic respiration + col_coutputs = soilbiogeochem_carbonflux_inst%hr_col(c) - ! calculate total column-level inputs - col_cinputs = gpp(c) - - ! calculate total column-level outputs - ! er = ar + hr, col_fire_closs includes patch-level fire losses - col_coutputs = er(c) + col_fire_closs(c) + col_hrv_xsmrpool_to_atm(c) + & - col_xsmrpool_to_atm(c) + gru_conv_cflux(c) - - ! Fluxes to product pools are included in column-level outputs: the product - ! pools are not included in totcolc, so are outside the system with respect to - ! these balance checks. (However, the dwt flux to product pools is NOT included, - ! since col_begcb is initialized after the dynamic area adjustments - i.e., - ! after the dwt term has already been taken out.) - col_coutputs = col_coutputs + & - wood_harvestc(c) + & - gru_wood_productc_gain(c) + & - crop_harvestc_to_cropprodc(c) + else + + ! calculate total column-level inputs + col_cinputs = gpp(c) + + ! calculate total column-level outputs + ! er = ar + hr, col_fire_closs includes patch-level fire losses + col_coutputs = er(c) + col_fire_closs(c) + col_hrv_xsmrpool_to_atm(c) + & + col_xsmrpool_to_atm(c) + gru_conv_cflux(c) + + ! Fluxes to product pools are included in column-level outputs: the product + ! pools are not included in totcolc, so are outside the system with respect to + ! these balance checks. (However, the dwt flux to product pools is NOT included, + ! since col_begcb is initialized after the dynamic area adjustments - i.e., + ! after the dwt term has already been taken out.) + col_coutputs = col_coutputs + & + wood_harvestc(c) + & + gru_wood_productc_gain(c) + & + crop_harvestc_to_cropprodc(c) + + end if ! subtract leaching flux col_coutputs = col_coutputs - som_c_leached(c) @@ -311,19 +364,29 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & if (err_found) then c = err_index write(iulog,*)'column cbalance error = ', col_errcb(c), c + write(iulog,*)'is fates column? = ', col%is_fates(c) write(iulog,*)'Latdeg,Londeg=',grc%latdeg(col%gridcell(c)),grc%londeg(col%gridcell(c)) write(iulog,*)'begcb = ',col_begcb(c) write(iulog,*)'endcb = ',col_endcb(c) write(iulog,*)'delta store = ',col_endcb(c)-col_begcb(c) write(iulog,*)'--- Inputs ---' - write(iulog,*)'gpp = ',gpp(c)*dt + if( col%is_fates(c) ) then + write(iulog,*)'fates litter_flux = ',fates_litter_flux(c)*dt + write(iulog,*)'fates wood product flux = ',fates_woodproduct_flux*dt + else + write(iulog,*)'gpp = ',gpp(c)*dt + end if write(iulog,*)'--- Outputs ---' - write(iulog,*)'er = ',er(c)*dt - write(iulog,*)'col_fire_closs = ',col_fire_closs(c)*dt - write(iulog,*)'col_hrv_xsmrpool_to_atm = ',col_hrv_xsmrpool_to_atm(c)*dt - write(iulog,*)'col_xsmrpool_to_atm = ',col_xsmrpool_to_atm(c)*dt - write(iulog,*)'wood_harvestc = ',wood_harvestc(c)*dt - write(iulog,*)'crop_harvestc_to_cropprodc = ', crop_harvestc_to_cropprodc(c)*dt + if( .not.col%is_fates(c) ) then + write(iulog,*)'er = ',er(c)*dt + write(iulog,*)'col_fire_closs = ',col_fire_closs(c)*dt + write(iulog,*)'col_hrv_xsmrpool_to_atm = ',col_hrv_xsmrpool_to_atm(c)*dt + write(iulog,*)'col_xsmrpool_to_atm = ',col_xsmrpool_to_atm(c)*dt + write(iulog,*)'wood_harvestc = ',wood_harvestc(c)*dt + write(iulog,*)'crop_harvestc_to_cropprodc = ', crop_harvestc_to_cropprodc(c)*dt + else + write(iulog,*)'hr = ',soilbiogeochem_carbonflux_inst%hr_col(c)*dt + end if write(iulog,*)'-1*som_c_leached = ',som_c_leached(c)*dt call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, msg=errMsg(sourcefile, __LINE__)) end if @@ -352,31 +415,45 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! We account for the latter fluxes as inputs below; the same ! fluxes have entered the pools earlier in the timestep. For true ! conservation we would need to add a flux out of npp into seed. - call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_end( & - bounds, hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg)) - call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_end( & - bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) - call cnveg_carbonflux_inst%gru_conv_cflux_dribbler%get_amount_left_to_dribble_end( & - bounds, gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) - grc_endcb(g) = totgrcc(g) + tot_woodprod_grc(g) + cropprod1_grc(g) + & - hrv_xsmrpool_amount_left_to_dribble(g) + & - gru_conv_cflux_amount_left_to_dribble(g) + & - dwt_conv_cflux_amount_left_to_dribble(g) - - ! calculate total gridcell-level inputs - ! slevis notes: - ! nbp_grc = nep_grc - fire_closs_grc - hrv_xsmrpool_to_atm_dribbled_grc - dwt_conv_cflux_dribbled_grc - gru_conv_cflux_dribbled_grc - product_closs_grc - grc_cinputs = nbp_grc(g) + & - dwt_seedc_to_leaf_grc(g) + dwt_seedc_to_deadstem_grc(g) - - ! calculate total gridcell-level outputs - grc_coutputs = - som_c_leached_grc(g) - - ! calculate the total gridcell-level carbon balance error - ! for this time step - grc_errcb(g) = (grc_cinputs - grc_coutputs) * dt - & - (grc_endcb(g) - grc_begcb(g)) + if(.not.use_fates_bgc)then + call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_end( & + bounds, hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_end( & + bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%gru_conv_cflux_dribbler%get_amount_left_to_dribble_end( & + bounds, gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + + grc_endcb(g) = totgrcc(g) + tot_woodprod_grc(g) + cropprod1_grc(g) + & + hrv_xsmrpool_amount_left_to_dribble(g) + & + gru_conv_cflux_amount_left_to_dribble(g) + & + dwt_conv_cflux_amount_left_to_dribble(g) + + ! calculate total gridcell-level inputs + ! slevis notes: + ! nbp_grc = nep_grc - fire_closs_grc - hrv_xsmrpool_to_atm_dribbled_grc - & + ! dwt_conv_cflux_dribbled_grc - gru_conv_cflux_dribbled_grc - product_closs_grc + grc_cinputs = nbp_grc(g) + & + dwt_seedc_to_leaf_grc(g) + dwt_seedc_to_deadstem_grc(g) + + ! calculate total gridcell-level outputs + grc_coutputs = - som_c_leached_grc(g) + + ! calculate the total gridcell-level carbon balance error + ! for this time step + grc_errcb(g) = (grc_cinputs - grc_coutputs) * dt - & + (grc_endcb(g) - grc_begcb(g)) + + else + + ! Totally punt on this for now. We just don't track these gridscale variables yet (RGK) + grc_cinputs = 0._r8 + grc_endcb(g) = grc_begcb(g) + grc_coutputs = 0._r8 + grc_errcb(g) = 0._r8 + + end if + ! check for significant errors if (abs(grc_errcb(g)) > this%cerror) then err_found = .true. @@ -409,8 +486,9 @@ end subroutine CBalanceCheck !----------------------------------------------------------------------- subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & - soilbiogeochem_nitrogenflux_inst, cnveg_nitrogenflux_inst, & - cnveg_nitrogenstate_inst, n_products_inst, atm2lnd_inst) + soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & + cnveg_nitrogenflux_inst, & + cnveg_nitrogenstate_inst, n_products_inst, atm2lnd_inst, clm_fates) ! ! !DESCRIPTION: ! Perform nitrogen mass conservation check @@ -426,17 +504,21 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc (:) ! filter for soil columns type(soilbiogeochem_nitrogenflux_type) , intent(in) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst type(cnveg_nitrogenflux_type) , intent(in) :: cnveg_nitrogenflux_inst type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst type(cn_products_type) , intent(in) :: n_products_inst type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + ! ! !LOCAL VARIABLES: - integer :: c,err_index,j ! indices - integer :: g ! gridcell index - integer :: fc ! lake filter indices - logical :: err_found ! error flag - real(r8):: dt ! radiation time step (seconds) + integer :: c,err_index,j,s ! indices + integer :: ic ! index of clump + integer :: g ! gridcell index + integer :: fc ! lake filter indices + logical :: err_found ! error flag + real(r8):: dt ! radiation time step (seconds) real(r8):: col_ninputs(bounds%begc:bounds%endc) real(r8):: col_noutputs(bounds%begc:bounds%endc) real(r8):: col_errnb(bounds%begc:bounds%endc) @@ -452,7 +534,7 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & associate( & grc_begnb => this%begnb_grc , & ! Input: [real(r8) (:) ] (gN/m2) gridcell nitrogen mass, beginning of time step grc_endnb => this%endnb_grc , & ! Output: [real(r8) (:) ] (gN/m2) gridcell nitrogen mass, end of time step - totgrcn => cnveg_nitrogenstate_inst%totn_grc , & ! Input: [real(r8) (:) ] (gN/m2) total gridcell nitrogen, incl veg + totgrcn => soilbiogeochem_nitrogenstate_inst%totn_grc , & ! Input: [real(r8) (:) ] (gN/m2) total gridcell nitrogen, incl veg cropprod1_grc => n_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gN/m2) nitrogen in crop products product_loss_grc => n_products_inst%product_loss_grc , & ! Input: [real(r8) (:)] (gN/m2) losses from wood & crop products tot_woodprod_grc => n_products_inst%tot_woodprod_grc , & ! Input: [real(r8) (:)] (gN/m2) total nitrogen in wood products @@ -482,9 +564,12 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & gru_wood_productn_gain_grc => cnveg_nitrogenflux_inst%gru_wood_productn_gain_grc, & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) summed to the gridcell level crop_harvestn_to_cropprodn => cnveg_nitrogenflux_inst%crop_harvestn_to_cropprodn_col , & ! Input: [real(r8) (:) ] (gN/m2/s) crop harvest N to 1-year crop product pool - totcoln => cnveg_nitrogenstate_inst%totn_col & ! Input: [real(r8) (:) ] (gN/m2) total column nitrogen, incl veg + totcoln => soilbiogeochem_nitrogenstate_inst%totn_col , & ! Input: [real(r8) (:) ] (gN/m2) total column nitrogen, incl veg + sminn_to_plant => soilbiogeochem_nitrogenflux_inst%sminn_to_plant_col, & + fates_litter_flux => soilbiogeochem_nitrogenflux_inst%fates_litter_flux & ! Total nitrogen litter flux from FATES to CLM [gN/m2/s] ) + ! set time steps dt = get_step_size_real() @@ -492,6 +577,9 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & col_ninputs_partial(:) = 0._r8 col_noutputs_partial(:) = 0._r8 + ! clump index + ic = bounds%clump_index + err_found = .false. do fc = 1,num_soilc c=filter_soilc(fc) @@ -501,6 +589,11 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! calculate total column-level inputs col_ninputs(c) = ndep_to_sminn(c) + nfix_to_sminn(c) + supplement_to_sminn(c) + + ! If using fates, pass in the decomposition flux + if( col%is_fates(c) ) then + col_ninputs(c) = col_ninputs(c) + fates_litter_flux(c) + end if if(use_fun)then col_ninputs(c) = col_ninputs(c) + ffix_to_sminn(c) ! for FUN, free living fixation is a seprate flux. RF. @@ -511,19 +604,30 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & end if col_ninputs_partial(c) = col_ninputs(c) - + ! calculate total column-level outputs - col_noutputs(c) = denit(c) + col_fire_nloss(c) + gru_conv_nflux(c) - - ! Fluxes to product pools are included in column-level outputs: the product - ! pools are not included in totcoln, so are outside the system with respect to - ! these balance checks. (However, the dwt flux to product pools is NOT included, - ! since col_begnb is initialized after the dynamic area adjustments - i.e., - ! after the dwt term has already been taken out.) - col_noutputs(c) = col_noutputs(c) + & - wood_harvestn(c) + & - gru_wood_productn_gain(c) + & - crop_harvestn_to_cropprodn(c) + + col_noutputs(c) = denit(c) + + if( .not.col%is_fates(c) ) then + + col_noutputs(c) = col_noutputs(c) + col_fire_nloss(c) + gru_conv_nflux(c) + + ! Fluxes to product pools are included in column-level outputs: the product + ! pools are not included in totcoln, so are outside the system with respect to + ! these balance checks. (However, the dwt flux to product pools is NOT included, + ! since col_begnb is initialized after the dynamic area adjustments - i.e., + ! after the dwt term has already been taken out.) + col_noutputs(c) = col_noutputs(c) + & + wood_harvestn(c) + & + gru_wood_productn_gain(c) + & + crop_harvestn_to_cropprodn(c) + else + + ! If we are using fates, remove plant uptake + col_noutputs(c) = col_noutputs(c) + sminn_to_plant(c) + + end if if (.not. use_nitrif_denitrif) then col_noutputs(c) = col_noutputs(c) + sminn_leached(c) @@ -534,11 +638,15 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & end if col_noutputs(c) = col_noutputs(c) - som_n_leached(c) + + col_noutputs_partial(c) = col_noutputs(c) - col_noutputs_partial(c) = col_noutputs(c) - & - wood_harvestn(c) - & - crop_harvestn_to_cropprodn(c) - + if( .not.col%is_fates(c) ) then + col_noutputs_partial(c) = col_noutputs_partial(c) - & + wood_harvestn(c) - & + crop_harvestn_to_cropprodn(c) + end if + ! calculate the total column-level nitrogen balance error for this time step col_errnb(c) = (col_ninputs(c) - col_noutputs(c))*dt - & (col_endnb(c) - col_begnb(c)) @@ -566,92 +674,103 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & write(iulog,*)'input mass = ',col_ninputs(c)*dt write(iulog,*)'output mass = ',col_noutputs(c)*dt write(iulog,*)'net flux = ',(col_ninputs(c)-col_noutputs(c))*dt - write(iulog,*)'inputs,ffix,nfix,ndep = ',ffix_to_sminn(c)*dt,nfix_to_sminn(c)*dt,ndep_to_sminn(c)*dt - write(iulog,*)'outputs,lch,roff,dnit = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt + if(col%is_fates(c))then + write(iulog,*)'inputs,ndep,nfix,suppn= ',ndep_to_sminn(c)*dt,nfix_to_sminn(c)*dt,supplement_to_sminn(c)*dt + else + write(iulog,*)'inputs,ffix,nfix,ndep = ',ffix_to_sminn(c)*dt,nfix_to_sminn(c)*dt,ndep_to_sminn(c)*dt + end if + if(col%is_fates(c))then + write(iulog,*)'outputs,lch,roff,dnit,plnt = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt,sminn_to_plant(c)*dt + else + write(iulog,*)'outputs,lch,roff,dnit = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt + end if call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, msg=errMsg(sourcefile, __LINE__)) end if - ! Repeat error check at the gridcell level - call c2g( bounds = bounds, & - carr = totcoln(bounds%begc:bounds%endc), & - garr = totgrcn(bounds%begg:bounds%endg), & - c2l_scale_type = 'unity', & - l2g_scale_type = 'unity') - call c2g( bounds = bounds, & - carr = col_ninputs_partial(bounds%begc:bounds%endc), & - garr = grc_ninputs_partial(bounds%begg:bounds%endg), & - c2l_scale_type = 'unity', & - l2g_scale_type = 'unity') - call c2g( bounds = bounds, & - carr = col_noutputs_partial(bounds%begc:bounds%endc), & - garr = grc_noutputs_partial(bounds%begg:bounds%endg), & - c2l_scale_type = 'unity', & - l2g_scale_type = 'unity') - - err_found = .false. - do g = bounds%begg, bounds%endg - ! calculate the total gridcell-level nitrogen storage, for mass conservation check - ! Notes: - ! Not including seedn_grc in grc_begnb and grc_endnb because - ! seedn_grc forms out of thin air, for now, and equals - ! -1 * (dwt_seedn_to_leaf_grc(g) + dwt_seedn_to_deadstem_grc(g)) - ! We account for the latter fluxes as inputs below; the same - ! fluxes have entered the pools earlier in the timestep. For true - ! conservation we would need to add a flux out of nfix into seed. - grc_endnb(g) = totgrcn(g) + tot_woodprod_grc(g) + cropprod1_grc(g) - - ! calculate total gridcell-level inputs - grc_ninputs(g) = grc_ninputs_partial(g) + & - dwt_seedn_to_leaf_grc(g) + & - dwt_seedn_to_deadstem_grc(g) - - ! calculate total gridcell-level outputs - grc_noutputs(g) = grc_noutputs_partial(g) + & - dwt_conv_nflux_grc(g) + & - product_loss_grc(g) - & - ! Subtract the next one because it is present in - ! grc_noutputs_partial but not needed at the - ! gridcell level - gru_wood_productn_gain_grc(g) - - ! calculate the total gridcell-level nitrogen balance error for this time step - grc_errnb(g) = (grc_ninputs(g) - grc_noutputs(g)) * dt - & - (grc_endnb(g) - grc_begnb(g)) - - if (abs(grc_errnb(g)) > this%nerror) then - err_found = .true. - err_index = g - end if - - if (abs(grc_errnb(g)) > this%nwarning) then - write(iulog,*) 'nbalance warning at g =', g, grc_errnb(g), grc_endnb(g) + if_notfates: if(.not.use_fates_bgc)then + + ! Repeat error check at the gridcell level + call c2g( bounds = bounds, & + carr = totcoln(bounds%begc:bounds%endc), & + garr = totgrcn(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + call c2g( bounds = bounds, & + carr = col_ninputs_partial(bounds%begc:bounds%endc), & + garr = grc_ninputs_partial(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + call c2g( bounds = bounds, & + carr = col_noutputs_partial(bounds%begc:bounds%endc), & + garr = grc_noutputs_partial(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + + err_found = .false. + do g = bounds%begg, bounds%endg + ! calculate the total gridcell-level nitrogen storage, for mass conservation check + ! Notes: + ! Not including seedn_grc in grc_begnb and grc_endnb because + ! seedn_grc forms out of thin air, for now, and equals + ! -1 * (dwt_seedn_to_leaf_grc(g) + dwt_seedn_to_deadstem_grc(g)) + ! We account for the latter fluxes as inputs below; the same + ! fluxes have entered the pools earlier in the timestep. For true + ! conservation we would need to add a flux out of nfix into seed. + grc_endnb(g) = totgrcn(g) + tot_woodprod_grc(g) + cropprod1_grc(g) + + ! calculate total gridcell-level inputs + grc_ninputs(g) = grc_ninputs_partial(g) + & + dwt_seedn_to_leaf_grc(g) + & + dwt_seedn_to_deadstem_grc(g) + + ! calculate total gridcell-level outputs + grc_noutputs(g) = grc_noutputs_partial(g) + & + dwt_conv_nflux_grc(g) + & + product_loss_grc(g) - & + ! Subtract the next one because it is present in + ! grc_noutputs_partial but not needed at the + ! gridcell level + gru_wood_productn_gain_grc(g) + + ! calculate the total gridcell-level nitrogen balance error for this time step + grc_errnb(g) = (grc_ninputs(g) - grc_noutputs(g)) * dt - & + (grc_endnb(g) - grc_begnb(g)) + + if (abs(grc_errnb(g)) > this%nerror) then + err_found = .true. + err_index = g + end if + + if (abs(grc_errnb(g)) > this%nwarning) then + write(iulog,*) 'nbalance warning at g =', g, grc_errnb(g), grc_endnb(g) + end if + end do + if (err_found) then + g = err_index + write(iulog,*) 'gridcell nbalance error =', grc_errnb(g), g + write(iulog,*) 'latdeg, londeg =', grc%latdeg(g), grc%londeg(g) + write(iulog,*) 'begnb =', grc_begnb(g) + write(iulog,*) 'endnb =', grc_endnb(g) + write(iulog,*) 'delta store =', grc_endnb(g) - grc_begnb(g) + write(iulog,*) 'input mass =', grc_ninputs(g) * dt + write(iulog,*) 'output mass =', grc_noutputs(g) * dt + write(iulog,*) 'net flux =', (grc_ninputs(g) - grc_noutputs(g)) * dt + write(iulog,*) '--- Inputs ---' + write(iulog,*) 'grc_ninputs_partial =', grc_ninputs_partial(g) * dt + write(iulog,*) 'dwt_seedn_to_leaf_grc =', dwt_seedn_to_leaf_grc(g) * dt + write(iulog,*) 'dwt_seedn_to_deadstem_grc =', dwt_seedn_to_deadstem_grc(g) * dt + write(iulog,*) '--- Outputs ---' + write(iulog,*) 'grc_noutputs_partial =', grc_noutputs_partial(g) * dt + write(iulog,*) 'dwt_conv_nflux_grc =', dwt_conv_nflux_grc(g) * dt + write(iulog,*) '-gru_wood_productn_gain_grc =', -gru_wood_productn_gain_grc(g) * dt + write(iulog,*) 'product_loss_grc =', product_loss_grc(g) * dt + call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) end if - end do - - if (err_found) then - g = err_index - write(iulog,*) 'gridcell nbalance error =', grc_errnb(g), g - write(iulog,*) 'latdeg, londeg =', grc%latdeg(g), grc%londeg(g) - write(iulog,*) 'begnb =', grc_begnb(g) - write(iulog,*) 'endnb =', grc_endnb(g) - write(iulog,*) 'delta store =', grc_endnb(g) - grc_begnb(g) - write(iulog,*) 'input mass =', grc_ninputs(g) * dt - write(iulog,*) 'output mass =', grc_noutputs(g) * dt - write(iulog,*) 'net flux =', (grc_ninputs(g) - grc_noutputs(g)) * dt - write(iulog,*) '--- Inputs ---' - write(iulog,*) 'grc_ninputs_partial =', grc_ninputs_partial(g) * dt - write(iulog,*) 'dwt_seedn_to_leaf_grc =', dwt_seedn_to_leaf_grc(g) * dt - write(iulog,*) 'dwt_seedn_to_deadstem_grc =', dwt_seedn_to_deadstem_grc(g) * dt - write(iulog,*) '--- Outputs ---' - write(iulog,*) 'grc_noutputs_partial =', grc_noutputs_partial(g) * dt - write(iulog,*) 'dwt_conv_nflux_grc =', dwt_conv_nflux_grc(g) * dt - write(iulog,*) '-gru_wood_productn_gain_grc =', -gru_wood_productn_gain_grc(g) * dt - write(iulog,*) 'product_loss_grc =', product_loss_grc(g) * dt - call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) - end if + + end if if_notfates end associate - + end subroutine NBalanceCheck end module CNBalanceCheckMod diff --git a/src/biogeochem/CNCIsoFluxMod.F90 b/src/biogeochem/CNCIsoFluxMod.F90 index a4706442fa..c10659a945 100644 --- a/src/biogeochem/CNCIsoFluxMod.F90 +++ b/src/biogeochem/CNCIsoFluxMod.F90 @@ -8,7 +8,7 @@ module CNCIsoFluxMod use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : ndecomp_cascade_transitions, nlevdecomp, ndecomp_pools - use clm_varpar , only : max_patch_per_col, maxsoil_patches + use clm_varpar , only : maxsoil_patches use clm_varpar , only : i_litr_min, i_litr_max, i_met_lit use abortutils , only : endrun use pftconMod , only : pftcon @@ -535,7 +535,7 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! For later clean-up, it would be possible to generalize this function to operate on a single ! patch-to-column flux. - call CNCIsoLitterToColumn(num_soilc, filter_soilc, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) + call CNCIsoLitterToColumn(num_soilp, filter_soilp, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) ! column-level non-mortality fluxes @@ -713,7 +713,7 @@ subroutine CIsoFlux2(num_soilc, filter_soilc, num_soilp , filter_soilp, & ! call routine to shift patch-level gap mortality fluxes to column , for isotopes ! the non-isotope version of this routine is in CNGapMortalityMod.F90. - call CNCIsoGapPftToColumn(num_soilc, filter_soilc, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) + call CNCIsoGapPftToColumn(num_soilp, filter_soilp, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) end associate @@ -1041,7 +1041,7 @@ subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & character(len=*) , intent(in) :: isotope ! 'c13' or 'c14' ! ! !LOCAL VARIABLES: - integer :: pi,pp,l,fc,cc,j,i + integer :: pi,pp,l,fp,cc,j,i,fc !----------------------------------------------------------------------- associate( & @@ -1276,26 +1276,21 @@ subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & ! calculate the column-level flux of deadstem and deadcrootc to cwdc as the result of fire mortality. - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - cc = filter_soilc(fc) - if ( pi <= col%npatches(cc) ) then - pp = col%patchi(cc) + pi - 1 - if (patch%active(pp)) then - do j = 1, nlevdecomp - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & - (iso_cnveg_cf%m_deadstemc_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livestemc_to_litter_fire_patch(pp)) * & - patch%wtcol(pp) * stem_prof(pp,j) - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & - (iso_cnveg_cf%m_deadcrootc_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livecrootc_to_litter_fire_patch(pp)) * & - patch%wtcol(pp) * croot_prof(pp,j) - end do - end if - end if + + do fp = 1,num_soilp + pp = filter_soilp(fp) + cc = patch%column(pp) + do j = 1, nlevdecomp + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & + (iso_cnveg_cf%m_deadstemc_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livestemc_to_litter_fire_patch(pp)) * & + patch%wtcol(pp) * stem_prof(pp,j) + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & + (iso_cnveg_cf%m_deadcrootc_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livecrootc_to_litter_fire_patch(pp)) * & + patch%wtcol(pp) * croot_prof(pp,j) end do end do @@ -1316,54 +1311,47 @@ subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & end do end do - - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - cc = filter_soilc(fc) - if ( pi <= col%npatches(cc) ) then - pp = col%patchi(cc) + pi - 1 - if (patch%active(pp)) then - do j = 1, nlevdecomp - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) = & - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) + & - ((iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i_met_lit) & - +iso_cnveg_cf%m_leafc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_leafc_xfer_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_gresp_storage_to_litter_fire_patch(pp) & - +iso_cnveg_cf%m_gresp_xfer_to_litter_fire_patch(pp))*leaf_prof(pp,j) + & - (iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i_met_lit) & - +iso_cnveg_cf%m_frootc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_frootc_xfer_to_litter_fire_patch(pp))*froot_prof(pp,j) & - +(iso_cnveg_cf%m_livestemc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livestemc_xfer_to_litter_fire_patch(pp) & - +iso_cnveg_cf%m_deadstemc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_deadstemc_xfer_to_litter_fire_patch(pp))* stem_prof(pp,j)& - +(iso_cnveg_cf%m_livecrootc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livecrootc_xfer_to_litter_fire_patch(pp) & - +iso_cnveg_cf%m_deadcrootc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_deadcrootc_xfer_to_litter_fire_patch(pp))* croot_prof(pp,j)) * patch%wtcol(pp) - - ! Here metabolic litter is treated differently than other - ! types of litter, so it remains outside this litter loop, - ! in the line above - do i = i_met_lit+1, i_litr_max - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) = & - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) + & - (iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i) * leaf_prof(pp,j) + & - iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i) * froot_prof(pp,j)) * patch%wtcol(pp) - end do - end do - end if - end if + do fp = 1,num_soilp + pp = filter_soilp(fp) + cc = patch%column(pp) + do j = 1, nlevdecomp + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) = & + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) + & + ((iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i_met_lit) & + +iso_cnveg_cf%m_leafc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_leafc_xfer_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_gresp_storage_to_litter_fire_patch(pp) & + +iso_cnveg_cf%m_gresp_xfer_to_litter_fire_patch(pp))*leaf_prof(pp,j) + & + (iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i_met_lit) & + +iso_cnveg_cf%m_frootc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_frootc_xfer_to_litter_fire_patch(pp))*froot_prof(pp,j) & + +(iso_cnveg_cf%m_livestemc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livestemc_xfer_to_litter_fire_patch(pp) & + +iso_cnveg_cf%m_deadstemc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_deadstemc_xfer_to_litter_fire_patch(pp))* stem_prof(pp,j)& + +(iso_cnveg_cf%m_livecrootc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livecrootc_xfer_to_litter_fire_patch(pp) & + +iso_cnveg_cf%m_deadcrootc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_deadcrootc_xfer_to_litter_fire_patch(pp))* croot_prof(pp,j)) * patch%wtcol(pp) + + ! Here metabolic litter is treated differently than other + ! types of litter, so it remains outside this litter loop, + ! in the line above + do i = i_met_lit+1, i_litr_max + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) = & + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) + & + (iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i) * leaf_prof(pp,j) + & + iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i) * froot_prof(pp,j)) * patch%wtcol(pp) + end do end do - end do + end do end associate end subroutine CIsoFlux3 !----------------------------------------------------------------------- - subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & + subroutine CNCIsoLitterToColumn (num_soilp, filter_soilp, & soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) ! ! !DESCRIPTION: @@ -1377,13 +1365,13 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & !DML ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! filter for soil patches type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonflux_type) , intent(inout) :: iso_cnveg_carbonflux_inst ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,k,j,i + integer :: c,pi,p,k,j,i,fp !----------------------------------------------------------------------- associate( & @@ -1405,59 +1393,52 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & ) do j = 1, nlevdecomp - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - c = filter_soilc(fc) - - if ( pi <= col%npatches(c) ) then - p = col%patchi(c) + pi - 1 - if (patch%active(p)) then - do i = i_litr_min, i_litr_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - ! leaf litter carbon fluxes - leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & - ! fine root litter carbon fluxes - frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + ! leaf litter carbon fluxes + leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root litter carbon fluxes + frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do + !DML - if (ivt(p) >= npcropmin) then ! add livestemc to litter - ! stem litter carbon fluxes - do i = i_litr_min, i_litr_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - - if (.not. use_grainproduct) then - ! grain litter carbon fluxes - do i = i_litr_min, i_litr_max - do k = repr_grain_min, repr_grain_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - end if - - ! reproductive structure litter carbon fluxes - do i = i_litr_min, i_litr_max - do k = repr_structure_min, repr_structure_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - - end if -!DML - end if + if (ivt(p) >= npcropmin) then ! add livestemc to litter + ! stem litter carbon fluxes + do i = i_litr_min, i_litr_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + + if (.not. use_grainproduct) then + ! grain litter carbon fluxes + do i = i_litr_min, i_litr_max + do k = repr_grain_min, repr_grain_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + end do end if - - end do + + ! reproductive structure litter carbon fluxes + do i = i_litr_min, i_litr_max + do k = repr_structure_min, repr_structure_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + end do + + end if + !DML end do - end do end associate @@ -1465,7 +1446,7 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & end subroutine CNCIsoLitterToColumn !----------------------------------------------------------------------- - subroutine CNCIsoGapPftToColumn (num_soilc, filter_soilc, & + subroutine CNCIsoGapPftToColumn (num_soilp, filter_soilp, & soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) ! ! !DESCRIPTION: @@ -1473,13 +1454,13 @@ subroutine CNCIsoGapPftToColumn (num_soilc, filter_soilc, & ! to the column level and assign them to the three litter pools (+ cwd pool) ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! soil column filter + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! soil patch filter type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonflux_type) , intent(inout) :: iso_cnveg_carbonflux_inst ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,j,i ! indices + integer :: fp,c,pi,p,j,i ! indices !----------------------------------------------------------------------- associate( & @@ -1520,66 +1501,58 @@ subroutine CNCIsoGapPftToColumn (num_soilc, filter_soilc, & ) do j = 1, nlevdecomp - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - - if (patch%active(p)) then - - do i = i_litr_min, i_litr_max - ! leaf gap mortality carbon fluxes - gap_mortality_c_to_litr_c(c,j,i) = & - gap_mortality_c_to_litr_c(c,j,i) + & - m_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - ! fine root gap mortality carbon fluxes - gap_mortality_c_to_litr_c(c,j,i) = & - gap_mortality_c_to_litr_c(c,j,i) + & - m_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do - - ! wood gap mortality carbon fluxes - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_deadstemc_to_litter(p) * wtcol(p) * stem_prof(p,j) - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - - ! Metabolic litter is treated differently than other types - ! of litter, so it gets this additional line after the - ! most recent loop over all litter types - gap_mortality_c_to_litr_c(c,j,i_met_lit) = & - gap_mortality_c_to_litr_c(c,j,i_met_lit) + & - ! storage gap mortality carbon fluxes - m_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - m_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - m_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - ! transfer gap mortality carbon fluxes - m_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - m_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - m_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) - - end if - end if + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + ! leaf gap mortality carbon fluxes + gap_mortality_c_to_litr_c(c,j,i) = & + gap_mortality_c_to_litr_c(c,j,i) + & + m_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + ! fine root gap mortality carbon fluxes + gap_mortality_c_to_litr_c(c,j,i) = & + gap_mortality_c_to_litr_c(c,j,i) + & + m_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) end do - + + ! wood gap mortality carbon fluxes + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_deadstemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! Metabolic litter is treated differently than other types + ! of litter, so it gets this additional line after the + ! most recent loop over all litter types + gap_mortality_c_to_litr_c(c,j,i_met_lit) = & + gap_mortality_c_to_litr_c(c,j,i_met_lit) + & + ! storage gap mortality carbon fluxes + m_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + m_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + m_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + ! transfer gap mortality carbon fluxes + m_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + m_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + m_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + end do end do + end associate end subroutine CNCIsoGapPftToColumn diff --git a/src/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index 843754f3cd..41051d0c39 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/biogeochem/CNCStateUpdate1Mod.F90 @@ -18,13 +18,16 @@ module CNCStateUpdate1Mod use CNVegCarbonStateType , only : cnveg_carbonstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use CropType , only : crop_type - use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max, repr_structure_min, repr_structure_max + use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max + use CropReprPoolsMod , only : repr_structure_min, repr_structure_max use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type use PatchType , only : patch - use clm_varctl , only : use_fates, use_cn, iulog, use_fates_sp use CNSharedParamsMod , only : use_matrixcn + use CLMFatesInterfaceMod , only : hlm_fates_interface_type + use ColumnType , only : col + ! implicit none private @@ -43,6 +46,7 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi ! ! !DESCRIPTION: ! Update carbon states based on fluxes from dyn_cnbal_patch + ! This routine is not called with FATES active. ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds @@ -71,26 +75,23 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi dt = get_step_size_real() - if (.not. use_fates) then - do j = 1,nlevdecomp - do fc = 1, num_soilc_with_inactive - c = filter_soilc_with_inactive(fc) - do i = i_litr_min, i_litr_max - cs_soil%decomp_cpools_vr_col(c,j,i) = & - cs_soil%decomp_cpools_vr_col(c,j,i) + & - cf_veg%dwt_frootc_to_litr_c_col(c,j,i) * dt - end do - cs_soil%decomp_cpools_vr_col(c,j,i_cwd) = cs_soil%decomp_cpools_vr_col(c,j,i_cwd) + & - ( cf_veg%dwt_livecrootc_to_cwdc_col(c,j) + cf_veg%dwt_deadcrootc_to_cwdc_col(c,j) ) * dt + do j = 1,nlevdecomp + do fc = 1, num_soilc_with_inactive + c = filter_soilc_with_inactive(fc) + do i = i_litr_min, i_litr_max + cs_soil%decomp_cpools_vr_col(c,j,i) = & + cs_soil%decomp_cpools_vr_col(c,j,i) + & + cf_veg%dwt_frootc_to_litr_c_col(c,j,i) * dt end do + cs_soil%decomp_cpools_vr_col(c,j,i_cwd) = cs_soil%decomp_cpools_vr_col(c,j,i_cwd) + & + ( cf_veg%dwt_livecrootc_to_cwdc_col(c,j) + cf_veg%dwt_deadcrootc_to_cwdc_col(c,j) ) * dt end do + end do - do g = bounds%begg, bounds%endg - cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_leaf_grc(g) * dt - cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_deadstem_grc(g) * dt - end do - - end if + do g = bounds%begg, bounds%endg + cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_leaf_grc(g) * dt + cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_deadstem_grc(g) * dt + end do end associate @@ -123,8 +124,6 @@ subroutine CStateUpdate0(num_soilp, filter_soilp, & ! set time steps dt = get_step_size_real() - - ! gross photosynthesis fluxes do fp = 1,num_soilp p = filter_soilp(fp) @@ -140,7 +139,8 @@ end subroutine CStateUpdate0 !----------------------------------------------------------------------- subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & crop_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, clump_index) ! ! !DESCRIPTION: ! On the radiation time step, update all the prognostic carbon state @@ -157,6 +157,8 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst logical , intent(in) :: dribble_crophrv_xsmrpool_2atm + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + integer , intent(in) :: clump_index ! ! !LOCAL VARIABLES: integer :: c,p,j,k,l,i ! indices @@ -186,12 +188,23 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & dt = get_step_size_real() ! Below is the input into the soil biogeochemistry model - - ! plant to litter fluxes - if (.not. use_fates) then - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + + fc_loop: do fc = 1,num_soilc + c = filter_soilc(fc) + + fates_if: if( col%is_fates(c) ) then + + ! If this is a fates column, then we ask fates for the + ! litter fluxes, the following routine simply copies + ! prepared litter c flux boundary conditions into + ! cf_soil%decomp_cpools_sourcesink_col + + call clm_fates%UpdateCLitterfluxes(cf_soil,clump_index,c) + + else + + do j = 1,nlevdecomp + ! ! State update without the matrix solution ! @@ -206,35 +219,40 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! terms have been moved to CStateUpdateDynPatch. I think this is zeroed every ! time step, but to be safe, I'm explicitly setting it to zero here. cf_soil%decomp_cpools_sourcesink_col(c,j,i_cwd) = 0._r8 - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in SoilMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! + ! + ! For the matrix solution the actual state update comes after the matrix + ! multiply in SoilMatrix, but the matrix needs to be setup with + ! the equivalent of above. Those changes can be here or in the + ! native subroutines dealing with that field + ! else ! phenology and dynamic land cover fluxes end if end do - end do - else if ( .not. use_fates_sp ) then !use_fates - ! here add all fates litterfall and CWD breakdown to litter fluxes + + end if fates_if + + end do fc_loop + + + ! litter and SOM HR fluxes + do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) - ! TODO(wjs, 2017-01-02) Should some portion or all of the following fluxes - ! be moved to the updates in CStateUpdateDynPatch? - do i = i_litr_min, i_litr_max - cf_soil%decomp_cpools_sourcesink_col(c,j,i) = & - cf_soil%FATES_c_to_litr_c_col(c,j,i) * dt - end do + ! + ! State update without the matrix solution + ! + if (.not. use_soil_matrixcn) then + cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_donor_pool(k)) = & + cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_donor_pool(k)) & + - ( cf_soil%decomp_cascade_hr_vr_col(c,j,k) + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k)) *dt + end if !not use_soil_matrixcn end do end do - endif - - if ( .not. use_fates_sp ) then !use_fates - ! litter and SOM HR fluxes - do k = 1, ndecomp_cascade_transitions + end do + do k = 1, ndecomp_cascade_transitions + if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) @@ -242,34 +260,16 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! State update without the matrix solution ! if (.not. use_soil_matrixcn) then - cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_donor_pool(k)) = & - cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_donor_pool(k)) & - - ( cf_soil%decomp_cascade_hr_vr_col(c,j,k) + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k)) *dt - end if !not use_soil_matrixcn - end do - end do - end do - do k = 1, ndecomp_cascade_transitions - if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! - ! State update without the matrix solution - ! - if (.not. use_soil_matrixcn) then - cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_receiver_pool(k)) = & + cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_receiver_pool(k)) = & cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_receiver_pool(k)) & + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k)*dt - end if !not use_soil_matrixcn - end do + end if !not use_soil_matrixcn end do - end if - end do - end if + end do + end if + end do - if (.not. use_fates) then -ptch: do fp = 1,num_soilp + soilpatch_loop: do fp = 1,num_soilp p = filter_soilp(fp) c = patch%column(p) @@ -674,8 +674,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & end if end if - end do ptch ! end of patch loop - end if ! end of NOT fates + end do soilpatch_loop ! end of patch loop end associate diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index 425c32e084..0907211add 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -6,12 +6,12 @@ module CNDriverMod ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varctl , only : use_c13, use_c14, use_fates, use_dynroot + use clm_varctl , only : use_c13, use_c14, use_fates, use_fates_bgc, use_dynroot use dynSubgridControlMod , only : get_do_harvest, get_do_grossunrep use decompMod , only : bounds_type use perf_mod , only : t_startf, t_stopf use clm_varctl , only : use_nitrif_denitrif, use_nguardrail - use clm_varctl , only : iulog, use_crop, use_crop_agsys + use clm_varctl , only : iulog, use_crop, use_crop_agsys, use_cn use SoilBiogeochemDecompCascadeConType, only : mimics_decomp, century_decomp, decomp_method use CNSharedParamsMod , only : use_fun use CNVegStateType , only : cnveg_state_type @@ -43,7 +43,7 @@ module CNDriverMod use ActiveLayerMod , only : active_layer_type use SoilWaterRetentionCurveMod , only : soil_water_retention_curve_type use CLMFatesInterfaceMod , only : hlm_fates_interface_type - use CropReprPoolsMod , only : nrepr + use CropReprPoolsMod , only : nrepr ! ! !PUBLIC TYPES: implicit none @@ -77,14 +77,15 @@ subroutine CNDriverInit(bounds, NLFilename, cnfire_method) class(fire_method_type) , intent(inout) :: cnfire_method !----------------------------------------------------------------------- call SoilBiogeochemCompetitionInit(bounds) - call CNPhenologyInit(bounds) - call cnfire_method%FireInit(bounds, NLFilename) - + if(use_cn)then + call CNPhenologyInit(bounds) + call cnfire_method%FireInit(bounds, NLFilename) + end if end subroutine CNDriverInit !----------------------------------------------------------------------- subroutine CNDriverNoLeaching(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & num_pcropp, filter_pcropp, num_soilnopcropp, filter_soilnopcropp, & num_actfirec, filter_actfirec, num_actfirep, filter_actfirep, & num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & @@ -151,10 +152,10 @@ subroutine CNDriverNoLeaching(bounds, ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for veg patches integer , intent(out) :: num_actfirep ! number of soil patches on fire in filter integer , intent(out) :: filter_actfirep(:) ! filter for soil patches on fire integer , intent(out) :: num_actfirec ! number of soil columns on fire in filter @@ -241,58 +242,59 @@ subroutine CNDriverNoLeaching(bounds, ! -------------------------------------------------- ! zero the column-level C and N fluxes ! -------------------------------------------------- - - call t_startf('CNZero') + call t_startf('CNZero') ! COMPILER_BUG(wjs, 2014-11-29, pgi 14.7) Without this, the filter is full of garbage ! in some situations call t_startf('CNZero-soilbgc-cflux') - dummy_to_make_pgi_happy = ubound(filter_soilc, 1) + dummy_to_make_pgi_happy = ubound(filter_bgc_soilc, 1) call soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) if ( use_c13 ) then call c13_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) end if if ( use_c14 ) then call c14_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) end if call t_stopf('CNZero-soilbgc-cflux') - call t_startf('CNZero-vegbgc-cflux') - call cnveg_carbonflux_inst%SetValues( & - nvegcpool,& - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) - if ( use_c13 ) then - call c13_cnveg_carbonflux_inst%SetValues( & + if(num_bgc_vegp>0)then + call t_startf('CNZero-vegbgc-cflux') + call cnveg_carbonflux_inst%SetValues( & nvegcpool,& - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) - end if - if ( use_c14 ) then - call c14_cnveg_carbonflux_inst%SetValues( & - nvegcpool,& - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) + if ( use_c13 ) then + call c13_cnveg_carbonflux_inst%SetValues( & + nvegcpool,& + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) + end if + if ( use_c14 ) then + call c14_cnveg_carbonflux_inst%SetValues( & + nvegcpool,& + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) + end if + call t_stopf('CNZero-vegbgc-cflux') + + call t_startf('CNZero-vegbgc-nflux') + call cnveg_nitrogenflux_inst%SetValues( & + nvegnpool, & + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) end if - call t_stopf('CNZero-vegbgc-cflux') - - call t_startf('CNZero-vegbgc-nflux') - call cnveg_nitrogenflux_inst%SetValues( & - nvegnpool, & - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) - + call t_stopf('CNZero-vegbgc-nflux') call t_startf('CNZero-soilbgc-nflux') call soilbiogeochem_nitrogenflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) call t_stopf('CNZero-soilbgc-nflux') call t_stopf('CNZero') - + ! -------------------------------------------------- ! Nitrogen Deposition, Fixation and Respiration ! -------------------------------------------------- @@ -304,30 +306,31 @@ subroutine CNDriverNoLeaching(bounds, if(use_fun)then call t_startf('CNFLivFixation') - call CNFreeLivingFixation( num_soilc, filter_soilc, & + call CNFreeLivingFixation( num_bgc_soilc, filter_bgc_soilc, & waterfluxbulk_inst, soilbiogeochem_nitrogenflux_inst) call t_stopf('CNFLivFixation') else call t_startf('CNFixation') - call CNNFixation( num_soilc, filter_soilc, & - cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst) + call CNNFixation( num_bgc_soilc, filter_bgc_soilc, & + cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, bounds%clump_index) call t_stopf('CNFixation') end if if (use_crop) then - call CNNFert(bounds, num_soilc,filter_soilc, & + call CNNFert(bounds, num_bgc_soilc,filter_bgc_soilc, & cnveg_nitrogenflux_inst, soilbiogeochem_nitrogenflux_inst) if (.not. use_fun) then ! if FUN is active, then soy fixation handled by FUN - call CNSoyfix (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CNSoyfix (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & waterdiagnosticbulk_inst, crop_inst, cnveg_state_inst, cnveg_nitrogenflux_inst , & soilbiogeochem_state_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) end if end if call t_startf('CNMResp') - call CNMResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CNMResp(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & canopystate_inst, soilstate_inst, temperature_inst, photosyns_inst, & cnveg_carbonflux_inst, cnveg_nitrogenstate_inst) call t_stopf('CNMResp') @@ -339,11 +342,11 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('SoilBiogeochem') call t_startf('DecompRate') if (decomp_method == century_decomp) then - call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & + call decomp_rate_constants_bgc(bounds, num_bgc_soilc, filter_bgc_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) else if (decomp_method == mimics_decomp) then - call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, clm_fates, & + call decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, clm_fates, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) end if @@ -351,7 +354,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('SoilBiogeochemPotential') ! calculate potential decomp rates and total immobilization demand (previously inlined in CNDecompAlloc) - call SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & + call SoilBiogeochemPotential (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & @@ -361,13 +364,14 @@ subroutine CNDriverNoLeaching(bounds, p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) call t_stopf('SoilBiogeochemPotential') - ! calculate vertical profiles for distributing soil and litter C and N (previously subroutine decomp_vertprofiles called from CNDecompAlloc) - call SoilBiogeochemVerticalProfile(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + ! calculate vertical profiles for distributing soil and litter C and N + ! (previously subroutine decomp_vertprofiles called from CNDecompAlloc) + call SoilBiogeochemVerticalProfile(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & active_layer_inst, soilstate_inst,soilbiogeochem_state_inst) ! calculate nitrification and denitrification rates (previously subroutine nitrif_denitrif called from CNDecompAlloc) if (use_nitrif_denitrif) then - call SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & + call SoilBiogeochemNitrifDenitrif(bounds, num_bgc_soilc, filter_bgc_soilc, & soilstate_inst, waterstatebulk_inst, temperature_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) end if @@ -389,43 +393,45 @@ subroutine CNDriverNoLeaching(bounds, ! do_nutrient_competition should be modified, but that modification should not significantly change ! the current interface. - !RF: moved ths call to before nutrient_demand, so that croplive didn't change half way through crop N cycle. - if ( use_fun ) then - call t_startf('CNPhenology_phase1') - call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & - filter_soilp, num_pcropp, filter_pcropp, & - waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & - crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & - cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & - c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & - phase=1) - call t_stopf('CNPhenology_phase1') - - call t_startf('CNFUNInit') - call CNFUNInit(bounds,cnveg_state_inst,cnveg_carbonstate_inst,cnveg_nitrogenstate_inst) - call t_stopf('CNFUNInit') - - end if - - call t_startf('cnalloc') - call calc_gpp_mr_availc( & - bounds, num_soilp, filter_soilp, & - crop_inst, photosyns_inst, canopystate_inst, & - cnveg_carbonstate_inst, cnveg_carbonflux_inst, & - c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst) - - if (.not. use_crop_agsys) then - call calc_crop_allocation_fractions(bounds, num_pcropp, filter_pcropp, & - crop_inst, cnveg_state_inst) - end if - - call calc_allometry(num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_state_inst) - call t_stopf('cnalloc') - + !RF: moved ths call to before nutrient_demand, so that croplive didn't change half way through crop N cycle. + if(num_bgc_vegp>0)then + if ( use_fun) then + call t_startf('CNPhenology_phase1') + call CNPhenology (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, & + filter_bgc_vegp, num_pcropp, filter_pcropp, & + waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & + crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & + cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + phase=1) + call t_stopf('CNPhenology_phase1') + + call t_startf('CNFUNInit') + call CNFUNInit(bounds,cnveg_state_inst,cnveg_carbonstate_inst,cnveg_nitrogenstate_inst) + call t_stopf('CNFUNInit') + + end if + + call t_startf('cnalloc') + call calc_gpp_mr_availc( & + bounds, num_bgc_vegp, filter_bgc_vegp, & + crop_inst, photosyns_inst, canopystate_inst, & + cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst) + + if (.not. use_crop_agsys) then + call calc_crop_allocation_fractions(bounds, num_pcropp, filter_pcropp, & + crop_inst, cnveg_state_inst) + end if + + call calc_allometry(num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_state_inst) + call t_stopf('cnalloc') + end if + call t_startf('calc_plant_nutrient_demand') ! We always call calc_plant_nutrient_demand for natural veg patches, but only call ! it for crop patches if NOT running with AgSys (since AgSys calculates the relevant @@ -451,16 +457,23 @@ subroutine CNDriverNoLeaching(bounds, ! get the column-averaged plant_ndemand (needed for following call to SoilBiogeochemCompetition) - call p2c(bounds, num_soilc, filter_soilc, & - cnveg_nitrogenflux_inst%plant_ndemand_patch(begp:endp), & - soilbiogeochem_state_inst%plant_ndemand_col(begc:endc)) + if(num_bgc_vegp>0)then + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + cnveg_nitrogenflux_inst%plant_ndemand_patch(begp:endp), & + soilbiogeochem_state_inst%plant_ndemand_col(begc:endc)) + else + ! With FATES N coupling, we will have a call to fill + ! this in on the filter_bgc_soilc + soilbiogeochem_state_inst%plant_ndemand_col(begc:endc) = 0._r8 + end if + call t_stopf('calc_plant_nutrient_demand') ! resolve plant/heterotroph competition for mineral N call t_startf('soilbiogeochemcompetition') - call SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, & + call SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,num_bgc_vegp, filter_bgc_vegp, & p_decomp_cn_gain, pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst, & cnveg_carbonstate_inst ,& @@ -475,7 +488,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('calc_plant_nutrient_competition') call nutrient_competition_method%calc_plant_nutrient_competition ( & - bounds, num_soilp, filter_soilp, & + bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_state_inst, crop_inst, canopystate_inst, & cnveg_carbonstate_inst, cnveg_carbonflux_inst, & c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst, & @@ -495,7 +508,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('SoilBiogeochemDecomp') - call SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, & + call SoilBiogeochemDecomp (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & @@ -511,12 +524,22 @@ subroutine CNDriverNoLeaching(bounds, ! CNphenology needs to be called after above calls, since it depends on current ! time-step fluxes to new growth on the lastlitterfall timestep in deciduous systems - - call t_startf('CNPhenology') - - if ( .not. use_fun ) then - call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & - filter_soilp, num_pcropp, filter_pcropp, & + if(num_bgc_vegp>0)then + call t_startf('CNPhenology') + if ( .not. use_fun ) then + call CNPhenology (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, & + filter_bgc_vegp, num_pcropp, filter_pcropp, & + waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & + crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & + cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + phase=1) + end if + call CNPhenology (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, & + filter_bgc_vegp, num_pcropp, filter_pcropp, & waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & @@ -524,28 +547,17 @@ subroutine CNDriverNoLeaching(bounds, c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & - phase=1) + phase=2) + + call t_stopf('CNPhenology') end if - call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & - filter_soilp, num_pcropp, filter_pcropp, & - waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & - crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & - cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & - c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & - phase=2) - - call t_stopf('CNPhenology') - !-------------------------------------------- ! Growth respiration !-------------------------------------------- call t_startf('CNGResp') - call CNGResp(num_soilp, filter_soilp,& + call CNGResp(num_bgc_vegp, filter_bgc_vegp,& cnveg_carbonflux_inst, canopystate_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNGResp') @@ -557,7 +569,7 @@ subroutine CNDriverNoLeaching(bounds, if( use_dynroot ) then call t_startf('CNRootDyn') - call CNRootDyn(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CNRootDyn(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, & cnveg_state_inst, crop_inst, soilstate_inst, soilbiogeochem_nitrogenstate_inst) @@ -573,24 +585,24 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('CNUpdate0') - call CStateUpdate0(num_soilp, filter_soilp, & + call CStateUpdate0(num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonflux_inst, cnveg_carbonstate_inst) if ( use_c13 ) then - call CStateUpdate0(num_soilp, filter_soilp, & + call CStateUpdate0(num_bgc_vegp, filter_bgc_vegp, & c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst) end if if ( use_c14 ) then - call CStateUpdate0(num_soilp, filter_soilp, & + call CStateUpdate0(num_bgc_vegp, filter_bgc_vegp, & c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst) end if call t_stopf('CNUpdate0') - if ( use_nguardrail ) then + if ( use_nguardrail .and. num_bgc_vegp>0 ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') @@ -607,7 +619,7 @@ subroutine CNDriverNoLeaching(bounds, ! Set the carbon isotopic flux variables (except for gap-phase mortality and fire fluxes) if ( use_c13 ) then - call CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CIsoFlux1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_state_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & cnveg_carbonflux_inst, cnveg_carbonstate_inst, & @@ -616,7 +628,7 @@ subroutine CNDriverNoLeaching(bounds, isotope='c13') end if if ( use_c14 ) then - call CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CIsoFlux1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_state_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & cnveg_carbonflux_inst, cnveg_carbonstate_inst, & @@ -626,36 +638,40 @@ subroutine CNDriverNoLeaching(bounds, end if ! Update all prognostic carbon state variables (except for gap-phase mortality and fire fluxes) - call CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CStateUpdate1( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & crop_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, bounds%clump_index) if ( use_c13 ) then - call CStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CStateUpdate1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & crop_inst, c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + c13_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, bounds%clump_index) end if if ( use_c14 ) then - call CStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CStateUpdate1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & crop_inst, c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + c14_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, bounds%clump_index) end if ! Update all prognostic nitrogen state variables (except for gap-phase mortality and fire fluxes) - call NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) + call NStateUpdate1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, bounds%clump_index) call t_stopf('CNUpdate1') - if ( use_nguardrail ) then + if ( use_nguardrail .and. num_bgc_vegp>0 ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') end if call t_startf('SoilBiogeochemStateUpdate1') - call SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & + call SoilBiogeochemNStateUpdate1(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) call t_stopf('SoilBiogeochemStateUpdate1') @@ -666,7 +682,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('SoilBiogeochemLittVertTransp') - call SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & + call SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_soilc, & active_layer_inst, soilbiogeochem_state_inst, & soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & @@ -679,282 +695,312 @@ subroutine CNDriverNoLeaching(bounds, ! Calculate the gap mortality carbon and nitrogen fluxes !-------------------------------------------- - call t_startf('CNGapMortality') - - call CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - dgvs_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, canopystate_inst, & - !cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & - croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & - stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full)) - - call t_stopf('CNGapMortality') - - !-------------------------------------------------------------------------- - ! Update2 (gap mortality) - ! The state updates are still called for the matrix solution (use_matrixn - ! and use_soil_matrixcn) but most of the state updates are done after - ! the matrix multiply in VegMatrix and SoilMatrix. - !-------------------------------------------------------------------------- - - call t_startf('CNUpdate2') - - ! Set the carbon isotopic fluxes for gap mortality - if ( use_c13 ) then - call CIsoFlux2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - iso_cnveg_carbonflux_inst=c13_cnveg_carbonflux_inst, & - iso_cnveg_carbonstate_inst=c13_cnveg_carbonstate_inst, & - isotope='c13') - end if - if ( use_c14 ) then - call CIsoFlux2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - iso_cnveg_carbonflux_inst=c14_cnveg_carbonflux_inst, & - iso_cnveg_carbonstate_inst=c14_cnveg_carbonstate_inst, & - isotope='c14') - end if - - ! Update all the prognostic carbon state variables affected by gap-phase mortality fluxes - call CStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_carbonflux_inst) - if ( use_c13 ) then - call CStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst) - end if - if ( use_c14 ) then - call CStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst) - end if - - ! Update all the prognostic nitrogen state variables affected by gap-phase mortality fluxes - call NStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst,soilbiogeochem_nitrogenstate_inst, & - soilbiogeochem_nitrogenflux_inst) - - !-------------------------------------------------------------------------- - ! Update2h (harvest) - ! The state updates are still called for the matrix solution (use_matrixn - ! and use_soil_matrixcn) but most of the state updates are done after - ! the matrix multiply in VegMatrix and SoilMatrix. - !-------------------------------------------------------------------------- - - ! Set harvest mortality routine - if (get_do_harvest()) then - call CNHarvest(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & - cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) - end if - - if ( use_c13 ) then - call CIsoFlux2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & - isotope='c13') - end if - if ( use_c14 ) then - call CIsoFlux2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & - isotope='c14') - end if + if_bgc_vegp1: if(num_bgc_vegp>0)then + + call t_startf('CNGapMortality') + call CNGapMortality (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + dgvs_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, canopystate_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & + croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full)) + call t_stopf('CNGapMortality') + + !-------------------------------------------------------------------------- + ! Update2 (gap mortality) + ! The state updates are still called for the matrix solution (use_matrixn + ! and use_soil_matrixcn) but most of the state updates are done after + ! the matrix multiply in VegMatrix and SoilMatrix. + !-------------------------------------------------------------------------- + + call t_startf('CNUpdate2') + ! Set the carbon isotopic fluxes for gap mortality + if ( use_c13 ) then + call CIsoFlux2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + iso_cnveg_carbonflux_inst=c13_cnveg_carbonflux_inst, & + iso_cnveg_carbonstate_inst=c13_cnveg_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + iso_cnveg_carbonflux_inst=c14_cnveg_carbonflux_inst, & + iso_cnveg_carbonstate_inst=c14_cnveg_carbonstate_inst, & + isotope='c14') + end if + + ! Update all the prognostic carbon state variables affected by gap-phase mortality fluxes + call CStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst) + if ( use_c13 ) then + call CStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & + c13_soilbiogeochem_carbonflux_inst) + end if + if ( use_c14 ) then + call CStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonflux_inst) + end if + + ! Update all the prognostic nitrogen state variables affected by gap-phase mortality fluxes + call NStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst,soilbiogeochem_nitrogenstate_inst, & + soilbiogeochem_nitrogenflux_inst) + + !-------------------------------------------------------------------------- + ! Update2h (harvest) + ! The state updates are still called for the matrix solution (use_matrixn + ! and use_soil_matrixcn) but most of the state updates are done after + ! the matrix multiply in VegMatrix and SoilMatrix. + !-------------------------------------------------------------------------- + + ! Set harvest mortality routine + if (get_do_harvest()) then + call CNHarvest(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + end if + + if ( use_c13 ) then + call CIsoFlux2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + isotope='c14') + end if - call CStateUpdate2h( num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_carbonflux_inst) - if ( use_c13 ) then - call CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CStateUpdate2h( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst) + if ( use_c13 ) then + call CStateUpdate2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonflux_inst) - end if - if ( use_c14 ) then - call CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst) - end if - - call NStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst, & - soilbiogeochem_nitrogenflux_inst) - - !-------------------------------------------- - ! Update2g (gross unrepresented landcover change) - !-------------------------------------------- - - ! Set gross unrepresented landcover change mortality routine - if (get_do_grossunrep()) then - call CNGrossUnrep(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & - cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) - end if - - if ( use_c13 ) then - call CIsoFlux2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & - isotope='c13') - end if - if ( use_c14 ) then - call CIsoFlux2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & - isotope='c14') - end if - - call CStateUpdate2g( num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst) - if ( use_c13 ) then - call CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst) - end if - if ( use_c14 ) then - call CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst) - end if + end if + if ( use_c14 ) then + call CStateUpdate2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonflux_inst) + end if + + call NStateUpdate2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst, & + soilbiogeochem_nitrogenflux_inst) + + !-------------------------------------------- + ! Update2g (gross unrepresented landcover change) + !-------------------------------------------- + + ! Set gross unrepresented landcover change mortality routine + if (get_do_grossunrep()) then + call CNGrossUnrep(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + end if + + if ( use_c13 ) then + call CIsoFlux2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + isotope='c14') + end if + + call CStateUpdate2g( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst) + if ( use_c13 ) then + call CStateUpdate2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst) + end if + if ( use_c14 ) then + call CStateUpdate2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst) + end if + + call NStateUpdate2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst) - call NStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst) + call t_stopf('CNUpdate2') - call t_stopf('CNUpdate2') + end if if_bgc_vegp1 + + if ( use_nguardrail .and. num_bgc_vegp>0 ) then - if ( use_nguardrail ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') + end if + !-------------------------------------------- ! Calculate loss fluxes from wood products pools ! and update product pool state variables !-------------------------------------------- call t_startf('CNWoodProducts') - call c_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - gru_wood_product_gain_patch = cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & - wood_harvest_patch = cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - dwt_crop_product_gain_patch = cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) - call t_stopf('CNWoodProducts') - - if (use_c13) then - call c13_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - gru_wood_product_gain_patch = c13_cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & - wood_harvest_patch = c13_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - dwt_crop_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = c13_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + + call c_products_inst%SetValues(bounds,0._r8) + if (use_c13) call c13_products_inst%SetValues(bounds,0._r8) + if (use_c14) call c14_products_inst%SetValues(bounds,0._r8) + call n_products_inst%SetValues(bounds,0._r8) + + if(use_fates_bgc) then + call clm_fates%wrap_WoodProducts(bounds, num_bgc_soilc, filter_bgc_soilc, c_products_inst, n_products_inst) end if - if (use_c14) then - call c14_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - gru_wood_product_gain_patch = c14_cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & - wood_harvest_patch = c14_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - dwt_crop_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = c14_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) - end if + if_bgc_vegp2: if(num_bgc_vegp>0)then + call c_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & + gru_wood_product_gain_patch = cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & + wood_harvest_patch = cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & + dwt_crop_product_gain_patch = cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + + if (use_c13) then + call c13_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & + gru_wood_product_gain_patch = c13_cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & + wood_harvest_patch = c13_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & + dwt_crop_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = c13_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + end if + + if (use_c14) then + call c14_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & + gru_wood_product_gain_patch = c14_cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & + wood_harvest_patch = c14_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & + dwt_crop_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = c14_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + end if + + call n_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = cnveg_nitrogenflux_inst%dwt_wood_productn_gain_patch(begp:endp), & + gru_wood_product_gain_patch = cnveg_nitrogenflux_inst%gru_wood_productn_gain_patch(begp:endp), & + wood_harvest_patch = cnveg_nitrogenflux_inst%wood_harvestn_patch(begp:endp), & + dwt_crop_product_gain_patch = cnveg_nitrogenflux_inst%dwt_crop_productn_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = cnveg_nitrogenflux_inst%crop_harvestn_to_cropprodn_patch(begp:endp)) + + end if if_bgc_vegp2 + + call c_products_inst%ComputeProductSummaryVars(bounds) + if (use_c13) call c13_products_inst%ComputeProductSummaryVars(bounds) + if (use_c14) call c14_products_inst%ComputeProductSummaryVars(bounds) + call n_products_inst%ComputeProductSummaryVars(bounds) - call n_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = cnveg_nitrogenflux_inst%dwt_wood_productn_gain_patch(begp:endp), & - gru_wood_product_gain_patch = cnveg_nitrogenflux_inst%gru_wood_productn_gain_patch(begp:endp), & - wood_harvest_patch = cnveg_nitrogenflux_inst%wood_harvestn_patch(begp:endp), & - dwt_crop_product_gain_patch = cnveg_nitrogenflux_inst%dwt_crop_productn_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = cnveg_nitrogenflux_inst%crop_harvestn_to_cropprodn_patch(begp:endp)) + call c_products_inst%ComputeSummaryVars(bounds) + if (use_c13) call c13_products_inst%ComputeSummaryVars(bounds) + if (use_c14) call c14_products_inst%ComputeSummaryVars(bounds) + call n_products_inst%ComputeSummaryVars(bounds) + + call t_stopf('CNWoodProducts') + !-------------------------------------------- ! Calculate fire area and fluxes !-------------------------------------------- - call t_startf('CNFire') - call cnfire_method%CNFireArea(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & - atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & - waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, & - totlitc_col=soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & - t_soi17cm_col=temperature_inst%t_soi17cm_col(begc:endc)) - - call cnfire_method%CNFireFluxes(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - num_actfirec, filter_actfirec, num_actfirep, filter_actfirep, & - dgvs_inst, cnveg_state_inst, & - cnveg_carbonstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & - soilbiogeochem_carbonflux_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & - croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & - stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full), & - totsomc_col=soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & - decomp_npools_vr_col=soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & - somc_fire_col=soilbiogeochem_carbonflux_inst%somc_fire_col(begc:endc)) - call t_stopf('CNFire') - - - !-------------------------------------------------------------------------- - ! Update3 - ! The state updates are still called for the matrix solution (use_matrixn - ! and use_soil_matrixcn) but most of the state updates are done after - ! the matrix multiply in VegMatrix and SoilMatrix. - !-------------------------------------------------------------------------- - - call t_startf('CNUpdate3') - if ( use_c13 ) then - call CIsoFlux3(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & - c13_soilbiogeochem_carbonstate_inst, & - isotope='c13') - end if - if ( use_c14 ) then - call CIsoFlux3(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & - c14_soilbiogeochem_carbonstate_inst, & - isotope='c14') - end if + if_bgc_vegp3: if(num_bgc_vegp>0)then + call t_startf('CNFire') + call cnfire_method%CNFireArea(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & + atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & + waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & + cnveg_state_inst, cnveg_carbonstate_inst, & + totlitc_col=soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & + decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & + t_soi17cm_col=temperature_inst%t_soi17cm_col(begc:endc)) + + call cnfire_method%CNFireFluxes(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + num_actfirec, filter_actfirec, num_actfirep, filter_actfirep, & + dgvs_inst, cnveg_state_inst, & + cnveg_carbonstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & + soilbiogeochem_carbonflux_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & + croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full), & + totsomc_col=soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & + decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & + decomp_npools_vr_col=soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & + somc_fire_col=soilbiogeochem_carbonflux_inst%somc_fire_col(begc:endc)) + call t_stopf('CNFire') + + !-------------------------------------------------------------------------- + ! Update3 + ! The state updates are still called for the matrix solution (use_matrixn + ! and use_soil_matrixcn) but most of the state updates are done after + ! the matrix multiply in VegMatrix and SoilMatrix. + !-------------------------------------------------------------------------- + + call t_startf('CNUpdate3') + if ( use_c13 ) then + call CIsoFlux3(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & + c13_soilbiogeochem_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux3(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + c14_soilbiogeochem_carbonstate_inst, & + isotope='c14') + end if - call CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_carbonflux_inst) + call CStateUpdate3( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst) - if ( use_c13 ) then - call CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst) - end if + if ( use_c13 ) then + call CStateUpdate3( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & + c13_soilbiogeochem_carbonflux_inst) + end if - if ( use_c14 ) then - call CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst) + if ( use_c14 ) then + call CStateUpdate3( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonflux_inst) - call C14Decay(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_cnveg_carbonflux_inst, c14_soilbiogeochem_carbonflux_inst) - end if - call t_stopf('CNUpdate3') + call C14Decay(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_soilbiogeochem_carbonflux_inst) + end if + call t_stopf('CNUpdate3') - if ( use_nguardrail ) then + end if if_bgc_vegp3 + + if ( use_nguardrail .and. num_bgc_vegp>0 ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') @@ -966,7 +1012,7 @@ end subroutine CNDriverNoLeaching !----------------------------------------------------------------------- subroutine CNDriverLeaching(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & num_actfirec, filter_actfirec, num_actfirep, filter_actfirep,& waterstatebulk_inst, waterfluxbulk_inst, & soilstate_inst, cnveg_state_inst, & @@ -986,16 +1032,17 @@ subroutine CNDriverLeaching(bounds, & ! !USES: use SoilBiogeochemNLeachingMod, only: SoilBiogeochemNLeaching use CNNStateUpdate3Mod , only: NStateUpdate3 - use clm_time_manager , only : is_first_step_of_this_run_segment,is_beg_curr_year,is_end_curr_year,get_curr_date - use CNSharedParamsMod , only : use_matrixcn + use CNNStateUpdate3Mod , only: NStateUpdateLeaching + use clm_time_manager , only: is_first_step_of_this_run_segment,is_beg_curr_year,is_end_curr_year,get_curr_date + use CNSharedParamsMod , only: use_matrixcn use SoilBiogeochemDecompCascadeConType , only : use_soil_matrixcn ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches integer , intent(in) :: num_actfirec ! number of soil columns on fire in filter integer , intent(in) :: filter_actfirec(:) ! filter for soil columns on fire integer , intent(in) :: num_actfirep ! number of soil patches on fire in filter @@ -1027,21 +1074,26 @@ subroutine CNDriverLeaching(bounds, & ! Mineral nitrogen dynamics (deposition, fixation, leaching) call t_startf('SoilBiogeochemNLeaching') - call SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & + call SoilBiogeochemNLeaching(bounds, num_bgc_soilc, filter_bgc_soilc, & waterstatebulk_inst, waterfluxbulk_inst, soilbiogeochem_nitrogenstate_inst, & soilbiogeochem_nitrogenflux_inst) - call t_stopf('SoilBiogeochemNLeaching') - - ! Nitrogen state variable update, mortality fluxes. - - call t_startf('NUpdate3') - - call NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + call NStateUpdateLeaching(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) + call t_stopf('SoilBiogeochemNLeaching') - call t_stopf('NUpdate3') + + + + ! Nitrogen state variable update, mortality fluxes. + if(num_bgc_vegp>0)then + call t_startf('NUpdate3') + call NStateUpdate3(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) + call t_stopf('NUpdate3') + end if + !-------------------------------------------------------------------------- ! Solve the matrix solution and do the state update for matrix solution as ! part of that @@ -1063,7 +1115,7 @@ end subroutine CNDriverLeaching !----------------------------------------------------------------------- subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & cnveg_nitrogenstate_inst, & soilbiogeochem_carbonstate_inst, & @@ -1080,10 +1132,10 @@ subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst @@ -1104,53 +1156,46 @@ subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & call t_startf('CNsum') ! ---------------------------------------------- - ! soilbiogeochem carbon/nitrogen state summary + ! cnveg carbon/nitrogen state summary ! ---------------------------------------------- + call cnveg_carbonstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) - call soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc) if ( use_c13 ) then - call c13_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc) + call c13_cnveg_carbonstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) end if + if ( use_c14 ) then - call c14_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc) + call c14_cnveg_carbonstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) end if - call soilbiogeochem_nitrogenstate_inst%summary(bounds, num_allc, filter_allc) ! ---------------------------------------------- - ! cnveg carbon/nitrogen state summary + ! soilbiogeochem carbon/nitrogen state summary + ! RGK 02-23: soilbiogeochem summary now depends on + ! cnveg summary, swapped call order ! ---------------------------------------------- - call cnveg_carbonstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col=soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & - soilbiogeochem_totlitc_col=soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - soilbiogeochem_totmicc_col=soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & - soilbiogeochem_totsomc_col=soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - soilbiogeochem_ctrunc_col=soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) - + call soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, cnveg_carbonstate_inst) if ( use_c13 ) then - call c13_cnveg_carbonstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col=c13_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & - soilbiogeochem_totlitc_col=c13_soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - soilbiogeochem_totmicc_col=c13_soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & - soilbiogeochem_totsomc_col=c13_soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - soilbiogeochem_ctrunc_col=c13_soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) + call c13_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, c13_cnveg_carbonstate_inst) end if - if ( use_c14 ) then - call c14_cnveg_carbonstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col=c14_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & - soilbiogeochem_totlitc_col=c14_soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - soilbiogeochem_totmicc_col=c14_soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & - soilbiogeochem_totsomc_col=c14_soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - soilbiogeochem_ctrunc_col=c14_soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) + call c14_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, c14_cnveg_carbonstate_inst) end if + + + ! RGK 02-23: This call will be moved to after cnveg nitr summary when we + ! couple in FATES N + + + call cnveg_nitrogenstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp) - call cnveg_nitrogenstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_nitrogenstate_inst) + call soilbiogeochem_nitrogenstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, cnveg_nitrogenstate_inst) + call t_stopf('CNsum') @@ -1158,7 +1203,7 @@ end subroutine CNDriverSummarizeStates !----------------------------------------------------------------------- subroutine CNDriverSummarizeFluxes(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonflux_inst, c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst, & cnveg_nitrogenflux_inst, & c_products_inst, c13_products_inst, c14_products_inst, & @@ -1179,10 +1224,10 @@ subroutine CNDriverSummarizeFluxes(bounds, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_carbonflux_type) , intent(inout) :: c13_cnveg_carbonflux_inst type(cnveg_carbonflux_type) , intent(inout) :: c14_cnveg_carbonflux_inst @@ -1217,72 +1262,74 @@ subroutine CNDriverSummarizeFluxes(bounds, & ! soilbiogeochem carbon/nitrogen flux summary ! ---------------------------------------------- - call soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call soilbiogeochem_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & - leafc_to_litter_patch=cnveg_carbonflux_inst%leafc_to_litter_patch(begp:endp), & - frootc_to_litter_patch=cnveg_carbonflux_inst%frootc_to_litter_patch(begp:endp)) + leafc_to_litter_patch=cnveg_carbonflux_inst%leafc_to_litter_patch, & + frootc_to_litter_patch=cnveg_carbonflux_inst%frootc_to_litter_patch) if ( use_c13 ) then - call c13_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call c13_soilbiogeochem_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & c13_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & c13_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & - leafc_to_litter_patch=c13_cnveg_carbonflux_inst%leafc_to_litter_patch(begp:endp), & - frootc_to_litter_patch=c13_cnveg_carbonflux_inst%frootc_to_litter_patch(begp:endp)) + leafc_to_litter_patch=c13_cnveg_carbonflux_inst%leafc_to_litter_patch, & + frootc_to_litter_patch=c13_cnveg_carbonflux_inst%frootc_to_litter_patch) end if if ( use_c14 ) then - call c14_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call c14_soilbiogeochem_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & c14_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & c14_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & - leafc_to_litter_patch=c14_cnveg_carbonflux_inst%leafc_to_litter_patch(begp:endp), & - frootc_to_litter_patch=c14_cnveg_carbonflux_inst%frootc_to_litter_patch(begp:endp)) + leafc_to_litter_patch=c14_cnveg_carbonflux_inst%leafc_to_litter_patch, & + frootc_to_litter_patch=c14_cnveg_carbonflux_inst%frootc_to_litter_patch) end if - call soilbiogeochem_nitrogenflux_inst%Summary(bounds, num_soilc, filter_soilc) + call soilbiogeochem_nitrogenflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc) ! ---------------------------------------------- ! cnveg carbon/nitrogen flux summary ! ---------------------------------------------- - call t_startf('CNvegCflux_summary') - call cnveg_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - isotope='bulk', & - soilbiogeochem_hr_col=soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & - soilbiogeochem_cwdhr_col=soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & - soilbiogeochem_lithr_col=soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & - soilbiogeochem_decomp_cascade_ctransfer_col=& - soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & - product_closs_grc=c_products_inst%product_loss_grc(begg:endg)) - - if ( use_c13 ) then - call c13_cnveg_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - isotope='c13', & - soilbiogeochem_hr_col=c13_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & - soilbiogeochem_cwdhr_col=c13_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & - soilbiogeochem_lithr_col=c13_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & - soilbiogeochem_decomp_cascade_ctransfer_col=& - c13_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & - product_closs_grc=c13_products_inst%product_loss_grc(begg:endg)) - end if - - if ( use_c14 ) then - call c14_cnveg_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - isotope='c14', & - soilbiogeochem_hr_col=c14_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & - soilbiogeochem_cwdhr_col=c14_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & - soilbiogeochem_lithr_col=c14_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & + if_bgc_vegp: if(num_bgc_vegp>0) then + call t_startf('CNvegCflux_summary') + call cnveg_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + isotope='bulk', & + soilbiogeochem_hr_col=soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & + soilbiogeochem_cwdhr_col=soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & + soilbiogeochem_lithr_col=soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & soilbiogeochem_decomp_cascade_ctransfer_col=& - c14_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & - product_closs_grc=c14_products_inst%product_loss_grc(begg:endg)) - end if - call t_stopf('CNvegCflux_summary') - - call cnveg_nitrogenflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp) + soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + product_closs_grc=c_products_inst%product_loss_grc(begg:endg)) + + if ( use_c13 ) then + call c13_cnveg_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + isotope='c13', & + soilbiogeochem_hr_col=c13_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & + soilbiogeochem_cwdhr_col=c13_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & + soilbiogeochem_lithr_col=c13_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & + soilbiogeochem_decomp_cascade_ctransfer_col=& + c13_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + product_closs_grc=c13_products_inst%product_loss_grc(begg:endg)) + end if + + if ( use_c14 ) then + call c14_cnveg_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + isotope='c14', & + soilbiogeochem_hr_col=c14_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & + soilbiogeochem_cwdhr_col=c14_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & + soilbiogeochem_lithr_col=c14_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & + soilbiogeochem_decomp_cascade_ctransfer_col=& + c14_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + product_closs_grc=c14_products_inst%product_loss_grc(begg:endg)) + end if + call t_stopf('CNvegCflux_summary') + call cnveg_nitrogenflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) + end if if_bgc_vegp + call t_stopf('CNsum') end subroutine CNDriverSummarizeFluxes diff --git a/src/biogeochem/CNFireEmissionsMod.F90 b/src/biogeochem/CNFireEmissionsMod.F90 index 645f074a7d..5a15e138d5 100644 --- a/src/biogeochem/CNFireEmissionsMod.F90 +++ b/src/biogeochem/CNFireEmissionsMod.F90 @@ -185,7 +185,7 @@ subroutine InitHistory(this, bounds) end subroutine InitHistory !----------------------------------------------------------------------- - subroutine CNFireEmisUpdate(bounds, num_soilp, filter_soilp, cnveg_cf_inst, cnveg_cs_inst, fireemis_inst ) + subroutine CNFireEmisUpdate(bounds, num_bgc_vegp, filter_bgc_vegp, cnveg_cf_inst, cnveg_cs_inst, fireemis_inst ) use CNVegcarbonfluxType, only : cnveg_carbonflux_type use CNVegCarbonStateType, only : cnveg_carbonstate_type @@ -194,8 +194,8 @@ subroutine CNFireEmisUpdate(bounds, num_soilp, filter_soilp, cnveg_cf_inst, cnve !ARGUMENTS: type(bounds_type), intent(in) :: bounds - integer, intent(in) :: num_soilp ! number of soil pfts in filter - integer, intent(in) :: filter_soilp(:) ! filter for soil pfts + integer, intent(in) :: num_bgc_vegp ! number of bgc veg patches + integer, intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches type(cnveg_carbonflux_type), intent(in) :: cnveg_cf_inst type(cnveg_carbonstate_type),intent(in) :: cnveg_cs_inst type(fireemis_type), intent(inout) :: fireemis_inst @@ -235,8 +235,8 @@ subroutine CNFireEmisUpdate(bounds, num_soilp, filter_soilp, cnveg_cf_inst, cnve ! Begin loop over points !_______________________________________________________________________________ - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) g = patch%gridcell(p) c = patch%column(p) diff --git a/src/biogeochem/CNGapMortalityMod.F90 b/src/biogeochem/CNGapMortalityMod.F90 index 91c937f655..ebda9db56d 100644 --- a/src/biogeochem/CNGapMortalityMod.F90 +++ b/src/biogeochem/CNGapMortalityMod.F90 @@ -312,7 +312,7 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so froot_prof_patch(bounds%begp:bounds%endp, 1:nlevdecomp_full), & croot_prof_patch(bounds%begp:bounds%endp, 1:nlevdecomp_full), & stem_prof_patch(bounds%begp:bounds%endp, 1:nlevdecomp_full)) - + end associate end subroutine CNGapMortality diff --git a/src/biogeochem/CNNDynamicsMod.F90 b/src/biogeochem/CNNDynamicsMod.F90 index a658a63768..10c0f5ea38 100644 --- a/src/biogeochem/CNNDynamicsMod.F90 +++ b/src/biogeochem/CNNDynamicsMod.F90 @@ -25,6 +25,7 @@ module CNNDynamicsMod use ColumnType , only : col use PatchType , only : patch use perf_mod , only : t_startf, t_stopf + use CLMFatesInterfaceMod , only : hlm_fates_interface_type ! implicit none private @@ -192,7 +193,8 @@ end subroutine CNFreeLivingFixation !----------------------------------------------------------------------- subroutine CNNFixation(num_soilc, filter_soilc, & - cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst) + cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, clump_index) ! ! !DESCRIPTION: ! On the radiation time step, update the nitrogen fixation rate @@ -209,12 +211,15 @@ subroutine CNNFixation(num_soilc, filter_soilc, & integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst - type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + integer , intent(in) :: clump_index ! ! !LOCAL VARIABLES: - integer :: c,fc ! indices + integer :: c,fc,s ! indices real(r8) :: t ! temporary real(r8) :: dayspyr ! days per year + real(r8) :: npp ! lag or smoothed net primary productivity (gC/m2/s) !----------------------------------------------------------------------- associate( & @@ -225,16 +230,26 @@ subroutine CNNFixation(num_soilc, filter_soilc, & ) dayspyr = get_curr_days_per_year() - if ( nfix_timeconst > 0._r8 .and. nfix_timeconst < 500._r8 ) then ! use exponential relaxation with time constant nfix_timeconst for NPP - NFIX relation ! Loop through columns do fc = 1,num_soilc c = filter_soilc(fc) - if (col_lag_npp(c) /= spval) then + if(col%is_fates(c))then + s = clm_fates%f2hmap(clump_index)%hsites(c) + ! %ema_npp is Smoothed [gc/m2/yr] + !npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp/(dayspyr*secspday) + ! FATES N cycling is not yet active, so runs are supplemented anyway + ! this will be added when FATES N cycling is completed. + npp = 0._r8 + else + npp = col_lag_npp(c) + end if + + if (npp /= spval) then ! need to put npp in units of gC/m^2/year here first - t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * col_lag_npp(c)*(secspday * dayspyr))))/(secspday * dayspyr) + t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp *(secspday * dayspyr))))/(secspday * dayspyr) nfix_to_sminn(c) = max(0._r8,t) else nfix_to_sminn(c) = 0._r8 @@ -245,7 +260,16 @@ subroutine CNNFixation(num_soilc, filter_soilc, & do fc = 1,num_soilc c = filter_soilc(fc) - t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * cannsum_npp(c))))/(secspday * dayspyr) + if(col%is_fates(c))then + s = clm_fates%f2hmap(clump_index)%hsites(c) + !npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp + ! See above regarding FATES and N fixation + npp = 0._r8 + else + npp = cannsum_npp(c) + end if + + t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp)))/(secspday * dayspyr) nfix_to_sminn(c) = max(0._r8,t) end do endif diff --git a/src/biogeochem/CNNStateUpdate1Mod.F90 b/src/biogeochem/CNNStateUpdate1Mod.F90 index c99729b2ee..5358c46de1 100644 --- a/src/biogeochem/CNNStateUpdate1Mod.F90 +++ b/src/biogeochem/CNNStateUpdate1Mod.F90 @@ -23,7 +23,10 @@ module CNNStateUpdate1Mod use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max, repr_structure_min, repr_structure_max - use PatchType , only : patch + use PatchType , only : patch + use CLMFatesInterfaceMod , only : hlm_fates_interface_type + use ColumnType , only : col + ! implicit none private @@ -96,7 +99,9 @@ end subroutine NStateUpdateDynPatch !----------------------------------------------------------------------- subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, clump_index) + use CNSharedParamsMod , only : use_fun ! ! !DESCRIPTION: @@ -111,6 +116,9 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + integer , intent(in) :: clump_index + ! ! !LOCAL VARIABLES: integer :: c,p,j,l,g,k,i ! indices @@ -134,9 +142,23 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! soilbiogeochemistry fluxes TODO - this should be moved elsewhere ! plant to litter fluxes - phenology and dynamic landcover fluxes - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + + fc_loop: do fc = 1,num_soilc + c = filter_soilc(fc) + + fates_if: if( col%is_fates(c) ) then + + ! If this is a fates column, then we ask fates for the + ! litter fluxes, the following routine simply copies + ! prepared litter c flux boundary conditions into + ! cf_soil%decomp_cpools_sourcesink_col + + call clm_fates%UpdateNLitterfluxes(nf_soil,clump_index,c) + + else + + do j = 1, nlevdecomp + ! ! State update without the matrix solution ! @@ -151,19 +173,20 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! time step, but to be safe, I'm explicitly setting it to zero here. nf_soil%decomp_npools_sourcesink_col(c,j,i_cwd) = 0._r8 - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in SoilMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! + ! + ! For the matrix solution the actual state update comes after the matrix + ! multiply in SoilMatrix, but the matrix needs to be setup with + ! the equivalent of above. Those changes can be here or in the + ! native subroutines dealing with that field + ! else ! Do the above to the matrix solution do i = i_litr_min, i_litr_max end do end if end do - end do + end if fates_if + end do fc_loop do fp = 1,num_soilp p = filter_soilp(fp) diff --git a/src/biogeochem/CNNStateUpdate3Mod.F90 b/src/biogeochem/CNNStateUpdate3Mod.F90 index b5e3f32fec..26902cef22 100644 --- a/src/biogeochem/CNNStateUpdate3Mod.F90 +++ b/src/biogeochem/CNNStateUpdate3Mod.F90 @@ -25,11 +25,63 @@ module CNNStateUpdate3Mod private ! ! !PUBLIC MEMBER FUNCTIONS: - public:: NStateUpdate3 + public :: NStateUpdate3 + public :: NStateUpdateLeaching !----------------------------------------------------------------------- contains + subroutine NStateUpdateLeaching(num_soilc, filter_soilc, & + soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) + ! + ! !DESCRIPTION: + ! On the radiation time step, update all the prognostic nitrogen state + ! variables affected by the Sminn leaching flux. + ! RGK: This code was separated from gap mortality fluxes to make this + ! compatible with FATES. + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst + + ! !LOCAL VARIABLES: + integer :: c,p,j,l,k ! indices + integer :: fp,fc ! lake filter indices + real(r8):: dt ! radiation time step (seconds) + !----------------------------------------------------------------------- + + associate( & + nf_soil => soilbiogeochem_nitrogenflux_inst , & ! Input + ns_soil => soilbiogeochem_nitrogenstate_inst & ! Output + ) + + ! set time steps + dt = get_step_size_real() + + do j = 1, nlevdecomp + ! column loop + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (.not. use_nitrif_denitrif) then + ! mineral N loss due to leaching + ns_soil%sminn_vr_col(c,j) = ns_soil%sminn_vr_col(c,j) - nf_soil%sminn_leached_vr_col(c,j) * dt + else + ! mineral N loss due to leaching and runoff + ns_soil%smin_no3_vr_col(c,j) = max( ns_soil%smin_no3_vr_col(c,j) - & + ( nf_soil%smin_no3_leached_vr_col(c,j) + nf_soil%smin_no3_runoff_vr_col(c,j) ) * dt, 0._r8) + + ns_soil%sminn_vr_col(c,j) = ns_soil%smin_no3_vr_col(c,j) + ns_soil%smin_nh4_vr_col(c,j) + end if + end do + end do + + end associate + return + end subroutine NStateUpdateLeaching + !----------------------------------------------------------------------- subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & @@ -37,7 +89,7 @@ subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! ! !DESCRIPTION: ! On the radiation time step, update all the prognostic nitrogen state - ! variables affected by gap-phase mortality fluxes. Also the Sminn leaching flux. + ! variables affected by gap-phase mortality fluxes. ! NOTE - associate statements have been removed where there are ! no science equations. This increases readability and maintainability. ! @@ -72,20 +124,8 @@ subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & do fc = 1,num_soilc c = filter_soilc(fc) - if (.not. use_nitrif_denitrif) then - ! mineral N loss due to leaching - ns_soil%sminn_vr_col(c,j) = ns_soil%sminn_vr_col(c,j) - nf_soil%sminn_leached_vr_col(c,j) * dt - else - ! mineral N loss due to leaching and runoff - ns_soil%smin_no3_vr_col(c,j) = max( ns_soil%smin_no3_vr_col(c,j) - & - ( nf_soil%smin_no3_leached_vr_col(c,j) + nf_soil%smin_no3_runoff_vr_col(c,j) ) * dt, 0._r8) - - ns_soil%sminn_vr_col(c,j) = ns_soil%smin_no3_vr_col(c,j) + ns_soil%smin_nh4_vr_col(c,j) - end if - ! column level nitrogen fluxes from fire ! patch-level wood to column-level CWD (uncombusted wood) - ! ! State update without the matrix solution ! diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index c2a66511f7..510f2ba508 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -422,7 +422,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & ! gather all patch-level litterfall fluxes to the column for litter C and N inputs - call CNLitterToColumn(bounds, num_soilc, filter_soilc, & + call CNLitterToColumn(bounds, num_soilp, filter_soilp, & cnveg_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), & froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) @@ -3666,7 +3666,7 @@ subroutine CNCropHarvestToProductPools(bounds, num_soilp, filter_soilp, num_soil end subroutine CNCropHarvestToProductPools !----------------------------------------------------------------------- - subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + subroutine CNLitterToColumn (bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_state_inst,cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch, froot_prof_patch) ! @@ -3675,14 +3675,14 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & ! to the column level and assign them to the three litter pools ! ! !USES: - use clm_varpar , only : max_patch_per_col, nlevdecomp + use clm_varpar , only : nlevdecomp use pftconMod , only : npcropmin use clm_varctl , only : use_grainproduct ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches type(cnveg_state_type) , intent(in) :: cnveg_state_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst @@ -3690,7 +3690,7 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & real(r8) , intent(in) :: froot_prof_patch(bounds%begp:,1:) ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,k,j,i ! indices + integer :: fp,c,pi,p,k,j,i ! indices !----------------------------------------------------------------------- SHR_ASSERT_ALL_FL((ubound(leaf_prof_patch) == (/bounds%endp,nlevdecomp_full/)), sourcefile, __LINE__) @@ -3720,96 +3720,88 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) phenology_n_to_litr_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_n_col & ! Output: [real(r8) (:,:,:) ] N fluxes associated with phenology (litterfall and crop) to litter pools (gN/m3/s) ) - - do j = 1, nlevdecomp - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - c = filter_soilc(fc) + + do_nlev: do j = 1, nlevdecomp - if ( pi <= col%npatches(c) ) then - p = col%patchi(c) + pi - 1 - if (patch%active(p)) then + do_vegp: do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) + c = patch%column(p) - do i = i_litr_min, i_litr_max - ! leaf litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! leaf litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! fine root litter carbon fluxes + do_ilit: do i = i_litr_min, i_litr_max + ! leaf litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! leaf litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! fine root litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + + ! fine root litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do do_ilit + + ! agroibis puts crop stem litter together with leaf litter + ! so I've used the leaf lf_f* parameters instead of making + ! new ones for now (slevis) + ! also for simplicity I've put "food" into the litter pools + + if (ivt(p) >= npcropmin) then ! add livestemc to litter + do i = i_litr_min, i_litr_max + ! stem litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! stem litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + livestemn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + + if (.not. use_grainproduct) then + do i = i_litr_min, i_litr_max + do k = repr_grain_min, repr_grain_max + ! grain litter carbon fluxes phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - - ! fine root litter nitrogen fluxes + phenology_c_to_litr_c(c,j,i) + & + repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! grain litter nitrogen fluxes phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + phenology_n_to_litr_n(c,j,i) + & + repr_grainn_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) end do - - ! agroibis puts crop stem litter together with leaf litter - ! so I've used the leaf lf_f* parameters instead of making - ! new ones for now (slevis) - ! also for simplicity I've put "food" into the litter pools - - if (ivt(p) >= npcropmin) then ! add livestemc to litter - do i = i_litr_min, i_litr_max - ! stem litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! stem litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - livestemn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - - if (.not. use_grainproduct) then - do i = i_litr_min, i_litr_max - do k = repr_grain_min, repr_grain_max - ! grain litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! grain litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - repr_grainn_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - end if - - do i = i_litr_min, i_litr_max - do k = repr_structure_min, repr_structure_max - ! reproductive structure litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! reproductive structure litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - repr_structuren_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - end if - end if + end do end if - - end do - - end do - end do - - end associate - + + do i = i_litr_min, i_litr_max + do k = repr_structure_min, repr_structure_max + ! reproductive structure litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! reproductive structure litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + repr_structuren_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + end do + end if + end do do_vegp + end do do_nlev + + end associate + end subroutine CNLitterToColumn end module CNPhenologyMod diff --git a/src/biogeochem/CNPrecisionControlMod.F90 b/src/biogeochem/CNPrecisionControlMod.F90 index 8b98f6c3fb..787a5b54d7 100644 --- a/src/biogeochem/CNPrecisionControlMod.F90 +++ b/src/biogeochem/CNPrecisionControlMod.F90 @@ -96,7 +96,7 @@ subroutine CNPrecisionControlReadNML( NLFilename ) end subroutine CNPrecisionControlReadNML !----------------------------------------------------------------------- - subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & + subroutine CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & cnveg_nitrogenstate_inst) ! @@ -111,8 +111,8 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst @@ -190,8 +190,8 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ) ! patch loop - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) ! initialize the patch-level C and N truncation terms pc(p) = 0._r8 @@ -205,7 +205,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! the C component, but truncate C, C13, and N components ! leaf C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%leafc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%leafc_patch(bounds%begp:bounds%endp), & ns%leafn_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) @@ -223,7 +223,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! leaf storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%leafc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%leafc_storage_patch(bounds%begp:bounds%endp), & ns%leafn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -238,7 +238,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! leaf transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%leafc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%leafc_xfer_patch(bounds%begp:bounds%endp), & ns%leafn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -256,7 +256,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! EBK KO DML: For some reason frootc/frootn can go negative and allowing ! it to be negative is important for C4 crops (otherwise they die) Jun/3/2016 if ( prec_control_for_froot ) then - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%frootc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%frootc_patch(bounds%begp:bounds%endp), & ns%frootn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, allowneg=.true.) if (use_c13) then @@ -272,7 +272,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! froot storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%frootc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%frootc_storage_patch(bounds%begp:bounds%endp), & ns%frootn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -287,7 +287,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! froot transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%frootc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%frootc_xfer_patch(bounds%begp:bounds%endp), & ns%frootn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -304,7 +304,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & if ( use_crop )then do k = 1, nrepr ! grain C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%reproductivec_patch(bounds%begp:bounds%endp,k), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%reproductivec_patch(bounds%begp:bounds%endp,k), & ns%reproductiven_patch(bounds%begp:bounds%endp,k), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, croponly=.true. ) if (use_c13) then @@ -319,7 +319,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! grain storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, & cs%reproductivec_storage_patch(bounds%begp:bounds%endp,k), & ns%reproductiven_storage_patch(bounds%begp:bounds%endp,k), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep, croponly=.true. ) @@ -336,7 +336,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! grain transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, & cs%reproductivec_xfer_patch(bounds%begp:bounds%endp,k), & ns%reproductiven_xfer_patch(bounds%begp:bounds%endp,k), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, croponly=.true.) @@ -352,7 +352,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if end do ! grain transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%cropseedc_deficit_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%cropseedc_deficit_patch(bounds%begp:bounds%endp), & ns%cropseedn_deficit_patch(bounds%begp:bounds%endp), pc(bounds%begp:), & pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, & @@ -371,7 +371,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livestem C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livestemc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livestemc_patch(bounds%begp:bounds%endp), & ns%livestemn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -386,7 +386,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livestem storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livestemc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livestemc_storage_patch(bounds%begp:bounds%endp), & ns%livestemn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) @@ -401,7 +401,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & __LINE__) end if ! livestem transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livestemc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livestemc_xfer_patch(bounds%begp:bounds%endp), & ns%livestemn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -416,7 +416,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadstem C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadstemc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadstemc_patch(bounds%begp:bounds%endp), & ns%deadstemn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -430,7 +430,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & __LINE__) end if ! deadstem storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadstemc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadstemc_storage_patch(bounds%begp:bounds%endp), & ns%deadstemn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -445,7 +445,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadstem transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadstemc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadstemc_xfer_patch(bounds%begp:bounds%endp), & ns%deadstemn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -460,7 +460,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livecroot C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livecrootc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livecrootc_patch(bounds%begp:bounds%endp), & ns%livecrootn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -475,7 +475,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livecroot storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livecrootc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livecrootc_storage_patch(bounds%begp:bounds%endp), & ns%livecrootn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -490,7 +490,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livecroot transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livecrootc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livecrootc_xfer_patch(bounds%begp:bounds%endp), & ns%livecrootn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) @@ -506,7 +506,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadcroot C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadcrootc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadcrootc_patch(bounds%begp:bounds%endp), & ns%deadcrootn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -521,7 +521,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadcroot storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadcrootc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadcrootc_storage_patch(bounds%begp:bounds%endp), & ns%deadcrootn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -536,7 +536,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadcroot transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadcrootc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadcrootc_xfer_patch(bounds%begp:bounds%endp), & ns%deadcrootn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -551,7 +551,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! gresp_storage (C only) - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%gresp_storage_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%gresp_storage_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep) if (use_c13) then call TruncateAdditional( bounds, num_truncatep, filter_truncatep, & @@ -565,7 +565,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! gresp_xfer(c only) - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%gresp_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%gresp_xfer_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep) if (use_c13) then call TruncateAdditional( bounds, num_truncatep, filter_truncatep, & @@ -579,7 +579,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! cpool (C only) - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%cpool_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%cpool_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep) if (use_c13) then call TruncateAdditional( bounds, num_truncatep, filter_truncatep, & @@ -595,7 +595,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & if ( use_crop )then ! xsmrpool (C only) ! xsmr is a pool to balance the budget and as such can be freely negative - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%xsmrpool_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%xsmrpool_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep, & allowneg=.true., croponly=.true. ) if (use_c13) then @@ -612,16 +612,16 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! retransn (N only) - call TruncateNStates( bounds, filter_soilp, num_soilp, ns%retransn_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & + call TruncateNStates( bounds, filter_bgc_vegp, num_bgc_vegp, ns%retransn_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & __LINE__ ) ! npool (N only) - call TruncateNStates( bounds, filter_soilp, num_soilp, ns%npool_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & + call TruncateNStates( bounds, filter_bgc_vegp, num_bgc_vegp, ns%npool_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & __LINE__ ) ! patch loop - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) cs%ctrunc_patch(p) = cs%ctrunc_patch(p) + pc(p) @@ -639,7 +639,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end subroutine CNPrecisionControl - subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, nitrogen_patch, pc, pn, lineno, & + subroutine TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, carbon_patch, nitrogen_patch, pc, pn, lineno, & num_truncatep, filter_truncatep, croponly, allowneg ) ! ! !DESCRIPTION: @@ -657,8 +657,8 @@ subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, n ! !ARGUMENTS: implicit none type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches real(r8), intent(inout) :: carbon_patch(bounds%begp:) real(r8), intent(inout) :: nitrogen_patch(bounds%begp:) real(r8), intent(inout) :: pc(bounds%begp:) @@ -688,8 +688,8 @@ subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, n end if num_truncatep = 0 - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) if ( .not. lcroponly .or. (patch%itype(p) >= nc3crop) ) then if ( .not. lallowneg .and. ((carbon_patch(p) < cnegcrit) .or. (nitrogen_patch(p) < nnegcrit)) ) then @@ -733,7 +733,7 @@ subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, n end do end subroutine TruncateCandNStates - subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, lineno, & + subroutine TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, carbon_patch, pc, lineno, & num_truncatep, filter_truncatep, croponly, allowneg ) ! ! !DESCRIPTION: @@ -751,8 +751,8 @@ subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, l ! !ARGUMENTS: implicit none type(bounds_type), intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches real(r8) , intent(inout) :: carbon_patch(bounds%begp:) real(r8) , intent(inout) :: pc(bounds%begp:) integer , intent(in) :: lineno @@ -780,8 +780,8 @@ subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, l end if num_truncatep = 0 - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) if ( .not. lcroponly .or. (patch%itype(p) >= nc3crop) ) then if ( .not. lallowneg .and. (carbon_patch(p) < cnegcrit) ) then @@ -801,7 +801,7 @@ subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, l end do end subroutine TruncateCStates - subroutine TruncateNStates( bounds, filter_soilp, num_soilp, nitrogen_patch, pn, lineno ) + subroutine TruncateNStates( bounds, filter_bgc_vegp, num_bgc_vegp, nitrogen_patch, pn, lineno ) ! ! !DESCRIPTION: ! Truncate Nitrogen states. If a nitrogen state is too small truncate it to @@ -816,8 +816,8 @@ subroutine TruncateNStates( bounds, filter_soilp, num_soilp, nitrogen_patch, pn, ! !ARGUMENTS: implicit none type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches real(r8), intent(inout) :: nitrogen_patch(bounds%begp:) real(r8), intent(inout) :: pn(bounds%begp:) integer, intent(in) :: lineno @@ -826,8 +826,8 @@ subroutine TruncateNStates( bounds, filter_soilp, num_soilp, nitrogen_patch, pn, SHR_ASSERT_ALL_FL((ubound(nitrogen_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(pn) == (/bounds%endp/)), sourcefile, __LINE__) - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) if ( nitrogen_patch(p) < nnegcrit ) then ! write(iulog,*) 'WARNING: Nitrogen patch negative = ', nitrogen_patch ! call endrun(subgrid_index=p, subgrid_level=subgrid_level_patch, & diff --git a/src/biogeochem/CNProductsMod.F90 b/src/biogeochem/CNProductsMod.F90 index d1684e367b..4ef5c7c86f 100644 --- a/src/biogeochem/CNProductsMod.F90 +++ b/src/biogeochem/CNProductsMod.F90 @@ -19,7 +19,9 @@ module CNProductsMod ! ! !PUBLIC TYPES: type, public :: cn_products_type - private + + private ! Default these procedures to private, unless specified otherwise + ! ------------------------------------------------------------------------ ! Public instance variables ! ------------------------------------------------------------------------ @@ -49,9 +51,9 @@ module CNProductsMod real(r8), pointer :: gru_prod100_gain_grc(:) ! (g[C or N]/m2/s) gross unrepresented landcover addition to 100-year wood product pool real(r8), pointer :: gru_woodprod_gain_grc(:) ! (g[C or N]/m2/s) gross unrepresented landcover addition to wood product pools real(r8), pointer :: hrv_deadstem_to_prod10_patch(:) ! (g[C or N]/m2/s) dead stem harvest to 10-year wood product pool - real(r8), pointer :: hrv_deadstem_to_prod10_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 10-year wood product pool + real(r8), pointer,public :: hrv_deadstem_to_prod10_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 10-year wood product pool real(r8), pointer :: hrv_deadstem_to_prod100_patch(:) ! (g[C or N]/m2/s) dead stem harvest to 100-year wood product pool - real(r8), pointer :: hrv_deadstem_to_prod100_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 100-year wood product pool + real(r8), pointer,public :: hrv_deadstem_to_prod100_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 100-year wood product pool real(r8), pointer :: crop_harvest_to_cropprod1_patch(:) ! (g[C or N]/m2/s) crop harvest to 1-year crop product pool real(r8), pointer :: crop_harvest_to_cropprod1_grc(:) ! (g[C or N]/m2/s) crop harvest to 1-year crop product pool @@ -69,12 +71,14 @@ module CNProductsMod procedure, private :: InitHistory procedure, private :: InitCold procedure, public :: Restart - + procedure, public :: SetValues + ! Science routines procedure, public :: UpdateProducts procedure, private :: PartitionWoodFluxes procedure, private :: PartitionCropFluxes - procedure, private :: ComputeSummaryVars + procedure, public :: ComputeProductSummaryVars + procedure, public :: ComputeSummaryVars end type cn_products_type @@ -160,6 +164,29 @@ subroutine InitAllocate(this, bounds) end subroutine InitAllocate + subroutine SetValues(this, bounds, setval) + + ! !ARGUMENTS: + class(cn_products_type), intent(inout) :: this + type(bounds_type), intent(in) :: bounds + real(r8), intent(in) :: setval + + ! This zero's arrays that are incremented on each model time-step + ! the hrv_deadstem arrays use a p2g routine for the use_cn portion + ! but we added this zero'ing here because FATES needs it zero'd + + this%dwt_prod10_gain_grc(bounds%begg:bounds%endg) = setval + this%dwt_prod100_gain_grc(bounds%begg:bounds%endg) = setval + this%dwt_cropprod1_gain_grc(bounds%begg:bounds%endg) = setval + + this%crop_harvest_to_cropprod1_grc(bounds%begg:bounds%endg) = setval + this%hrv_deadstem_to_prod10_grc(bounds%begg:bounds%endg) = setval + this%hrv_deadstem_to_prod100_grc(bounds%begg:bounds%endg) = setval + + return + end subroutine SetValues + + !----------------------------------------------------------------------- subroutine InitHistory(this, bounds) ! !USES: @@ -475,6 +502,7 @@ subroutine UpdateProducts(this, bounds, & ! !DESCRIPTION: ! Update all loss fluxes from wood and crop product pools, and update product pool ! state variables for both loss and gain terms + ! This is only for non-fates patches and columns ! ! !ARGUMENTS: class(cn_products_type) , intent(inout) :: this @@ -484,13 +512,13 @@ subroutine UpdateProducts(this, bounds, & ! dynamic landcover addition to wood product pools (g/m2/s) [patch]; although this is ! a patch-level flux, it is expressed per unit GRIDCELL area - real(r8), intent(in) :: dwt_wood_product_gain_patch( bounds%begp: ) + real(r8), intent(in) :: dwt_wood_product_gain_patch(bounds%begp:) ! gross unrepresented landcover addition to wood product pools (g/m2/s) [patch] real(r8), intent(in) :: gru_wood_product_gain_patch( bounds%begp: ) ! wood harvest addition to wood product pools (g/m2/s) [patch] - real(r8), intent(in) :: wood_harvest_patch( bounds%begp: ) + real(r8), intent(in) :: wood_harvest_patch(bounds%begp:) ! dynamic landcover addition to crop product pools (g/m2/s) [patch]; although this is ! a patch-level flux, it is expressed per unit GRIDCELL area @@ -498,78 +526,30 @@ subroutine UpdateProducts(this, bounds, & ! crop harvest to crop product pool (g/m2/s) [patch] real(r8), intent(in) :: crop_harvest_to_cropprod_patch( bounds%begp: ) - ! - ! !LOCAL VARIABLES: - integer :: g ! indices - real(r8) :: dt ! time step (seconds) - real(r8) :: kprod1 ! decay constant for 1-year product pool - real(r8) :: kprod10 ! decay constant for 10-year product pool - real(r8) :: kprod100 ! decay constant for 100-year product pool - !----------------------------------------------------------------------- + SHR_ASSERT_ALL_FL((ubound(dwt_wood_product_gain_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(gru_wood_product_gain_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(wood_harvest_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(dwt_crop_product_gain_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(crop_harvest_to_cropprod_patch) == (/bounds%endp/)), sourcefile, __LINE__) - + call this%PartitionWoodFluxes(bounds, & num_soilp, filter_soilp, & dwt_wood_product_gain_patch(bounds%begp:bounds%endp), & gru_wood_product_gain_patch(bounds%begp:bounds%endp), & wood_harvest_patch(bounds%begp:bounds%endp)) - + call this%PartitionCropFluxes(bounds, & num_soilp, filter_soilp, & dwt_crop_product_gain_patch(bounds%begp:bounds%endp), & crop_harvest_to_cropprod_patch(bounds%begp:bounds%endp)) - ! calculate losses from product pools - ! the following (1/s) rate constants result in ~90% loss of initial state over 1, 10 and 100 years, - ! respectively, using a discrete-time fractional decay algorithm. - kprod1 = 7.2e-8_r8 - kprod10 = 7.2e-9_r8 - kprod100 = 7.2e-10_r8 - - do g = bounds%begg, bounds%endg - ! calculate fluxes out of product pools (1/sec) - this%cropprod1_loss_grc(g) = this%cropprod1_grc(g) * kprod1 - this%prod10_loss_grc(g) = this%prod10_grc(g) * kprod10 - this%prod100_loss_grc(g) = this%prod100_grc(g) * kprod100 - end do - - ! set time steps - dt = get_step_size_real() - - ! update product state variables - do g = bounds%begg, bounds%endg - - ! fluxes into wood & crop product pools, from landcover change - this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%dwt_cropprod1_gain_grc(g)*dt - this%prod10_grc(g) = this%prod10_grc(g) + this%dwt_prod10_gain_grc(g)*dt - this%prod100_grc(g) = this%prod100_grc(g) + this%dwt_prod100_gain_grc(g)*dt - - ! fluxes into wood & crop product pools, from gross unrepresented landcover change - this%prod10_grc(g) = this%prod10_grc(g) + this%gru_prod10_gain_grc(g)*dt - this%prod100_grc(g) = this%prod100_grc(g) + this%gru_prod100_gain_grc(g)*dt - - ! fluxes into wood & crop product pools, from harvest - this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%crop_harvest_to_cropprod1_grc(g)*dt - this%prod10_grc(g) = this%prod10_grc(g) + this%hrv_deadstem_to_prod10_grc(g)*dt - this%prod100_grc(g) = this%prod100_grc(g) + this%hrv_deadstem_to_prod100_grc(g)*dt - - ! fluxes out of wood & crop product pools, from decomposition - this%cropprod1_grc(g) = this%cropprod1_grc(g) - this%cropprod1_loss_grc(g)*dt - this%prod10_grc(g) = this%prod10_grc(g) - this%prod10_loss_grc(g)*dt - this%prod100_grc(g) = this%prod100_grc(g) - this%prod100_loss_grc(g)*dt - - end do - - call this%ComputeSummaryVars(bounds) - + return end subroutine UpdateProducts !----------------------------------------------------------------------- + subroutine PartitionWoodFluxes(this, bounds, & num_soilp, filter_soilp, & dwt_wood_product_gain_patch, & @@ -659,7 +639,7 @@ subroutine PartitionWoodFluxes(this, bounds, & this%hrv_deadstem_to_prod100_patch(p) = & wood_harvest_patch(p) * (1.0_r8 - pftcon%pprodharv10(patch%itype(p))) end do - + ! Average harvest fluxes from patch to gridcell call p2g(bounds, & this%hrv_deadstem_to_prod10_patch(bounds%begp:bounds%endp), & @@ -667,24 +647,18 @@ subroutine PartitionWoodFluxes(this, bounds, & p2c_scale_type = 'unity', & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') - + call p2g(bounds, & this%hrv_deadstem_to_prod100_patch(bounds%begp:bounds%endp), & this%hrv_deadstem_to_prod100_grc(bounds%begg:bounds%endg), & p2c_scale_type = 'unity', & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') - - ! Zero the dwt gains - do g = bounds%begg, bounds%endg - this%dwt_prod10_gain_grc(g) = 0._r8 - this%dwt_prod100_gain_grc(g) = 0._r8 - end do - + ! Partition dynamic land cover fluxes to 10 and 100-year product pools. do p = bounds%begp, bounds%endp g = patch%gridcell(p) - + ! Note that pprod10 + pprod100 do NOT sum to 1: some fraction of the dwt changes ! was lost to other fluxes. dwt_wood_product_gain_patch gives the amount that goes ! to all product pools, so we need to determine the fraction of that flux that @@ -702,14 +676,15 @@ subroutine PartitionWoodFluxes(this, bounds, & dwt_wood_product_gain_patch(p) * pprod10_frac this%dwt_prod100_gain_grc(g) = this%dwt_prod100_gain_grc(g) + & dwt_wood_product_gain_patch(p) * pprod100_frac + else if (dwt_wood_product_gain_patch(p) > 0) then call endrun(& msg='ERROR: dwt_wood_product_gain_patch(p) > 0' // & errMsg(sourcefile, __LINE__)) end if - + end do - + end subroutine PartitionWoodFluxes !----------------------------------------------------------------------- @@ -768,10 +743,6 @@ subroutine PartitionCropFluxes(this, bounds, & ! Determine gains from dynamic landcover - do g = bounds%begg, bounds%endg - this%dwt_cropprod1_gain_grc(g) = 0._r8 - end do - do p = bounds%begp, bounds%endp g = patch%gridcell(p) @@ -784,6 +755,61 @@ subroutine PartitionCropFluxes(this, bounds, & end subroutine PartitionCropFluxes + !----------------------------------------------------------------------- + subroutine ComputeProductSummaryVars(this, bounds) + + class(cn_products_type) , intent(inout) :: this + type(bounds_type) , intent(in) :: bounds + + integer :: g ! indices + real(r8) :: dt ! time step (seconds) + real(r8) :: kprod1 ! decay constant for 1-year product pool + real(r8) :: kprod10 ! decay constant for 10-year product pool + real(r8) :: kprod100 ! decay constant for 100-year product pool + + ! calculate losses from product pools + ! the following (1/s) rate constants result in ~90% loss of initial state over 1, 10 and 100 years, + ! respectively, using a discrete-time fractional decay algorithm. + kprod1 = 7.2e-8_r8 + kprod10 = 7.2e-9_r8 + kprod100 = 7.2e-10_r8 + + do g = bounds%begg, bounds%endg + ! calculate fluxes out of product pools (1/sec) + this%cropprod1_loss_grc(g) = this%cropprod1_grc(g) * kprod1 + this%prod10_loss_grc(g) = this%prod10_grc(g) * kprod10 + this%prod100_loss_grc(g) = this%prod100_grc(g) * kprod100 + end do + + ! set time steps + dt = get_step_size_real() + + ! update product state variables + do g = bounds%begg, bounds%endg + + ! fluxes into wood & crop product pools, from landcover change + this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%dwt_cropprod1_gain_grc(g)*dt + this%prod10_grc(g) = this%prod10_grc(g) + this%dwt_prod10_gain_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) + this%dwt_prod100_gain_grc(g)*dt + + ! fluxes into wood & grain product pools, from gross unrepresented landcover change + this%prod10_grc(g) = this%prod10_grc(g) + this%gru_prod10_gain_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) + this%gru_prod100_gain_grc(g)*dt + + ! fluxes into wood & crop product pools, from harvest + this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%crop_harvest_to_cropprod1_grc(g)*dt + this%prod10_grc(g) = this%prod10_grc(g) + this%hrv_deadstem_to_prod10_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) + this%hrv_deadstem_to_prod100_grc(g)*dt + + ! fluxes out of wood & crop product pools, from decomposition + this%cropprod1_grc(g) = this%cropprod1_grc(g) - this%cropprod1_loss_grc(g)*dt + this%prod10_grc(g) = this%prod10_grc(g) - this%prod10_loss_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) - this%prod100_loss_grc(g)*dt + end do + + return + end subroutine ComputeProductSummaryVars + !----------------------------------------------------------------------- subroutine ComputeSummaryVars(this, bounds) @@ -799,10 +825,9 @@ subroutine ComputeSummaryVars(this, bounds) ! ! !LOCAL VARIABLES: integer :: g ! indices - - character(len=*), parameter :: subname = 'ComputeSummaryVars' !----------------------------------------------------------------------- - + character(len=*), parameter :: subname = 'ComputeSummaryVars' + do g = bounds%begg, bounds%endg ! total wood products diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index c2025fca47..21a4fc902c 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -434,21 +434,23 @@ module CNVegCarbonFluxType contains !------------------------------------------------------------------------ - subroutine Init(this, bounds, carbon_type, dribble_crophrv_xsmrpool_2atm) + subroutine Init(this, bounds, carbon_type, dribble_crophrv_xsmrpool_2atm,alloc_full_veg) class(cnveg_carbonflux_type) :: this type(bounds_type), intent(in) :: bounds character(len=3) , intent(in) :: carbon_type ! one of ['c12', c13','c14'] logical , intent(in) :: dribble_crophrv_xsmrpool_2atm + logical , intent(in) :: alloc_full_veg this%dribble_crophrv_xsmrpool_2atm = dribble_crophrv_xsmrpool_2atm - call this%InitAllocate ( bounds, carbon_type) - if(use_matrixcn)then - call this%InitTransfer () + call this%InitAllocate ( bounds, carbon_type,alloc_full_veg) + if(alloc_full_veg)then + if(use_matrixcn)then + call this%InitTransfer () + end if + call this%InitHistory ( bounds, carbon_type ) + call this%InitCold (bounds ) end if - call this%InitHistory ( bounds, carbon_type ) - call this%InitCold (bounds ) - end subroutine Init subroutine InitTransfer (this) @@ -461,12 +463,13 @@ subroutine InitTransfer (this) end subroutine InitTransfer !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds, carbon_type) + subroutine InitAllocate(this, bounds, carbon_type, alloc_full_veg) ! ! !ARGUMENTS: class (cnveg_carbonflux_type) :: this type(bounds_type), intent(in) :: bounds character(len=*) , intent(in) :: carbon_type ! one of ['c12', c13','c14'] + logical , intent(in) :: alloc_full_veg ! ! !LOCAL VARIABLES: integer :: begp,endp @@ -476,9 +479,15 @@ subroutine InitAllocate(this, bounds, carbon_type) character(len=:), allocatable :: carbon_type_suffix !------------------------------------------------------------------------ - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg + if(alloc_full_veg)then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0; endp = 0 + begc = 0; endc = 0 + begg = 0; endg = 0 + end if allocate(this%m_leafc_to_litter_patch (begp:endp)) ; this%m_leafc_to_litter_patch (:) = nan allocate(this%m_frootc_to_litter_patch (begp:endp)) ; this%m_frootc_to_litter_patch (:) = nan diff --git a/src/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index 610689fdb6..7515051d38 100644 --- a/src/biogeochem/CNVegCarbonStateType.F90 +++ b/src/biogeochem/CNVegCarbonStateType.F90 @@ -68,7 +68,6 @@ module CNVegCarbonStateType real(r8), pointer :: ctrunc_patch (:) ! (gC/m2) patch-level sink for C truncation real(r8), pointer :: woodc_patch (:) ! (gC/m2) wood C real(r8), pointer :: leafcmax_patch (:) ! (gC/m2) ann max leaf C - real(r8), pointer :: totc_patch (:) ! (gC/m2) total patch-level carbon, including cpool real(r8), pointer :: rootc_col (:) ! (gC/m2) root carbon at column level (fire) real(r8), pointer :: leafc_col (:) ! (gC/m2) column-level leafc (fire) real(r8), pointer :: deadstemc_col (:) ! (gC/m2) column-level deadstemc (fire) @@ -82,21 +81,21 @@ module CNVegCarbonStateType ! summary (diagnostic) state variables, not involved in mass balance real(r8), pointer :: dispvegc_patch (:) ! (gC/m2) displayed veg carbon, excluding storage and cpool real(r8), pointer :: storvegc_patch (:) ! (gC/m2) stored vegetation carbon, excluding cpool + + logical, private :: dribble_crophrv_xsmrpool_2atm ! Flag to indicate if should harvest xsmrpool to the atmosphere + ! it originates and is defined in CNVegetationFacade.F90 + + ! Total C pools + real(r8), pointer :: totc_patch (:) ! (gC/m2) total patch-level carbon, including cpool real(r8), pointer :: totvegc_patch (:) ! (gC/m2) total vegetation carbon, excluding cpool - real(r8), pointer :: totvegc_col (:) ! (gC/m2) total vegetation carbon, excluding cpool averaged to column (p2c) - - ! Total C pools + real(r8), pointer :: totvegc_col (:) ! (gC/m2) total vegetation carbon, excluding cpool averaged to column (p2c) real(r8), pointer :: totc_p2c_col (:) ! (gC/m2) totc_patch averaged to col - real(r8), pointer :: totc_col (:) ! (gC/m2) total column carbon, incl veg and cpool - real(r8), pointer :: totecosysc_col (:) ! (gC/m2) total ecosystem carbon, incl veg but excl cpool - real(r8), pointer :: totc_grc (:) ! (gC/m2) total gridcell carbon - - logical, private :: dribble_crophrv_xsmrpool_2atm + contains procedure , public :: Init procedure , public :: SetValues - procedure , public :: ZeroDWT + procedure , public :: ZeroDwt procedure , public :: Restart procedure , public :: Summary => Summary_carbonstate procedure , public :: DynamicPatchAdjustments ! adjust state variables when patch areas change @@ -127,7 +126,7 @@ module CNVegCarbonStateType !------------------------------------------------------------------------ subroutine Init(this, bounds, carbon_type, ratio, NLFilename, & - dribble_crophrv_xsmrpool_2atm, c12_cnveg_carbonstate_inst) + dribble_crophrv_xsmrpool_2atm, alloc_full_veg, c12_cnveg_carbonstate_inst) class(cnveg_carbonstate_type) :: this type(bounds_type) , intent(in) :: bounds @@ -135,6 +134,7 @@ subroutine Init(this, bounds, carbon_type, ratio, NLFilename, & character(len=*) , intent(in) :: carbon_type ! Carbon isotope type C12, C13 or C1 character(len=*) , intent(in) :: NLFilename ! Namelist filename logical , intent(in) :: dribble_crophrv_xsmrpool_2atm + logical , intent(in) :: alloc_full_veg ! total number of bgc patches (non-fates) type(cnveg_carbonstate_type) , intent(in), optional :: c12_cnveg_carbonstate_inst ! cnveg_carbonstate for C12 (if C13 or C14) !----------------------------------------------------------------------- @@ -142,15 +142,17 @@ subroutine Init(this, bounds, carbon_type, ratio, NLFilename, & this%dribble_crophrv_xsmrpool_2atm = dribble_crophrv_xsmrpool_2atm - call this%InitAllocate ( bounds) - call this%InitReadNML ( NLFilename ) - call this%InitHistory ( bounds, carbon_type) - if (present(c12_cnveg_carbonstate_inst)) then - call this%InitCold ( bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst ) - else - call this%InitCold ( bounds, ratio, carbon_type ) + call this%InitAllocate ( bounds, alloc_full_veg) + if(alloc_full_veg)then + call this%InitReadNML ( NLFilename ) + call this%InitHistory ( bounds, carbon_type) + if (present(c12_cnveg_carbonstate_inst)) then + call this%InitCold ( bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst ) + else + call this%InitCold ( bounds, ratio, carbon_type ) + end if end if - + end subroutine Init !------------------------------------------------------------------------ @@ -214,21 +216,28 @@ subroutine InitReadNML(this, NLFilename) end subroutine InitReadNML !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !ARGUMENTS: class (cnveg_carbonstate_type) :: this - type(bounds_type), intent(in) :: bounds + type(bounds_type), intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! Total number of bgc patches on the proc (non_fates) ! ! !LOCAL VARIABLES: integer :: begp,endp integer :: begc,endc integer :: begg,endg !------------------------------------------------------------------------ - - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg + + if(alloc_full_veg)then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0;endp=0 + begc = 0;endc=0 + begg = 0;endg=0 + end if allocate(this%leafc_patch (begp:endp)) ; this%leafc_patch (:) = nan allocate(this%leafc_storage_patch (begp:endp)) ; this%leafc_storage_patch (:) = nan @@ -277,9 +286,6 @@ subroutine InitAllocate(this, bounds) allocate(this%totvegc_col (begc:endc)) ; this%totvegc_col (:) = nan allocate(this%totc_p2c_col (begc:endc)) ; this%totc_p2c_col (:) = nan - allocate(this%totc_col (begc:endc)) ; this%totc_col (:) = nan - allocate(this%totecosysc_col (begc:endc)) ; this%totecosysc_col (:) = nan - allocate(this%totc_grc (begg:endg)) ; this%totc_grc (:) = nan ! Matrix solution variables if(use_matrixcn)then @@ -509,16 +515,6 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='fuel load', & ptr_col=this%fuelc_col) - this%totc_col(begc:endc) = spval - call hist_addfld1d (fname='TOTCOLC', units='gC/m^2', & - avgflag='A', long_name='total column carbon, incl veg and cpool but excl product pools', & - ptr_col=this%totc_col) - - this%totecosysc_col(begc:endc) = spval - call hist_addfld1d (fname='TOTECOSYSC', units='gC/m^2', & - avgflag='A', long_name='total ecosystem carbon, incl veg but excl cpool and product pools', & - ptr_col=this%totecosysc_col) - ! Matrix solution history variables if ( use_matrixcn )then end if @@ -675,16 +671,6 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 pool for seeding new PFTs via dynamic landcover', & ptr_gcell=this%seedc_grc, default='inactive') - this%totc_col(begc:endc) = spval - call hist_addfld1d (fname='C13_TOTCOLC', units='gC13/m^2', & - avgflag='A', long_name='C13 total column carbon, incl veg and cpool but excl product pools', & - ptr_col=this%totc_col, default='inactive') - - this%totecosysc_col(begc:endc) = spval - call hist_addfld1d (fname='C13_TOTECOSYSC', units='gC13/m^2', & - avgflag='A', long_name='C13 total ecosystem carbon, incl veg but excl cpool and product pools', & - ptr_col=this%totecosysc_col) - if (use_crop) then this%reproductivec_patch(begp:endp,:) = spval do k = 1, nrepr @@ -866,16 +852,6 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 pool for seeding new PFTs via dynamic landcover', & ptr_gcell=this%seedc_grc, default='inactive') - this%totc_col(begc:endc) = spval - call hist_addfld1d (fname='C14_TOTCOLC', units='gC14/m^2', & - avgflag='A', long_name='C14 total column carbon, incl veg and cpool but excl product pools', & - ptr_col=this%totc_col, default='inactive') - - this%totecosysc_col(begc:endc) = spval - call hist_addfld1d (fname='C14_TOTECOSYSC', units='gC14/m^2', & - avgflag='A', long_name='C14 total ecosystem carbon, incl veg but excl cpool and product pools', & - ptr_col=this%totecosysc_col) - if (use_crop) then this%reproductivec_patch(begp:endp,:) = spval do k = 1, nrepr @@ -1099,16 +1075,14 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst ! this%totgrainc_col(c) = 0._r8 ! total carbon pools - this%totecosysc_col(c) = 0._r8 this%totc_p2c_col(c) = 0._r8 - this%totc_col(c) = 0._r8 + end if end do do g = bounds%begg, bounds%endg this%seedc_grc(g) = 0._r8 - this%totc_grc(g) = 0._r8 end do ! initialize fields for special filters @@ -2596,8 +2570,6 @@ subroutine SetValues ( this, & this%fuelc_crop_col(i) = value_column this%totvegc_col(i) = value_column this%totc_p2c_col(i) = value_column - this%totc_col(i) = value_column - this%totecosysc_col(i) = value_column end do end subroutine SetValues @@ -2625,11 +2597,8 @@ subroutine ZeroDwt( this, bounds ) end subroutine ZeroDwt !----------------------------------------------------------------------- - subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col, soilbiogeochem_totlitc_col, & - soilbiogeochem_totmicc_col, soilbiogeochem_totsomc_col, & - soilbiogeochem_ctrunc_col) + subroutine Summary_carbonstate(this, bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) + ! ! !USES: use subgridAveMod, only : p2c @@ -2642,33 +2611,20 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & ! !ARGUMENTS: class(cnveg_carbonstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter - integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches - real(r8) , intent(in) :: soilbiogeochem_cwdc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_totmicc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_totlitc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_totsomc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_ctrunc_col(bounds%begc:) + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches + ! ! !LOCAL VARIABLES: integer :: c,p,j,k,l ! indices integer :: fp,fc ! lake filter indices !----------------------------------------------------------------------- - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_cwdc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totmicc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totlitc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totsomc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_ctrunc_col) == (/bounds%endc/)), sourcefile, __LINE__) - ! calculate patch -level summary of carbon state - - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) ! displayed vegetation carbon, excluding storage and cpool (DISPVEGC) this%dispvegc_patch(p) = & @@ -2738,36 +2694,16 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & ! -------------------------------------------- ! column level summary ! -------------------------------------------- - - call p2c(bounds, num_soilc, filter_soilc, & - this%totvegc_patch(bounds%begp:bounds%endp), & - this%totvegc_col(bounds%begc:bounds%endc)) - - call p2c(bounds, num_soilc, filter_soilc, & - this%totc_patch(bounds%begp:bounds%endp), & - this%totc_p2c_col(bounds%begc:bounds%endc)) - - do fc = 1,num_allc - c = filter_allc(fc) - - ! total ecosystem carbon, including veg but excluding cpool (TOTECOSYSC) - this%totecosysc_col(c) = & - soilbiogeochem_cwdc_col(c) + & - soilbiogeochem_totmicc_col(c) + & - soilbiogeochem_totlitc_col(c) + & - soilbiogeochem_totsomc_col(c) + & - this%totvegc_col(c) - - ! total column carbon, including veg and cpool (TOTCOLC) - this%totc_col(c) = this%totc_p2c_col(c) + & - soilbiogeochem_cwdc_col(c) + & - soilbiogeochem_totmicc_col(c) + & - soilbiogeochem_totlitc_col(c) + & - soilbiogeochem_totsomc_col(c) + & - soilbiogeochem_ctrunc_col(c) - - end do - + if(num_bgc_vegp>0)then + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + this%totvegc_patch(bounds%begp:bounds%endp), & + this%totvegc_col(bounds%begc:bounds%endc)) + + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + this%totc_patch(bounds%begp:bounds%endp), & + this%totc_p2c_col(bounds%begc:bounds%endc)) + end if + end subroutine Summary_carbonstate !----------------------------------------------------------------------- diff --git a/src/biogeochem/CNVegNitrogenFluxType.F90 b/src/biogeochem/CNVegNitrogenFluxType.F90 index ce164b4c37..b06ec367d0 100644 --- a/src/biogeochem/CNVegNitrogenFluxType.F90 +++ b/src/biogeochem/CNVegNitrogenFluxType.F90 @@ -292,18 +292,21 @@ module CNVegNitrogenFluxType contains !------------------------------------------------------------------------ - subroutine Init(this, bounds) + subroutine Init(this, bounds, alloc_full_veg) class(cnveg_nitrogenflux_type) :: this - type(bounds_type), intent(in) :: bounds + type(bounds_type), intent(in) :: bounds + logical,intent(in) :: alloc_full_veg - call this%InitAllocate (bounds) - if(use_matrixcn)then - call this%InitTransfer () + call this%InitAllocate (bounds,alloc_full_veg) + if(alloc_full_veg)then + if(use_matrixcn)then + call this%InitTransfer () + end if + call this%InitHistory (bounds) + call this%InitCold (bounds) end if - call this%InitHistory (bounds) - call this%InitCold (bounds) - + end subroutine Init subroutine InitTransfer (this) @@ -323,14 +326,15 @@ subroutine InitTransfer (this) end subroutine InitTransfer !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !DESCRIPTION: ! Initialize patch nitrogen flux ! ! !ARGUMENTS: class (cnveg_nitrogenflux_type) :: this - type(bounds_type) , intent(in) :: bounds + type(bounds_type) , intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! ! !LOCAL VARIABLES: integer :: begp,endp @@ -338,10 +342,16 @@ subroutine InitAllocate(this, bounds) integer :: begg,endg !------------------------------------------------------------------------ - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg - + if(alloc_full_veg)then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0; endp = 0 + begc = 0; endc = 0 + begg = 0; endg = 0 + end if + allocate(this%m_leafn_to_litter_patch (begp:endp)) ; this%m_leafn_to_litter_patch (:) = nan allocate(this%m_frootn_to_litter_patch (begp:endp)) ; this%m_frootn_to_litter_patch (:) = nan allocate(this%m_leafn_storage_to_litter_patch (begp:endp)) ; this%m_leafn_storage_to_litter_patch (:) = nan diff --git a/src/biogeochem/CNVegNitrogenStateType.F90 b/src/biogeochem/CNVegNitrogenStateType.F90 index f09311e518..8983eccb4e 100644 --- a/src/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/biogeochem/CNVegNitrogenStateType.F90 @@ -69,9 +69,7 @@ module CNVegNitrogenStateType real(r8), pointer :: totvegn_col (:) ! (gN/m2) total vegetation nitrogen (p2c) real(r8), pointer :: totn_patch (:) ! (gN/m2) total patch-level nitrogen real(r8), pointer :: totn_p2c_col (:) ! (gN/m2) totn_patch averaged to col - real(r8), pointer :: totn_col (:) ! (gN/m2) total column nitrogen, incl veg - real(r8), pointer :: totecosysn_col (:) ! (gN/m2) total ecosystem nitrogen, incl veg - real(r8), pointer :: totn_grc (:) ! (gN/m2) total gridcell nitrogen + ! acc spinup for matrix solution @@ -98,40 +96,49 @@ module CNVegNitrogenStateType !------------------------------------------------------------------------ subroutine Init(this, bounds, & - leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, deadstemc_patch) + leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, & + deadstemc_patch, alloc_full_veg) class(cnveg_nitrogenstate_type) :: this type(bounds_type) , intent(in) :: bounds - real(r8) , intent(in) :: leafc_patch (bounds%begp:) - real(r8) , intent(in) :: leafc_storage_patch (bounds%begp:) - real(r8) , intent(in) :: frootc_patch (bounds%begp:) - real(r8) , intent(in) :: frootc_storage_patch (bounds%begp:) - real(r8) , intent(in) :: deadstemc_patch (bounds%begp:) - - call this%InitAllocate (bounds ) - call this%InitHistory (bounds) - call this%InitCold ( bounds, & - leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, deadstemc_patch) - + real(r8) , intent(in) :: leafc_patch (:) !(begp:) + real(r8) , intent(in) :: leafc_storage_patch (:) !(begp:) + real(r8) , intent(in) :: frootc_patch (:) !(begp:) + real(r8) , intent(in) :: frootc_storage_patch(:) !(begp:) + real(r8) , intent(in) :: deadstemc_patch (:) !(begp:) + logical , intent(in) :: alloc_full_veg + + call this%InitAllocate (bounds, alloc_full_veg) + if(alloc_full_veg) then + call this%InitHistory (bounds) + call this%InitCold ( bounds, & + leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, deadstemc_patch) + end if end subroutine Init !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !ARGUMENTS: class (cnveg_nitrogenstate_type) :: this - type(bounds_type) , intent(in) :: bounds + type(bounds_type) , intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! ! !LOCAL VARIABLES: integer :: begp,endp integer :: begc,endc integer :: begg,endg !------------------------------------------------------------------------ - - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg - + if(alloc_full_veg) then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0; endp = 0 + begc = 0; endc = 0 + begg = 0; endg = 0 + end if + allocate(this%reproductiven_patch (begp:endp, nrepr)) ; this%reproductiven_patch (:,:) = nan allocate(this%reproductiven_storage_patch (begp:endp, nrepr)) ; this%reproductiven_storage_patch (:,:) = nan allocate(this%reproductiven_xfer_patch (begp:endp, nrepr)) ; this%reproductiven_xfer_patch (:,:) = nan @@ -167,9 +174,7 @@ subroutine InitAllocate(this, bounds) allocate(this%seedn_grc (begg:endg)) ; this%seedn_grc (:) = nan allocate(this%totvegn_col (begc:endc)) ; this%totvegn_col (:) = nan allocate(this%totn_p2c_col (begc:endc)) ; this%totn_p2c_col (:) = nan - allocate(this%totn_col (begc:endc)) ; this%totn_col (:) = nan - allocate(this%totecosysn_col (begc:endc)) ; this%totecosysn_col (:) = nan - allocate(this%totn_grc (begg:endg)) ; this%totn_grc (:) = nan + ! Matrix solution allocations if ( use_matrixcn )then @@ -376,15 +381,7 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='pool for seeding new PFTs via dynamic landcover', & ptr_gcell=this%seedn_grc) - this%totecosysn_col(begc:endc) = spval - call hist_addfld1d (fname='TOTECOSYSN', units='gN/m^2', & - avgflag='A', long_name='total ecosystem N, excluding product pools', & - ptr_col=this%totecosysn_col) - this%totn_col(begc:endc) = spval - call hist_addfld1d (fname='TOTCOLN', units='gN/m^2', & - avgflag='A', long_name='total column-level N, excluding product pools', & - ptr_col=this%totn_col) end subroutine InitHistory @@ -558,16 +555,13 @@ subroutine InitCold(this, bounds, & l = col%landunit(c) if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then ! total nitrogen pools - this%totecosysn_col(c) = 0._r8 this%totn_p2c_col(c) = 0._r8 - this%totn_col(c) = 0._r8 end if end do do g = bounds%begg, bounds%endg this%seedn_grc(g) = 0._r8 - this%totn_grc(g) = 0._r8 end do ! now loop through special filters and explicitly set the variables that @@ -1024,11 +1018,8 @@ subroutine SetValues ( this, & do fi = 1,num_column i = filter_column(fi) - - this%totecosysn_col(i) = value_column this%totvegn_col(i) = value_column this%totn_p2c_col(i) = value_column - this%totn_col(i) = value_column end do end subroutine SetValues @@ -1057,24 +1048,20 @@ subroutine ZeroDwt( this, bounds ) end subroutine ZeroDwt !----------------------------------------------------------------------- - subroutine Summary_nitrogenstate(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp,& - soilbiogeochem_nitrogenstate_inst) + subroutine Summary_nitrogenstate(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soilp) ! ! !USES: use subgridAveMod, only : p2c - use SoilBiogeochemNitrogenStateType, only : soilbiogeochem_nitrogenstate_type + ! ! !ARGUMENTS: class(cnveg_nitrogenstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter - integer , intent(in) :: filter_allc(:) ! filter for all active columns integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches - type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst + ! ! !LOCAL VARIABLES: integer :: c,p,j,k,l ! indices @@ -1148,38 +1135,16 @@ subroutine Summary_nitrogenstate(this, bounds, num_allc, filter_allc, & ! -------------------------------------------- ! column level summary ! -------------------------------------------- + if(num_soilp>0)then + call p2c(bounds, num_soilc, filter_soilc, & + this%totvegn_patch(bounds%begp:bounds%endp), & + this%totvegn_col(bounds%begc:bounds%endc)) + + call p2c(bounds, num_soilc, filter_soilc, & + this%totn_patch(bounds%begp:bounds%endp), & + this%totn_p2c_col(bounds%begc:bounds%endc)) + end if - call p2c(bounds, num_soilc, filter_soilc, & - this%totvegn_patch(bounds%begp:bounds%endp), & - this%totvegn_col(bounds%begc:bounds%endc)) - - call p2c(bounds, num_soilc, filter_soilc, & - this%totn_patch(bounds%begp:bounds%endp), & - this%totn_p2c_col(bounds%begc:bounds%endc)) - - do fc = 1,num_allc - c = filter_allc(fc) - - ! total ecosystem nitrogen, including veg (TOTECOSYSN) - this%totecosysn_col(c) = & - soilbiogeochem_nitrogenstate_inst%cwdn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totlitn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totmicn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totsomn_col(c) + & - soilbiogeochem_nitrogenstate_inst%sminn_col(c) + & - this%totvegn_col(c) - - ! total column nitrogen, including patch (TOTCOLN) - - this%totn_col(c) = this%totn_p2c_col(c) + & - soilbiogeochem_nitrogenstate_inst%cwdn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totlitn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totmicn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totsomn_col(c) + & - soilbiogeochem_nitrogenstate_inst%sminn_col(c) + & - soilbiogeochem_nitrogenstate_inst%ntrunc_col(c) - - end do end subroutine Summary_nitrogenstate diff --git a/src/biogeochem/CNVegStateType.F90 b/src/biogeochem/CNVegStateType.F90 index e7e61c75bf..c286c0344f 100644 --- a/src/biogeochem/CNVegStateType.F90 +++ b/src/biogeochem/CNVegStateType.F90 @@ -130,21 +130,24 @@ module CNVegStateType contains !------------------------------------------------------------------------ - subroutine Init(this, bounds) + subroutine Init(this, bounds, alloc_full_veg) class(cnveg_state_type) :: this type(bounds_type), intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! Total number of bgc patches on proc (non-fates) - call this%InitAllocate ( bounds ) + call this%InitAllocate ( bounds, alloc_full_veg) if (use_cn) then call this%InitHistory ( bounds ) end if - call this%InitCold ( bounds ) - + if(alloc_full_veg) then !This is true if not use_fates_bgc + call this%InitCold ( bounds ) + end if + end subroutine Init !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !DESCRIPTION: ! Initialize module data structure @@ -156,6 +159,7 @@ subroutine InitAllocate(this, bounds) ! !ARGUMENTS: class(cnveg_state_type) :: this type(bounds_type), intent(in) :: bounds + logical, intent(in) :: alloc_full_veg ! Total number of bgc patches on proc (non-fates) ! ! !LOCAL VARIABLES: integer :: begp, endp @@ -163,9 +167,15 @@ subroutine InitAllocate(this, bounds) logical :: allows_non_annual_delta !------------------------------------------------------------------------ - begp = bounds%begp; endp= bounds%endp - begc = bounds%begc; endc= bounds%endc - + if(alloc_full_veg)then + begp = bounds%begp; endp= bounds%endp + begc = bounds%begc; endc= bounds%endc + else + begp = 0;endp = 0 + begc = 0;endc = 0 + end if + + ! Note that we set allows_non_annual_delta to false because we expect land cover ! change to be applied entirely at the start of the year. Currently the fire code ! appears to assume that the land cover change rate is constant throughout the year, @@ -495,7 +505,7 @@ subroutine InitHistory(this, bounds) end subroutine InitHistory !----------------------------------------------------------------------- - subroutine initCold(this, bounds) + subroutine InitCold(this, bounds) ! ! !USES: ! @@ -615,7 +625,7 @@ subroutine initCold(this, bounds) this%lfc2_col(c) = 0._r8 end do - end subroutine initCold + end subroutine InitCold !------------------------------------------------------------------------ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & diff --git a/src/biogeochem/CNVegStructUpdateMod.F90 b/src/biogeochem/CNVegStructUpdateMod.F90 index 01209c678f..2e8ed8539b 100644 --- a/src/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/biogeochem/CNVegStructUpdateMod.F90 @@ -143,7 +143,7 @@ subroutine CNVegStructUpdate(bounds,num_soilp, filter_soilp, & dt = real( get_rad_step_size(), r8 ) ! patch loop - do fp = 1,num_soilp + do_patch:do fp = 1,num_soilp p = filter_soilp(fp) c = patch%column(p) g = patch%gridcell(p) @@ -317,7 +317,7 @@ subroutine CNVegStructUpdate(bounds,num_soilp, filter_soilp, & frac_veg_nosno_alb(p) = 0 end if - end do + end do do_patch end associate diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90 index cc625e2a36..61e2e9cf91 100644 --- a/src/biogeochem/CNVegetationFacade.F90 +++ b/src/biogeochem/CNVegetationFacade.F90 @@ -44,7 +44,7 @@ module CNVegetationFacade use shr_log_mod , only : errMsg => shr_log_errMsg use perf_mod , only : t_startf, t_stopf use decompMod , only : bounds_type - use clm_varctl , only : iulog, use_cn, use_cndv, use_c13, use_c14 + use clm_varctl , only : iulog, use_cn, use_cndv, use_c13, use_c14, use_fates_bgc use abortutils , only : endrun use spmdMod , only : masterproc use clm_time_manager , only : get_curr_date, get_ref_date @@ -206,6 +206,8 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) use CNFireFactoryMod , only : create_cnfire_method use clm_varcon , only : c13ratio, c14ratio use ncdio_pio , only : file_desc_t + use filterMod , only : filter + use decompMod , only : get_proc_clumps ! ! !ARGUMENTS: class(cn_vegetation_type), intent(inout) :: this @@ -215,16 +217,30 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) type(file_desc_t), intent(inout) :: params_ncid ! NetCDF handle to parameter file ! ! !LOCAL VARIABLES: - integer :: begp, endp + integer :: begp, endp, ci + integer :: nclumps ! number of clumps on the proc + logical :: alloc_full_veg ! Signal to allocate vegetation data fully or trivialy + character(len=*), parameter :: subname = 'Init' !----------------------------------------------------------------------- - begp = bounds%begp - endp = bounds%endp - ! Note - always initialize the memory for cnveg_state_inst (used in biogeophys/) - call this%cnveg_state_inst%Init(bounds) + ! - Even if FATES is the only vegetation option, we still allocate + ! - a single value for both column and patch, using index 0 only + ! - that is why we pass the number of bgc veg patches here + + if(use_fates_bgc)then + alloc_full_veg=.false. + begp = 0 + endp = 0 + else + alloc_full_veg=.true. + begp = bounds%begp + endp = bounds%endp + end if + + call this%cnveg_state_inst%Init(bounds,alloc_full_veg) skip_steps = nskip_steps @@ -232,34 +248,43 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) ! Read in the general CN namelist call this%CNReadNML( NLFilename ) ! MUST be called first as passes down control information to others + end if + if(use_cn.or.use_fates_bgc)then call this%cnveg_carbonstate_inst%Init(bounds, carbon_type='c12', ratio=1._r8, & - NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm ) + NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, & + alloc_full_veg=alloc_full_veg) + if (use_c13) then call this%c13_cnveg_carbonstate_inst%Init(bounds, carbon_type='c13', ratio=c13ratio, & NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, & - c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) + alloc_full_veg=alloc_full_veg, c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) end if if (use_c14) then call this%c14_cnveg_carbonstate_inst%Init(bounds, carbon_type='c14', ratio=c14ratio, & NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, & - c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) + alloc_full_veg=alloc_full_veg,c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) end if - call this%cnveg_carbonflux_inst%Init(bounds, carbon_type='c12', dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm ) + + call this%cnveg_carbonflux_inst%Init(bounds, carbon_type='c12', & + dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, alloc_full_veg=alloc_full_veg ) if (use_c13) then - call this%c13_cnveg_carbonflux_inst%Init(bounds, carbon_type='c13', dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm) + call this%c13_cnveg_carbonflux_inst%Init(bounds, carbon_type='c13', & + dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm,alloc_full_veg=alloc_full_veg) end if if (use_c14) then - call this%c14_cnveg_carbonflux_inst%Init(bounds, carbon_type='c14', dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm) + call this%c14_cnveg_carbonflux_inst%Init(bounds, carbon_type='c14', & + dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm,alloc_full_veg=alloc_full_veg) end if call this%cnveg_nitrogenstate_inst%Init(bounds, & this%cnveg_carbonstate_inst%leafc_patch(begp:endp), & this%cnveg_carbonstate_inst%leafc_storage_patch(begp:endp), & this%cnveg_carbonstate_inst%frootc_patch(begp:endp), & this%cnveg_carbonstate_inst%frootc_storage_patch(begp:endp), & - this%cnveg_carbonstate_inst%deadstemc_patch(begp:endp) ) - call this%cnveg_nitrogenflux_inst%Init(bounds) - + this%cnveg_carbonstate_inst%deadstemc_patch(begp:endp), & + alloc_full_veg=alloc_full_veg) + call this%cnveg_nitrogenflux_inst%Init(bounds,alloc_full_veg=alloc_full_veg) + call this%c_products_inst%Init(bounds, species_non_isotope_type('C')) if (use_c13) then call this%c13_products_inst%Init(bounds, species_isotope_type('C', '13')) @@ -268,15 +293,17 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) call this%c14_products_inst%Init(bounds, species_isotope_type('C', '14')) end if call this%n_products_inst%Init(bounds, species_non_isotope_type('N')) - + call this%cn_balance_inst%Init(bounds) - + end if + + if(use_cn)then ! Initialize the memory for the dgvs_inst data structure regardless of whether ! use_cndv is true so that it can be used in associate statements (nag compiler ! complains otherwise) call this%dgvs_inst%Init(bounds) end if - + call create_cnfire_method(NLFilename, this%cnfire_method) call this%cnfire_method%CNFireReadParams( params_ncid ) @@ -502,6 +529,10 @@ subroutine Restart(this, bounds, ncid, flag) cnveg_nitrogenstate=this%cnveg_nitrogenstate_inst, & filter_reseed_patch=reseed_patch, num_reseed_patch=num_reseed_patch) + end if + + if (use_cn .or. use_fates_bgc) then + call this%c_products_inst%restart(bounds, ncid, flag) if (use_c13) then call this%c13_products_inst%restart(bounds, ncid, flag, & @@ -514,9 +545,8 @@ subroutine Restart(this, bounds, ncid, flag) template_multiplier = c14ratio) end if call this%n_products_inst%restart(bounds, ncid, flag) - end if - + if (use_cndv) then call this%dgvs_inst%Restart(bounds, ncid, flag=flag) end if @@ -554,7 +584,7 @@ end subroutine Init2 !----------------------------------------------------------------------- - subroutine InitEachTimeStep(this, bounds, num_soilc, filter_soilc) + subroutine InitEachTimeStep(this, bounds, num_bgc_soilc, filter_bgc_soilc) ! ! !DESCRIPTION: ! Do initializations that need to be done at the start of every time step @@ -568,8 +598,8 @@ subroutine InitEachTimeStep(this, bounds, num_soilc, filter_soilc) ! !ARGUMENTS: class(cn_vegetation_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns ! ! !LOCAL VARIABLES: @@ -763,7 +793,7 @@ end subroutine DynamicAreaConservation !----------------------------------------------------------------------- subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -782,10 +812,10 @@ subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc vegetation patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc vegetation patches type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst @@ -798,8 +828,8 @@ subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & call CNDriverSummarizeStates(bounds, & num_allc, filter_allc, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonstate_inst, & this%c13_cnveg_carbonstate_inst, & this%c14_cnveg_carbonstate_inst, & @@ -810,15 +840,15 @@ subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & soilbiogeochem_nitrogenstate_inst) call this%cn_balance_inst%BeginCNColumnBalance( & - bounds, num_soilc, filter_soilc, & - this%cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst) + bounds, num_bgc_soilc, filter_bgc_soilc, & + soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) end subroutine InitColumnBalance !----------------------------------------------------------------------- subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -838,10 +868,10 @@ subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc vegetation patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc vegetation patches type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst @@ -852,10 +882,11 @@ subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & character(len=*), parameter :: subname = 'InitGridcellBalance' !----------------------------------------------------------------------- + call CNDriverSummarizeStates(bounds, & num_allc, filter_allc, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonstate_inst, & this%c13_cnveg_carbonstate_inst, & this%c14_cnveg_carbonstate_inst, & @@ -867,20 +898,22 @@ subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & ! total gridcell carbon (TOTGRIDCELLC) call c2g( bounds = bounds, & - carr = this%cnveg_carbonstate_inst%totc_col(bounds%begc:bounds%endc), & - garr = this%cnveg_carbonstate_inst%totc_grc(bounds%begg:bounds%endg), & + carr = soilbiogeochem_carbonstate_inst%totc_col(bounds%begc:bounds%endc), & + garr = soilbiogeochem_carbonstate_inst%totc_grc(bounds%begg:bounds%endg), & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') + ! total gridcell nitrogen (TOTGRIDCELLN) call c2g( bounds = bounds, & - carr = this%cnveg_nitrogenstate_inst%totn_col(bounds%begc:bounds%endc), & - garr = this%cnveg_nitrogenstate_inst%totn_grc(bounds%begg:bounds%endg), & + carr = soilbiogeochem_nitrogenstate_inst%totn_col(bounds%begc:bounds%endc), & + garr = soilbiogeochem_nitrogenstate_inst%totn_grc(bounds%begg:bounds%endg), & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') call this%cn_balance_inst%BeginCNGridcellBalance( bounds, & this%cnveg_carbonflux_inst, & - this%cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst, & + soilbiogeochem_carbonstate_inst, & + soilbiogeochem_nitrogenstate_inst, & this%c_products_inst, this%n_products_inst) end subroutine InitGridcellBalance @@ -888,8 +921,8 @@ end subroutine InitGridcellBalance !----------------------------------------------------------------------- subroutine EcosystemDynamicsPreDrainage(this, bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & num_actfirec, filter_actfirec, & num_actfirep, filter_actfirep, & num_pcropp, filter_pcropp, & @@ -909,9 +942,10 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & nutrient_competition_method, fireemis_inst) ! ! !DESCRIPTION: - ! Do the main science for CN vegetation that needs to be done before hydrology-drainage + ! Do the main science for biogeochemistry that needs to be done before hydrology-drainage ! - ! Should only be called if use_cn is true + ! Can be called for either use_cn or use_fates_bgc. + ! Will skip most vegetation patch calls for the latter ! ! !USES: @@ -919,10 +953,10 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & ! !ARGUMENTS: class(cn_vegetation_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches integer , intent(out) :: num_actfirec ! number of soil columns on fire in filter integer , intent(out) :: filter_actfirec(:)! filter for soil columns on fire integer , intent(out) :: num_actfirep ! number of soil patches on fire in filter @@ -971,8 +1005,8 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & call crop_inst%CropIncrementYear(num_pcropp, filter_pcropp) call CNDriverNoLeaching(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & num_pcropp, filter_pcropp, & num_soilnopcropp, filter_soilnopcropp, & num_actfirec, filter_actfirec, & @@ -999,19 +1033,19 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & nutrient_competition_method, this%cnfire_method, this%dribble_crophrv_xsmrpool_2atm) ! fire carbon emissions - call CNFireEmisUpdate(bounds, num_soilp, filter_soilp, & + call CNFireEmisUpdate(bounds, num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonflux_inst, this%cnveg_carbonstate_inst, fireemis_inst ) call CNAnnualUpdate(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_state_inst, this%cnveg_carbonflux_inst) end subroutine EcosystemDynamicsPreDrainage !----------------------------------------------------------------------- subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, num_actfirec, filter_actfirec, num_actfirep, filter_actfirep,& + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, num_actfirec, filter_actfirec, num_actfirep, filter_actfirep,& doalb, crop_inst, soilstate_inst, soilbiogeochem_state_inst, & waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst, frictionvel_inst, canopystate_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & @@ -1022,7 +1056,7 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! !DESCRIPTION: ! Do the main science for CN vegetation that needs to be done after hydrology-drainage ! - ! Should only be called if use_cn is true + ! Should only be called if use_cn is true or use_fates_bgc is true ! ! !USES: ! @@ -1031,10 +1065,10 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches integer , intent(in) :: num_actfirec ! number of soil columns on fire in filter integer , intent(in) :: filter_actfirec(:) ! filter for soil columns on fire integer , intent(in) :: num_actfirep ! number of soil patches on fire in filter @@ -1066,8 +1100,8 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! and total soil water outflow. call CNDriverLeaching(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & num_actfirec, filter_actfirec, & num_actfirep, filter_actfirep, & waterstatebulk_inst, waterfluxbulk_inst, soilstate_inst, this%cnveg_state_inst, & @@ -1082,24 +1116,26 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! Set controls on very low values in critical state variables - call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & - this%cnveg_carbonstate_inst, this%c13_cnveg_carbonstate_inst, & - this%c14_cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst) - call t_stopf('CNPrecisionControl') - + if(num_bgc_vegp>0)then + call t_startf('CNPrecisionControl') + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & + this%cnveg_carbonstate_inst, this%c13_cnveg_carbonstate_inst, & + this%c14_cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst) + call t_stopf('CNPrecisionControl') + end if + call t_startf('SoilBiogeochemPrecisionControl') - call SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & + call SoilBiogeochemPrecisionControl(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) call t_stopf('SoilBiogeochemPrecisionControl') ! Call to all CN summary routines - call CNDriverSummarizeStates(bounds, & + call CNDriverSummarizeStates(bounds, & num_allc, filter_allc, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonstate_inst, & this%c13_cnveg_carbonstate_inst, & this%c14_cnveg_carbonstate_inst, & @@ -1109,9 +1145,9 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & c14_soilbiogeochem_carbonstate_inst, & soilbiogeochem_nitrogenstate_inst) - call CNDriverSummarizeFluxes(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call CNDriverSummarizeFluxes(bounds, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonflux_inst, & this%c13_cnveg_carbonflux_inst, & this%c14_cnveg_carbonflux_inst, & @@ -1128,24 +1164,27 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! On the radiation time step, use C state variables to calculate ! vegetation structure (LAI, SAI, height) - - if (doalb) then - call CNVegStructUpdate(bounds,num_soilp, filter_soilp, & - waterdiagnosticbulk_inst, frictionvel_inst, this%dgvs_inst, this%cnveg_state_inst, & - crop_inst, this%cnveg_carbonstate_inst, canopystate_inst) + if(num_bgc_vegp>0)then + if (doalb) then + call CNVegStructUpdate(bounds,num_bgc_vegp, filter_bgc_vegp, & + waterdiagnosticbulk_inst, frictionvel_inst, this%dgvs_inst, this%cnveg_state_inst, & + crop_inst, this%cnveg_carbonstate_inst, canopystate_inst) + end if end if - + end subroutine EcosystemDynamicsPostDrainage !----------------------------------------------------------------------- - subroutine BalanceCheck(this, bounds, num_soilc, filter_soilc, & + subroutine BalanceCheck(this, bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonflux_inst, soilbiogeochem_nitrogenflux_inst, & - atm2lnd_inst) + soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst, & + atm2lnd_inst, clm_fates) + ! ! !DESCRIPTION: ! Check the carbon and nitrogen balance ! - ! Should only be called if use_cn is true + ! Should only be called if use_cn is true or use_fates_bgc is true ! ! !USES: use clm_time_manager , only : get_nstep_since_startup_or_lastDA_restart_or_pause @@ -1153,11 +1192,14 @@ subroutine BalanceCheck(this, bounds, num_soilc, filter_soilc, & ! !ARGUMENTS: class(cn_vegetation_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates ! ! !LOCAL VARIABLES: integer :: DA_nstep ! time step number @@ -1175,19 +1217,23 @@ subroutine BalanceCheck(this, bounds, num_soilc, filter_soilc, & else call this%cn_balance_inst%CBalanceCheck( & - bounds, num_soilc, filter_soilc, & + bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonflux_inst, & + soilbiogeochem_carbonstate_inst, & this%cnveg_carbonflux_inst, & this%cnveg_carbonstate_inst, & - this%c_products_inst) + this%c_products_inst, & + clm_fates) call this%cn_balance_inst%NBalanceCheck( & - bounds, num_soilc, filter_soilc, & + bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_nitrogenflux_inst, & + soilbiogeochem_nitrogenstate_inst, & this%cnveg_nitrogenflux_inst, & this%cnveg_nitrogenstate_inst, & this%n_products_inst, & - atm2lnd_inst) + atm2lnd_inst, & + clm_fates) end if diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 deleted file mode 100644 index eb13932d13..0000000000 --- a/src/biogeochem/EDBGCDynMod.F90 +++ /dev/null @@ -1,370 +0,0 @@ -module EDBGCDynMod - -! This module creates a pathway to call the belowground biogeochemistry code as driven by the fates vegetation model -! but bypassing the aboveground CN vegetation code. It is modeled after the CNDriverMod in its call sequence and -! functionality. - - use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varctl , only : use_c13, use_c14, use_fates - use decompMod , only : bounds_type - use perf_mod , only : t_startf, t_stopf - use shr_log_mod , only : errMsg => shr_log_errMsg - use abortutils , only : endrun - use SoilBiogeochemDecompCascadeConType , only : no_soil_decomp, mimics_decomp, century_decomp, decomp_method - use CNVegCarbonStateType , only : cnveg_carbonstate_type - use CNVegCarbonFluxType , only : cnveg_carbonflux_type - use SoilBiogeochemStateType , only : soilbiogeochem_state_type - use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type - use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type - use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type - use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type - use CanopyStateType , only : canopystate_type - use SoilStateType , only : soilstate_type - use SoilHydrologyType , only : soilhydrology_type - use TemperatureType , only : temperature_type - use WaterFluxBulkType , only : waterfluxbulk_type - use ActiveLayerMod , only : active_layer_type - use atm2lndType , only : atm2lnd_type - use SoilStateType , only : soilstate_type - use ch4Mod , only : ch4_type - use CLMFatesInterfaceMod , only : hlm_fates_interface_type - - implicit none - - ! public :: EDBGCDynInit ! BGC dynamics: initialization - public :: EDBGCDyn ! BGC Dynamics - public :: EDBGCDynSummary ! BGC dynamics: summary - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - -contains - - - !----------------------------------------------------------------------- - subroutine EDBGCDyn(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, num_pcropp, filter_pcropp, doalb, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_state_inst, clm_fates, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & - c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst, & - active_layer_inst, atm2lnd_inst, waterfluxbulk_inst, & - canopystate_inst, soilstate_inst, temperature_inst, crop_inst, ch4_inst) - ! - ! !DESCRIPTION: - - ! - ! !USES: - use clm_varpar , only: nlevgrnd, nlevdecomp_full - use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools - use subgridAveMod , only: p2c - use CropType , only: crop_type - use CNNDynamicsMod , only: CNNDeposition,CNNFixation, CNNFert, CNSoyfix - use CNMRespMod , only: CNMResp - use CNPhenologyMod , only: CNPhenology - use CNGRespMod , only: CNGResp - use CNCIsoFluxMod , only: CIsoFlux1, CIsoFlux2, CIsoFlux2h, CIsoFlux3 - use CNC14DecayMod , only: C14Decay - use CNCStateUpdate1Mod , only: CStateUpdate1,CStateUpdate0 - use CNCStateUpdate2Mod , only: CStateUpdate2, CStateUpdate2h - use CNCStateUpdate3Mod , only: CStateUpdate3 - use CNNStateUpdate1Mod , only: NStateUpdate1 - use CNNStateUpdate2Mod , only: NStateUpdate2, NStateUpdate2h - use CNGapMortalityMod , only: CNGapMortality - use SoilBiogeochemDecompCascadeMIMICSMod, only: decomp_rates_mimics - use SoilBiogeochemDecompCascadeBGCMod , only: decomp_rate_constants_bgc - use SoilBiogeochemDecompMod , only: SoilBiogeochemDecomp - use SoilBiogeochemLittVertTranspMod , only: SoilBiogeochemLittVertTransp - use SoilBiogeochemPotentialMod , only: SoilBiogeochemPotential - use SoilBiogeochemVerticalProfileMod , only: SoilBiogeochemVerticalProfile - use SoilBiogeochemNitrifDenitrifMod , only: SoilBiogeochemNitrifDenitrif - use SoilBiogeochemNStateUpdate1Mod , only: SoilBiogeochemNStateUpdate1 - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches - integer , intent(in) :: num_pcropp ! number of prog. crop patches in filter - integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches - logical , intent(in) :: doalb ! true = surface albedo calculation time step - type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst - type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst - type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c13_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c14_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst - type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst - type(active_layer_type) , intent(in) :: active_layer_inst - type(atm2lnd_type) , intent(in) :: atm2lnd_inst - type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst - type(canopystate_type) , intent(in) :: canopystate_inst - type(soilstate_type) , intent(in) :: soilstate_inst - type(temperature_type) , intent(inout) :: temperature_inst - type(crop_type) , intent(in) :: crop_inst - type(ch4_type) , intent(in) :: ch4_inst - type(hlm_fates_interface_type) , intent(inout) :: clm_fates - ! - ! !LOCAL VARIABLES: - real(r8):: cn_decomp_pools(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) - real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another - real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another - real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N - real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) ! C:N ratio of the flux gained by the receiver pool - integer :: begc,endc - !----------------------------------------------------------------------- - - begc = bounds%begc; endc = bounds%endc - - associate( & - laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:) ] sunlit projected leaf area index - laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:) ] shaded projected leaf area index - frac_veg_nosno => canopystate_inst%frac_veg_nosno_patch , & ! Input: [integer (:) ] fraction of vegetation not covered by snow (0 OR 1) [-] - frac_veg_nosno_alb => canopystate_inst%frac_veg_nosno_alb_patch , & ! Output: [integer (:) ] frac of vegetation not covered by snow [-] - tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow - tsai => canopystate_inst%tsai_patch , & ! Input: [real(r8) (:) ] one-sided stem area index, no burying by snow - elai => canopystate_inst%elai_patch , & ! Output: [real(r8) (:) ] one-sided leaf area index with burying by snow - esai => canopystate_inst%esai_patch , & ! Output: [real(r8) (:) ] one-sided stem area index with burying by snow - htop => canopystate_inst%htop_patch , & ! Output: [real(r8) (:) ] canopy top (m) - hbot => canopystate_inst%hbot_patch & ! Output: [real(r8) (:) ] canopy bottom (m) - ) - - ! -------------------------------------------------- - ! zero the column-level C and N fluxes - ! -------------------------------------------------- - - if ( decomp_method /= no_soil_decomp )then - call t_startf('SoilBGCZero') - - call soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) - if ( use_c13 ) then - call c13_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) - end if - if ( use_c14 ) then - call c14_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) - end if - - call t_stopf('SoilBGCZero') - end if - - ! -------------------------------------------------- - ! Nitrogen Deposition, Fixation and Respiration - ! -------------------------------------------------- - - ! call t_startf('CNDeposition') - ! call CNNDeposition(bounds, & - ! atm2lnd_inst, soilbiogeochem_nitrogenflux_inst) - ! call t_stopf('CNDeposition') - - - ! if (crop_prog) then - ! call CNNFert(bounds, num_soilc,filter_soilc, & - ! cnveg_nitrogenflux_inst, soilbiogeochem_nitrogenflux_inst) - - ! call CNSoyfix (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - ! waterstate_inst, crop_inst, cnveg_state_inst, cnveg_nitrogenflux_inst , & - ! soilbiogeochem_state_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) - ! end if - - !-------------------------------------------- - ! Soil Biogeochemistry - !-------------------------------------------- - - if (decomp_method == century_decomp) then - call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & - soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) - else if (decomp_method == mimics_decomp) then - call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, clm_fates, & - soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) - end if - - if ( decomp_method /= no_soil_decomp )then - ! calculate potential decomp rates and total immobilization demand (previously inlined in CNDecompAlloc) - call SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & - soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & - p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_pools), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) - end if - - !-------------------------------------------- - ! Resolve the competition between plants and soil heterotrophs - ! for available soil mineral N resource - !-------------------------------------------- - ! will add this back in when integrtating hte nutirent cycles - - - !-------------------------------------------- - ! Calculate litter and soil decomposition rate - !-------------------------------------------- - - ! Calculation of actual immobilization and decomp rates, following - ! resolution of plant/heterotroph competition for mineral N (previously inlined in CNDecompAllocation in CNDecompMod) - - if ( decomp_method /= no_soil_decomp )then - call t_startf('SoilBiogeochemDecomp') - - call SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, & - soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & - p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) - - call t_stopf('SoilBiogeochemDecomp') - - - !-------------------------------------------- - ! Update1 - !-------------------------------------------- - - call t_startf('BNGCUpdate1') - - - ! Update all prognostic carbon state variables (except for gap-phase mortality and fire fluxes) - call CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & - crop_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm=.False.) - - call t_stopf('BNGCUpdate1') - - !-------------------------------------------- - ! Calculate vertical mixing of soil and litter pools - !-------------------------------------------- - - call t_startf('SoilBiogeochemLittVertTransp') - - call SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & - active_layer_inst, soilbiogeochem_state_inst, & - soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & - c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & - c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) - - call t_stopf('SoilBiogeochemLittVertTransp') - end if - - ! Wood product fluxes will eventually be added to FATES-CLM. However - ! it is likely this will be implemented during or after we break away from - ! using this module. This module and the current coupling stategy bypasses - ! a number of processes in CLM, which includes the wood product modules. - ! Therefore the following call is a placeholder so that the wood-product - ! wrapper code can be copied from here and applied at the right place when the time comes. - ! RGK 06-2022 - - !call FatesWrapWoodProducts(bounds, num_soilc, filter_soilc,c_products_inst) - !call t_startf('CNWoodProducts') - !call c_products_inst%UpdateProducts(bounds, & - ! num_soilp, filter_soilp, & - ! dwt_wood_product_gain_patch = cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - ! wood_harvest_patch = cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - ! dwt_crop_product_gain_patch = cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - ! crop_harvest_to_cropprod_patch = cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) - !call t_stopf('CNWoodProducts') - - - end associate - - end subroutine EDBGCDyn - - - !----------------------------------------------------------------------- - subroutine EDBGCDynSummary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst, c13_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - nc) - ! - ! !DESCRIPTION: - ! Call to all CN and SoilBiogeochem summary routines - ! also aggregate production and decomposition fluxes to whole-ecosystem balance fluxes - ! - ! !USES: - use clm_varpar , only: ndecomp_cascade_transitions - use CNPrecisionControlMod , only: CNPrecisionControl - use SoilBiogeochemPrecisionControlMod , only: SoilBiogeochemPrecisionControl - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches - type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c13_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c14_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst - type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst - integer , intent(in) :: nc ! thread index - ! - ! !LOCAL VARIABLES: - integer :: begc,endc - !----------------------------------------------------------------------- - - begc = bounds%begc; endc= bounds%endc - - ! Call to all summary routines - - call t_startf('BGCsum') - - ! Set controls on very low values in critical state variables - - call SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & - soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) - - ! Note - all summary updates to cnveg_carbonstate_inst and cnveg_carbonflux_inst are done in - ! soilbiogeochem_carbonstate_inst%summary and CNVeg_carbonstate_inst%summary - - ! ---------------------------------------------- - ! soilbiogeochem carbon/nitrogen state summary - ! ---------------------------------------------- - - call soilbiogeochem_carbonstate_inst%summary(bounds, num_soilc, filter_soilc) - if ( use_c13 ) then - call c13_soilbiogeochem_carbonstate_inst%summary(bounds, num_soilc, filter_soilc) - end if - if ( use_c14 ) then - call c14_soilbiogeochem_carbonstate_inst%summary(bounds, num_soilc, filter_soilc) - end if - ! call soilbiogeochem_nitrogenstate_inst%summary(bounds, num_soilc, filter_soilc) - - ! ---------------------------------------------- - ! soilbiogeochem carbon/nitrogen flux summary - ! ---------------------------------------------- - - call soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc) - if ( use_c13 ) then - call c13_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc) - end if - if ( use_c14 ) then - call c14_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc) - end if - ! call soilbiogeochem_nitrogenflux_inst%Summary(bounds, num_soilc, filter_soilc) - - - call t_stopf('BGCsum') - - end subroutine EDBGCDynSummary - -end module EDBGCDynMod diff --git a/src/biogeochem/ch4Mod.F90 b/src/biogeochem/ch4Mod.F90 index afb8af351b..f199e7913f 100644 --- a/src/biogeochem/ch4Mod.F90 +++ b/src/biogeochem/ch4Mod.F90 @@ -17,7 +17,7 @@ module ch4Mod use clm_varcon , only : catomw, s_con, d_con_w, d_con_g, c_h_inv, kh_theta, kh_tbase use landunit_varcon , only : istsoil, istcrop, istdlak use clm_time_manager , only : get_step_size_real, get_nstep - use clm_varctl , only : iulog, use_cn, use_nitrif_denitrif, use_lch4, use_cn, use_fates + use clm_varctl , only : iulog, use_cn, use_nitrif_denitrif, use_lch4, use_fates_bgc use abortutils , only : endrun use decompMod , only : bounds_type, subgrid_level_gridcell, subgrid_level_column use atm2lndType , only : atm2lnd_type @@ -2521,7 +2521,7 @@ subroutine ch4_prod (bounds, num_methc, filter_methc, num_methp, & end if end do - if(use_fates) then + if(use_fates_bgc) then nc = bounds%clump_index do s = 1,clm_fates%fates(nc)%nsites c = clm_fates%f2hmap(nc)%fcolumn(s) @@ -2544,7 +2544,7 @@ subroutine ch4_prod (bounds, num_methc, filter_methc, num_methp, & if (.not. lake) then - if (use_cn .or. use_fates) then + if (use_cn .or. use_fates_bgc) then ! Use soil heterotrophic respiration (based on Wania) base_decomp = (somhr(c)+lithr(c)) / catomw ! Convert from gC to molC @@ -2567,7 +2567,7 @@ subroutine ch4_prod (bounds, num_methc, filter_methc, num_methp, & else call endrun(msg=' ERROR: No source for decomp rate in CH4Prod.'//& ' CH4 model currently requires CN or FATES.'//errMsg(sourcefile, __LINE__)) - end if ! use_cn + end if ! use_cn or use_fates_bgc ! For sensitivity studies base_decomp = base_decomp * cnscalefactor diff --git a/src/biogeophys/WaterDiagnosticType.F90 b/src/biogeophys/WaterDiagnosticType.F90 index 7fa76b42b0..57be0e62af 100644 --- a/src/biogeophys/WaterDiagnosticType.F90 +++ b/src/biogeophys/WaterDiagnosticType.F90 @@ -164,13 +164,7 @@ subroutine InitHistory(this, bounds) begc = bounds%begc; endc= bounds%endc begg = bounds%begg; endg= bounds%endg - this%h2ocan_patch(begp:endp) = spval - call hist_addfld1d ( & - fname=this%info%fname('H2OCAN'), & - units='mm', & - avgflag='A', & - long_name=this%info%lname('intercepted water'), & - ptr_patch=this%h2ocan_patch) + this%h2osoi_liqice_10cm_col(begc:endc) = spval call hist_addfld1d ( & @@ -205,8 +199,15 @@ subroutine InitHistory(this, bounds) long_name=this%info%lname('2m specific humidity'), & ptr_patch=this%q_ref2m_patch) + this%h2ocan_patch(begp:endp) = spval + call hist_addfld1d ( & + fname=this%info%fname('H2OCAN'), & + units='mm', & + avgflag='A', & + long_name=this%info%lname('intercepted water'), & + ptr_patch=this%h2ocan_patch) - + ! Snow properties - these will be vertically averaged over the snow profile this%snowliq_col(begc:endc) = spval diff --git a/src/main/clm_driver.F90 b/src/main/clm_driver.F90 index c8873840f3..3a5e981d74 100644 --- a/src/main/clm_driver.F90 +++ b/src/main/clm_driver.F90 @@ -9,7 +9,7 @@ module clm_driver ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varctl , only : iulog, use_fates, use_fates_sp + use clm_varctl , only : iulog, use_fates, use_fates_sp, use_fates_bgc use clm_varctl , only : use_cn, use_lch4, use_noio, use_c13, use_c14 use CNSharedParamsMod , only : use_matrixcn use clm_varctl , only : use_crop, irrigate, ndep_from_cpl @@ -82,7 +82,6 @@ module clm_driver use ColumnType , only : col use PatchType , only : patch use clm_instMod - use EDBGCDynMod , only : EDBGCDyn, EDBGCDynSummary use SoilMoistureStreamMod , only : PrescribedSoilMoistureInterp, PrescribedSoilMoistureAdvance use SoilBiogeochemDecompCascadeConType , only : no_soil_decomp, decomp_method ! @@ -207,7 +206,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! ======================================================================== need_glacier_initialization = is_first_step() - + if (need_glacier_initialization) then !$OMP PARALLEL DO PRIVATE (nc, bounds_clump) do nc = 1, nclumps @@ -291,10 +290,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call active_layer_inst%alt_calc(filter_inactive_and_active(nc)%num_soilc, filter_inactive_and_active(nc)%soilc, & temperature_inst) - if (use_cn .and. decomp_method /= no_soil_decomp) then + ! Filter bgc_soilc operates on all non-sp soil columns + ! Filter bgc_vegp operates on all non-fates, non-sp patches (use_cn) on soil + if ((use_cn .or. use_fates_bgc) .and. decomp_method /= no_soil_decomp) then call SoilBiogeochemVerticalProfile(bounds_clump , & - filter_inactive_and_active(nc)%num_soilc, filter_inactive_and_active(nc)%soilc , & - filter_inactive_and_active(nc)%num_soilp, filter_inactive_and_active(nc)%soilp , & + filter_inactive_and_active(nc)%num_bgc_soilc, filter_inactive_and_active(nc)%bgc_soilc , & + filter_inactive_and_active(nc)%num_bgc_vegp, filter_inactive_and_active(nc)%bgc_vegp , & active_layer_inst, soilstate_inst, soilbiogeochem_state_inst) end if @@ -327,12 +328,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call get_clump_bounds(nc, bounds_clump) call t_startf('begcnbal_grc') - if (use_cn) then + if (use_cn .or. use_fates_bgc) then ! Initialize gridcell-level balance check call bgc_vegetation_inst%InitGridcellBalance(bounds_clump, & filter(nc)%num_allc, filter(nc)%allc, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -417,12 +418,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call t_stopf('begwbal') call t_startf('begcnbal_col') - if (use_cn) then + if (use_cn .or. use_fates_bgc) then ! Initialize column-level balance check call bgc_vegetation_inst%InitColumnBalance(bounds_clump, & filter(nc)%num_allc, filter(nc)%allc, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -446,15 +447,18 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! re-written to go inside. ! ============================================================================ - if (use_cn) then - call t_startf('bgc_interp') + if (use_cn) then ! .or. use_fates_bgc) then (ndep with fates will be added soon) if (.not. ndep_from_cpl) then call ndep_interp(bounds_proc, atm2lnd_inst) end if + end if + + if(use_cn) then + call t_startf('bgc_interp') call bgc_vegetation_inst%InterpFileInputs(bounds_proc) call t_stopf('bgc_interp') - ! fates_spitfire_mode is assigned an integer value in the namelist - ! see bld/namelist_files/namelist_definition_clm4_5.xml for details + ! fates_spitfire_mode is assigned an integer value in the namelist + ! see bld/namelist_files/namelist_definition_clm4_5.xml for details else if (fates_spitfire_mode > scalar_lightning) then call clm_fates%InterpFileInputs(bounds_proc) end if @@ -1005,17 +1009,20 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! - CNDV defined: prognostic biogeography; else prescribed ! - crop model: crop algorithms called from within CNDriver - if (use_cn) then + ! Filter bgc_soilc operates on all non-sp soil columns + ! Filter bgc_vegp operates on all non-fates, non-sp patches (use_cn) on soil + + if(use_cn .or. use_fates_bgc)then call t_startf('ecosysdyn') call bgc_vegetation_inst%EcosystemDynamicsPreDrainage(bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & - filter(nc)%num_actfirec, filter(nc)%actfirec, & - filter(nc)%num_actfirep, filter(nc)%actfirep, & - filter(nc)%num_pcropp, filter(nc)%pcropp, & - filter(nc)%num_soilnopcropp, filter(nc)%soilnopcropp, & - filter(nc)%num_exposedvegp, filter(nc)%exposedvegp, & - filter(nc)%num_noexposedvegp, filter(nc)%noexposedvegp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & + filter(nc)%num_actfirec, filter(nc)%actfirec, & + filter(nc)%num_actfirep, filter(nc)%actfirep, & + filter(nc)%num_pcropp, filter(nc)%pcropp, & + filter(nc)%num_soilnopcropp, filter(nc)%soilnopcropp, & + filter(nc)%num_exposedvegp, filter(nc)%exposedvegp, & + filter(nc)%num_noexposedvegp, filter(nc)%noexposedvegp, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonflux_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & @@ -1028,9 +1035,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro soil_water_retention_curve, crop_inst, ch4_inst, & photosyns_inst, saturated_excess_runoff_inst, energyflux_inst, & nutrient_competition_method, fireemis_inst) - call t_stopf('ecosysdyn') - end if ! Prescribed biogeography - prescribed canopy structure, some prognostic carbon fluxes @@ -1092,13 +1097,13 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call t_stopf('hydro2_drainage') - if (use_cn) then - + + if (use_cn .or. use_fates_bgc) then call t_startf('EcosysDynPostDrainage') call bgc_vegetation_inst%EcosystemDynamicsPostDrainage(bounds_clump, & filter(nc)%num_allc, filter(nc)%allc, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & filter(nc)%num_actfirec, filter(nc)%actfirec, & filter(nc)%num_actfirep, filter(nc)%actfirep, & doalb, crop_inst, & @@ -1110,11 +1115,8 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) call t_stopf('EcosysDynPostDrainage') - end if - - if ( use_fates) then ! FATES has its own running mean functions, such as 24hr @@ -1123,30 +1125,6 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! moving averages are updated here call clm_fates%WrapUpdateFatesRmean(nc,temperature_inst) - call EDBGCDyn(bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & - filter(nc)%num_pcropp, filter(nc)%pcropp, doalb, & - bgc_vegetation_inst%cnveg_carbonflux_inst, & - bgc_vegetation_inst%cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_state_inst, clm_fates, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & - c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst, & - active_layer_inst, atm2lnd_inst, water_inst%waterfluxbulk_inst, & - canopystate_inst, soilstate_inst, temperature_inst, crop_inst, ch4_inst) - - if ( decomp_method /= no_soil_decomp )then - call EDBGCDynSummary(bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst, c13_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - nc) - end if call clm_fates%wrap_update_hifrq_hist(bounds_clump, & soilbiogeochem_carbonflux_inst, & @@ -1159,9 +1137,6 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! This is the main call to FATES dynamics ! -------------------------------------------------------------------------- - if ( masterproc ) then - write(iulog,*) 'clm: calling FATES model ', get_nstep() - end if call clm_fates%dynamics_driv( nc, bounds_clump, & atm2lnd_inst, soilstate_inst, temperature_inst, active_layer_inst, & water_inst%waterstatebulk_inst, water_inst%waterdiagnosticbulk_inst, & @@ -1191,15 +1166,18 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! Check the carbon and nitrogen balance ! ============================================================================ - if (use_cn) then + if(use_cn .or. use_fates_bgc)then call t_startf('cnbalchk') call bgc_vegetation_inst%BalanceCheck( & - bounds_clump, filter(nc)%num_soilc, filter(nc)%soilc, & - soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenflux_inst, atm2lnd_inst ) + bounds_clump, filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + soilbiogeochem_carbonflux_inst, & + soilbiogeochem_nitrogenflux_inst, & + soilbiogeochem_carbonstate_inst, & + soilbiogeochem_nitrogenstate_inst, & + atm2lnd_inst, clm_fates ) call t_stopf('cnbalchk') end if - + ! Calculation of methane fluxes if (use_lch4) then @@ -1418,7 +1396,6 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! Update history buffer ! ============================================================================ - call t_startf('hbuf') call hist_update_hbuf(bounds_proc) call t_stopf('hbuf') diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index 251c106ce0..970fd49162 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -10,10 +10,11 @@ module clm_initializeMod use spmdMod , only : masterproc, mpicom use decompMod , only : bounds_type, get_proc_bounds, get_proc_clumps, get_clump_bounds use abortutils , only : endrun - use clm_varctl , only : nsrest, nsrStartup, nsrContinue, nsrBranch, use_fates_sp + use clm_varctl , only : nsrest, nsrStartup, nsrContinue, nsrBranch + use clm_varctl , only : use_fates_sp, use_fates_bgc, use_fates use clm_varctl , only : is_cold_start use clm_varctl , only : iulog - use clm_varctl , only : use_lch4, use_cn, use_cndv, use_c13, use_c14, use_fates + use clm_varctl , only : use_lch4, use_cn, use_cndv, use_c13, use_c14 use clm_varctl , only : use_soil_moisture_streams use clm_instur , only : wt_lunit, urban_valid, wt_nat_patch, wt_cft, fert_cft use clm_instur , only : irrig_method, wt_glc_mec, topo_glc_mec, haslake, pct_urban_max @@ -431,8 +432,11 @@ subroutine initialize2(ni,nj) !$OMP END PARALLEL DO ! Initialize modules (after time-manager initialization in most cases) - if (use_cn) then + if (use_cn .or. use_fates) then call bgc_vegetation_inst%Init2(bounds_proc, NLFilename) + end if + + if (use_cn) then ! NOTE(wjs, 2016-02-23) Maybe the rest of the body of this conditional should also ! be moved into bgc_vegetation_inst%Init2 @@ -624,7 +628,7 @@ subroutine initialize2(ni,nj) !$OMP END PARALLEL DO ! Initialize nitrogen deposition - if (use_cn) then + if (use_cn ) then !.or. use_fates_bgc) then (ndep with fates will be added soon RGK) call t_startf('init_ndep') if (.not. ndep_from_cpl) then call ndep_init(bounds_proc, NLFilename) diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index 205bd7e8e2..1ca450b48d 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -8,7 +8,7 @@ module clm_instMod use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod , only : bounds_type use clm_varpar , only : ndecomp_pools, nlevdecomp_full - use clm_varctl , only : use_cn, use_c13, use_c14, use_lch4, use_cndv, use_fates + use clm_varctl , only : use_cn, use_c13, use_c14, use_lch4, use_cndv, use_fates, use_fates_bgc use clm_varctl , only : iulog use clm_varctl , only : use_crop, snow_cover_fraction_method, paramfile use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, no_soil_decomp, century_decomp, decomp_method @@ -231,7 +231,6 @@ subroutine clm_instInit(bounds) allocate (h2osno_col(begc:endc)) allocate (snow_depth_col(begc:endc)) - ! snow water do c = begc,endc l = col%landunit(c) @@ -371,7 +370,7 @@ subroutine clm_instInit(bounds) call drydepvel_inst%Init(bounds) - if (decomp_method /= no_soil_decomp) then + if_decomp: if (decomp_method /= no_soil_decomp) then ! Initialize soilbiogeochem_state_inst @@ -423,9 +422,10 @@ subroutine clm_instInit(bounds) call SoilBiogeochemPrecisionControlInit( soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst) - end if ! end of if use_cn + end if if_decomp ! Note - always call Init for bgc_vegetation_inst: some pieces need to be initialized always + ! Even for a FATES simulation, we call this to initialize product pools call bgc_vegetation_inst%Init(bounds, nlfilename, GetBalanceCheckSkipSteps(), params_ncid ) if (use_cn .or. use_fates) then @@ -553,7 +553,7 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) call ch4_inst%restart(bounds, ncid, flag=flag) end if - if ( use_cn ) then + if ( use_cn .or. use_fates_bgc) then ! Need to do vegetation restart before soil bgc restart to get totvegc_col for purpose ! of resetting soil carbon at exit spinup when no vegetation is growing. call bgc_vegetation_inst%restart(bounds, ncid, flag=flag) @@ -591,7 +591,8 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) canopystate_inst=canopystate_inst, & soilstate_inst=soilstate_inst, & active_layer_inst=active_layer_inst, & - soilbiogeochem_carbonflux_inst=soilbiogeochem_carbonflux_inst) + soilbiogeochem_carbonflux_inst=soilbiogeochem_carbonflux_inst, & + soilbiogeochem_nitrogenflux_inst=soilbiogeochem_nitrogenflux_inst) end if diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 64aa40d94d..800fce2139 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -249,27 +249,33 @@ module clm_varctl ! FATES switches !---------------------------------------------------------- - logical, public :: use_fates = .false. ! true => use fates + logical, public :: use_fates = .false. ! true => use fates ! These are INTERNAL to the FATES module - integer, public :: fates_parteh_mode = -9 ! 1 => carbon only - ! 2 => C+N+P (not enabled yet) - ! no others enabled + + integer, public :: fates_parteh_mode = -9 ! 1 => carbon only + ! 2 => C+N+P (not enabled yet) + ! no others enabled integer, public :: fates_spitfire_mode = 0 - ! 0 for no fire; 1 for constant ignitions; > 1 for external data (lightning and/or anthropogenic ignitions) - ! see bld/namelist_files/namelist_definition_clm4_5.xml for details - logical, public :: use_fates_tree_damage = .false. ! true => turn on tree damage module - logical, public :: use_fates_logging = .false. ! true => turn on logging module - logical, public :: use_fates_planthydro = .false. ! true => turn on fates hydro + ! 0 for no fire; 1 for constant ignitions; + ! > 1 for external data (lightning and/or anthropogenic ignitions) + ! see bld/namelist_files/namelist_definition_clm4_5.xml for details + logical, public :: use_fates_tree_damage = .false. ! true => turn on tree damage module + logical, public :: use_fates_logging = .false. ! true => turn on logging module + logical, public :: use_fates_planthydro = .false. ! true => turn on fates hydro logical, public :: use_fates_cohort_age_tracking = .false. ! true => turn on cohort age tracking - logical, public :: use_fates_ed_st3 = .false. ! true => static stand structure - logical, public :: use_fates_ed_prescribed_phys = .false. ! true => prescribed physiology - logical, public :: use_fates_inventory_init = .false. ! true => initialize fates from inventory - logical, public :: use_fates_fixed_biogeog = .false. ! true => use fixed biogeography mode - logical, public :: use_fates_nocomp = .false. ! true => use no comopetition mode - logical, public :: use_fates_sp = .false. ! true => use FATES satellite phenology mode - character(len=256), public :: fates_inventory_ctrl_filename = '' ! filename for inventory control - + logical, public :: use_fates_ed_st3 = .false. ! true => static stand structure + logical, public :: use_fates_ed_prescribed_phys = .false. ! true => prescribed physiology + logical, public :: use_fates_inventory_init = .false. ! true => initialize fates from inventory + logical, public :: use_fates_fixed_biogeog = .false. ! true => use fixed biogeography mode + logical, public :: use_fates_nocomp = .false. ! true => use no comopetition mode + character(len=256), public :: fates_inventory_ctrl_filename = '' ! filename for inventory control + + ! FATES SP AND FATES BGC are MUTUTALLY EXCLUSIVE, THEY CAN'T BOTH BE ON + ! BUT... THEY CAN BOTH BE OFF (IF FATES IS OFF) + logical, public :: use_fates_sp = .false. ! true => use FATES satellite phenology mode + logical, public :: use_fates_bgc = .false. ! true => use FATES along with CLM soil biogeochemistry + !---------------------------------------------------------- ! LUNA switches !---------------------------------------------------------- diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index c1a7959459..541c5a00e7 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -232,8 +232,8 @@ subroutine control_init(dtime) fates_parteh_mode, & use_fates_tree_damage - ! Ozone vegetation stress method - namelist / clm_inparam / o3_veg_stress_method + ! Ozone vegetation stress method + namelist / clm_inparam / o3_veg_stress_method ! CLM 5.0 nitrogen flags namelist /clm_inparm/ use_flexibleCN, use_luna @@ -435,6 +435,21 @@ subroutine control_init(dtime) ! Check compatibility with the FATES model if ( use_fates ) then + if(use_fates_sp) then + use_fates_bgc = .false. + else + use_fates_bgc = .true. + end if + + if (fates_parteh_mode == 1 .and. suplnitro == suplnNon .and. use_fates_bgc )then + write(iulog,*) ' When FATES with fates_parteh_mode == 1 (ie carbon only mode),' + write(iulog,*) ' you must have supplemental nitrogen turned on, there will be' + write(iulog,*) ' no nitrogen dynamics with the plants, and therefore no' + write(iulog,*) ' meaningful limitations to nitrogen.' + call endrun(msg=' ERROR: fates_parteh_mode=1 must have suplnitro set to suplnAll.'//& + errMsg(sourcefile, __LINE__)) + end if + if ( use_cn) then call endrun(msg=' ERROR: use_cn and use_fates cannot both be set to true.'//& errMsg(sourcefile, __LINE__)) @@ -460,6 +475,18 @@ subroutine control_init(dtime) errMsg(sourcefile, __LINE__)) end if + if (use_c13 .or. use_c14) then + call endrun(msg=' ERROR: C13 and C14 dynamics are not compatible with FATES.'//& + errMsg(sourcefile, __LINE__)) + end if + + else + + ! These do default to false anyway, but this emphasizes they + ! are false when fates is false + use_fates_sp = .false. + use_fates_bgc = .false. + end if ! If nfix_timeconst is equal to the junk default value, then it was not specified @@ -528,7 +555,8 @@ subroutine control_init(dtime) end if call soilHydReadNML( NLFilename ) - if ( use_cn ) then + + if( use_cn ) then call CNFireReadNML( NLFilename ) call CNPrecisionControlReadNML( NLFilename ) call CNNDynamicsReadNML ( NLFilename ) @@ -691,7 +719,10 @@ subroutine control_spmd() ! BGC call mpi_bcast (co2_type, len(co2_type), MPI_CHARACTER, 0, mpicom, ier) - if (use_cn) then + + call mpi_bcast (use_fates, 1, MPI_LOGICAL, 0, mpicom, ier) + + if (use_cn .or. use_fates) then call mpi_bcast (suplnitro, len(suplnitro), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (nfix_timeconst, 1, MPI_REAL8, 0, mpicom, ier) call mpi_bcast (spinup_state, 1, MPI_INTEGER, 0, mpicom, ier) @@ -703,8 +734,6 @@ subroutine control_spmd() call mpi_bcast (use_c14, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (for_testing_allow_interp_non_ciso_to_ciso, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (use_fates, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (fates_spitfire_mode, 1, MPI_INTEGER, 0, mpicom, ier) call mpi_bcast (use_fates_logging, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_planthydro, 1, MPI_LOGICAL, 0, mpicom, ier) @@ -716,6 +745,7 @@ subroutine control_spmd() call mpi_bcast (use_fates_fixed_biogeog, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_nocomp, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_sp, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_fates_bgc, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (fates_inventory_ctrl_filename, len(fates_inventory_ctrl_filename), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fates_paramfile, len(fates_paramfile) , MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fates_parteh_mode, 1, MPI_INTEGER, 0, mpicom, ier) @@ -749,7 +779,7 @@ subroutine control_spmd() call mpi_bcast (use_dynroot, 1, MPI_LOGICAL, 0, mpicom, ier) - if (use_cn ) then + if (use_cn .or. use_fates) then ! vertical soil mixing variables call mpi_bcast (som_adv_flux, 1, MPI_REAL8, 0, mpicom, ier) call mpi_bcast (max_depth_cryoturb, 1, MPI_REAL8, 0, mpicom, ier) @@ -758,7 +788,7 @@ subroutine control_spmd() call mpi_bcast (surfprof_exp, 1, MPI_REAL8, 0, mpicom, ier) end if - if (use_cn .and. use_nitrif_denitrif) then + if ((use_cn.or.use_fates) .and. use_nitrif_denitrif) then call mpi_bcast (no_frozen_nitrif_denitrif, 1, MPI_LOGICAL, 0, mpicom, ier) end if @@ -906,7 +936,8 @@ subroutine control_print () write(iulog,*) ' Threshold above which the model keeps the lake landunit =', toosmall_lake write(iulog,*) ' Threshold above which the model keeps the wetland landunit =', toosmall_wetland write(iulog,*) ' Threshold above which the model keeps the urban landunits =', toosmall_urban - if (use_cn) then + + if (use_cn .or. use_fates) then if (suplnitro /= suplnNon)then write(iulog,*) ' Supplemental Nitrogen mode is set to run over Patches: ', & trim(suplnitro) @@ -937,13 +968,13 @@ subroutine control_print () write(iulog,*) ' override_bgc_restart_mismatch_dump : ', override_bgc_restart_mismatch_dump end if - if (use_cn ) then + if (use_cn .or. use_fates) then write(iulog, *) ' som_adv_flux, the advection term in soil mixing (m/s) : ', som_adv_flux write(iulog, *) ' max_depth_cryoturb (m) : ', max_depth_cryoturb write(iulog, *) ' surfprof_exp : ', surfprof_exp end if - if (use_cn .and. .not. use_nitrif_denitrif) then + if ((use_cn .or. use_fates) .and. .not. use_nitrif_denitrif) then write(iulog, *) ' no_frozen_nitrif_denitrif : ', no_frozen_nitrif_denitrif end if diff --git a/src/main/filterMod.F90 b/src/main/filterMod.F90 index 526cb7c8f3..2fb7d23079 100644 --- a/src/main/filterMod.F90 +++ b/src/main/filterMod.F90 @@ -19,6 +19,7 @@ module filterMod use ColumnType , only : col use PatchType , only : patch use glcBehaviorMod , only : glc_behavior_type + use clm_varctl , only : use_cn, use_fates, use_fates_bgc ! ! !PUBLIC TYPES: implicit none @@ -32,9 +33,10 @@ module filterMod integer, pointer :: natvegp(:) ! CNDV nat-vegetated (present) filter (patches) integer :: num_natvegp ! number of patches in nat-vegetated filter - integer, pointer :: pcropp(:) ! prognostic crop filter (patches) + integer, pointer :: pcropp(:) ! prognostic crop filter (patches) integer :: num_pcropp ! number of patches in prognostic crop filter - integer, pointer :: soilnopcropp(:) ! soil w/o prog. crops (patches) + + integer, pointer :: soilnopcropp(:) ! soil w/o prog. crops (patches) integer :: num_soilnopcropp ! number of patches in soil w/o prog crops integer, pointer :: all_soil_patches(:) ! all soil or crop patches. Used for updating FATES SP drivers @@ -49,6 +51,14 @@ module filterMod integer, pointer :: nolakec(:) ! non-lake filter (columns) integer :: num_nolakec ! number of columns in non-lake filter + integer, pointer :: bgc_soilc(:) ! soil with biogeochemistry active, negates + ! SP type runs, could be CN, FATES or CROP + integer :: num_bgc_soilc + + integer, pointer :: bgc_vegp(:) ! patches with vegetation biochemistry active, negates + ! SP type runs, could be CN or Crop (NOT FATES) + integer :: num_bgc_vegp + integer, pointer :: soilc(:) ! soil filter (columns) integer :: num_soilc ! number of columns in soil filter integer, pointer :: soilp(:) ! soil filter (patches) @@ -211,6 +221,9 @@ subroutine allocFiltersOneGroup(this_filter) allocate(this_filter(nc)%soilc(bounds%endc-bounds%begc+1)) allocate(this_filter(nc)%soilp(bounds%endp-bounds%begp+1)) + allocate(this_filter(nc)%bgc_soilc(bounds%endc-bounds%begc+1)) + allocate(this_filter(nc)%bgc_vegp(bounds%endp-bounds%begp+1)) + allocate(this_filter(nc)%snowc(bounds%endc-bounds%begc+1)) allocate(this_filter(nc)%nosnowc(bounds%endc-bounds%begc+1)) @@ -380,6 +393,39 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio this_filter(nc)%num_nolakep = fnl this_filter(nc)%num_nolakeurbanp = fnlu + + ! Create the soil bgc filter, all non-sp columns for vegetation + fs = 0 + if( use_cn .or. use_fates_bgc )then + do c = bounds%begc,bounds%endc + if (col%active(c) .or. include_inactive) then + l =col%landunit(c) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + fs = fs + 1 + this_filter(nc)%bgc_soilc(fs) = c + end if + end if + end do + end if + this_filter(nc)%num_bgc_soilc = fs + + ! Create a filter at patch-level for vegetation biochemistry + ! all non-SP and non-fates patches on soil + fs = 0 + if(use_cn)then + do p = bounds%begp,bounds%endp + if (patch%active(p) .or. include_inactive) then + l =patch%landunit(p) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + fs = fs + 1 + this_filter(nc)%bgc_vegp(fs) = p + end if + end if + end do + end if + this_filter(nc)%num_bgc_vegp = fs + + ! Create soil filter at column-level fs = 0 @@ -393,8 +439,12 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio end if end do this_filter(nc)%num_soilc = fs - ! Create soil filter at patch-level + + + + + ! Create soil filter at patch-level fs = 0 do p = bounds%begp,bounds%endp if (patch%active(p) .or. include_inactive) then @@ -405,6 +455,7 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio end if end if end do + this_filter(nc)%num_soilp = fs ! Create column-level hydrology filter (soil and Urban pervious road cols) @@ -426,15 +477,17 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio fl = 0 fnl = 0 do p = bounds%begp,bounds%endp - if (patch%active(p) .or. include_inactive) then - if (patch%itype(p) >= npcropmin) then !skips 2 generic crop types - fl = fl + 1 - this_filter(nc)%pcropp(fl) = p - else - l =patch%landunit(p) - if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then - fnl = fnl + 1 - this_filter(nc)%soilnopcropp(fnl) = p + if(.not.use_fates)then + if (patch%active(p) .or. include_inactive) then + if (patch%itype(p) >= npcropmin) then !skips 2 generic crop types + fl = fl + 1 + this_filter(nc)%pcropp(fl) = p + else + l =patch%landunit(p) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + fnl = fnl + 1 + this_filter(nc)%soilnopcropp(fnl) = p + end if end if end if end if diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index 114019a3d7..212cb6a5e2 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -6,6 +6,7 @@ module SoilBiogeochemCarbonFluxType use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan use clm_varpar , only : nlevdecomp_full, nlevgrnd, nlevdecomp, nlevsoi, i_cwdl2 use clm_varcon , only : spval, ispval, dzsoi_decomp + use clm_varctl , only : use_fates,use_cn use pftconMod , only : pftcon use landunit_varcon , only : istsoil, istcrop, istdlak use ch4varcon , only : allowlakeprod @@ -14,7 +15,6 @@ module SoilBiogeochemCarbonFluxType use ColumnType , only : col use LandunitType , only : lun use SparseMatrixMultiplyMod , only : sparse_matrix_type, diag_matrix_type, vector_type - use clm_varctl , only : use_fates ! ! !PUBLIC TYPES: @@ -58,13 +58,11 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: lithr_col (:) ! (gC/m2/s) litter heterotrophic respiration: donor-pool based definition real(r8), pointer :: somhr_col (:) ! (gC/m2/s) soil organic matter heterotrophic res: donor-pool based definition real(r8), pointer :: soilc_change_col (:) ! (gC/m2/s) FUN used soil C + real(r8), pointer :: fates_litter_flux (:) ! (gC/m2/s) A summary of the total litter + ! flux passed in from FATES. + ! This is a diagnostic for balance checks only - ! fluxes to receive carbon inputs from FATES - real(r8), pointer :: FATES_c_to_litr_c_col (:,:,:) ! total litter coming from ED. gC/m3/s - real(r8), pointer :: FATES_c_to_litr_lab_c_col (:,:) ! total labile litter coming from ED. gC/m3/s - real(r8), pointer :: FATES_c_to_litr_cel_c_col (:,:) ! total cellulose litter coming from ED. gC/m3/s - real(r8), pointer :: FATES_c_to_litr_lig_c_col (:,:) ! total lignin litter coming from ED. gC/m3/s - + contains procedure , public :: Init @@ -162,25 +160,16 @@ subroutine InitAllocate(this, bounds) allocate(this%lithr_col (begc:endc)) ; this%lithr_col (:) = nan allocate(this%somhr_col (begc:endc)) ; this%somhr_col (:) = nan allocate(this%soilc_change_col (begc:endc)) ; this%soilc_change_col (:) = nan - + + if(use_fates)then + allocate(this%fates_litter_flux(begc:endc)); this%fates_litter_flux(:) = nan + else + allocate(this%fates_litter_flux(0:0)); this%fates_litter_flux(:) = nan + end if + if(use_soil_matrixcn)then end if - if ( use_fates ) then - ! initialize these variables to be zero rather than a bad number since they are not zeroed every timestep (due to a need for them to persist) - - allocate(this%FATES_c_to_litr_c_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) - this%FATES_c_to_litr_c_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools) = 0._r8 - - allocate(this%FATES_c_to_litr_lab_c_col(begc:endc,1:nlevdecomp_full)) - this%FATES_c_to_litr_lab_c_col(begc:endc,1:nlevdecomp_full) = 0._r8 - - allocate(this%FATES_c_to_litr_cel_c_col(begc:endc,1:nlevdecomp_full)) - this%FATES_c_to_litr_cel_c_col(begc:endc,1:nlevdecomp_full) = 0._r8 - - allocate(this%FATES_c_to_litr_lig_c_col(begc:endc,1:nlevdecomp_full)) - this%FATES_c_to_litr_lig_c_col(begc:endc,1:nlevdecomp_full) = 0._r8 - endif allocate(this%litr_lig_c_to_n_col(begc:endc)) this%litr_lig_c_to_n_col(:)= 0._r8 @@ -625,23 +614,6 @@ subroutine InitHistory(this, bounds, carbon_type) end do - if ( use_fates ) then - - call hist_addfld_decomp(fname='FATES_c_to_litr_lab_c', units='gC/m^3/s', type2d='levdcmp', & - avgflag='A', long_name='litter labile carbon flux from FATES to BGC', & - ptr_col=this%FATES_c_to_litr_lab_c_col) - - call hist_addfld_decomp(fname='FATES_c_to_litr_cel_c', units='gC/m^3/s', type2d='levdcmp', & - avgflag='A', long_name='litter celluluse carbon flux from FATES to BGC', & - ptr_col=this%FATES_c_to_litr_cel_c_col) - - call hist_addfld_decomp(fname='FATES_c_to_litr_lig_c', units='gC/m^3/s', type2d='levdcmp', & - avgflag='A', long_name='litter lignin carbon flux from FATES to BGC', & - ptr_col=this%FATES_c_to_litr_lig_c_col) - - endif - - end subroutine InitHistory !----------------------------------------------------------------------- @@ -694,40 +666,6 @@ subroutine Restart(this, bounds, ncid, flag) logical :: readvar !----------------------------------------------------------------------- - ! - ! if FATES is enabled, need to restart the variables used to transfer from FATES to CLM as they - ! are persistent between daily FATES dynamics calls and half-hourly CLM timesteps - ! - if ( use_fates ) then - - ptr2d => this%FATES_c_to_litr_lab_c_col - call restartvar(ncid=ncid, flag=flag, varname='FATES_c_to_litr_lab_c_col', xtype=ncd_double, & - dim1name='column', dim2name='levgrnd', switchdim=.true., & - long_name='', units='gC/m3/s', scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=ptr2d) - - ptr2d => this%FATES_c_to_litr_cel_c_col - call restartvar(ncid=ncid, flag=flag, varname='FATES_c_to_litr_cel_c_col', xtype=ncd_double, & - dim1name='column', dim2name='levgrnd', switchdim=.true., & - long_name='', units='gC/m3/s', scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=ptr2d) - - ptr2d => this%FATES_c_to_litr_lig_c_col - call restartvar(ncid=ncid, flag=flag, varname='FATES_c_to_litr_lig_c_col', xtype=ncd_double, & - dim1name='column', dim2name='levgrnd', switchdim=.true., & - long_name='', units='gC/m3/s', scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=ptr2d) - - ! Copy last 3 variables to an array of litter pools for use in do loops. - ! Repeat copy in src/utils/clmfates_interfaceMod.F90. - ! Keep the three originals to avoid backwards compatibility issues with - ! restart files. - this%FATES_c_to_litr_c_col(:,:,1) = this%FATES_c_to_litr_lab_c_col(:,:) - this%FATES_c_to_litr_c_col(:,:,2) = this%FATES_c_to_litr_cel_c_col(:,:) - this%FATES_c_to_litr_c_col(:,:,3) = this%FATES_c_to_litr_lig_c_col(:,:) - - end if - call restartvar(ncid=ncid, flag=flag, varname='ligninNratioAvg', xtype=ncd_double, & dim1name='column', & long_name='', units='', & @@ -806,13 +744,11 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%soilc_change_col(i) = value_column end do - ! NOTE: do not zero the fates to BGC C flux variables since they need to persist from the daily fates timestep s to the half-hourly BGC timesteps. I.e. FATES_c_to_litr_lab_c_col, FATES_c_to_litr_cel_c_col, FATES_c_to_litr_lig_c_col - end subroutine SetValues !----------------------------------------------------------------------- subroutine Summary(this, bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_soilp, filter_soilp, & soilbiogeochem_decomp_cascade_ctransfer_col, & soilbiogeochem_cwdc_col, soilbiogeochem_cwdn_col, & leafc_to_litter_patch, frootc_to_litter_patch) @@ -827,15 +763,16 @@ subroutine Summary(this, bounds, & ! !ARGUMENTS: class(soilbiogeochem_carbonflux_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns integer, intent(in), optional :: num_soilp ! number of patches in filter integer, intent(in), optional :: filter_soilp(:) ! filter for patches real(r8), intent(in), optional :: soilbiogeochem_cwdc_col(bounds%begc:) real(r8), intent(in), optional :: soilbiogeochem_cwdn_col(bounds%begc:) real(r8), intent(in), optional :: soilbiogeochem_decomp_cascade_ctransfer_col(bounds%begc:,1:) - real(r8), intent(in), optional :: leafc_to_litter_patch(bounds%begp:) - real(r8), intent(in), optional :: frootc_to_litter_patch(bounds%begp:) + + real(r8), intent(in), optional :: leafc_to_litter_patch(:) + real(r8), intent(in), optional :: frootc_to_litter_patch(:) ! ! !LOCAL VARIABLES: integer :: c,j,k,l,p @@ -850,16 +787,16 @@ subroutine Summary(this, bounds, & !----------------------------------------------------------------------- - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%som_c_leached_col(c) = 0._r8 end do ! vertically integrate HR and decomposition cascade fluxes do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cascade_hr_col(c,k) = & this%decomp_cascade_hr_col(c,k) + & this%decomp_cascade_hr_vr_col(c,j,k) * dzsoi_decomp(j) @@ -873,15 +810,15 @@ subroutine Summary(this, bounds, & ! total heterotrophic respiration, vertically resolved (HR) do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%hr_vr_col(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%hr_vr_col(c,j) = & this%hr_vr_col(c,j) + & this%decomp_cascade_hr_vr_col(c,j,k) @@ -891,19 +828,19 @@ subroutine Summary(this, bounds, & ! add up all vertical transport tendency terms and calculate total som leaching loss as the sum of these do l = 1, ndecomp_pools - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cpools_leached_col(c,l) = 0._r8 end do do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cpools_leached_col(c,l) = this%decomp_cpools_leached_col(c,l) + & this%decomp_cpools_transport_tendency_col(c,j,l) * dzsoi_decomp(j) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%som_c_leached_col(c) = this%som_c_leached_col(c) + this%decomp_cpools_leached_col(c,l) end do end do @@ -912,8 +849,8 @@ subroutine Summary(this, bounds, & associate(is_soil => decomp_cascade_con%is_soil) ! TRUE => pool is a soil pool do k = 1, ndecomp_cascade_transitions if ( is_soil(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%somhr_col(c) = this%somhr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -924,8 +861,8 @@ subroutine Summary(this, bounds, & associate(is_litter => decomp_cascade_con%is_litter) ! TRUE => pool is a litter pool do k = 1, ndecomp_cascade_transitions if ( is_litter(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%lithr_col(c) = this%lithr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -936,8 +873,8 @@ subroutine Summary(this, bounds, & associate(is_cwd => decomp_cascade_con%is_cwd) ! TRUE => pool is a cwd pool do k = 1, ndecomp_cascade_transitions if ( is_cwd(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%cwdhr_col(c) = this%cwdhr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -948,8 +885,8 @@ subroutine Summary(this, bounds, & associate(is_microbe => decomp_cascade_con%is_microbe) ! TRUE => pool is a microbial pool do k = 1, ndecomp_cascade_transitions if ( is_microbe(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%michr_col(c) = this%michr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -957,64 +894,73 @@ subroutine Summary(this, bounds, & end associate ! total heterotrophic respiration (HR) - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) - this%hr_col(c) = & - this%michr_col(c) + & - this%cwdhr_col(c) + & - this%lithr_col(c) + & - this%somhr_col(c) + this%hr_col(c) = & + this%michr_col(c) + & + this%cwdhr_col(c) + & + this%lithr_col(c) + & + this%somhr_col(c) - end do + end do ! Calculate ligninNratio ! FATES does its own calculation - if (.not. use_fates .and. decomp_method == mimics_decomp) then - do fp = 1,num_soilp - p = filter_soilp(fp) - - associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type - ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & - pftcon%lflitcn(ivt(p)) * & - leafc_to_litter_patch(p) - ligninNratio_froot_patch(p) = pftcon%fr_flig(ivt(p)) * & - pftcon%frootcn(ivt(p)) * & - frootc_to_litter_patch(p) - end associate - end do - - call p2c(bounds, num_soilc, filter_soilc, & - ligninNratio_leaf_patch(bounds%begp:bounds%endp), & - ligninNratio_leaf_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - ligninNratio_froot_patch(bounds%begp:bounds%endp), & - ligninNratio_froot_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - leafc_to_litter_patch(bounds%begp:bounds%endp), & - leafc_to_litter_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - frootc_to_litter_patch(bounds%begp:bounds%endp), & - frootc_to_litter_col(bounds%begc:bounds%endc)) + if_mimics: if (decomp_method == mimics_decomp ) then + + if(num_soilp>0)then + do fp = 1,num_soilp + p = filter_soilp(fp) + associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type + ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & + pftcon%lflitcn(ivt(p)) * & + leafc_to_litter_patch(p) + ligninNratio_froot_patch(p) = pftcon%fr_flig(ivt(p)) * & + pftcon%frootcn(ivt(p)) * & + frootc_to_litter_patch(p) + end associate + end do + + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + ligninNratio_leaf_patch(bounds%begp:bounds%endp), & + ligninNratio_leaf_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + ligninNratio_froot_patch(bounds%begp:bounds%endp), & + ligninNratio_froot_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + leafc_to_litter_patch(bounds%begp:bounds%endp), & + leafc_to_litter_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + frootc_to_litter_patch(bounds%begp:bounds%endp), & + frootc_to_litter_col(bounds%begc:bounds%endc)) + + end if ! Calculate ligninNratioAve - do fc = 1,num_soilc - c = filter_soilc(fc) - if (soilbiogeochem_cwdn_col(c) > 0._r8) then - ligninNratio_cwd = CNParamsShareInst%cwd_flig * & - (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & - soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) - else - ligninNratio_cwd = 0._r8 + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) + if(.not.col%is_fates(c)) then + if (soilbiogeochem_cwdn_col(c) > 0._r8) then + ligninNratio_cwd = CNParamsShareInst%cwd_flig * & + (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & + soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) + else + ligninNratio_cwd = 0._r8 + end if + this%litr_lig_c_to_n_col(c) = & + (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & + ligninNratio_cwd) / & + max(1.0e-3_r8, leafc_to_litter_col(c) + & + frootc_to_litter_col(c) + & + soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2)) + !else + ! For FATES: + ! this array is currently updated here: + ! clmfates_interfaceMod.F90:wrap_update_hlmfates_dyn() end if - this%litr_lig_c_to_n_col(c) = & - (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & - ligninNratio_cwd) / & - max(1.0e-3_r8, leafc_to_litter_col(c) + & - frootc_to_litter_col(c) + & - soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2)) end do - end if + end if if_mimics end subroutine Summary diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 index a09441069a..a915a88862 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 @@ -7,7 +7,7 @@ module SoilBiogeochemCarbonStateType use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan use clm_varpar , only : nlevdecomp_full, nlevdecomp, nlevsoi use clm_varcon , only : spval, ispval, dzsoi_decomp, zisoi, zsoi, c3_r2 - use clm_varctl , only : iulog, spinup_state, use_fates + use clm_varctl , only : iulog, spinup_state, use_fates_bgc use landunit_varcon , only : istcrop, istsoil use abortutils , only : endrun use spmdMod , only : masterproc @@ -17,6 +17,7 @@ module SoilBiogeochemCarbonStateType use GridcellType , only : grc use SoilBiogeochemStateType , only : get_spinup_latitude_term use SparseMatrixMultiplyMod , only : sparse_matrix_type, vector_type + use CNVegCarbonStateType , only : cnveg_carbonstate_type ! ! !PUBLIC TYPES: implicit none @@ -30,19 +31,28 @@ module SoilBiogeochemCarbonStateType real(r8), pointer :: ctrunc_vr_col (:,:) ! (gC/m3) vertically-resolved column-level sink for C truncation ! summary (diagnostic) state variables, not involved in mass balance - real(r8), pointer :: ctrunc_col (:) ! (gC/m2) column-level sink for C truncation - real(r8), pointer :: totmicc_col (:) ! (gC/m2) total microbial carbon - real(r8), pointer :: totlitc_col (:) ! (gC/m2) total litter carbon - real(r8), pointer :: totlitc_1m_col (:) ! (gC/m2) total litter carbon to 1 meter - real(r8), pointer :: totsomc_col (:) ! (gC/m2) total soil organic matter carbon - real(r8), pointer :: totsomc_1m_col (:) ! (gC/m2) total soil organic matter carbon to 1 meter - real(r8), pointer :: cwdc_col (:) ! (gC/m2) coarse woody debris C (diagnostic) - real(r8), pointer :: decomp_cpools_1m_col (:,:) ! (gC/m2) Diagnostic: decomposing (litter, cwd, soil) c pools to 1 meter - real(r8), pointer :: decomp_cpools_col (:,:) ! (gC/m2) decomposing (litter, cwd, soil) c pools - real(r8), pointer :: dyn_cbal_adjustments_col(:) ! (gC/m2) adjustments to each column made in this timestep via dynamic column area adjustments (note: this variable only makes sense at the column-level: it is meaningless if averaged to the gridcell-level) - integer :: restart_file_spinup_state ! spinup state as read from restart file, for determining whether to enter or exit spinup mode. - real(r8) :: totvegcthresh ! threshold for total vegetation carbon to zero out decomposition pools + real(r8), pointer :: ctrunc_col (:) ! (gC/m2) column-level sink for C truncation + real(r8), pointer :: totmicc_col (:) ! (gC/m2) total microbial carbon + real(r8), pointer :: totlitc_col (:) ! (gC/m2) total litter carbon + real(r8), pointer :: totlitc_1m_col (:) ! (gC/m2) total litter carbon to 1 meter + real(r8), pointer :: totsomc_col (:) ! (gC/m2) total soil organic matter carbon + real(r8), pointer :: totsomc_1m_col (:) ! (gC/m2) total soil organic matter carbon to 1 meter + real(r8), pointer :: cwdc_col (:) ! (gC/m2) coarse woody debris C (diagnostic) + real(r8), pointer :: decomp_cpools_1m_col (:,:) ! (gC/m2) Diagnostic: decomposing (litter, cwd, soil) c pools to 1 meter + real(r8), pointer :: decomp_cpools_col (:,:) ! (gC/m2) decomposing (litter, cwd, soil) c pools + real(r8), pointer :: dyn_cbal_adjustments_col(:) ! (gC/m2) adjustments to each column made in this timestep via dynamic column + ! area adjustments (note: this variable only makes sense at the column-level: + ! it is meaningless if averaged to the gridcell-level) + integer :: restart_file_spinup_state ! spinup state as read from restart file, for determining whether to enter or exit spinup mode. + real(r8) :: totvegcthresh ! threshold for total vegetation carbon to zero out decomposition pools + + + ! Carbon totals, includes soil, cpool and vegetation + real(r8), pointer :: totc_col (:) ! (gC/m2) total column carbon, incl veg and cpool + real(r8), pointer :: totecosysc_col (:) ! (gC/m2) total ecosystem carbon, incl veg but excl cpool + real(r8), pointer :: totc_grc (:) ! (gC/m2) total gridcell carbon + ! Matrix-cn contains @@ -95,9 +105,11 @@ subroutine InitAllocate(this, bounds) ! ! !LOCAL VARIABLES: integer :: begc,endc + integer :: begg,endg !------------------------------------------------------------------------ begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg allocate( this%decomp_cpools_col (begc :endc,1:ndecomp_pools)) ; this%decomp_cpools_col (:,:) = nan allocate( this%decomp_cpools_1m_col (begc :endc,1:ndecomp_pools)) ; this%decomp_cpools_1m_col (:,:) = nan @@ -116,9 +128,8 @@ subroutine InitAllocate(this, bounds) this%decomp_soilc_vr_col(:,:)= nan allocate(this%ctrunc_col (begc :endc)) ; this%ctrunc_col (:) = nan - if ( .not. use_fates ) then - allocate(this%cwdc_col (begc :endc)) ; this%cwdc_col (:) = nan - endif + allocate(this%cwdc_col (begc :endc)) ; this%cwdc_col (:) = nan + allocate(this%totmicc_col (begc :endc)) ; this%totmicc_col (:) = nan allocate(this%totlitc_col (begc :endc)) ; this%totlitc_col (:) = nan allocate(this%totsomc_col (begc :endc)) ; this%totsomc_col (:) = nan @@ -126,6 +137,10 @@ subroutine InitAllocate(this, bounds) allocate(this%totsomc_1m_col (begc :endc)) ; this%totsomc_1m_col (:) = nan allocate(this%dyn_cbal_adjustments_col (begc:endc)) ; this%dyn_cbal_adjustments_col (:) = nan + allocate(this%totc_col (begc:endc)) ; this%totc_col (:) = nan + allocate(this%totecosysc_col (begc:endc)) ; this%totecosysc_col (:) = nan + allocate(this%totc_grc (begg:endg)) ; this%totc_grc (:) = nan + this%restart_file_spinup_state = huge(1) end subroutine InitAllocate @@ -249,6 +264,16 @@ subroutine InitHistory(this, bounds, carbon_type) &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_cbal_adjustments_col, default='inactive') + this%totc_col(begc:endc) = spval + call hist_addfld1d (fname='TOTCOLC', units='gC/m^2', & + avgflag='A', long_name='total column carbon, incl veg and cpool but excl product pools', & + ptr_col=this%totc_col) + + this%totecosysc_col(begc:endc) = spval + call hist_addfld1d (fname='TOTECOSYSC', units='gC/m^2', & + avgflag='A', long_name='total ecosystem carbon, incl veg but excl cpool and product pools', & + ptr_col=this%totecosysc_col) + end if !------------------------------- @@ -336,6 +361,17 @@ subroutine InitHistory(this, bounds, carbon_type) long_name='C13 adjustments in soil carbon due to dynamic column areas; & &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_cbal_adjustments_col, default='inactive') + + this%totc_col(begc:endc) = spval + call hist_addfld1d (fname='C13_TOTCOLC', units='gC13/m^2', & + avgflag='A', long_name='C13 total column carbon, incl veg and cpool but excl product pools', & + ptr_col=this%totc_col, default='inactive') + + this%totecosysc_col(begc:endc) = spval + call hist_addfld1d (fname='C13_TOTECOSYSC', units='gC13/m^2', & + avgflag='A', long_name='C13 total ecosystem carbon, incl veg but excl cpool and product pools', & + ptr_col=this%totecosysc_col) + endif !------------------------------- @@ -426,6 +462,17 @@ subroutine InitHistory(this, bounds, carbon_type) long_name='C14 adjustments in soil carbon due to dynamic column areas; & &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_cbal_adjustments_col, default='inactive') + + this%totc_col(begc:endc) = spval + call hist_addfld1d (fname='C14_TOTCOLC', units='gC14/m^2', & + avgflag='A', long_name='C14 total column carbon, incl veg and cpool but excl product pools', & + ptr_col=this%totc_col, default='inactive') + + this%totecosysc_col(begc:endc) = spval + call hist_addfld1d (fname='C14_TOTECOSYSC', units='gC14/m^2', & + avgflag='A', long_name='C14 total ecosystem carbon, incl veg but excl cpool and product pools', & + ptr_col=this%totecosysc_col) + endif end subroutine InitHistory @@ -445,7 +492,7 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) type(soilbiogeochem_carbonstate_type), intent(in), optional :: c12_soilbiogeochem_carbonstate_inst ! ! !LOCAL VARIABLES: - integer :: p,c,l,j,k + integer :: p,c,l,j,k,g integer :: fc ! filter index integer :: num_special_col ! number of good values in special_col filter integer :: special_col(bounds%endc-bounds%begc+1) ! special landunit filter - columns @@ -523,23 +570,30 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) end if end if - if ( .not. use_fates ) then - if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then - if (present(c12_soilbiogeochem_carbonstate_inst)) then - this%cwdc_col(c) = c12_soilbiogeochem_carbonstate_inst%cwdc_col(c) * ratio - else - this%cwdc_col(c) = 0._r8 - end if - this%ctrunc_col(c) = 0._r8 - this%totmicc_col(c) = 0._r8 - this%totlitc_col(c) = 0._r8 - this%totsomc_col(c) = 0._r8 - this%totlitc_1m_col(c) = 0._r8 - this%totsomc_1m_col(c) = 0._r8 + + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + if (present(c12_soilbiogeochem_carbonstate_inst) .and. (.not.col%is_fates(c)) ) then + this%cwdc_col(c) = c12_soilbiogeochem_carbonstate_inst%cwdc_col(c) * ratio + else + this%cwdc_col(c) = 0._r8 end if + this%ctrunc_col(c) = 0._r8 + this%totmicc_col(c) = 0._r8 + this%totlitc_col(c) = 0._r8 + this%totsomc_col(c) = 0._r8 + this%totlitc_1m_col(c) = 0._r8 + this%totsomc_1m_col(c) = 0._r8 + + this%totc_col(c) = 0._r8 + this%totecosysc_col(c) = 0._r8 end if + end do + do g = bounds%begg, bounds%endg + this%totc_grc(g) = 0._r8 + end do + ! now loop through special filters and explicitly set the variables that ! have to be in place for biogeophysics @@ -815,7 +869,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) do fi = 1,num_column i = filter_column(fi) - if ( .not. use_fates ) then + if ( .not. col%is_fates(i) ) then this%cwdc_col(i) = value_column end if this%ctrunc_col(i) = value_column @@ -824,6 +878,8 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%totlitc_1m_col(i) = value_column this%totsomc_col(i) = value_column this%totsomc_1m_col(i) = value_column + this%totc_col(i) = value_column + this%totecosysc_col(i) = value_column end do do j = 1,nlevdecomp_full @@ -875,7 +931,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) end subroutine SetValues !----------------------------------------------------------------------- - subroutine Summary(this, bounds, num_allc, filter_allc) + subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bgc_soilc,cnveg_carbonstate_inst) ! ! !DESCRIPTION: ! Perform column-level carbon summary calculations @@ -883,13 +939,22 @@ subroutine Summary(this, bounds, num_allc, filter_allc) ! !ARGUMENTS: class(soilbiogeochem_carbonstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter + integer , intent(in) :: num_allc ! number of columns in soil filter integer , intent(in) :: filter_allc(:) ! filter for all active columns + integer , intent(in) :: num_bgc_soilc ! number of columns in soil filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for all active columns + type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + ! ! !LOCAL VARIABLES: integer :: c,j,k,l ! indices integer :: fc ! filter indices real(r8) :: maxdepth ! depth to integrate soil variables + integer :: num_local ! Either num_bgc_soilc or num_allc, depending + ! on if its a fates run, its different because + ! the cnveg variables are not allocated w/ fates + real(r8) :: ecovegc_col + real(r8) :: totvegc_col !----------------------------------------------------------------------- ! vertically integrate each of the decomposing C pools @@ -1056,23 +1121,53 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end if end do - ! coarse woody debris carbon - if (.not. use_fates ) then - do fc = 1,num_allc + do fc = 1,num_allc + c = filter_allc(fc) + ! coarse woody debris carbon + this%cwdc_col(c) = 0._r8 + end do + + if (use_fates_bgc) then + num_local = num_bgc_soilc + else + num_local = num_allc + end if + do fc = 1,num_local + if(use_fates_bgc) then + c = filter_bgc_soilc(fc) + else c = filter_allc(fc) - this%cwdc_col(c) = 0._r8 - end do - do l = 1, ndecomp_pools - if ( decomp_cascade_con%is_cwd(l) ) then - do fc = 1,num_allc - c = filter_allc(fc) + end if + if(col%is_fates(c)) then + totvegc_col = 0._r8 + ecovegc_col = 0._r8 + else + do l = 1, ndecomp_pools + if ( decomp_cascade_con%is_cwd(l) ) then this%cwdc_col(c) = this%cwdc_col(c) + this%decomp_cpools_col(c,l) - end do - end if - end do + end if + end do + totvegc_col = cnveg_carbonstate_inst%totc_p2c_col(c) + ecovegc_col = cnveg_carbonstate_inst%totvegc_col(c) + end if + + ! total ecosystem carbon, including veg but excluding cpool (TOTECOSYSC) + this%totecosysc_col(c) = & + this%cwdc_col(c) + & + this%totmicc_col(c) + & + this%totlitc_col(c) + & + this%totsomc_col(c) + & + ecovegc_col + ! total column carbon, including veg and cpool (TOTCOLC) + this%totc_col(c) = & + this%cwdc_col(c) + & + this%totmicc_col(c) + & + this%totlitc_col(c) + & + this%totsomc_col(c) + & + this%ctrunc_col(c) + & + totvegc_col + end do - end if - end subroutine Summary !------------------------------------------------------------------------ diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index eec9e00f80..57bc82984e 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -165,7 +165,7 @@ subroutine SoilBiogeochemCompetitionInit ( bounds) end subroutine SoilBiogeochemCompetitionInit !----------------------------------------------------------------------- - subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, & + subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,num_bgc_vegp, filter_bgc_vegp, & p_decomp_cn_gain, pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst, temperature_inst,soilstate_inst, & cnveg_state_inst,cnveg_carbonstate_inst, & @@ -187,10 +187,10 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for veg patches real(r8) , intent(in) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux from one pool to another (gN/m3/s) real(r8) , intent(in) :: p_decomp_cn_gain(bounds%begc:,1:,1:) ! C:N ratio of the flux gained by the receiver pool type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst @@ -284,7 +284,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! calcualte nitrogen uptake profile ! nuptake_prof(:,:) = nan ! call SoilBiogelchemNitrogenUptakeProfile(bounds, & - ! nlevdecomp, num_soilc, filter_soilc, & + ! nlevdecomp, num_bgc_soilc, filter_bgc_soilc, & ! sminn_vr, dzsoi_decomp, nfixation_prof, nuptake_prof) ! column loops to resolve plant/heterotroph competition for mineral N @@ -293,24 +293,24 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, local_use_fun = use_fun - if (.not. use_nitrif_denitrif) then + if_nitrif: if (.not. use_nitrif_denitrif) then ! init sminn_tot - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = 0. end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = sminn_tot(c) + sminn_vr(c,j) * dzsoi_decomp(j) end do end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (sminn_tot(c) > 0.) then nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) else @@ -320,15 +320,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sum_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + potential_immob_vr(c,j) end do end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) l = col%landunit(c) if (sum_ndemand_vr(c,j)*dt < sminn_vr(c,j)) then @@ -376,7 +376,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if ( local_use_fun ) then call t_startf( 'CNFUN' ) - call CNFUN(bounds,num_soilc,filter_soilc,num_soilp,filter_soilp,waterstatebulk_inst, & + call CNFUN(bounds,num_bgc_soilc,filter_bgc_soilc,num_bgc_vegp,filter_bgc_vegp,waterstatebulk_inst, & waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst,cnveg_carbonstate_inst,& cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst ,& soilbiogeochem_nitrogenflux_inst,soilbiogeochem_carbonflux_inst,canopystate_inst, & @@ -390,8 +390,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! sum up N fluxes to plant do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) if ( local_use_fun ) then if (sminn_to_plant_fun_vr(c,j).gt.sminn_to_plant_vr(c,j)) then @@ -402,19 +402,19 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! give plants a second pass to see if there is any mineral N left over with which to satisfy residual N demand. - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_sminn(c) = 0._r8 end do ! sum up total N left over after initial plant and immobilization fluxes - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_plant_ndemand(c) = plant_ndemand(c) - sminn_to_plant(c) end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (residual_plant_ndemand(c) > 0._r8 ) then if (nlimit(c,j) .eq. 0) then residual_sminn_vr(c,j) = max(sminn_vr(c,j) - (actual_immob_vr(c,j) + sminn_to_plant_vr(c,j) ) * dt, 0._r8) @@ -428,8 +428,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! distribute residual N to plants do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( residual_plant_ndemand(c) > 0._r8 .and. residual_sminn(c) > 0._r8 .and. nlimit(c,j) .eq. 0) then sminn_to_plant_vr(c,j) = sminn_to_plant_vr(c,j) + residual_sminn_vr(c,j) * & min(( residual_plant_ndemand(c) * dt ) / residual_sminn(c), 1._r8) / dt @@ -438,13 +438,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! re-sum up N fluxes to plant - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) if ( .not. local_use_fun ) then sum_ndemand_vr(c,j) = potential_immob_vr(c,j) + sminn_to_plant_vr(c,j) @@ -459,8 +459,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! be lost to denitrification, in addition to the constant ! proportion lost in the decomposition pathways do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( .not. local_use_fun ) then if ((sminn_to_plant_vr(c,j) + actual_immob_vr(c,j))*dt < sminn_vr(c,j)) then sminn_to_denit_excess_vr(c,j) = max(bdnr*((sminn_vr(c,j)/dt) - sum_ndemand_vr(c,j)),0._r8) @@ -479,15 +479,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! sum up N fluxes to immobilization do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) actual_immob(c) = actual_immob(c) + actual_immob_vr(c,j) * dzsoi_decomp(j) potential_immob(c) = potential_immob(c) + potential_immob_vr(c,j) * dzsoi_decomp(j) end do end do - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the fraction of potential growth that can be ! acheived with the N available to plants if (plant_ndemand(c) > 0.0_r8) then @@ -520,23 +520,23 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, compet_nit = params_inst%compet_nit ! init total mineral N pools - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = 0. end do ! sum up total mineral N pools do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = sminn_tot(c) + (smin_no3_vr(c,j) + smin_nh4_vr(c,j)) * dzsoi_decomp(j) end do end do ! define N uptake profile for initial vertical distribution of plant N uptake, assuming plant seeks N from where it is most abundant do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (sminn_tot(c) > 0.) then nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) else @@ -547,8 +547,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! main column/vertical loop do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) l = col%landunit(c) ! first compete for nh4 @@ -630,8 +630,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, sum_no3_demand_scaled(c,j) = (plant_ndemand(c)*nuptake_prof(c,j))*compet_plant_no3 + & (potential_immob_vr(c,j)-actual_immob_nh4_vr(c,j))*compet_decomp_no3 + pot_f_denit_vr(c,j)*compet_denit endif - - if (sum_no3_demand(c,j)*dt < smin_no3_vr(c,j)) then @@ -655,7 +653,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, smin_no3_to_plant_vr(c,j) = smin_no3_vr(c,j)/dt - actual_immob_no3_vr(c,j) - f_denit_vr(c,j) end if endif - + else ! NO3 availability can not satisfy the sum of immobilization, denitrification, and @@ -756,7 +754,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if ( local_use_fun ) then call t_startf( 'CNFUN' ) - call CNFUN(bounds,num_soilc,filter_soilc,num_soilp,filter_soilp,waterstatebulk_inst,& + call CNFUN(bounds,num_bgc_soilc,filter_bgc_soilc,num_bgc_vegp,filter_bgc_vegp,waterstatebulk_inst,& waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst,cnveg_carbonstate_inst,& cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst ,& soilbiogeochem_nitrogenflux_inst,soilbiogeochem_carbonflux_inst,canopystate_inst, & @@ -778,20 +776,20 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if(.not.local_use_fun)then - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! sum up N fluxes to plant after initial competition sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) end do end do else - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! sum up N fluxes to plant after initial competition sminn_to_plant(c) = 0._r8 !this isn't use in fun. do j = 1, nlevdecomp @@ -815,8 +813,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if (decomp_method == mimics_decomp) then do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) do k = 1, ndecomp_cascade_transitions if (cascade_receiver_pool(k) == i_cop_mic .or. & @@ -848,14 +846,14 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if(.not.local_use_fun)then ! give plants a second pass to see if there is any mineral N left over with which to satisfy residual N demand. ! first take frm nh4 pool; then take from no3 pool - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_plant_ndemand(c) = plant_ndemand(c) - sminn_to_plant(c) residual_smin_nh4(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (residual_plant_ndemand(c) > 0._r8 ) then if (nlimit_nh4(c,j) .eq. 0) then residual_smin_nh4_vr(c,j) = max(smin_nh4_vr(c,j) - (actual_immob_nh4_vr(c,j) + & @@ -875,13 +873,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! re-sum up N fluxes to plant after second pass for nh4 - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) sminn_to_plant(c) = sminn_to_plant(c) + (sminn_to_plant_vr(c,j)) * dzsoi_decomp(j) end do @@ -889,15 +887,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! ! and now do second pass for no3 - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_plant_ndemand(c) = plant_ndemand(c) - sminn_to_plant(c) residual_smin_no3(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (residual_plant_ndemand(c) > 0._r8 ) then if (nlimit_no3(c,j) .eq. 0) then residual_smin_no3_vr(c,j) = max(smin_no3_vr(c,j) - (actual_immob_no3_vr(c,j) + & @@ -916,13 +914,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! re-sum up N fluxes to plant after second passes of both no3 and nh4 - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) sminn_to_plant(c) = sminn_to_plant(c) + (sminn_to_plant_vr(c,j)) * dzsoi_decomp(j) end do @@ -930,13 +928,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, else !use_fun !calculate maximum N available to plants. - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) sminn_to_plant(c) = sminn_to_plant(c) + (sminn_to_plant_vr(c,j)) * dzsoi_decomp(j) end do @@ -945,8 +943,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! add up fun fluxes from SMINN to plant. do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_new(c) = sminn_to_plant_new(c) + & (sminn_to_plant_fun_no3_vr(c,j) + sminn_to_plant_fun_nh4_vr(c,j)) * dzsoi_decomp(j) @@ -956,14 +954,14 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if !use_f ! sum up N fluxes to immobilization - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) actual_immob(c) = 0._r8 potential_immob(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) actual_immob(c) = actual_immob(c) + actual_immob_vr(c,j) * dzsoi_decomp(j) potential_immob(c) = potential_immob(c) + potential_immob_vr(c,j) * dzsoi_decomp(j) end do @@ -972,8 +970,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the fraction of potential growth that can be ! acheived with the N available to plants ! calculate the fraction of immobilization realized (for diagnostic purposes) @@ -993,7 +991,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if end do ! end of column loops - end if !end of if_not_use_nitrif_denitrif + end if if_nitrif !end of if_not_use_nitrif_denitrif end associate diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index b65fc5f17f..c32e177b1b 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -510,7 +510,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i end subroutine init_decompcascade_bgc !----------------------------------------------------------------------- - subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & + subroutine decomp_rate_constants_bgc(bounds, num_bgc_soilc, filter_bgc_soilc, & soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) ! ! !DESCRIPTION: @@ -524,8 +524,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilstate_type) , intent(in) :: soilstate_inst type(temperature_type) , intent(in) :: temperature_inst type(ch4_type) , intent(in) :: ch4_inst @@ -619,8 +619,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & catanf_30 = catanf(30._r8) if ( spinup_state >= 1 ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. eps) then spinup_geogterm_l1(c) = spinup_factor(i_met_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) @@ -662,8 +662,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! end do else - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) spinup_geogterm_l1(c) = 1._r8 spinup_geogterm_l23(c) = 1._r8 spinup_geogterm_cwd(c) = 1._r8 @@ -686,14 +686,14 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & nlev_soildecomp_standard=5 allocate(fr(bounds%begc:bounds%endc,nlev_soildecomp_standard)) do j=1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) frw(c) = frw(c) + col%dz(c,j) end do end do do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (frw(c) /= 0._r8) then fr(c,j) = col%dz(c,j) / frw(c) else @@ -708,8 +708,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! limiting conditions at 25 C. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) t_scalar(c,:) = 0._r8 if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then t_scalar(c,1)=t_scalar(c,1) + & @@ -724,8 +724,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & else ! original century uses an arctangent function to calculate the temperature dependence of decomposition do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) t_scalar(c,:) = 0._r8 t_scalar(c,1)=t_scalar(c,1) +max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30*fr(c,j),0.01_r8) @@ -743,8 +743,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) w_scalar(c,:) = 0._r8 psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi @@ -760,8 +760,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! Check for anoxia w/o LCH4 now done in controlMod. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) o_scalar(c,:) = 0._r8 @@ -790,8 +790,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! the base rates at 25 C, which are calibrated from microcosm studies. do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then t_scalar(c,j)= (Q10**((t_soisno(c,j)-(SHR_CONST_TKFRZ+25._r8))/10._r8)) else @@ -803,8 +803,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & else do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) t_scalar(c,j)= max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30, 0.01_r8) end do end do @@ -820,8 +820,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi if (psi > minpsi) then @@ -838,8 +838,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & if (anoxia) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) o_scalar(c,j) = max(o2stress_unsat(c,j), mino2lim) end do @@ -857,8 +857,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! scale all decomposition rates by a constant to compensate for offset between original CENTURY temp func and Q10 normalization_factor = (catanf(normalization_tref)/catanf_30) / (q10**((normalization_tref-25._r8)/10._r8)) do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) t_scalar(c,j) = t_scalar(c,j) * normalization_factor end do end do @@ -867,16 +867,16 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! add a term to reduce decomposition rate at depth ! for now used a fixed e-folding depth do j = 1, nlevdecomp - do fc = 1, num_soilc - c = filter_soilc(fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) end do end do ! calculate rate constants for all litter and som pools do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) decomp_k(c,j,i_met_lit) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) decomp_k(c,j,i_cel_lit) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * & diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 index 4f6cf04eaf..0474ab9a63 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 @@ -63,7 +63,7 @@ module SoilBiogeochemDecompCascadeConType !------------------------------------------------------------------------ subroutine decomp_cascade_par_init( NLFilename ) - use clm_varctl , only : use_fates, use_cn, use_fates_sp + use clm_varctl , only : use_cn, use_fates_bgc use clm_varpar , only : ndecomp_pools_max use spmdMod , only : masterproc, mpicom use clm_nlUtilsMod , only : find_nlgroup_name @@ -110,9 +110,9 @@ subroutine decomp_cascade_par_init( NLFilename ) if ( decomp_method == no_soil_decomp )then call endrun('When running with BGC an active soil_decomp_method must be used') end if - else if ( use_fates ) then - if ( .not. use_fates_sp .and. (decomp_method == no_soil_decomp) )then - call endrun('When running with FATES and without FATES-SP an active soil_decomp_method must be used') + else if ( use_fates_bgc ) then + if ( decomp_method == no_soil_decomp )then + call endrun('When running with FATES and without FATES-SP, an active soil_decomp_method must be used') end if else if ( decomp_method /= no_soil_decomp )then @@ -128,7 +128,7 @@ subroutine decomp_cascade_par_init( NLFilename ) ! ndecomp_pools would get the value of i_pas_som or i_cwd and ! ndecomp_cascade_transitions would get the value of i_s3s1 or i_cwdl3 ! depending on how use_fates is set. - if ( use_fates ) then + if ( use_fates_bgc ) then if (decomp_method == century_decomp) then ndecomp_pools = 6 ndecomp_cascade_transitions = 8 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index f820db01b6..e2a2a4ab99 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -752,7 +752,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat end subroutine init_decompcascade_mimics !----------------------------------------------------------------------- - subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & + subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & num_soilp, filter_soilp, clm_fates, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, & ch4_inst, soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) @@ -773,8 +773,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilstate_type) , intent(in) :: soilstate_inst type(temperature_type) , intent(in) :: temperature_inst type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst @@ -895,8 +895,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! calc ref rate if ( spinup_state >= 1 ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. eps) then spinup_geogterm_l1(c) = spinup_factor(i_met_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) @@ -950,8 +950,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! end do else - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) spinup_geogterm_l1(c) = 1._r8 spinup_geogterm_l2(c) = 1._r8 spinup_geogterm_cwd(c) = 1._r8 @@ -975,14 +975,14 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & frw(bounds%begc:bounds%endc) = 0._r8 allocate(fr(bounds%begc:bounds%endc,nlev_soildecomp_standard)) do j=1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) frw(c) = frw(c) + col%dz(c,j) end do end do do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (frw(c) /= 0._r8) then fr(c,j) = col%dz(c,j) / frw(c) else @@ -1000,8 +1000,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) w_scalar(c,:) = 0._r8 psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi @@ -1017,8 +1017,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & if (anoxia) then do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) o_scalar(c,:) = 0._r8 @@ -1042,8 +1042,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi if (psi > minpsi) then @@ -1059,8 +1059,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & if (anoxia) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) o_scalar(c,j) = max(o2stress_unsat(c,j), mino2lim) end do @@ -1074,8 +1074,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Term that reduces decomposition rate at depth ! Placeholder. For now depth_scalar = 1. do j = 1, nlevdecomp - do fc = 1, num_soilc - c = filter_soilc(fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) ! Using fixed e-folding depth as in ! SoilBiogeochemDecompCascadeBGCMod.F90 ! depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) @@ -1135,7 +1135,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do ! p loop ! Calculate the column-level average - call p2c(bounds, num_soilc, filter_soilc, & + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & annsum_npp(bounds%begp:bounds%endp), & annsum_npp_col_local(bounds%begc:bounds%endc)) else @@ -1146,8 +1146,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end if fates_if ! calculate rates for all litter and som pools - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (use_fates) then annsum_npp_col_scalar = max(0._r8, annsum_npp_col_local(c)) diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index a46f999143..9bd8b13008 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -11,7 +11,7 @@ module SoilBiogeochemDecompMod use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type use clm_varpar , only : nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools - use clm_varctl , only : use_nitrif_denitrif, use_lch4, use_fates, iulog + use clm_varctl , only : use_nitrif_denitrif, use_lch4, iulog use clm_varcon , only : dzsoi_decomp use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, mimics_decomp, decomp_method, use_soil_matrixcn use SoilBiogeochemStateType , only : soilbiogeochem_state_type @@ -67,7 +67,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemDecomp (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools, p_decomp_cpool_loss, pmnf_decomp_cascade, & @@ -78,8 +78,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! ! !ARGUMENT: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst type(soilbiogeochem_carbonstate_type) , intent(in) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst @@ -137,13 +137,12 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! column loop to calculate actual immobilization and decomp rates, following ! resolution of plant/heterotroph competition for mineral N - if ( .not. use_fates) then ! calculate c:n ratios of applicable pools do l = 1, ndecomp_pools if ( floating_cn_ratio_decomp_pools(l) ) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( decomp_npools_vr(c,j,l) > 0._r8 ) then cn_decomp_pools(c,j,l) = decomp_cpools_vr(c,j,l) / decomp_npools_vr(c,j,l) end if @@ -151,8 +150,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, end do else do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) cn_decomp_pools(c,j,l) = initial_cn_ratio(l) end do end do @@ -170,8 +169,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (decomp_cpools_vr(c,j,cascade_donor_pool(k)) > 0._r8) then if ( pmnf_decomp_cascade(c,j,k) > 0._r8 ) then @@ -221,38 +220,21 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, end do end do end do - else - do k = 1, ndecomp_cascade_transitions - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! - decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) - decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) - if (decomp_method == mimics_decomp) then - decomp_cascade_hr_vr(c,j,k) = min( & - p_decomp_cpool_loss(c,j,k), & - decomp_cascade_hr_vr(c,j,k) + c_overflow_vr(c,j,k)) - decomp_cascade_ctransfer_vr(c,j,k) = max(0.0_r8, p_decomp_cpool_loss(c,j,k) - decomp_cascade_hr_vr(c,j,k)) - end if - ! - end do - end do - end do - end if + + if (use_lch4) then ! Calculate total fraction of potential HR, for methane code do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) hrsum(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) hrsum(c,j) = hrsum(c,j) + rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) end do end do @@ -261,8 +243,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! Nitrogen limitation / (low)-moisture limitation do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (phr_vr(c,j) > 0._r8) then fphr(c,j) = hrsum(c,j) / phr_vr(c,j) * w_scalar(c,j) fphr(c,j) = max(fphr(c,j), 0.01_r8) ! Prevent overflow errors for 0 respiration @@ -276,16 +258,11 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! vertically integrate net and gross mineralization fluxes for diagnostic output - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) do j = 1,nlevdecomp - if(.not.use_fates)then net_nmin(c) = net_nmin(c) + net_nmin_vr(c,j) * dzsoi_decomp(j) gross_nmin(c) = gross_nmin(c) + gross_nmin_vr(c,j) * dzsoi_decomp(j) - ! else - ! net_nmin(c) = 0.0_r8 - ! gross_nmin(c) = 0.0_r8 - endif end do end do diff --git a/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 b/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 index 616f995bd7..e58e2f22d6 100644 --- a/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 @@ -5,7 +5,7 @@ module SoilBiogeochemLittVertTranspMod ! use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg - use clm_varctl , only : iulog, use_c13, use_c14, spinup_state, use_fates, use_cn + use clm_varctl , only : iulog, use_c13, use_c14, spinup_state use clm_varcon , only : secspday use decompMod , only : bounds_type use abortutils , only : endrun @@ -81,7 +81,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_soilc, & active_layer_inst, soilbiogeochem_state_inst, & soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & @@ -105,8 +105,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(active_layer_type) , intent(in) :: active_layer_inst type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst @@ -182,16 +182,13 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & if ( use_c14 ) then ntype = ntype+1 endif - if ( use_fates ) then - ntype = 1 - endif spinup_term = 1._r8 epsilon = 1.e-30 !------ first get diffusivity / advection terms -------! ! use different mixing rates for bioturbation and cryoturbation, with fixed bioturbation and cryoturbation set to a maximum depth - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) if (( max(altmax(c), altmax_lastyear(c)) <= max_altdepth_cryoturbation ) .and. & ( max(altmax(c), altmax_lastyear(c)) > 0._r8) ) then ! use mixing profile modified slightly from Koven et al. (2009): constant through active layer, linear decrease from base of active layer to zero at a fixed depth @@ -247,11 +244,9 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & source => soilbiogeochem_carbonflux_inst%decomp_cpools_sourcesink_col trcr_tendency_ptr => soilbiogeochem_carbonflux_inst%decomp_cpools_transport_tendency_col case (2) ! N - if (use_cn ) then - conc_ptr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col - source => soilbiogeochem_nitrogenflux_inst%decomp_npools_sourcesink_col - trcr_tendency_ptr => soilbiogeochem_nitrogenflux_inst%decomp_npools_transport_tendency_col - endif + conc_ptr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col + source => soilbiogeochem_nitrogenflux_inst%decomp_npools_sourcesink_col + trcr_tendency_ptr => soilbiogeochem_nitrogenflux_inst%decomp_npools_transport_tendency_col case (3) if ( use_c13 ) then ! C13 @@ -280,8 +275,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & if ( .not. is_cwd(s) ) then if(.not. use_soil_matrixcn .or. s .eq. 1)then do j = 1,nlevdecomp+1 - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) ! if ( spinup_state >= 1 ) then ! increase transport (both advection and diffusion) by the same factor as accelerated decomposition for a given pool @@ -311,16 +306,16 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! Set Pe (Peclet #) and D/dz throughout column - do fc = 1, num_soilc ! dummy terms here - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc ! dummy terms here + c = filter_bgc_soilc (fc) conc_trcr(c,0) = 0._r8 conc_trcr(c,col%nbedrock(c)+1:nlevdecomp+1) = 0._r8 end do do j = 1,nlevdecomp+1 - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) conc_trcr(c,j) = conc_ptr(c,j,s) @@ -384,8 +379,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! Calculate the tridiagonal coefficients do j = 0,nlevdecomp +1 - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) ! g = cgridcell(c) if (j > 0 .and. j < nlevdecomp+1) then @@ -433,14 +428,14 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & enddo ! fc; column enddo ! j; nlevdecomp - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) jtop(c) = 0 enddo ! subtract initial concentration and source terms for tendency calculation - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) do j = 1, nlevdecomp if (.not. use_soil_matrixcn) then trcr_tendency_ptr(c,j,s) = 0.-(conc_trcr(c,j) + source(c,j,s)) @@ -454,15 +449,15 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! Solve for the concentration profile for this time step call Tridiagonal(bounds, 0, nlevdecomp+1, & jtop(bounds%begc:bounds%endc), & - num_soilc, filter_soilc, & + num_bgc_soilc, filter_bgc_soilc, & a_tri(bounds%begc:bounds%endc, :), & b_tri(bounds%begc:bounds%endc, :), & c_tri(bounds%begc:bounds%endc, :), & r_tri(bounds%begc:bounds%endc, :), & conc_trcr(bounds%begc:bounds%endc,0:nlevdecomp+1)) ! add post-transport concentration to calculate tendency term - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) do j = 1, nlevdecomp trcr_tendency_ptr(c,j,s) = trcr_tendency_ptr(c,j,s) + conc_trcr(c,j) trcr_tendency_ptr(c,j,s) = trcr_tendency_ptr(c,j,s) / dtime @@ -471,16 +466,16 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & else ! For matrix solution set the matrix input array do j = 1,nlevdecomp - do fc =1,num_soilc - c = filter_soilc(fc) + do fc =1,num_bgc_soilc + c = filter_bgc_soilc(fc) end do end do end if !soil_matrix else ! for CWD pools, just add do j = 1,nlevdecomp - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) if(.not. use_soil_matrixcn)then conc_trcr(c,j) = conc_ptr(c,j,s) + source(c,j,s) else @@ -498,8 +493,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & if (.not. use_soil_matrixcn) then do j = 1,nlevdecomp - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) conc_ptr(c,j,s) = conc_trcr(c,j) ! Correct for small amounts of carbon that leak into bedrock if (j > col%nbedrock(c)) then diff --git a/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 b/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 index 02d22d6613..a646feb1d7 100644 --- a/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 @@ -72,7 +72,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemNLeaching(bounds, num_bgc_soilc, filter_bgc_soilc, & waterstatebulk_inst, waterfluxbulk_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) ! @@ -86,8 +86,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst @@ -133,8 +133,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & ! calculate the total soil water tot_water(bounds%begc:bounds%endc) = 0._r8 do j = 1,nlevsoi - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) tot_water(c) = tot_water(c) + h2osoi_liq(c,j) end do end do @@ -143,21 +143,21 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & surface_water(bounds%begc:bounds%endc) = 0._r8 do j = 1,nlevsoi if ( zisoi(j) <= depth_runoff_Nloss) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) surface_water(c) = surface_water(c) + h2osoi_liq(c,j) end do elseif ( zisoi(j-1) < depth_runoff_Nloss) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) surface_water(c) = surface_water(c) + h2osoi_liq(c,j) * ( (depth_runoff_Nloss - zisoi(j-1)) / col%dz(c,j)) end do endif end do ! Loop through columns - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) drain_tot(c) = qflx_drain(c) end do @@ -170,8 +170,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & do j = 1,nlevdecomp ! Loop through columns - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the dissolved mineral N concentration (gN/kg water) ! assumes that 10% of mineral nitrogen is soluble @@ -203,8 +203,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & do j = 1,nlevdecomp ! Loop through columns - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the dissolved mineral N concentration (gN/kg water) ! assumes that 10% of mineral nitrogen is soluble diff --git a/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 b/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 index 197a1d015b..4b70459aca 100644 --- a/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 @@ -27,7 +27,7 @@ module SoilBiogeochemNStateUpdate1Mod contains !----------------------------------------------------------------------- - subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & + subroutine SoilBiogeochemNStateUpdate1(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) ! ! !DESCRIPTION: @@ -35,8 +35,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & ! variables (except for gap-phase mortality and fire fluxes) ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst @@ -63,8 +63,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & dt = get_step_size_real() do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if(use_fun)then !RF in FUN logic, the fixed N goes straight into the plant, and not into the SMINN pool. ! N deposition and fixation (put all into NH4 pool) ns%smin_nh4_vr_col(c,j) = ns%smin_nh4_vr_col(c,j) + nf%ndep_to_sminn_col(c)*dt * ndep_prof(c,j) @@ -94,8 +94,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (.not. use_nitrif_denitrif) then ! N deposition and fixation @@ -122,8 +122,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & do k = 1, ndecomp_cascade_transitions do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) = & nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) - & @@ -137,8 +137,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) nf%decomp_npools_sourcesink_col(c,j,cascade_receiver_pool(k)) = & nf%decomp_npools_sourcesink_col(c,j,cascade_receiver_pool(k)) + & @@ -149,8 +149,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & else ! terminal transitions do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) = & nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) - & nf%decomp_cascade_sminn_flux_vr_col(c,j,k) * dt @@ -173,8 +173,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ns%sminn_vr_col(c,j) = ns%sminn_vr_col(c,j) - & (nf%sminn_to_denit_decomp_cascade_vr_col(c,j,k) + & nf%decomp_cascade_sminn_flux_vr_col(c,j,k))* dt @@ -183,8 +183,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & else do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ns%sminn_vr_col(c,j) = ns%sminn_vr_col(c,j) - & nf%sminn_to_denit_decomp_cascade_vr_col(c,j,k)* dt @@ -198,8 +198,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! "bulk denitrification" ns%sminn_vr_col(c,j) = ns%sminn_vr_col(c,j) - nf%sminn_to_denit_excess_vr_col(c,j) * dt @@ -222,8 +222,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! mineralization fluxes (divert a fraction of this stream to nitrification flux, add the rest to NH4 pool) ns%smin_nh4_vr_col(c,j) = ns%smin_nh4_vr_col(c,j) + nf%gross_nmin_vr_col(c,j)*dt diff --git a/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 b/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 index 3993439a1c..b30ff759b4 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 @@ -12,7 +12,7 @@ module SoilBiogeochemNitrifDenitrifMod use clm_varpar , only : nlevdecomp use clm_varcon , only : rpi, grav use clm_varcon , only : d_con_g, d_con_w, secspday - use clm_varctl , only : use_lch4, use_fates + use clm_varctl , only : use_lch4 use abortutils , only : endrun use decompMod , only : bounds_type use SoilStatetype , only : soilstate_type @@ -74,6 +74,7 @@ subroutine readParams ( ncid ) ! ! read in constants ! + tString='surface_tension_water' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -137,7 +138,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemNitrifDenitrif(bounds, num_bgc_soilc, filter_bgc_soilc, & soilstate_inst, waterstatebulk_inst, temperature_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) ! @@ -150,8 +151,8 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilstate_type) , intent(in) :: soilstate_inst type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst type(temperature_type) , intent(in) :: temperature_inst @@ -260,8 +261,8 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & co2diff_con(2) = 0.0009_r8 do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) !---------------- calculate soil anoxia state ! calculate gas diffusivity of soil at field capacity here diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 index 839f69379a..5907d109d5 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 @@ -7,7 +7,7 @@ module SoilBiogeochemNitrogenFluxType use clm_varpar , only : nlevdecomp_full, nlevdecomp use clm_varcon , only : spval, ispval, dzsoi_decomp use decompMod , only : bounds_type - use clm_varctl , only : use_nitrif_denitrif, use_crop + use clm_varctl , only : use_nitrif_denitrif, use_crop, use_fates use CNSharedParamsMod , only : use_fun use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn use abortutils , only : endrun @@ -127,8 +127,10 @@ module SoilBiogeochemNitrogenFluxType ! all n pools involved in decomposition real(r8), pointer :: decomp_npools_sourcesink_col (:,:,:) ! col (gN/m3) change in decomposing n pools ! (sum of all additions and subtractions from stateupdate1). - real(r8), pointer :: sminn_to_plant_fun_vr_col (:,:) ! col total layer soil N uptake of FUN (gN/m2/s) - + real(r8), pointer :: sminn_to_plant_fun_vr_col (:,:) ! col total layer soil N uptake of FUN (gN/m2/s) + real(r8), pointer :: fates_litter_flux (:) ! (gN/m2/s) A summary of the total litter + ! flux passed in from FATES. + ! This is a diagnostic for balance checks only ! track tradiagonal matrix contains @@ -274,6 +276,12 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_npools_sourcesink_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) this%decomp_npools_sourcesink_col (:,:,:) = nan + if(use_fates)then + allocate(this%fates_litter_flux(begc:endc)); this%fates_litter_flux(:) = nan + else + allocate(this%fates_litter_flux(0:0)); this%fates_litter_flux(:) = nan + end if + ! Allocate soil Matrix setug if(use_soil_matrixcn)then end if @@ -1044,7 +1052,7 @@ subroutine SetValues ( this, & end subroutine SetValues !----------------------------------------------------------------------- - subroutine Summary(this, bounds, num_soilc, filter_soilc) + subroutine Summary(this, bounds, num_bgc_soilc, filter_bgc_soilc) ! ! !USES: use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions,ndecomp_pools @@ -1053,16 +1061,16 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! !ARGUMENTS: class (soilbiogeochem_nitrogenflux_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns ! ! !LOCAL VARIABLES: integer :: c,j,k,l ! indices integer :: fc ! filter indices !----------------------------------------------------------------------- - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = 0._r8 this%supplement_to_sminn_col(c) = 0._r8 this%som_n_leached_col(c) = 0._r8 @@ -1071,8 +1079,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate decomposing N cascade fluxes and soil mineral N fluxes associated with decomposition cascade do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cascade_ntransfer_col(c,k) = & this%decomp_cascade_ntransfer_col(c,k) + & @@ -1090,8 +1098,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate each denitrification flux do l = 1, ndecomp_cascade_transitions do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%sminn_to_denit_decomp_cascade_col(c,l) = & this%sminn_to_denit_decomp_cascade_col(c,l) + & this%sminn_to_denit_decomp_cascade_vr_col(c,j,l) * dzsoi_decomp(j) @@ -1101,8 +1109,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate bulk denitrification and leaching flux do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%sminn_to_denit_excess_col(c) = & this%sminn_to_denit_excess_col(c) + & this%sminn_to_denit_excess_vr_col(c,j) * dzsoi_decomp(j) @@ -1115,16 +1123,16 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! total N denitrification (DENIT) do l = 1, ndecomp_cascade_transitions - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = & this%denit_col(c) + & this%sminn_to_denit_decomp_cascade_col(c,l) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = & this%denit_col(c) + & this%sminn_to_denit_excess_col(c) @@ -1134,8 +1142,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate NO3 NH4 N2O fluxes and pools do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! nitrification and denitrification fluxes this%f_nit_col(c) = & @@ -1174,8 +1182,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = this%f_denit_col(c) end do @@ -1183,8 +1191,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! supplementary N supplement_to_sminn do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%supplement_to_sminn_col(c) = & this%supplement_to_sminn_col(c) + & this%supplement_to_sminn_vr_col(c,j) * dzsoi_decomp(j) @@ -1193,22 +1201,22 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! add up all vertical transport tendency terms and calculate total som leaching loss as the sum of these do l = 1, ndecomp_pools - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_npools_leached_col(c,l) = 0._r8 end do do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_npools_leached_col(c,l) = & this%decomp_npools_leached_col(c,l) + & this%decomp_npools_transport_tendency_col(c,j,l) * dzsoi_decomp(j) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%som_n_leached_col(c) = & this%som_n_leached_col(c) + & this%decomp_npools_leached_col(c,l) diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 index 3e54e52436..3a217dd4c3 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 @@ -11,7 +11,7 @@ module SoilBiogeochemNitrogenStateType use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan use clm_varpar , only : nlevdecomp_full, nlevdecomp, nlevsoi use clm_varcon , only : spval, dzsoi_decomp, zisoi - use clm_varctl , only : use_nitrif_denitrif + use clm_varctl , only : use_nitrif_denitrif, use_fates_bgc use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, century_decomp, decomp_method, use_soil_matrixcn use clm_varctl , only : iulog, override_bgc_restart_mismatch_dump, spinup_state use landunit_varcon , only : istcrop, istsoil @@ -21,6 +21,7 @@ module SoilBiogeochemNitrogenStateType use GridcellType , only : grc use SoilBiogeochemStateType , only : get_spinup_latitude_term use SparseMatrixMultiplyMod , only : sparse_matrix_type, vector_type + use CNVegNitrogenStateType , only : cnveg_nitrogenstate_type ! ! !PUBLIC TYPES: implicit none @@ -59,7 +60,11 @@ module SoilBiogeochemNitrogenStateType real(r8), pointer :: dyn_no3bal_adjustments_col (:) ! (gN/m2) NO3 adjustments to each column made in this timestep via dynamic column area adjustments (only makes sense at the column-level: meaningless if averaged to the gridcell-level) real(r8), pointer :: dyn_nh4bal_adjustments_col (:) ! (gN/m2) NH4 adjustments to each column made in this timestep via dynamic column adjustments (only makes sense at the column-level: meaningless if averaged to the gridcell-level) real(r8) :: totvegcthresh ! threshold for total vegetation carbon to zero out decomposition pools - + + real(r8), pointer :: totn_col (:) ! (gN/m2) total column nitrogen, incl veg + real(r8), pointer :: totecosysn_col (:) ! (gN/m2) total ecosystem nitrogen, incl veg + real(r8), pointer :: totn_grc (:) ! (gN/m2) total gridcell nitrogen + ! Matrix-cn contains @@ -144,6 +149,10 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_soiln_vr_col(begc:endc,1:nlevdecomp_full)) this%decomp_soiln_vr_col(:,:)= nan + allocate(this%totn_col (begc:endc)) ; this%totn_col (:) = nan + allocate(this%totecosysn_col (begc:endc)) ; this%totecosysn_col (:) = nan + allocate(this%totn_grc (bounds%begg:bounds%endg)) ; this%totn_grc (:) = nan + end subroutine InitAllocate !------------------------------------------------------------------------ @@ -329,6 +338,17 @@ subroutine InitHistory(this, bounds) &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_nh4bal_adjustments_col, default='inactive') end if + + this%totecosysn_col(begc:endc) = spval + call hist_addfld1d (fname='TOTECOSYSN', units='gN/m^2', & + avgflag='A', long_name='total ecosystem N, excluding product pools', & + ptr_col=this%totecosysn_col) + + this%totn_col(begc:endc) = spval + call hist_addfld1d (fname='TOTCOLN', units='gN/m^2', & + avgflag='A', long_name='total column-level N, excluding product pools', & + ptr_col=this%totn_col) + end subroutine InitHistory !----------------------------------------------------------------------- @@ -434,6 +454,21 @@ subroutine InitCold(this, bounds, & end if end do + do c = bounds%begc, bounds%endc + l = col%landunit(c) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + ! total nitrogen pools + this%totecosysn_col(c) = 0._r8 + this%totn_col(c) = 0._r8 + end if + end do + + + do g = bounds%begg, bounds%endg + this%totn_grc(g) = 0._r8 + end do + + call this%SetValues (num_column=num_special_col, filter_column=special_col, value_column=0._r8) end subroutine InitCold @@ -756,6 +791,12 @@ subroutine SetValues ( this, num_column, filter_column, value_column ) end do end do + do fi = 1,num_column + i = filter_column(fi) + this%totecosysn_col(i) = value_column + this%totn_col(i) = value_column + end do + ! Set values for the matrix solution if(use_soil_matrixcn)then end if @@ -763,18 +804,29 @@ subroutine SetValues ( this, num_column, filter_column, value_column ) end subroutine SetValues !----------------------------------------------------------------------- - subroutine Summary(this, bounds, num_allc, filter_allc) + + subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bgc_soilc, cnveg_nitrogenstate_inst) + ! ! !ARGUMENTS: class (soilbiogeochem_nitrogenstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter - integer , intent(in) :: filter_allc(:) ! filter for all active columns + integer , intent(in) :: num_allc ! number of bgc columns in soilc filter + integer , intent(in) :: filter_allc(:) ! filter for bgc columns + integer , intent(in) :: num_bgc_soilc ! number of bgc columns in soilc filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc columns + type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst + ! ! !LOCAL VARIABLES: integer :: c,j,k,l ! indices integer :: fc ! lake filter indices + integer :: num_local ! we do summary on different set when fates is + ! active becuase the CN variables aren't allocated + ! this preserves B4B real(r8) :: maxdepth ! depth to integrate soil variables + real(r8) :: totvegn_col ! local total ecosys veg N, allows 0 for fates + real(r8) :: ecovegn_col ! local total veg N, allows 0 for fates !----------------------------------------------------------------------- ! vertically integrate NO3 NH4 N2O pools @@ -952,21 +1004,6 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end if end do - ! total cwdn - do fc = 1,num_allc - c = filter_allc(fc) - this%cwdn_col(c) = 0._r8 - end do - do l = 1, ndecomp_pools - if ( decomp_cascade_con%is_cwd(l) ) then - do fc = 1,num_allc - c = filter_allc(fc) - this%cwdn_col(c) = this%cwdn_col(c) + & - this%decomp_npools_col(c,l) - end do - end if - end do - ! total sminn do fc = 1,num_allc c = filter_allc(fc) @@ -993,6 +1030,61 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end do end do + ! total cwdn + do fc = 1,num_allc + c = filter_allc(fc) + this%cwdn_col(c) = 0._r8 + end do + + if(use_fates_bgc)then + num_local = num_bgc_soilc + else + num_local = num_allc + end if + + do fc = 1,num_local + if(use_fates_bgc) then + c = filter_bgc_soilc(fc) + else + c = filter_allc(fc) + end if + + if(col%is_fates(c)) then + totvegn_col = 0._r8 + ecovegn_col = 0._r8 + else + do l = 1, ndecomp_pools + if ( decomp_cascade_con%is_cwd(l) ) then + this%cwdn_col(c) = this%cwdn_col(c) + & + this%decomp_npools_col(c,l) + end if + end do + totvegn_col = cnveg_nitrogenstate_inst%totn_p2c_col(c) + ecovegn_col = cnveg_nitrogenstate_inst%totvegn_col(c) + end if + + ! total ecosystem nitrogen, including veg (TOTECOSYSN) + this%totecosysn_col(c) = & + this%cwdn_col(c) + & + this%totlitn_col(c) + & + this%totmicn_col(c) + & + this%totsomn_col(c) + & + this%sminn_col(c) + & + ecovegn_col + + ! total column nitrogen, including patch (TOTCOLN) + + this%totn_col(c) = & + this%cwdn_col(c) + & + this%totlitn_col(c) + & + this%totmicn_col(c) + & + this%totsomn_col(c) + & + this%sminn_col(c) + & + this%ntrunc_col(c) + & + totvegn_col + + end do + end subroutine Summary !----------------------------------------------------------------------- diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 index 40c6a0bff9..a566a5882a 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 @@ -24,7 +24,7 @@ module SoilBiogeochemNitrogenUptakeMod contains !----------------------------------------------------------------------- - subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_soilc, filter_soilc, & + subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_bgc_soilc, filter_bgc_soilc, & sminn_vr, dzsoi_decomp, nfixation_prof, nuptake_prof) ! ! DESCRIPTION @@ -33,8 +33,8 @@ subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_soilc, filter_so ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds integer , intent(in) :: nlevdecomp ! number of vertical layers - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns real(r8) , intent(in) :: sminn_vr(bounds%begc: , 1: ) ! soil mineral nitrogen profile real(r8) , intent(in) :: dzsoi_decomp(1: ) ! layer thickness real(r8) , intent(in) :: nfixation_prof(bounds%begc: , 1: ) ! nitrogen fixation profile @@ -51,21 +51,21 @@ subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_soilc, filter_so SHR_ASSERT_ALL_FL((ubound(nuptake_prof) == (/bounds%endc, nlevdecomp/)) , sourcefile, __LINE__) ! init sminn_tot - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = 0. end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = sminn_tot(c) + sminn_vr(c,j) * dzsoi_decomp(j) end do end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (sminn_tot(c) > 0.) then nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) else diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index da46e178b7..deb9bdbf78 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -68,7 +68,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemPotential (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools, p_decomp_cpool_loss, p_decomp_cn_gain, & @@ -80,8 +80,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! ! !ARGUMENT: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst type(soilbiogeochem_carbonstate_type) , intent(in) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst @@ -137,8 +137,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Input: [real(r8) (:,:,:) ] decomposition rate coefficient (1./sec) phr_vr => soilbiogeochem_carbonflux_inst%phr_vr_col & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) ) - - if ( .not. use_fates ) then + + ! set initial values for potential C and N fluxes p_decomp_cpool_loss(begc:endc, :, :) = 0._r8 pmnf_decomp_cascade(begc:endc, :, :) = 0._r8 @@ -149,8 +149,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & do l = 1, ndecomp_pools if ( floating_cn_ratio_decomp_pools(l) ) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( decomp_npools_vr(c,j,l) > 0._r8 ) then cn_decomp_pools(c,j,l) = decomp_cpools_vr(c,j,l) / decomp_npools_vr(c,j,l) end if @@ -158,8 +158,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end do else do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) cn_decomp_pools(c,j,l) = initial_cn_ratio(l) end do end do @@ -173,8 +173,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (decomp_cpools_vr(c,j,cascade_donor_pool(k)) > 0._r8 .and. & decomp_k(c,j,cascade_donor_pool(k)) > 0._r8 ) then @@ -236,8 +236,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! transitions loop). if (decomp_method == mimics_decomp) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! Sum C & N fluxes from all transitions into m1 & m2 pools. ! Had to form a new loop for the summation due to the order ! necessary, ie do k as the innermost loop. @@ -293,15 +293,15 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! Sum up all the potential immobilization fluxes (positive pmnf flux) ! and all the mineralization fluxes (negative pmnf flux) do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) immob(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (pmnf_decomp_cascade(c,j,k) > 0._r8) then immob(c,j) = immob(c,j) + pmnf_decomp_cascade(c,j,k) else @@ -315,42 +315,29 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end do do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) potential_immob_vr(c,j) = immob(c,j) end do end do - else ! use_fates - ! As a first step we are making this a C-only model, so no N downregulation of fluxes. - do k = 1, ndecomp_cascade_transitions - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! - p_decomp_cpool_loss(c,j,k) = decomp_cpools_vr(c,j,cascade_donor_pool(k)) & - * decomp_k(c,j,cascade_donor_pool(k)) * pathfrac_decomp_cascade(c,j,k) - ! - end do - end do - end do - end if ! Add up potential hr for methane calculations do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) phr_vr(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) phr_vr(c,j) = phr_vr(c,j) + rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) end do end do end do + end associate end subroutine SoilBiogeochemPotential diff --git a/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 b/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 index 3740700ab1..cc349ad8bc 100644 --- a/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 @@ -60,7 +60,7 @@ subroutine SoilBiogeochemPrecisionControlInit( soilbiogeochem_carbonstate_inst, end subroutine SoilBiogeochemPrecisionControlInit !----------------------------------------------------------------------- - subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & + subroutine SoilBiogeochemPrecisionControl(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst) @@ -70,13 +70,13 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & ! they get too small. ! ! !USES: - use clm_varctl , only : iulog, use_c13, use_c14, use_nitrif_denitrif, use_cn + use clm_varctl , only : iulog, use_c13, use_c14, use_nitrif_denitrif use clm_varpar , only : nlevdecomp use CNSharedParamsMod, only: use_fun ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst @@ -106,8 +106,8 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & ) ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) do j = 1,nlevdecomp ! initialize the column-level C and N truncation terms @@ -125,13 +125,12 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & do k = 1, ndecomp_pools if (abs(cs%decomp_cpools_vr_col(c,j,k)) < ccrit) then + cc = cc + cs%decomp_cpools_vr_col(c,j,k) cs%decomp_cpools_vr_col(c,j,k) = 0._r8 - if (use_cn) then - cn = cn + ns%decomp_npools_vr_col(c,j,k) - ns%decomp_npools_vr_col(c,j,k) = 0._r8 - endif + cn = cn + ns%decomp_npools_vr_col(c,j,k) + ns%decomp_npools_vr_col(c,j,k) = 0._r8 if ( use_c13 ) then cc13 = cc13 + c13cs%decomp_cpools_vr_col(c,j,k) @@ -150,9 +149,8 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & cs%ctrunc_vr_col(c,j) = cs%ctrunc_vr_col(c,j) + cc - if (use_cn) then - ns%ntrunc_vr_col(c,j) = ns%ntrunc_vr_col(c,j) + cn - endif + ns%ntrunc_vr_col(c,j) = ns%ntrunc_vr_col(c,j) + cn + if ( use_c13 ) then c13cs%ctrunc_vr_col(c,j) = c13cs%ctrunc_vr_col(c,j) + cc13 endif @@ -167,8 +165,8 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & if (use_nitrif_denitrif) then ! remove small negative perturbations for stability purposes, if any should arise. - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) do j = 1,nlevdecomp if (abs(ns%smin_no3_vr_col(c,j)) < ncrit/1e4_r8) then if ( ns%smin_no3_vr_col(c,j) < 0._r8 ) then diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index fcdced386d..69055aec9b 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -11,7 +11,7 @@ module SoilBiogeochemStateType use clm_varcon , only : spval, ispval, c14ratio, grlnd use landunit_varcon, only : istsoil, istcrop use clm_varpar , only : nlevsno, nlevgrnd, nlevlak - use clm_varctl , only : use_cn + use clm_varctl , only : use_cn, use_fates_bgc use clm_varctl , only : iulog use LandunitType , only : lun use ColumnType , only : col @@ -60,7 +60,7 @@ subroutine Init(this, bounds) type(bounds_type), intent(in) :: bounds call this%InitAllocate ( bounds ) - if (use_cn) then + if (use_cn .or. use_fates_bgc) then call this%InitHistory ( bounds ) end if call this%InitCold ( bounds ) @@ -103,7 +103,7 @@ subroutine InitAllocate(this, bounds) allocate(this%nue_decomp_cascade_col(1:ndecomp_cascade_transitions)); this%nue_decomp_cascade_col(:) = nan - + end subroutine InitAllocate !------------------------------------------------------------------------ @@ -132,26 +132,30 @@ subroutine InitHistory(this, bounds) begp = bounds%begp; endp= bounds%endp begc = bounds%begc; endc= bounds%endc - this%croot_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='CROOT_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from coarse roots', & - ptr_patch=this%croot_prof_patch, default='inactive') - - this%froot_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='FROOT_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from fine roots', & - ptr_patch=this%froot_prof_patch, default='inactive') - - this%leaf_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='LEAF_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from leaves', & - ptr_patch=this%leaf_prof_patch, default='inactive') - - this%stem_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='STEM_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from stems', & - ptr_patch=this%stem_prof_patch, default='inactive') - + if_usecn: if(use_cn) then + this%croot_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='CROOT_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from coarse roots', & + ptr_patch=this%croot_prof_patch, default='inactive') + + this%froot_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='FROOT_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from fine roots', & + ptr_patch=this%froot_prof_patch, default='inactive') + + this%leaf_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='LEAF_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from leaves', & + ptr_patch=this%leaf_prof_patch, default='inactive') + + this%stem_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='STEM_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from stems', & + ptr_patch=this%stem_prof_patch, default='inactive') + end if if_usecn + + ! These output variables are valid for both use_cn AND use_fates_bgc + this%nfixation_prof_col(begc:endc,:) = spval call hist_addfld_decomp (fname='NFIXATION_PROF', units='1/m', type2d='levdcmp', & avgflag='A', long_name='profile for biological N fixation', & @@ -161,7 +165,7 @@ subroutine InitHistory(this, bounds) call hist_addfld_decomp (fname='NDEP_PROF', units='1/m', type2d='levdcmp', & avgflag='A', long_name='profile for atmospheric N deposition', & ptr_col=this%ndep_prof_col, default='inactive') - + this%som_adv_coef_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SOM_ADV_COEF', units='m/s', type2d='levdcmp', & avgflag='A', long_name='advection term for vertical SOM translocation', & diff --git a/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 b/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 index 7209bd8278..9a15140c76 100644 --- a/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 @@ -24,7 +24,7 @@ module SoilBiogeochemVerticalProfileMod contains !----------------------------------------------------------------------- - subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soilp,filter_soilp, & + subroutine SoilBiogeochemVerticalProfile(bounds, num_bgc_soilc,filter_bgc_soilc,num_bgc_vegp,filter_bgc_vegp, & active_layer_inst, soilstate_inst, soilbiogeochem_state_inst) ! ! !DESCRIPTION: @@ -57,10 +57,10 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches type(active_layer_type) , intent(in) :: active_layer_inst type(soilstate_type) , intent(in) :: soilstate_inst type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst @@ -124,21 +124,20 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil cinput_rootfr(begp:endp, :) = 0._r8 col_cinput_rootfr(begc:endc, :) = 0._r8 - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) c = patch%column(p) if (patch%itype(p) /= noveg) then do j = 1, nlevdecomp cinput_rootfr(p,j) = crootfr(p,j) / dzsoi_decomp(j) end do - else cinput_rootfr(p,1) = 0. endif end do - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) c = patch%column(p) ! integrate rootfr over active layer of soil column rootfr_tot = 0._r8 @@ -168,7 +167,6 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil leaf_prof(p,1) = 1./dzsoi_decomp(1) stem_prof(p,1) = 1./dzsoi_decomp(1) endif - end do !! aggregate root profile to column @@ -176,42 +174,65 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil ! cinput_rootfr(bounds%begp:bounds%endp, :), & ! col_cinput_rootfr(bounds%begc:bounds%endc, :), & ! 'unity') - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - do j = 1,nlevdecomp - col_cinput_rootfr(c,j) = col_cinput_rootfr(c,j) + cinput_rootfr(p,j) * patch%wtcol(p) - end do - end if - end do + + + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) + if(.not.col%is_fates(c))then + do pi = 1,col%npatches(c) !maxsoil_patches + !if (pi <= col%npatches(c)) then + p = col%patchi(c) + pi - 1 + do j = 1,nlevdecomp + col_cinput_rootfr(c,j) = col_cinput_rootfr(c,j) + cinput_rootfr(p,j) * patch%wtcol(p) + end do + !end if + end do + end if end do + ! repeat for column-native profiles: Ndep and Nfix - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) rootfr_tot = 0._r8 surface_prof_tot = 0._r8 - ! redo column ntegration over active layer for column-native profiles - do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) - rootfr_tot = rootfr_tot + col_cinput_rootfr(c,j) * dzsoi_decomp(j) - surface_prof_tot = surface_prof_tot + surface_prof(j) * dzsoi_decomp(j) - end do - if ( (altmax_lastyear_indx(c) > 0) .and. (rootfr_tot > 0._r8) .and. (surface_prof_tot > 0._r8) ) then - do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) - nfixation_prof(c,j) = col_cinput_rootfr(c,j) / rootfr_tot - ndep_prof(c,j) = surface_prof(j)/ surface_prof_tot + if_fates: if(col%is_fates(c))then + ! For FATES, we just use the e-folding depth for both fixation and deposition + ! partially because the fixation may be free-living depending on FATES-side + ! fixation choices, and partially for simplicity + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + surface_prof_tot = surface_prof_tot + surface_prof(j) * dzsoi_decomp(j) end do + if ( (altmax_lastyear_indx(c) > 0) .and. (surface_prof_tot > 0._r8) ) then + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + nfixation_prof(c,j) = surface_prof(j)/ surface_prof_tot + ndep_prof(c,j) = surface_prof(j)/ surface_prof_tot + end do + else + nfixation_prof(c,1) = 1./dzsoi_decomp(1) + ndep_prof(c,1) = 1./dzsoi_decomp(1) + endif else - nfixation_prof(c,1) = 1./dzsoi_decomp(1) - ndep_prof(c,1) = 1./dzsoi_decomp(1) - endif + ! redo column ntegration over active layer for column-native profiles + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + rootfr_tot = rootfr_tot + col_cinput_rootfr(c,j) * dzsoi_decomp(j) + surface_prof_tot = surface_prof_tot + surface_prof(j) * dzsoi_decomp(j) + end do + if ( (altmax_lastyear_indx(c) > 0) .and. (rootfr_tot > 0._r8) .and. (surface_prof_tot > 0._r8) ) then + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + nfixation_prof(c,j) = col_cinput_rootfr(c,j) / rootfr_tot + ndep_prof(c,j) = surface_prof(j)/ surface_prof_tot + end do + else + nfixation_prof(c,1) = 1./dzsoi_decomp(1) + ndep_prof(c,1) = 1./dzsoi_decomp(1) + endif + end if if_fates end do ! check to make sure integral of all profiles = 1. - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ndep_prof_sum = 0. nfixation_prof_sum = 0. do j = 1, nlevdecomp @@ -237,8 +258,8 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil endif end do - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) froot_prof_sum = 0. croot_prof_sum = 0. leaf_prof_sum = 0. diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index 6b611613bb..4dc1faacd1 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -48,6 +48,7 @@ module CLMFatesInterfaceMod use CNProductsMod , only : cn_products_type use clm_varctl , only : iulog use clm_varctl , only : fates_parteh_mode + use PRTGenericMod , only : prt_cnp_flex_allom_hyp use clm_varctl , only : use_fates use clm_varctl , only : fates_spitfire_mode use clm_varctl , only : use_fates_tree_damage @@ -80,6 +81,8 @@ module CLMFatesInterfaceMod use SolarAbsorbedType , only : solarabs_type use SoilBiogeochemCarbonFluxType, only : soilbiogeochem_carbonflux_type use SoilBiogeochemCarbonStateType, only : soilbiogeochem_carbonstate_type + use SoilBiogeochemNitrogenFluxType, only : soilbiogeochem_nitrogenflux_type + use SoilBiogeochemNitrogenStateType, only : soilbiogeochem_nitrogenstate_type use FrictionVelocityMod , only : frictionvel_type use clm_time_manager , only : is_restart, is_first_restart_step use ncdio_pio , only : file_desc_t, ncd_int, ncd_double @@ -225,7 +228,8 @@ module CLMFatesInterfaceMod procedure, public :: wrap_hydraulics_drive procedure, public :: WrapUpdateFatesRmean procedure, public :: wrap_WoodProducts - + procedure, public :: UpdateCLitterFluxes + procedure, public :: UPdateNLitterFluxes end type hlm_fates_interface_type ! hlm_bounds_to_fates_bounds is not currently called outside the interface. @@ -563,8 +567,6 @@ subroutine init(this, bounds_proc ) use clm_instur , only : wt_nat_patch use FATESFireFactoryMod , only: create_fates_fire_data_method - implicit none - ! Input Arguments class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_proc @@ -771,7 +773,6 @@ subroutine check_hlm_active(this, nc, bounds_clump) ! in handy when we have dynamic sites in FATES ! --------------------------------------------------------------------------------- - implicit none class(hlm_fates_interface_type), intent(inout) :: this integer :: nc type(bounds_type),intent(in) :: bounds_clump @@ -822,7 +823,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & use subgridMod, only : natveg_patch_exists ! !ARGUMENTS: - implicit none + class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_clump type(atm2lnd_type) , intent(in) :: atm2lnd_inst @@ -1055,43 +1056,6 @@ subroutine dynamics_driv(this, nc, bounds_clump, & this%fates(nc)%bc_out(s)) enddo - ! --------------------------------------------------------------------------------- - ! Part III: Process FATES output into the dimensions and structures that are part - ! of the HLMs API. (column, depth, and litter fractions) - ! --------------------------------------------------------------------------------- - - if ( decomp_method /= no_soil_decomp )then - do s = 1, this%fates(nc)%nsites - c = this%f2hmap(nc)%fcolumn(s) - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lab_c_col(c,1:nlevdecomp) = 0.0_r8 - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_cel_c_col(c,1:nlevdecomp) = 0.0_r8 - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lig_c_col(c,1:nlevdecomp) = 0.0_r8 - - nld_si = this%fates(nc)%bc_in(s)%nlevdecomp - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lab_c_col(c,1:nld_si) = & - this%fates(nc)%bc_out(s)%litt_flux_lab_c_si(1:nld_si) - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_cel_c_col(c,1:nld_si) = & - this%fates(nc)%bc_out(s)%litt_flux_cel_c_si(1:nld_si) - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lig_c_col(c,1:nld_si) = & - this%fates(nc)%bc_out(s)%litt_flux_lig_c_si(1:nld_si) - - ! Copy last 3 variables to an array of litter pools for use in do loops - ! and repeat copy in soilbiogeochem/SoilBiogeochemCarbonFluxType.F90. - ! Keep the three originals to avoid backwards compatibility issues with - ! restart files. - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_c_col(c,1:nld_si,1) = & - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lab_c_col(c,1:nld_si) - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_c_col(c,1:nld_si,2) = & - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_cel_c_col(c,1:nld_si) - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_c_col(c,1:nld_si,3) = & - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lig_c_col(c,1:nld_si) - - end do - end if ! --------------------------------------------------------------------------------- @@ -1124,8 +1088,159 @@ subroutine dynamics_driv(this, nc, bounds_clump, & return end subroutine dynamics_driv - ! ------------------------------------------------------------------------------------ + ! =============================================================================== + + subroutine UpdateNLitterFluxes(this,soilbiogeochem_nitrogenflux_inst,ci,c) + + use clm_varpar, only : i_met_lit + + class(hlm_fates_interface_type), intent(inout) :: this + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + integer , intent(in) :: ci ! clump index + integer , intent(in) :: c ! column index + + integer :: s ! site index + real(r8) :: dtime + integer :: i_lig_lit, i_cel_lit ! indices for lignan and cellulose + + dtime = get_step_size_real() + s = this%f2hmap(ci)%hsites(c) + + associate(nf_soil => soilbiogeochem_nitrogenflux_inst) + nf_soil%decomp_npools_sourcesink_col(c,:,:) = 0._r8 + + if ( .not. use_fates_sp ) then + + ! (gC/m3/timestep) + !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) = & + ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) + & + ! this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp)*dtime + + ! Used for mass balance checking (gC/m2/s) + !nf_soil%fates_litter_flux(c) = sum(this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp) * & + ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + i_cel_lit = i_met_lit + 1 + + !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) = & + ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) + & + ! this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp)*dtime + + !nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & + ! sum(this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp) * & + ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + if (decomp_method == mimics_decomp) then + ! Mimics has a structural pool, which is cellulose and lignan + i_lig_lit = i_cel_lit + elseif(decomp_method == century_decomp ) then + ! CENTURY has a separate lignan pool from cellulose + i_lig_lit = i_cel_lit + 1 + end if + + !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) = & + ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) + & + ! this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp)*dtime + + !nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & + ! sum(this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp) * & + ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + nf_soil%fates_litter_flux = 0._r8 + + else + + ! In SP mode their is no mass flux between the two + nf_soil%fates_litter_flux = 0._r8 + + end if + + end associate + + return + end subroutine UpdateNLitterFluxes + + ! =========================================================== + + subroutine UpdateCLitterFluxes(this,soilbiogeochem_carbonflux_inst,ci,c) + + use clm_varpar, only : i_met_lit + + class(hlm_fates_interface_type), intent(inout) :: this + type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst + integer , intent(in) :: ci ! clump index + integer , intent(in) :: c ! column index + + integer :: s ! site index + real(r8) :: dtime + integer :: i_lig_lit, i_cel_lit ! indices for lignan and cellulose + + dtime = get_step_size_real() + s = this%f2hmap(ci)%hsites(c) + + associate(cf_soil => soilbiogeochem_carbonflux_inst) + + ! This is zeroed in CNDriverNoLeaching -> soilbiogeochem_carbonflux_inst%SetValues() + ! Which is called prior to this call, which is later in the CNDriverNoLeaching() + ! routine. + ! cf_soil%decomp_cpools_sourcesink_col(c,:,:) = 0._r8 + + if ( .not. use_fates_sp ) then + + + call FluxIntoLitterPools(this%fates(ci)%sites(s), & + this%fates(ci)%bc_in(s), & + this%fates(ci)%bc_out(s)) + + ! (gC/m3/timestep) + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_met_lit) = & + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_met_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_lab_c_si(1:nlevdecomp)*dtime + + ! Used for mass balance checking (gC/m2/s) + cf_soil%fates_litter_flux(c) = sum(this%fates(ci)%bc_out(s)%litt_flux_lab_c_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + i_cel_lit = i_met_lit + 1 + + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) = & + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_cel_c_si(1:nlevdecomp)*dtime + + cf_soil%fates_litter_flux(c) = cf_soil%fates_litter_flux(c) + & + sum(this%fates(ci)%bc_out(s)%litt_flux_cel_c_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + if (decomp_method == mimics_decomp) then + ! Mimics has a structural pool, which is cellulose and lignan + i_lig_lit = i_cel_lit + elseif(decomp_method == century_decomp ) then + ! CENTURY has a separate lignan pool from cellulose + i_lig_lit = i_cel_lit + 1 + end if + + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) = & + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_lig_c_si(1:nlevdecomp)*dtime + + cf_soil%fates_litter_flux(c) = cf_soil%fates_litter_flux(c) + & + sum(this%fates(ci)%bc_out(s)%litt_flux_lig_c_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + else + ! In SP mode their is no mass flux between the two + + cf_soil%fates_litter_flux = 0._r8 + end if + + end associate + + return + end subroutine UpdateCLitterFluxes + + ! =================================================================================== + subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & waterdiagnosticbulk_inst, canopystate_inst, & soilbiogeochem_carbonflux_inst, is_initing_from_restart) @@ -1136,7 +1251,6 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & ! provides boundary conditions (such as vegetation fractional coverage) ! --------------------------------------------------------------------------------- - implicit none class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_clump integer , intent(in) :: nc @@ -1356,7 +1470,8 @@ end subroutine wrap_update_hlmfates_dyn subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & waterstatebulk_inst, canopystate_inst, soilstate_inst, & - active_layer_inst, soilbiogeochem_carbonflux_inst) + active_layer_inst, soilbiogeochem_carbonflux_inst, & + soilbiogeochem_nitrogenflux_inst) ! --------------------------------------------------------------------------------- ! The ability to restart the model is handled through three different types of calls @@ -1380,8 +1495,6 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & use EDMainMod, only : ed_update_site use FatesInterfaceTypesMod, only: fates_maxElementsPerSite - implicit none - ! Arguments class(hlm_fates_interface_type), intent(inout) :: this @@ -1394,7 +1507,8 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & type(soilstate_type) , intent(inout) :: soilstate_inst type(active_layer_type) , intent(in) :: active_layer_inst type(soilbiogeochem_carbonflux_type), intent(inout) :: soilbiogeochem_carbonflux_inst - + type(soilbiogeochem_nitrogenflux_type), intent(inout) :: soilbiogeochem_nitrogenflux_inst + ! Locals type(bounds_type) :: bounds_clump integer :: nc @@ -1603,13 +1717,6 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & this%fates(nc)%bc_in(s), & this%fates(nc)%bc_out(s) ) - ! This call sends internal fates variables into the - ! output boundary condition structures. Note: this is called - ! internally in fates dynamics as well. - call FluxIntoLitterPools(this%fates(nc)%sites(s), & - this%fates(nc)%bc_in(s), & - this%fates(nc)%bc_out(s)) - end do if(use_fates_sp)then @@ -1834,13 +1941,6 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & this%fates(nc)%bc_in(s), & this%fates(nc)%bc_out(s)) - ! This call sends internal fates variables into the - ! output boundary condition structures. Note: this is called - ! internally in fates dynamics as well. - call FluxIntoLitterPools(this%fates(nc)%sites(s), & - this%fates(nc)%bc_in(s), & - this%fates(nc)%bc_out(s)) - end do ! ------------------------------------------------------------------------ @@ -1883,8 +1983,6 @@ subroutine wrap_sunfrac(this,nc,atm2lnd_inst,canopystate_inst) ! of the canopy that is exposed to sun. ! --------------------------------------------------------------------------------- - implicit none - ! Input Arguments class(hlm_fates_interface_type), intent(inout) :: this @@ -2019,7 +2117,7 @@ subroutine wrap_btran(this,nc,fn,filterc,soilstate_inst, & ! ! --------------------------------------------------------------------------------- - implicit none + use SoilWaterRetentionCurveMod, only : soil_water_retention_curve_type ! Arguments class(hlm_fates_interface_type), intent(inout) :: this @@ -2347,50 +2445,56 @@ end subroutine wrap_accumulatefluxes ! ====================================================================================== - subroutine wrap_WoodProducts(this, bounds_clump, fc, filterc, c_products_inst) + subroutine wrap_WoodProducts(this, bounds_clump, num_soilc, filter_soilc, & + c_products_inst, n_products_inst) ! !ARGUMENTS: class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type) , intent(in) :: bounds_clump - integer , intent(in) :: fc ! size of column filter - integer , intent(in) :: filterc(fc) ! column filter + integer , intent(in) :: num_soilc ! size of column filter + integer , intent(in) :: filter_soilc(:) ! column filter type(cn_products_type) , intent(inout) :: c_products_inst + type(cn_products_type) , intent(inout) :: n_products_inst ! Locals - integer :: s,c,icc,g - integer :: nc - - ! This wrapper is not active. This is just place-holder code until - ! harvest-product flux is fully implemented. RGK-05-2022 + integer :: s,c,g,fc + integer :: ci ! Clump index + + ci = bounds_clump%clump_index - !associate( & - ! prod10c => c_products_inst%hrv_deadstem_to_prod10_grc, & - ! prod100c => c_products_inst%hrv_deadstem_to_prod100_grc) + ! Loop over columns + do fc = 1, num_soilc + + c = filter_soilc(fc) + g = col%gridcell(c) + s = this%f2hmap(ci)%hsites(c) - ! nc = bounds_clump%clump_index - ! Loop over columns - do icc = 1,fc - c = filterc(icc) - g = col%gridcell(c) - s = this%f2hmap(nc)%hsites(c) - - ! Shijie: Pass harvested wood products to ELM variable - ! prod10c(g) = prod10c(g) + & - ! this%fates(nc)%bc_out(s)%hrv_deadstemc_to_prod10c - ! prod100c(g) = prod100c(g) + & - ! this%fates(nc)%bc_out(s)%hrv_deadstemc_to_prod100c - - ! RGK: THere is also a patch level variable - !do ifp = 1,this%fates(nc)%sites(s)%youngest_patch%patchno - ! p = ifp+col%patchi(c) - ! hrv_deadstemc_to_prod10c(p) = - ! hrv_deadstemc_to_prod100c(p) - !end do + ! Shijie: Pass harvested wood products to CLM product pools + c_products_inst%hrv_deadstem_to_prod10_grc(g) = & + c_products_inst%hrv_deadstem_to_prod10_grc(g) + & + this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod10c + + c_products_inst%hrv_deadstem_to_prod100_grc(g) = & + c_products_inst%hrv_deadstem_to_prod100_grc(g) + & + this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod100c + + ! If N cycling is on + if(fates_parteh_mode .eq. prt_cnp_flex_allom_hyp ) then + + !n_products_inst%hrv_deadstem_to_prod10_grc(g) = & + ! n_products_inst%hrv_deadstem_to_prod10_grc(g) + & + ! this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod10c + + !n_products_inst%hrv_deadstem_to_prod100_grc(g) = & + ! n_products_inst%hrv_deadstem_to_prod100_grc(g) + & + ! this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod100c + + end if + - end do + end do - ! end associate - return + return end subroutine wrap_WoodProducts ! ====================================================================================== @@ -3009,35 +3113,6 @@ subroutine ComputeRootSoilFlux(this, bounds_clump, num_filterc, filterc, & end subroutine ComputeRootSoilFlux - ! ====================================================================================== -! -! THIS WAS MOVED TO WRAP_HYDRAULICS_DRIVE() -! -! subroutine TransferPlantWaterStorage(this, bounds_clump, nc, waterstate_inst) -! -! implicit none -! class(hlm_fates_interface_type), intent(inout) :: this -! type(bounds_type),intent(in) :: bounds_clump -! integer,intent(in) :: nc -! type(waterstate_type) , intent(inout) :: waterstate_inst -! -! ! locals -! integer :: s -! integer :: c -! -! if (.not. (use_fates .and. use_fates_planthydro) ) return -! -! do s = 1, this%fates(nc)%nsites -! c = this%f2hmap(nc)%fcolumn(s) -! waterstate_inst%total_plant_stored_h2o_col(c) = & -! this%fates(nc)%bc_out(s)%plant_stored_h2o_si -! end do -! return -!end subroutine TransferPlantWaterStorage - - - - ! ====================================================================================== subroutine wrap_hydraulics_drive(this, bounds_clump, nc, & @@ -3045,7 +3120,6 @@ subroutine wrap_hydraulics_drive(this, bounds_clump, nc, & fn, filterp, solarabs_inst, energyflux_inst) - implicit none class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_clump integer,intent(in) :: nc @@ -3167,8 +3241,6 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates) use FatesInterfaceTypesMod, only : numpft_fates => numpft - implicit none - type(bounds_type), intent(in) :: hlm type(fates_bounds_type), intent(out) :: fates