diff --git a/cime/config/acme/machines/Makefile b/cime/config/acme/machines/Makefile index e5e7608facf2..701cd2add737 100644 --- a/cime/config/acme/machines/Makefile +++ b/cime/config/acme/machines/Makefile @@ -251,8 +251,9 @@ ifeq ($(strip $(USE_PETSC)), TRUE) $(error PETSC_PATH must be defined when USE_PETSC is TRUE) endif - # Get the "PETSC_LIB" list an env var - include $(PETSC_PATH)/conf/variables + # Get the "PETSC_LIB" list an env var + include $(PETSC_PATH)/lib/petsc/conf/variables + endif # Set Trilinos info if it is being used @@ -564,7 +565,7 @@ endif # Add PETSc libraries ifeq ($(strip $(USE_PETSC)), TRUE) - SLIBS += -L${LIB_PETSC} ${PETSC_LIB} + SLIBS += ${PETSC_LIB} endif # Add trilinos libraries; too be safe, we include all libraries included in the trilinos build, @@ -904,7 +905,7 @@ cleanrof: $(RM) -fr $(EXEROOT)/rof/obj cleanlnd: - $(RM) -f $(LIBROOT)/liblnd.a + $(RM) -f $(LIBROOT)/$(LNDLIB) $(RM) -fr $(EXEROOT)/lnd/obj cleancsmshare: diff --git a/cime/config/acme/machines/config_compilers.xml b/cime/config/acme/machines/config_compilers.xml index 05d7cc5c753b..91039fc856f3 100644 --- a/cime/config/acme/machines/config_compilers.xml +++ b/cime/config/acme/machines/config_compilers.xml @@ -82,6 +82,18 @@ for mct, etc. -D_USE_FLOW_CONTROL + + + + + -I$(CLM_PFLOTRAN_SOURCE_DIR) + -DCLM_PFLOTRAN + -DCOLUMN_MODE + -L$(CLM_PFLOTRAN_SOURCE_DIR) -lpflotran $(PETSC_LIB) + + + + + + /software/user_tools/current/cades-ccsi/petsc4pf/openmpi-1.10-gcc-5.3 + + FALSE + FALSE + + /lustre/or-hydra/cades-ccsi/$USER/models/pflotran-interface/src/clm-pflotran + diff --git a/cime/config/acme/testmods_dirs/allactive/clm/bgcinterface/user_nl_clm b/cime/config/acme/testmods_dirs/allactive/clm/bgcinterface/user_nl_clm new file mode 100644 index 000000000000..2b5ce8492090 --- /dev/null +++ b/cime/config/acme/testmods_dirs/allactive/clm/bgcinterface/user_nl_clm @@ -0,0 +1,2 @@ +use_clm_interface = .true. +use_clm_bgc = .true. diff --git a/cime/scripts/lib/update_acme_tests.py b/cime/scripts/lib/update_acme_tests.py index 0207dfd1e387..de1e98a3b1fb 100644 --- a/cime/scripts/lib/update_acme_tests.py +++ b/cime/scripts/lib/update_acme_tests.py @@ -73,6 +73,7 @@ ("SMS_Ld4.f45_f45.ICLM45ED","clm-fates"), ("ERS.f19_g16.I1850CLM45","clm-betr"), ("ERS.f19_g16.I1850CLM45","clm-vst"), + ("ERS.f09_g16.I1850CLM45CN","clm-bgcinterface"), "ERS.ne11_oQU240.I20TRCLM45", "ERS.f09_g16.IMCLM45BC") ), diff --git a/components/clm/bld/namelist_files/namelist_definition_clm4_5.xml b/components/clm/bld/namelist_files/namelist_definition_clm4_5.xml index 58d008e78544..00a5d0b213da 100644 --- a/components/clm/bld/namelist_files/namelist_definition_clm4_5.xml +++ b/components/clm/bld/namelist_files/namelist_definition_clm4_5.xml @@ -1599,7 +1599,7 @@ Specifies the method for decomposing CLM grids across processors. - Runtime flag to turn on/off bgc interface. diff --git a/components/clm/src/biogeochem/CNAllocationBetrMod.F90 b/components/clm/src/biogeochem/CNAllocationBetrMod.F90 index 6147c22870b1..30befa38fc2c 100644 --- a/components/clm/src/biogeochem/CNAllocationBetrMod.F90 +++ b/components/clm/src/biogeochem/CNAllocationBetrMod.F90 @@ -30,7 +30,6 @@ module CNAllocationBeTRMod use ColumnType , only : col_pp use VegetationType , only : veg_pp ! bgc interface & pflotran module switches - use clm_varctl , only: use_bgc_interface,use_clm_bgc, use_pflotran, pf_cmode use clm_varctl , only : nu_com use SoilStatetype , only : soilstate_type use WaterStateType , only : waterstate_type diff --git a/components/clm/src/biogeochem/CNAllocationMod.F90 b/components/clm/src/biogeochem/CNAllocationMod.F90 index e6711180c0fb..7a971b4730b2 100755 --- a/components/clm/src/biogeochem/CNAllocationMod.F90 +++ b/components/clm/src/biogeochem/CNAllocationMod.F90 @@ -30,7 +30,7 @@ module CNAllocationMod use ColumnType , only : col_pp use VegetationType , only : veg_pp ! bgc interface & pflotran module switches - use clm_varctl , only: use_bgc_interface,use_clm_bgc, use_pflotran, pf_cmode + use clm_varctl , only: use_clm_interface,use_clm_bgc, use_pflotran, pf_cmode use clm_varctl , only : nu_com use SoilStatetype , only : soilstate_type use WaterStateType , only : waterstate_type @@ -46,12 +46,12 @@ module CNAllocationMod public :: readCNAllocParams public :: CNAllocationInit ! Initialization ! public :: CNAllocation ! run method - !!----------------------------------------------------------------------------------------------------- - !! CNAllocation is divided into 3 subroutines/phases: - public :: CNAllocation1_PlantNPDemand !!Plant N/P Demand; called in CNEcosystemDynNoLeaching1 - public :: CNAllocation2_ResolveNPLimit !!Resolve N/P Limitation; called in CNDecompAlloc - public :: CNAllocation3_PlantCNPAlloc !!Plant C/N/P Allocation; called in CNDecompAlloc2 - !!----------------------------------------------------------------------------------------------------- + !----------------------------------------------------------------------------------------------------- + ! CNAllocation is divided into 3 subroutines/phases: + public :: CNAllocation1_PlantNPDemand !Plant N/P Demand; called in CNEcosystemDynNoLeaching1 + public :: CNAllocation2_ResolveNPLimit !Resolve N/P Limitation; called in CNDecompAlloc + public :: CNAllocation3_PlantCNPAlloc !Plant C/N/P Allocation; called in CNDecompAlloc2 + !----------------------------------------------------------------------------------------------------- public :: dynamic_plant_alloc ! dynamic plant carbon allocation based on different nutrient stress type :: CNAllocParamsType @@ -283,13 +283,13 @@ subroutine CNAllocationInit ( bounds) end subroutine CNAllocationInit -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine CNAllocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & photosyns_vars, crop_vars, canopystate_vars, cnstate_vars, & carbonstate_vars, carbonflux_vars, c13_carbonflux_vars, c14_carbonflux_vars, & nitrogenstate_vars, nitrogenflux_vars,& phosphorusstate_vars,phosphorusflux_vars) - !! PHASE-1 of CNAllocation: loop over patches to assess the total plant N demand and P demand + ! PHASE-1 of CNAllocation: loop over patches to assess the total plant N demand and P demand ! !USES: use shr_sys_mod , only: shr_sys_flush use clm_varctl , only: iulog,cnallocate_carbon_only,cnallocate_carbonnitrogen_only,& @@ -1034,7 +1034,7 @@ subroutine CNAllocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soi end do ! pflotran will need an input from CN: modified 'sum_ndemand_vr' ('potential_immob' excluded). - if (use_bgc_interface.and.use_pflotran .and. pf_cmode) then + if (use_clm_interface.and.use_pflotran .and. pf_cmode) then do j = 1, nlevdecomp do fc=1, num_soilc c = filter_soilc(fc) @@ -1048,7 +1048,7 @@ subroutine CNAllocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soi end subroutine CNAllocation1_PlantNPDemand -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine CNAllocation2_ResolveNPLimit (bounds, num_soilc, filter_soilc , & num_soilp, filter_soilp , & @@ -1057,13 +1057,13 @@ subroutine CNAllocation2_ResolveNPLimit (bounds, num_soilc, filter_soilc , & nitrogenstate_vars, nitrogenflux_vars , & phosphorusstate_vars,phosphorusflux_vars , & soilstate_vars,waterstate_vars) - !! PHASE-2 of CNAllocation: resolving N/P limitation + ! PHASE-2 of CNAllocation: resolving N/P limitation ! !USES: use shr_sys_mod , only: shr_sys_flush use clm_varctl , only: iulog,cnallocate_carbon_only,cnallocate_carbonnitrogen_only,& cnallocate_carbonphosphorus_only ! use pftvarcon , only: npcropmin, declfact, bfact, aleaff, arootf, astemf -! use pftvarcon , only: arooti, fleafi, allconsl, allconss, grperc, grpnow, nsoybean !! +! use pftvarcon , only: arooti, fleafi, allconsl, allconss, grperc, grpnow, nsoybean use pftvarcon , only: noveg use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions use clm_varcon , only: nitrif_n2o_loss_frac, secspday @@ -1076,14 +1076,9 @@ subroutine CNAllocation2_ResolveNPLimit (bounds, num_soilc, filter_soilc , & 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(photosyns_type) , intent(in) :: photosyns_vars -! type(crop_type) , intent(in) :: crop_vars -! type(canopystate_type) , intent(in) :: canopystate_vars type(cnstate_type) , intent(inout) :: cnstate_vars type(carbonstate_type) , intent(in) :: carbonstate_vars type(carbonflux_type) , intent(inout) :: carbonflux_vars -! type(carbonflux_type) , intent(inout) :: c13_carbonflux_vars -! type(carbonflux_type) , intent(inout) :: c14_carbonflux_vars type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars ! !! add phosphorus -X.YANG @@ -1161,10 +1156,10 @@ subroutine CNAllocation2_ResolveNPLimit (bounds, num_soilc, filter_soilc , & associate( & ivt => veg_pp%itype , & ! Input: [integer (:) ] pft vegetation type - !! new variables due to partition of CNAllocation to 3 subroutines: BEG + ! new variables due to partition of CNAllocation to 3 subroutines: BEG plant_ndemand_col => nitrogenflux_vars%plant_ndemand_col , & ! Output: [real(r8) (:,:) ] plant_pdemand_col => phosphorusflux_vars%plant_pdemand_col , & ! Output: [real(r8) (:,:) ] - !! new variables due to partition of CNAllocation to 3 subroutines: END + ! new variables due to partition of CNAllocation to 3 subroutines: END fpg => cnstate_vars%fpg_col , & ! Output: [real(r8) (:) ] fraction of potential gpp (no units) fpi => cnstate_vars%fpi_col , & ! Output: [real(r8) (:) ] fraction of potential immobilization (no units) @@ -1276,7 +1271,7 @@ subroutine CNAllocation2_ResolveNPLimit (bounds, num_soilc, filter_soilc , & ndep_prof => cnstate_vars%ndep_prof_col , & gross_pmin_vr => phosphorusflux_vars%gross_pmin_vr_col , & - !!! add phosphorus variables - X. YANG + !! add phosphorus variables - X. YANG ! sminp_vr => phosphorusstate_vars%sminp_vr_col , & ! Input: [real(r8) (:,:) ] (gP/m3) soil mineral P solutionp_vr => phosphorusstate_vars%solutionp_vr_col , & ! Input: [real(r8) (:,:) ] (gP/m3) soil mineral P @@ -1304,7 +1299,7 @@ subroutine CNAllocation2_ResolveNPLimit (bounds, num_soilc, filter_soilc , & if (nu_com .eq. 'RD') then ! 'RD' : relative demand approach - !!local var = flux_type%var + !local var = flux_type%var do fc=1, num_soilc c = filter_soilc(fc) col_plant_ndemand(c) = plant_ndemand_col(c) @@ -2892,7 +2887,7 @@ subroutine CNAllocation2_ResolveNPLimit (bounds, num_soilc, filter_soilc , & end subroutine CNAllocation2_ResolveNPLimit -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine CNAllocation3_PlantCNPAlloc (bounds , & num_soilc, filter_soilc, num_soilp, filter_soilp , & canopystate_vars , & @@ -2900,7 +2895,7 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & c13_carbonflux_vars, c14_carbonflux_vars , & nitrogenstate_vars, nitrogenflux_vars , & phosphorusstate_vars, phosphorusflux_vars) - !! PHASE-3 of CNAllocation: start new pft loop to distribute the available N/P between the + ! PHASE-3 of CNAllocation: start new pft loop to distribute the available N/P between the ! competing patches on the basis of relative demand, and allocate C/N/P to new growth and storage ! !USES: @@ -2911,10 +2906,10 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & ! use pftvarcon , only: arooti, fleafi, allconsl, allconss, grperc, grpnow, nsoybean use pftvarcon , only: noveg use pftvarcon , only: npcropmin, grperc, grpnow - use clm_varpar , only: nlevdecomp !!nlevsoi, + use clm_varpar , only: nlevdecomp use clm_varcon , only: nitrif_n2o_loss_frac, secspday ! use landunit_varcon , only: istsoil, istcrop -! use clm_time_manager , only: get_step_size + use clm_time_manager , only: get_step_size ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -2922,8 +2917,7 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & 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(photosyns_type) , intent(in) :: photosyns_vars -! type(crop_type) , intent(in) :: crop_vars + type(canopystate_type) , intent(in) :: canopystate_vars type(cnstate_type) , intent(inout) :: cnstate_vars type(carbonstate_type) , intent(in) :: carbonstate_vars @@ -2938,7 +2932,7 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & ! ! !LOCAL VARIABLES: ! - integer :: c,p,j !!l,pi, !indices + integer :: c,p,j !indices integer :: fp !lake filter pft index integer :: fc !lake filter column index real(r8):: mr !maintenance respiration (gC/m2/s) @@ -2969,6 +2963,7 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & real(r8):: cp_stoich_var=0.4 ! variability of CP ratio real(r8):: curmr, curmr_ratio !xsmrpool temporary variables real(r8):: xsmr_ratio ! ratio of mr comes from non-structue carobn hydrate pool + real(r8):: dt !----------------------------------------------------------------------- associate( & @@ -3139,6 +3134,8 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & ! ! !------------------------------------------------------------------- + ! set time steps + dt = real( get_step_size(), r8 ) ! debug do fc=1,num_soilc @@ -3926,22 +3923,22 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & if (nu_com .eq. 'RD') then if(suplphos == suplpNon) then !!! No supplemental Phosphorus - call p2c(bounds,num_soilc,filter_soilc, & + call p2c(bounds,num_soilc,filter_soilc, & sminn_to_npool(bounds%begp:bounds%endp), & sminn_to_plant(bounds%begc:bounds%endc)) - call calc_nuptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, nitrogenstate_vars, nuptake_prof) - do j = 1, nlevdecomp + call calc_nuptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, nitrogenstate_vars, nuptake_prof) + do j = 1, nlevdecomp do fc=1,num_soilc c = filter_soilc(fc) sminn_to_plant_vr(c,j) = sminn_to_plant(c) * nuptake_prof(c,j) end do - end do - end if + end do + end if - !! Phosphorus + !! Phosphorus - if( .not. use_nitrif_denitrif) then + if( .not. use_nitrif_denitrif) then call p2c(bounds,num_soilc,filter_soilc, & sminp_to_ppool(bounds%begp:bounds%endp), & @@ -3955,23 +3952,25 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & end do end do - else ! use_nitrif_denitrif + else ! use_nitrif_denitrif - if( .not.cnallocate_carbonphosphorus_only().and. .not.cnallocate_carbonnitrogen_only().and. .not.cnallocate_carbon_only() )then + if( .not.cnallocate_carbonphosphorus_only() .and. & + .not.cnallocate_carbonnitrogen_only().and. & + .not.cnallocate_carbon_only() )then temp_sminn_to_plant = sminn_to_plant temp_sminp_to_plant = sminp_to_plant - call p2c(bounds,num_soilc,filter_soilc, & + call p2c(bounds,num_soilc,filter_soilc, & sminn_to_npool(bounds%begp:bounds%endp), & sminn_to_plant(bounds%begc:bounds%endc)) - call p2c(bounds,num_soilc,filter_soilc, & + call p2c(bounds,num_soilc,filter_soilc, & sminp_to_ppool(bounds%begp:bounds%endp), & sminp_to_plant(bounds%begc:bounds%endc)) - do j = 1, nlevdecomp + do j = 1, nlevdecomp do fc=1,num_soilc c = filter_soilc(fc) if ( temp_sminn_to_plant(c) > 0._r8) then @@ -3990,20 +3989,20 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & sminp_to_plant_vr(c,j) = 0._r8 endif end do - end do + end do - end if ! carbonnitrogenphosphorus + end if ! carbonnitrogenphosphorus - if( cnallocate_carbonnitrogen_only() )then + if( cnallocate_carbonnitrogen_only() )then temp_sminp_to_plant = sminp_to_plant - call p2c(bounds,num_soilc,filter_soilc, & + call p2c(bounds,num_soilc,filter_soilc, & sminp_to_ppool(bounds%begp:bounds%endp), & sminp_to_plant(bounds%begc:bounds%endc)) - do j = 1, nlevdecomp + do j = 1, nlevdecomp do fc=1,num_soilc c = filter_soilc(fc) @@ -4013,11 +4012,13 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & sminp_to_plant_vr(c,j) = 0._r8 endif end do - end do - end if ! carbonnitrogen + end do + end if ! carbonnitrogen + + end if ! use_nitrif_denitrif + end if ! nu_com .eq. RD - end if ! !---------------------------------------------------------------- @@ -4025,11 +4026,10 @@ subroutine CNAllocation3_PlantCNPAlloc (bounds , & end subroutine CNAllocation3_PlantCNPAlloc -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine calc_nuptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, nitrogenstate_vars, nuptake_prof) -! use clm_varcon , only : dzsoi_decomp !! declared in module CNAllocationMod - !! bgc interface & pflotran: - !! nuptake_prof is used in CNAllocation1, 2, 3 + ! bgc interface & pflotran: + ! nuptake_prof is used in CNAllocation1, 2, 3 ! !USES: use clm_varpar , only: nlevdecomp ! !ARGUMENTS: @@ -4070,7 +4070,12 @@ subroutine calc_nuptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, nitr else sminn_vr_loc(c,j) = smin_no3_vr(c,j) + smin_nh4_vr(c,j) end if - sminn_tot(c) = sminn_tot(c) + sminn_vr_loc(c,j) * dzsoi_decomp(j) !!original: if (use_nitrif_denitrif): sminn_tot(c) = sminn_tot(c) + (smin_no3_vr(c,j) + smin_nh4_vr(c,j)) * dzsoi_decomp(j) + if(use_pflotran .and. pf_cmode) then + sminn_tot(c) = sminn_tot(c) + sminn_vr_loc(c,j) * dzsoi_decomp(j) & + *(nfixation_prof(c,j)*dzsoi_decomp(j)) ! weighted by froot fractions in annual max. active layers + else + sminn_tot(c) = sminn_tot(c) + sminn_vr_loc(c,j) * dzsoi_decomp(j) + end if end do end do @@ -4078,12 +4083,16 @@ subroutine calc_nuptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, nitr do fc=1,num_soilc c = filter_soilc(fc) if (sminn_tot(c) > 0.) then - nuptake_prof(c,j) = sminn_vr_loc(c,j) / sminn_tot(c) !!original: if (use_nitrif_denitrif): nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) + if(use_pflotran .and. pf_cmode) then + nuptake_prof(c,j) = sminn_vr_loc(c,j) / sminn_tot(c) & + *(nfixation_prof(c,j)*dzsoi_decomp(j)) ! weighted by froot fractions in annual max. active layers + else + nuptake_prof(c,j) = sminn_vr_loc(c,j) / sminn_tot(c) !original: if (use_nitrif_denitrif): nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) + end if else nuptake_prof(c,j) = nfixation_prof(c,j) - endif - !! sum_ndemand_vr will be calculated after calling calc_nuptake_prof -! sum_ndemand_vr(c,j) = col_plant_ndemand(c) * nuptake_prof(c,j) + potential_immob_vr(c,j) + end if + end do end do @@ -4091,11 +4100,10 @@ subroutine calc_nuptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, nitr end subroutine calc_nuptake_prof -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine calc_puptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, phosphorusstate_vars, puptake_prof) -! use clm_varcon , only : dzsoi_decomp !! declared in module CNAllocationMod - !! bgc interface & pflotran: - !! puptake_prof is used in CNAllocation1, 2, & 3 + ! bgc interface & pflotran: + ! puptake_prof is used in CNAllocation1, 2, & 3 ! !USES: use clm_varpar , only: nlevdecomp ! !ARGUMENTS: @@ -4114,7 +4122,7 @@ subroutine calc_puptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, phos associate( & nfixation_prof => cnstate_vars%nfixation_prof_col , & ! Output: [real(r8) (:,:) ] - solutionp_vr => phosphorusstate_vars%solutionp_vr_col & ! Input: [real(r8) (:,:) ] (gN/m3) soil mineral N + solutionp_vr => phosphorusstate_vars%solutionp_vr_col & ! Input: [real(r8) (:,:) ] (gN/m3) soil mineral N ) @@ -4139,10 +4147,9 @@ subroutine calc_puptake_prof(bounds, num_soilc, filter_soilc, cnstate_vars, phos if (solutionp_tot(c) > 0.) then puptake_prof(c,j) = solutionp_vr(c,j) / solutionp_tot(c) else - puptake_prof(c,j) = nfixation_prof(c,j) !!!! need modifications !!!! + puptake_prof(c,j) = nfixation_prof(c,j) ! need modifications endif - !! sum_pdemand_vr will be calculated after calling calc_puptake_prof -! sum_pdemand_vr(c,j) = col_plant_pdemand(c) * puptake_prof(c,j) + potential_immob_p_vr(c,j) + end do end do end associate diff --git a/components/clm/src/biogeochem/CNBalanceCheckMod.F90 b/components/clm/src/biogeochem/CNBalanceCheckMod.F90 index 36b147dc7780..ba46eeade070 100644 --- a/components/clm/src/biogeochem/CNBalanceCheckMod.F90 +++ b/components/clm/src/biogeochem/CNBalanceCheckMod.F90 @@ -132,14 +132,14 @@ subroutine BeginPBalance(bounds, num_soilc, filter_soilc, & integer :: fc ! lake filter indices !----------------------------------------------------------------------- - associate( & + associate( & totcolp => phosphorusstate_vars%totcolp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg !X.YANG - checking P balance problem, starting from VEGP totpftp => phosphorusstate_vars%totpftp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg totsomp => phosphorusstate_vars%totsomp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg - cwdp => phosphorusstate_vars%cwdp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg + cwdp => phosphorusstate_vars%cwdp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg totlitp => phosphorusstate_vars%totlitp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg - sminp => phosphorusstate_vars%sminp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg + sminp => phosphorusstate_vars%sminp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg col_begpb => phosphorusstate_vars%begpb_col & ! Output: [real(r8) (:)] phosphorus mass, beginning of time step (gP/m**2) ) @@ -186,7 +186,7 @@ subroutine CBalanceCheck(bounds, & gpp => carbonflux_vars%gpp_col , & ! Input: [real(r8) (:) ] (gC/m2/s) gross primary production er => carbonflux_vars%er_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total ecosystem respiration, autotrophic + heterotrophic - col_fire_closs => carbonflux_vars%fire_closs_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total column-level fire C loss + col_fire_closs => carbonflux_vars%fire_closs_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total column-level fire C loss col_hrv_xsmrpool_to_atm => carbonflux_vars%hrv_xsmrpool_to_atm_col , & ! Input: [real(r8) (:) ] (gC/m2/s) excess MR pool harvest mortality dwt_closs => carbonflux_vars%dwt_closs_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total carbon loss from product pools and conversion product_closs => carbonflux_vars%product_closs_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total wood product carbon loss @@ -254,6 +254,11 @@ subroutine CBalanceCheck(bounds, & write(iulog,*)'begcb = ',col_begcb(c) write(iulog,*)'endcb = ',col_endcb(c),carbonstate_vars%totsomc_col(c) write(iulog,*)'delta store = ',col_endcb(c)-col_begcb(c) + + if (use_pflotran .and. pf_cmode) then + write(iulog,*)'pf_delta_decompc = ',col_decompc_delta(c)*dt + end if + call endrun(msg=errMsg(__FILE__, __LINE__)) end if end if !use_ed @@ -286,7 +291,7 @@ subroutine NBalanceCheck(bounds, & real(r8):: dt ! radiation time step (seconds) !----------------------------------------------------------------------- - associate( & + associate( & totcoln => nitrogenstate_vars%totcoln_col , & ! Input: [real(r8) (:)] (gN/m2) total column nitrogen, incl veg ndep_to_sminn => nitrogenflux_vars%ndep_to_sminn_col , & ! Input: [real(r8) (:)] atmospheric N deposition to soil mineral N (gN/m2/s) nfix_to_sminn => nitrogenflux_vars%nfix_to_sminn_col , & ! Input: [real(r8) (:)] symbiotic/asymbiotic N fixation to soil mineral N (gN/m2/s) @@ -298,16 +303,15 @@ subroutine NBalanceCheck(bounds, & smin_no3_leached => nitrogenflux_vars%smin_no3_leached_col , & ! Input: [real(r8) (:)] soil mineral NO3 pool loss to leaching (gN/m2/s) smin_no3_runoff => nitrogenflux_vars%smin_no3_runoff_col , & ! Input: [real(r8) (:)] soil mineral NO3 pool loss to runoff (gN/m2/s) f_n2o_nit => nitrogenflux_vars%f_n2o_nit_col , & ! Input: [real(r8) (:)] flux of N2o from nitrification [gN/m^2/s] - col_fire_nloss => nitrogenflux_vars%fire_nloss_col , & ! Input: [real(r8) (:)] total column-level fire N loss (gN/m2/s) + col_fire_nloss => nitrogenflux_vars%fire_nloss_col , & ! Input: [real(r8) (:)] total column-level fire N loss (gN/m2/s) dwt_nloss => nitrogenflux_vars%dwt_nloss_col , & ! Input: [real(r8) (:)] (gN/m2/s) total nitrogen loss from product pools and conversion product_nloss => nitrogenflux_vars%product_nloss_col , & ! Input: [real(r8) (:)] (gN/m2/s) total wood product nitrogen loss som_n_leached => nitrogenflux_vars%som_n_leached_col , & ! Input: [real(r8) (:)] total SOM N loss from vertical transport ! pflotran: - col_decompn_delta => nitrogenflux_vars%externaln_to_decomp_delta_col, & ! Input: [real(r8) (:) ] (gN/m2/s) summarized net change of whole column N i/o to decomposing pool bwtn time-step - col_no3_delta => nitrogenflux_vars%no3_net_transport_delta_col , & ! Input: [real(r8) (:) ] (gN/m2/s) summarized net change of whole column NO3 leaching bwtn time-step + col_decompn_delta => nitrogenflux_vars%externaln_to_decomp_delta_col , & ! Input: [real(r8) (:) ] (gN/m2/s) summarized net change of whole column N i/o to decomposing pool bwtn time-step - col_ninputs => nitrogenflux_vars%ninputs_col , & ! Output: [real(r8) (:)] column-level N inputs (gN/m2/s) - col_noutputs => nitrogenflux_vars%noutputs_col , & ! Output: [real(r8) (:)] column-level N outputs (gN/m2/s) + col_ninputs => nitrogenflux_vars%ninputs_col , & ! Output: [real(r8) (:)] column-level N inputs (gN/m2/s) + col_noutputs => nitrogenflux_vars%noutputs_col , & ! Output: [real(r8) (:)] column-level N outputs (gN/m2/s) col_begnb => nitrogenstate_vars%begnb_col , & ! Output: [real(r8) (:)] nitrogen mass, beginning of time step (gN/m**2) col_endnb => nitrogenstate_vars%endnb_col , & ! Output: [real(r8) (:)] nitrogen mass, end of time step (gN/m**2) col_errnb => nitrogenstate_vars%errnb_col & ! Output: [real(r8) (:)] nitrogen balance error for the timestep (gN/m**2) @@ -342,7 +346,15 @@ subroutine NBalanceCheck(bounds, & else col_noutputs(c) = col_noutputs(c) + f_n2o_nit(c) - col_noutputs(c) = col_noutputs(c) + smin_no3_leached(c) + smin_no3_runoff(c) + if(use_pflotran .and. pf_cmode) then + ! inclusion of aq. NH4 transport by PFLOTRAN-bgc + col_noutputs(c) = col_noutputs(c) + sminn_leached(c) + else + + col_noutputs(c) = col_noutputs(c) + smin_no3_leached(c) + smin_no3_runoff(c) + + endif + end if endif @@ -358,10 +370,6 @@ subroutine NBalanceCheck(bounds, & if (use_pflotran .and. pf_cmode) then col_errnb(c) = col_errnb(c) - col_decompn_delta(c)*dt ! here is '-' adjustment. It says that the adding to PF decomp n pools was less. - - ! if not hydrology-coupled, NO3 leaching/runoff at previous time-step used as 'source' (out, -) to PFLOTRAN bgc - if (.not.pf_hmode) col_errnb(c) = col_errnb(c) + col_no3_delta(c)*dt - ! here is '+' adjustment. It says that the taking to PF no3 pools was more. end if if (abs(col_errnb(c)) > 1e-8_r8) then @@ -394,7 +402,14 @@ subroutine NBalanceCheck(bounds, & write(iulog,*)'fire = ',col_fire_nloss(c)*dt write(iulog,*)'dwt = ',dwt_nloss(c)*dt write(iulog,*)'prod = ',product_nloss(c)*dt + + if (use_pflotran .and. pf_cmode) then + write(iulog,*)'pf_delta_decompn = ',col_decompn_delta(c)*dt + end if + call endrun(msg=errMsg(__FILE__, __LINE__)) + + end if end associate @@ -426,37 +441,37 @@ subroutine PBalanceCheck(bounds, & real(r8) :: leafp_to_litter_col(bounds%begc:bounds%endc) real(r8) :: frootp_to_litter_col(bounds%begc:bounds%endc) - real(r8):: flux_mineralization_col(bounds%begc:bounds%endc) !! local temperary variable + real(r8):: flux_mineralization_col(bounds%begc:bounds%endc) ! local temperary variable !----------------------------------------------------------------------- - associate( & + associate( & totcolp => phosphorusstate_vars%totcolp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg supplement_to_sminp => phosphorusflux_vars%supplement_to_sminp_col , & ! Input: [real(r8) (:)] supplemental P supply (gP/m2/s) sminp_leached => phosphorusflux_vars%sminp_leached_col , & ! Input: [real(r8) (:)] soil mineral P pool loss to leaching (gP/m2/s) - col_fire_ploss => phosphorusflux_vars%fire_ploss_col , & ! Input: [real(r8) (:)] total column-level fire P loss (gP/m2/s) + col_fire_ploss => phosphorusflux_vars%fire_ploss_col , & ! Input: [real(r8) (:)] total column-level fire P loss (gP/m2/s) dwt_ploss => phosphorusflux_vars%dwt_ploss_col , & ! Input: [real(r8) (:)] (gP/m2/s) total phosphorus loss from product pools and conversion product_ploss => phosphorusflux_vars%product_ploss_col , & ! Input: [real(r8) (:)] (gP/m2/s) total wood product phosphorus loss - primp_to_labilep=> phosphorusflux_vars%primp_to_labilep_col , & - secondp_to_occlp=> phosphorusflux_vars%secondp_to_occlp_col , & - fert_p_to_sminp => phosphorusflux_vars%fert_p_to_sminp_col , & + primp_to_labilep => phosphorusflux_vars%primp_to_labilep_col , & + secondp_to_occlp => phosphorusflux_vars%secondp_to_occlp_col , & + fert_p_to_sminp => phosphorusflux_vars%fert_p_to_sminp_col , & - col_pinputs => phosphorusflux_vars%pinputs_col , & ! Output: [real(r8) (:)] column-level P inputs (gP/m2/s) - col_poutputs => phosphorusflux_vars%poutputs_col , & ! Output: [real(r8) (:)] column-level P outputs (gP/m2/s) + col_pinputs => phosphorusflux_vars%pinputs_col , & ! Output: [real(r8) (:)] column-level P inputs (gP/m2/s) + col_poutputs => phosphorusflux_vars%poutputs_col , & ! Output: [real(r8) (:)] column-level P outputs (gP/m2/s) col_begpb => phosphorusstate_vars%begpb_col , & ! Output: [real(r8) (:)] phosphorus mass, beginning of time step (gP/m**2) col_endpb => phosphorusstate_vars%endpb_col , & ! Output: [real(r8) (:)] phosphorus mass, end of time step (gP/m**2) - col_errpb => phosphorusstate_vars%errpb_col , & ! Output: [real(r8) (:)] phosphorus balance error for the timestep (gP/m**2) + col_errpb => phosphorusstate_vars%errpb_col , & ! Output: [real(r8) (:)] phosphorus balance error for the timestep (gP/m**2) !X.YANG testing P Balance, from VEGP totpftp => phosphorusstate_vars%totpftp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg totsomp => phosphorusstate_vars%totsomp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg - cwdp => phosphorusstate_vars%cwdp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg - totlitp => phosphorusstate_vars%totlitp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg - sminp => phosphorusstate_vars%sminp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg - leafp_to_litter => phosphorusflux_vars%leafp_to_litter_patch , & ! Input: [real(r8) (:)] soil mineral P pool loss to leaching (gP/m2/s) - frootp_to_litter => phosphorusflux_vars%frootp_to_litter_patch , & ! Input: [real(r8) (:)] soil mineral P pool loss to leaching (gP/m2/s) - sminp_to_plant => phosphorusflux_vars%sminp_to_plant_col ,& - cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & - pf => phosphorusflux_vars & + cwdp => phosphorusstate_vars%cwdp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg + totlitp => phosphorusstate_vars%totlitp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg + sminp => phosphorusstate_vars%sminp_col , & ! Input: [real(r8) (:)] (gP/m2) total column phosphorus, incl veg + leafp_to_litter => phosphorusflux_vars%leafp_to_litter_patch , & ! Input: [real(r8) (:)] soil mineral P pool loss to leaching (gP/m2/s) + frootp_to_litter => phosphorusflux_vars%frootp_to_litter_patch , & ! Input: [real(r8) (:)] soil mineral P pool loss to leaching (gP/m2/s) + sminp_to_plant => phosphorusflux_vars%sminp_to_plant_col , & + cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool , & + pf => phosphorusflux_vars & ) ! set time steps @@ -473,18 +488,18 @@ subroutine PBalanceCheck(bounds, & !! immobilization/mineralization in litter-to-SOM and SOM-to-SOM fluxes !! - X.YANG - ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) - flux_mineralization_col(c) = 0._r8 - enddo + ! column loop + do fc = 1,num_soilc + c = filter_soilc(fc) + flux_mineralization_col(c) = 0._r8 + enddo do k = 1, ndecomp_cascade_transitions if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions ! column loop do fc = 1,num_soilc c = filter_soilc(fc) - flux_mineralization_col(c) = flux_mineralization_col(c) - & + flux_mineralization_col(c) = flux_mineralization_col(c) - & pf%decomp_cascade_sminp_flux_col(c,k)*dt end do else @@ -498,6 +513,12 @@ subroutine PBalanceCheck(bounds, & endif end do + ! column loop + do fc = 1,num_soilc + c = filter_soilc(fc) + flux_mineralization_col(c) = flux_mineralization_col(c) + & + pf%biochem_pmin_col(c) + end do ! column loop diff --git a/components/clm/src/biogeochem/CNCStateUpdate3Mod.F90 b/components/clm/src/biogeochem/CNCStateUpdate3Mod.F90 index 8646ebc78130..43d69440fc37 100644 --- a/components/clm/src/biogeochem/CNCStateUpdate3Mod.F90 +++ b/components/clm/src/biogeochem/CNCStateUpdate3Mod.F90 @@ -12,7 +12,7 @@ module CNCStateUpdate3Mod use clm_varpar , only : nlevdecomp, ndecomp_pools, i_cwd, i_met_lit, i_cel_lit, i_lig_lit use CNCarbonStateType, only : carbonstate_type use CNCarbonFluxType , only : carbonflux_type - !! bgc interface & pflotran: + ! bgc interface & pflotran: use clm_varctl , only : use_pflotran, pf_cmode ! implicit none @@ -59,18 +59,20 @@ subroutine CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & if ( .not.is_active_betr_bgc )then ! column level carbon fluxes from fire - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! pft-level wood to column-level CWD (uncombusted wood) - cs%decomp_cpools_vr_col(c,j,i_cwd) = cs%decomp_cpools_vr_col(c,j,i_cwd) + cf%fire_mortality_c_to_cwdc_col(c,j) * dt - - ! pft-level wood to column-level litter (uncombusted wood) - cs%decomp_cpools_vr_col(c,j,i_met_lit) = cs%decomp_cpools_vr_col(c,j,i_met_lit) + cf%m_c_to_litr_met_fire_col(c,j)* dt - cs%decomp_cpools_vr_col(c,j,i_cel_lit) = cs%decomp_cpools_vr_col(c,j,i_cel_lit) + cf%m_c_to_litr_cel_fire_col(c,j)* dt - cs%decomp_cpools_vr_col(c,j,i_lig_lit) = cs%decomp_cpools_vr_col(c,j,i_lig_lit) + cf%m_c_to_litr_lig_fire_col(c,j)* dt - end do - end do + if (.not.(use_pflotran .and. pf_cmode)) then + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + ! pft-level wood to column-level CWD (uncombusted wood) + cs%decomp_cpools_vr_col(c,j,i_cwd) = cs%decomp_cpools_vr_col(c,j,i_cwd) + cf%fire_mortality_c_to_cwdc_col(c,j) * dt + + ! pft-level wood to column-level litter (uncombusted wood) + cs%decomp_cpools_vr_col(c,j,i_met_lit) = cs%decomp_cpools_vr_col(c,j,i_met_lit) + cf%m_c_to_litr_met_fire_col(c,j)* dt + cs%decomp_cpools_vr_col(c,j,i_cel_lit) = cs%decomp_cpools_vr_col(c,j,i_cel_lit) + cf%m_c_to_litr_cel_fire_col(c,j)* dt + cs%decomp_cpools_vr_col(c,j,i_lig_lit) = cs%decomp_cpools_vr_col(c,j,i_lig_lit) + cf%m_c_to_litr_lig_fire_col(c,j)* dt + end do + end do + end if !(.not.(use_pflotran .and. pf_cmode)) ! litter and CWD losses to fire do l = 1, ndecomp_pools diff --git a/components/clm/src/biogeochem/CNCarbonFluxType.F90 b/components/clm/src/biogeochem/CNCarbonFluxType.F90 index 42b4db144d3d..768d68bf7317 100644 --- a/components/clm/src/biogeochem/CNCarbonFluxType.F90 +++ b/components/clm/src/biogeochem/CNCarbonFluxType.F90 @@ -17,7 +17,7 @@ module CNCarbonFluxType use LandunitType , only : lun_pp use clm_varctl , only : nu_com ! bgc interface & pflotran - use clm_varctl , only : use_bgc_interface, use_pflotran, pf_cmode, use_vertsoilc + use clm_varctl , only : use_clm_interface, use_pflotran, pf_cmode, use_vertsoilc ! ! !PUBLIC TYPES: implicit none @@ -394,7 +394,7 @@ module CNCarbonFluxType real(r8), pointer :: allocation_stem (:) ! check allocation to stem for dynamic allocation scheme real(r8), pointer :: allocation_froot (:) ! check allocation to fine root for dynamic allocation scheme - ! new variables for clm_bgc_interface & pflotran + ! new variables for clm_interface_funcsMod & pflotran !------------------------------------------------------------------------ real(r8), pointer :: externalc_to_decomp_cpools_col (:,:,:) ! col (gC/m3/s) net C fluxes associated with litter/som-adding/removal to decomp pools ! (sum of all external C additions and removals, excluding decomposition/hr). @@ -787,7 +787,7 @@ subroutine InitAllocate(this, bounds) allocate(this%allocation_stem (begp:endp)) ; this%allocation_stem (:) = nan allocate(this%allocation_froot (begp:endp)) ; this%allocation_froot (:) = nan - ! clm_bgc_interface & pflotran + ! clm_interface & pflotran !------------------------------------------------------------------------ allocate(this%externalc_to_decomp_cpools_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%externalc_to_decomp_cpools_col(:,:,:) = spval allocate(this%externalc_to_decomp_delta_col (begc:endc)); this%externalc_to_decomp_delta_col (:) = spval @@ -3919,7 +3919,7 @@ subroutine Restart ( this, bounds, ncid, flag ) interpinic_flag='interp', readvar=readvar, data=this%annsum_litfall_patch) end if - ! clm_bgc_interface & pflotran + ! clm_interface & pflotran !------------------------------------------------------------------------ if (use_pflotran .and. pf_cmode) then ! externalc_to_decomp_npools_col @@ -4377,6 +4377,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil use subgridAveMod , only : p2c use tracer_varcon , only : is_active_betr_bgc use MathfuncMod , only : dot_sum + use clm_varpar , only : nlevdecomp_full ! ! !ARGUMENTS: class(carbonflux_type) :: this @@ -4392,6 +4393,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil integer :: c,p,j,k,l ! indices integer :: fp,fc ! lake filter indices real(r8) :: maxdepth ! depth to integrate soil variables + integer :: nlev !----------------------------------------------------------------------- associate(& @@ -4772,6 +4774,9 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil endif ! column soil variables + ! column variables + nlev = nlevdecomp + if (use_pflotran .and. pf_cmode) nlev = nlevdecomp_full ! some zeroing do fc = 1,num_soilc @@ -4786,9 +4791,9 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! 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 j = 1,nlev + do fc = 1,num_soilc + c = filter_soilc(fc) this%decomp_cascade_ctransfer_col(c,k) = & this%decomp_cascade_ctransfer_col(c,k) + & @@ -4818,10 +4823,10 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! bgc interface & pflotran: !---------------------------------------------------------------- - if (use_bgc_interface) then - call CSummary_interface(this, bounds, num_soilc, filter_soilc) + if (use_clm_interface) then + call CSummary_interface(this, bounds, num_soilc, filter_soilc) end if - !! CSummary_interface: hr_col(c) will be used below + ! CSummary_interface: hr_col(c) will be used below !---------------------------------------------------------------- do fc = 1,num_soilc @@ -4857,7 +4862,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! vertically integrate column-level carbon fire losses do l = 1, ndecomp_pools - do j = 1,nlevdecomp + do j = 1,nlev do fc = 1,num_soilc c = filter_soilc(fc) this%m_decomp_cpools_to_fire_col(c,l) = & @@ -4914,10 +4919,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%landuseflux_col(c) end do - ! for vertically-resolved soil biogeochemistry, calculate some diagnostics of carbon pools to a given depth - - if ( (.not. is_active_betr_bgc) .and. & - (.not.(use_pflotran .and. pf_cmode)) ) then + if (.not. is_active_betr_bgc) then ! _col(cWDC_HR) - coarse woody debris heterotrophic respiration do fc = 1,num_soilc @@ -4948,99 +4950,104 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil end if end do - ! (LITTERC_LOSS) - litter C loss - do fc = 1,num_soilc - c = filter_soilc(fc) - this%litterc_loss_col(c) = this%lithr_col(c) - end do + if (.not.(use_pflotran .and. pf_cmode)) then + ! (LITTERC_LOSS) - litter C loss + do fc = 1,num_soilc + c = filter_soilc(fc) + this%litterc_loss_col(c) = this%lithr_col(c) + end do + end if !(.not.(use_pflotran .and. pf_cmode)) + do l = 1, ndecomp_pools if ( is_litter(l) ) then do fc = 1,num_soilc - c = filter_soilc(fc) - this%litterc_loss_col(c) = & - this%litterc_loss_col(c) + & - this%m_decomp_cpools_to_fire_col(c,l) + c = filter_soilc(fc) + this%litterc_loss_col(c) = & + this%litterc_loss_col(c) + & + this%m_decomp_cpools_to_fire_col(c,l) end do end if end do - - + + 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) - this%litterc_loss_col(c) = & - this%litterc_loss_col(c) + & - this%decomp_cascade_ctransfer_col(c,k) - end do - end if + if ( is_litter(decomp_cascade_con%cascade_donor_pool(k)) ) then + do fc = 1,num_soilc + c = filter_soilc(fc) + this%litterc_loss_col(c) = & + this%litterc_loss_col(c) + & + this%decomp_cascade_ctransfer_col(c,k) + end do + end if end do - else if ((use_pflotran .and. pf_cmode)) then - - ! 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) - this%decomp_cpools_leached_col(c,l) = 0._r8 - end do - do j = 1, nlevdecomp + if (use_pflotran .and. pf_cmode) then + ! note: the follwoing should be useful to non-pflotran-coupled, but seems cause 1 BFB test unmatching. + ! 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) - this%decomp_cpools_leached_col(c,l) = & + this%decomp_cpools_leached_col(c,l) = 0._r8 + end do + do j = 1, nlev + do fc = 1,num_soilc + c = filter_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) + this%som_c_leached_col(c) = & + this%som_c_leached_col(c) + & + this%decomp_cpools_leached_col(c,l) end do end do - do fc = 1,num_soilc - c = filter_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 - endif + end if + end if + ! debug do fc = 1,num_soilc - c = filter_soilc(fc) - this%plant_to_litter_cflux(c) = 0._r8 - this%plant_to_cwd_cflux(c) = 0._r8 - do j = 1, nlevdecomp - this%plant_to_litter_cflux(c) = & - this%plant_to_litter_cflux(c) + & - this%phenology_c_to_litr_met_c_col(c,j)* dzsoi_decomp(j) + & - this%phenology_c_to_litr_cel_c_col(c,j)* dzsoi_decomp(j) + & - this%phenology_c_to_litr_lig_c_col(c,j)* dzsoi_decomp(j) + & - this%gap_mortality_c_to_litr_met_c_col(c,j)* dzsoi_decomp(j) + & - this%gap_mortality_c_to_litr_cel_c_col(c,j)* dzsoi_decomp(j) + & - this%gap_mortality_c_to_litr_lig_c_col(c,j)* dzsoi_decomp(j) + & - this%m_c_to_litr_met_fire_col(c,j)* dzsoi_decomp(j) + & - this%m_c_to_litr_cel_fire_col(c,j)* dzsoi_decomp(j) + & - this%m_c_to_litr_lig_fire_col(c,j)* dzsoi_decomp(j) - this%plant_to_cwd_cflux(c) = & - this%plant_to_cwd_cflux(c) + & - this%gap_mortality_c_to_cwdc_col(c,j)* dzsoi_decomp(j) + & - this%fire_mortality_c_to_cwdc_col(c,j)* dzsoi_decomp(j) - end do + c = filter_soilc(fc) + this%plant_to_litter_cflux(c) = 0._r8 + this%plant_to_cwd_cflux(c) = 0._r8 + do j = 1, nlev + this%plant_to_litter_cflux(c) = & + this%plant_to_litter_cflux(c) + & + this%phenology_c_to_litr_met_c_col(c,j)* dzsoi_decomp(j) + & + this%phenology_c_to_litr_cel_c_col(c,j)* dzsoi_decomp(j) + & + this%phenology_c_to_litr_lig_c_col(c,j)* dzsoi_decomp(j) + & + this%gap_mortality_c_to_litr_met_c_col(c,j)* dzsoi_decomp(j) + & + this%gap_mortality_c_to_litr_cel_c_col(c,j)* dzsoi_decomp(j) + & + this%gap_mortality_c_to_litr_lig_c_col(c,j)* dzsoi_decomp(j) + & + this%m_c_to_litr_met_fire_col(c,j)* dzsoi_decomp(j) + & + this%m_c_to_litr_cel_fire_col(c,j)* dzsoi_decomp(j) + & + this%m_c_to_litr_lig_fire_col(c,j)* dzsoi_decomp(j) + this%plant_to_cwd_cflux(c) = & + this%plant_to_cwd_cflux(c) + & + this%gap_mortality_c_to_cwdc_col(c,j)* dzsoi_decomp(j) + & + this%fire_mortality_c_to_cwdc_col(c,j)* dzsoi_decomp(j) + end do end do end associate end subroutine Summary -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- ! !INTERFACE: subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) ! ! !DESCRIPTION: -!! bgc interface & pflotran: +! bgc interface & pflotran: ! On the radiation time step, perform column-level carbon ! summary calculations, which mainly from PFLOTRAN bgc ! ! !USES: use shr_sys_mod, only: shr_sys_flush - use clm_varpar , only: nlevdecomp,ndecomp_pools,ndecomp_cascade_transitions + use clm_varpar , only: nlevdecomp_full,ndecomp_pools,ndecomp_cascade_transitions use clm_varpar , only: i_met_lit, i_cel_lit, i_lig_lit, i_cwd use clm_time_manager , only : get_step_size ! @@ -5054,10 +5061,7 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) ! !CALLED FROM: ! subroutine Summary (if plotran bgc coupled with CLM-CN ! -! !REVISION HISTORY: -!!06/17/2015: modified by Gangsheng Wang -! ! -! !LOCAL VARIABLES: +! LOCAL VARIABLES: real(r8) :: dtime ! time-step (s) integer :: c,j,l ! indices integer :: fc ! column filter indices @@ -5069,11 +5073,10 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) ) dtime = get_step_size() -!!--------------------------------------------------------------------------------------------------- - if (use_pflotran.and.pf_cmode) then - ! total heterotrophic respiration (HR) +!--------------------------------------------------------------------------------------------------- + ! total heterotrophic respiration (HR) this%hr_col(:) = 0._r8 - do j = 1,nlevdecomp + do j = 1,nlevdecomp_full do fc = 1,num_soilc c = filter_soilc(fc) this%hr_col(c) = this%hr_col(c) + & @@ -5086,7 +5089,7 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) c = filter_soilc(fc) this%f_co2_soil_col(c) = 0._r8 end do - do j = 1,nlevdecomp + do j = 1,nlevdecomp_full do fc = 1,num_soilc c = filter_soilc(fc) this%f_co2_soil_col(c) = this%f_co2_soil_col(c) + & @@ -5107,7 +5110,7 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) if ( is_cwd(l) ) then do fc = 1,num_soilc c = filter_soilc(fc) - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full this%cwdc_loss_col(c) = & this%cwdc_loss_col(c) + & this%decomp_cpools_sourcesink_col(c,j,l) / dtime @@ -5118,7 +5121,7 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) if ( is_litter(l) ) then do fc = 1,num_soilc c = filter_soilc(fc) - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full this%litterc_loss_col(c) = & this%litterc_loss_col(c) + & this%decomp_cpools_sourcesink_col(c,j,l) / dtime @@ -5127,7 +5130,6 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) end if end do - end if !!if (use_pflotran.and.pf_cmode) ! add up all vertically-resolved addition/removal rates (gC/m3/s) of decomp_pools for PFLOTRAN-bgc ! (note: this can be for general purpose, although here added an 'if...endif' block for PF-bgc) @@ -5135,7 +5137,7 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) ! for calculating the net changes, which are used to do balance check this%externalc_to_decomp_delta_col(:) = 0._r8 do l = 1, ndecomp_pools - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full do fc = 1, num_soilc c = filter_soilc(fc) this%externalc_to_decomp_delta_col(c) = this%externalc_to_decomp_delta_col(c) + & @@ -5143,14 +5145,13 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) end do end do end do -!write(*,'(A40,E14.6)')">>>DEBUG | externC[t-1]=",this%externalc_to_decomp_delta_col(1)*dtime ! ! do the initialization for the following variable here. ! DON'T do so in the beginning of CLM-CN time-step (otherwise the above saved will not work) this%externalc_to_decomp_cpools_col(:,:,:) = 0._r8 do l = 1, ndecomp_pools - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full do fc = 1,num_soilc c = filter_soilc(fc) @@ -5161,10 +5162,8 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) + this%phenology_c_to_litr_met_c_col(c,j) & + this%dwt_frootc_to_litr_met_c_col(c,j) & + this%gap_mortality_c_to_litr_met_c_col(c,j) & - + this%harvest_c_to_litr_met_c_col(c,j) !!& -! + this%m_c_to_litr_met_fire_col(c,j) & -! + this%decomp_cpools_transport_tendency_col(c,j,l) & -! - this%m_decomp_cpools_to_fire_vr_col(c,j,l) + + this%harvest_c_to_litr_met_c_col(c,j) & + + this%m_c_to_litr_met_fire_col(c,j) elseif (l==i_cel_lit) then this%externalc_to_decomp_cpools_col(c,j,l) = & @@ -5172,10 +5171,8 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) + this%phenology_c_to_litr_cel_c_col(c,j) & + this%dwt_frootc_to_litr_cel_c_col(c,j) & + this%gap_mortality_c_to_litr_cel_c_col(c,j) & - + this%harvest_c_to_litr_cel_c_col(c,j) !!& -! + this%m_c_to_litr_cel_fire_col(c,j) & -! + this%decomp_cpools_transport_tendency_col(c,j,l) & -! - this%m_decomp_cpools_to_fire_vr_col(c,j,l) + + this%harvest_c_to_litr_cel_c_col(c,j) & + + this%m_c_to_litr_cel_fire_col(c,j) elseif (l==i_lig_lit) then this%externalc_to_decomp_cpools_col(c,j,l) = & @@ -5183,10 +5180,8 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) + this%phenology_c_to_litr_lig_c_col(c,j) & + this%dwt_frootc_to_litr_lig_c_col(c,j) & + this%gap_mortality_c_to_litr_lig_c_col(c,j) & - + this%harvest_c_to_litr_lig_c_col(c,j) !!& -! + this%m_c_to_litr_lig_fire_col(c,j) & -! + this%decomp_cpools_transport_tendency_col(c,j,l) & -! - this%m_decomp_cpools_to_fire_vr_col(c,j,l) + + this%harvest_c_to_litr_lig_c_col(c,j) & + + this%m_c_to_litr_lig_fire_col(c,j) ! for cwd elseif (l==i_cwd) then @@ -5195,18 +5190,8 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) + this%dwt_livecrootc_to_cwdc_col(c,j) & + this%dwt_deadcrootc_to_cwdc_col(c,j) & + this%gap_mortality_c_to_cwdc_col(c,j) & - + this%harvest_c_to_cwdc_col(c,j) !!& -! + this%fire_mortality_c_to_cwdc_col(c,j) & -! + this%decomp_cpools_transport_tendency_col(c,j,l) & -! - this%m_decomp_cpools_to_fire_vr_col(c,j,l) - - ! for som - ! no external input to som -! else -! this%externalc_to_decomp_cpools_col(c,j,l) = & -! this%externalc_to_decomp_cpools_col(c,j,l) & -! + this%decomp_cpools_transport_tendency_col(c,j,l) & -! - this%m_decomp_cpools_to_fire_vr_col(c,j,l) + + this%harvest_c_to_cwdc_col(c,j) & + + this%fire_mortality_c_to_cwdc_col(c,j) end if @@ -5233,7 +5218,7 @@ subroutine CSummary_interface(this, bounds, num_soilc, filter_soilc) end associate end subroutine CSummary_interface -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- !------------------------------------------------------------ subroutine summary_rr(this, bounds, num_soilp, filter_soilp, num_soilc, filter_soilc) @@ -5338,7 +5323,11 @@ subroutine summary_cflux_for_ch4( this, bounds, num_soilp, filter_soilp, num_soi this%somhr_col(c) = 0._r8 this%lithr_col(c) = 0._r8 this%decomp_cascade_hr_col(c,1:ndecomp_cascade_transitions)= 0._r8 - this%hr_vr_col(c,1:nlevdecomp) = 0._r8 + if (.not. (use_pflotran .and. pf_cmode)) then + ! pflotran has returned 'hr_vr_col(begc:endc,1:nlevdecomp)' to ALM before this subroutine is called in CNEcosystemDynNoLeaching2 + ! thus 'hr_vr_col' should NOT be set to 0 + this%hr_vr_col(c,1:nlevdecomp) = 0._r8 + end if enddo if ( (.not. is_active_betr_bgc ) .and. & diff --git a/components/clm/src/biogeochem/CNCarbonStateType.F90 b/components/clm/src/biogeochem/CNCarbonStateType.F90 index 4862e06982a2..8844f87c8c3f 100644 --- a/components/clm/src/biogeochem/CNCarbonStateType.F90 +++ b/components/clm/src/biogeochem/CNCarbonStateType.F90 @@ -20,6 +20,9 @@ module CNCarbonStateType use ColumnType , only : col_pp use clm_varctl , only : nu_com, use_ed use VegetationType , only : veg_pp + + ! bgc interface & pflotran + use clm_varctl , only : use_clm_interface, use_pflotran, pf_cmode ! ! !PUBLIC TYPES: @@ -2735,13 +2738,13 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, c12_carbonstate_var do k = 1, ndecomp_pools do c = bounds%begc, bounds%endc do j = 1, nlevdecomp - if ( exit_spinup ) then - m = decomp_cascade_con%spinup_factor(k) - if (decomp_cascade_con%spinup_factor(k) > 1) m = m / cnstate_vars%scalaravg_col(c) + if ( exit_spinup ) then + m = decomp_cascade_con%spinup_factor(k) + if (decomp_cascade_con%spinup_factor(k) > 1) m = m / cnstate_vars%scalaravg_col(c) else if ( enter_spinup ) then - m = 1. / decomp_cascade_con%spinup_factor(k) - if (decomp_cascade_con%spinup_factor(k) > 1) m = m * cnstate_vars%scalaravg_col(c) - end if + m = 1. / decomp_cascade_con%spinup_factor(k) + if (decomp_cascade_con%spinup_factor(k) > 1) m = m * cnstate_vars%scalaravg_col(c) + end if this%decomp_cpools_vr_col(c,j,k) = this%decomp_cpools_vr_col(c,j,k) * m end do end do @@ -2901,7 +2904,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil use clm_varctl , only: iulog use clm_time_manager , only: get_step_size use clm_varcon , only: secspday - use clm_varpar , only: nlevdecomp, ndecomp_pools + use clm_varpar , only: nlevdecomp, ndecomp_pools, nlevdecomp_full ! ! !ARGUMENTS: class(carbonstate_type) :: this @@ -2916,6 +2919,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil integer :: c,p,j,k,l ! indices integer :: fp,fc ! lake filter indices real(r8) :: maxdepth ! depth to integrate soil variables + integer :: nlev !----------------------------------------------------------------------- ! calculate patch -level summary of carbon state @@ -2995,6 +2999,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! column level summary + nlev = nlevdecomp + if (use_pflotran .and. pf_cmode) nlev = nlevdecomp_full ! vertically integrate each of the decomposing C pools @@ -3005,7 +3011,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil end do end do do l = 1, ndecomp_pools - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%decomp_cpools_col(c,l) = & @@ -3133,7 +3139,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil c = filter_soilc(fc) this%ctrunc_col(c) = 0._r8 end do - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%ctrunc_col(c) = & diff --git a/components/clm/src/biogeochem/CNDecompCascadeBGCMod.F90 b/components/clm/src/biogeochem/CNDecompCascadeBGCMod.F90 index 45d42ee1ef18..4c0ff8a6c8e3 100644 --- a/components/clm/src/biogeochem/CNDecompCascadeBGCMod.F90 +++ b/components/clm/src/biogeochem/CNDecompCascadeBGCMod.F90 @@ -684,7 +684,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & t_scalar => carbonflux_vars%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => carbonflux_vars%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => carbonflux_vars%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia - decomp_k => carbonflux_vars%decomp_k_col & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + decomp_k => carbonflux_vars%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + decomp_k_pools => decomp_cascade_con%decomp_k_pools & !(0: ndecomp_pools) ! pflotran (0 for atm. co2) ) mino2lim = CNParamsShareInst%mino2lim @@ -738,13 +739,6 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! calc ref rate catanf_30 = catanf(30._r8) - ! The following code implements the acceleration part of the AD spinup algorithm - - if ( spinup_state .eq. 1 ) then - k_s1 = k_s1 * CNDecompBgcParamsInst%spinup_vector(1) - k_s2 = k_s2 * CNDecompBgcParamsInst%spinup_vector(2) - k_s3 = k_s3 * CNDecompBgcParamsInst%spinup_vector(3) - endif i_litr1 = 1 i_litr2 = 2 @@ -759,6 +753,23 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & i_soil3 = 6 end if + ! pflotran:beg---saving orignal k (not scaled) for passing to pflotran bgc decomposition sandboxes + decomp_k_pools(i_litr1) = k_l1 + decomp_k_pools(i_litr2) = k_l2_l3 + decomp_k_pools(i_litr3) = k_l2_l3 + decomp_k_pools(i_cwd) = k_frag + decomp_k_pools(i_soil1) = k_s1 + decomp_k_pools(i_soil2) = k_s2 + decomp_k_pools(i_soil3) = k_s3 + ! pflotran:end + + ! The following code implements the acceleration part of the AD spinup algorithm + if ( spinup_state .eq. 1 ) then + k_s1 = k_s1 * CNDecompBgcParamsInst%spinup_vector(1) + k_s2 = k_s2 * CNDecompBgcParamsInst%spinup_vector(2) + k_s3 = k_s3 * CNDecompBgcParamsInst%spinup_vector(3) + endif + !--- time dependent coefficients-----! if ( nlevdecomp .eq. 1 ) then diff --git a/components/clm/src/biogeochem/CNDecompCascadeCNMod.F90 b/components/clm/src/biogeochem/CNDecompCascadeCNMod.F90 index bc16102c2e72..3d6a9ecdecf3 100644 --- a/components/clm/src/biogeochem/CNDecompCascadeCNMod.F90 +++ b/components/clm/src/biogeochem/CNDecompCascadeCNMod.F90 @@ -74,7 +74,7 @@ module CNDecompCascadeCNMod integer :: nsompools = 4 integer :: nlitpools = 3 integer :: ncwdpools = 1 - real(r8), allocatable :: spinup_vector(:) ! multipliers for soil decomp during accelerated spinup + real(r8), allocatable :: spinup_vector(:) ! multipliers for soil decomp during accelerated spinup end type CNDecompCnParamsType @@ -694,7 +694,8 @@ subroutine decomp_rate_constants_cn(bounds, & t_scalar => carbonflux_vars%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp w_scalar => carbonflux_vars%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => carbonflux_vars%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia - decomp_k => carbonflux_vars%decomp_k_col & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + decomp_k => carbonflux_vars%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + decomp_k_pools => decomp_cascade_con%decomp_k_pools & !(0: ndecomp_pools) ! pflotran (0 for atm. co2) ) mino2lim = CNParamsShareInst%mino2lim @@ -744,20 +745,6 @@ subroutine decomp_rate_constants_cn(bounds, & decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding end if - ! The following code implements the acceleration part of the AD spinup - ! algorithm, by multiplying all of the SOM decomposition base rates by 10.0. - - if ( spinup_state .eq. 1 ) then - k_l1 = k_l1 * CNDecompCnParamsInst%spinup_vector(1) - k_l2 = k_l2 * CNDecompCnParamsInst%spinup_vector(2) - k_l3 = k_l3 * CNDecompCnParamsInst%spinup_vector(3) - k_s1 = k_s1 * CNDecompCnParamsInst%spinup_vector(4) - k_s2 = k_s2 * CNDecompCnParamsInst%spinup_vector(5) - k_s3 = k_s3 * CNDecompCnParamsInst%spinup_vector(6) - k_s4 = k_s4 * CNDecompCnParamsInst%spinup_vector(7) - k_frag = k_frag * CNDecompCnParamsInst%spinup_vector(8) - endif - i_litr1 = 1 i_litr2 = 2 i_litr3 = 3 @@ -773,6 +760,31 @@ subroutine decomp_rate_constants_cn(bounds, & i_soil4 = 7 end if + ! pflotran:beg---saving kd (NOT ad scaled) for passing to pflotran bgc decomposition sandboxes + decomp_k_pools(i_litr1) = k_l1 / dt + decomp_k_pools(i_litr2) = k_l2 / dt + decomp_k_pools(i_litr3) = k_l3 / dt + if (.not.use_ed) decomp_k_pools(i_cwd) = k_frag / dt + decomp_k_pools(i_soil1) = k_s1 / dt + decomp_k_pools(i_soil2) = k_s2 / dt + decomp_k_pools(i_soil3) = k_s3 / dt + decomp_k_pools(i_soil4) = k_s4 / dt + ! pflotran:end + + ! The following code implements the acceleration part of the AD spinup + ! algorithm, by multiplying all of the SOM decomposition base rates by 10.0. + + if ( spinup_state .eq. 1 ) then + k_l1 = k_l1 * CNDecompCnParamsInst%spinup_vector(1) + k_l2 = k_l2 * CNDecompCnParamsInst%spinup_vector(2) + k_l3 = k_l3 * CNDecompCnParamsInst%spinup_vector(3) + k_s1 = k_s1 * CNDecompCnParamsInst%spinup_vector(4) + k_s2 = k_s2 * CNDecompCnParamsInst%spinup_vector(5) + k_s3 = k_s3 * CNDecompCnParamsInst%spinup_vector(6) + k_s4 = k_s4 * CNDecompCnParamsInst%spinup_vector(7) + if (.not.use_ed) k_frag = k_frag * CNDecompCnParamsInst%spinup_vector(8) + endif + !--- time dependent coefficients-----! if ( nlevdecomp .eq. 1 ) then @@ -979,8 +991,8 @@ subroutine decomp_rate_constants_cn(bounds, & call get_curr_date(year, mon, day, sec) if (year >= 20 .and. year < 40) then !as a first test, use level 4 (10cm) - this is used to cacluate location-specific acceleration factors - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_soilc + c = filter_soilc(fc) cnstate_vars%scalaravg_col(c) = cnstate_vars%scalaravg_col(c) + & (t_scalar(c,4) * w_scalar(c,4) * o_scalar(c,4) ) * dt / (86400._r8 * 365._r8 * 20._r8) if (cnstate_vars%scalaravg_col(c) < 1.0e-2) cnstate_vars%scalaravg_col(c) = 1.0e-2 diff --git a/components/clm/src/biogeochem/CNDecompCascadeConType.F90 b/components/clm/src/biogeochem/CNDecompCascadeConType.F90 index 7d85f418e4e8..22266b3bd18d 100644 --- a/components/clm/src/biogeochem/CNDecompCascadeConType.F90 +++ b/components/clm/src/biogeochem/CNDecompCascadeConType.F90 @@ -39,7 +39,8 @@ module CNDecompCascadeConType logical , pointer :: is_metabolic(:) ! TRUE => pool is metabolic material logical , pointer :: is_cellulose(:) ! TRUE => pool is cellulose logical , pointer :: is_lignin(:) ! TRUE => pool is lignin - real(r8) , pointer :: spinup_factor(:) ! factor by which to scale AD and relevant processes by + real(r8) , pointer :: spinup_factor(:) ! factor by which to scale AD and relevant processes + real(r8) , pointer :: decomp_k_pools(:) ! Kd in 1/sec for pool end type decomp_cascade_type type(decomp_cascade_type), public :: decomp_cascade_con @@ -76,6 +77,7 @@ subroutine init_decomp_cascade_constants() allocate(decomp_cascade_con%is_cellulose(0:ndecomp_pools)) allocate(decomp_cascade_con%is_lignin(0:ndecomp_pools)) allocate(decomp_cascade_con%spinup_factor(0:ndecomp_pools)) + allocate(decomp_cascade_con%decomp_k_pools(0:ndecomp_pools)) !-- properties of each pathway along decomposition cascade decomp_cascade_con%cascade_step_name(1:ndecomp_cascade_transitions) = '' @@ -99,6 +101,7 @@ subroutine init_decomp_cascade_constants() decomp_cascade_con%is_cellulose(0:ndecomp_pools) = .false. decomp_cascade_con%is_lignin(0:ndecomp_pools) = .false. decomp_cascade_con%spinup_factor(0:ndecomp_pools) = nan + decomp_cascade_con%decomp_k_pools(0:ndecomp_pools) = nan end subroutine init_decomp_cascade_constants diff --git a/components/clm/src/biogeochem/CNDecompMod.F90 b/components/clm/src/biogeochem/CNDecompMod.F90 index ee3f92b804c7..96228d6c30b8 100644 --- a/components/clm/src/biogeochem/CNDecompMod.F90 +++ b/components/clm/src/biogeochem/CNDecompMod.F90 @@ -35,8 +35,8 @@ module CNDecompMod use WaterStateType , only : waterstate_type use ch4Mod , only : ch4_type use cropType , only : crop_type - !! bgc interface & pflotran: - use clm_varctl , only : use_bgc_interface, use_pflotran, pf_cmode + ! clm interface & pflotran: + use clm_varctl , only : use_clm_interface, use_pflotran, pf_cmode ! implicit none save @@ -88,7 +88,7 @@ subroutine readCNDecompParams ( ncid ) end subroutine readCNDecompParams -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & num_soilp, filter_soilp, & canopystate_vars, soilstate_vars, & @@ -98,20 +98,20 @@ subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & nitrogenstate_vars, nitrogenflux_vars, & phosphorusstate_vars,phosphorusflux_vars) - !!----------------------------------------------------------------------------- - !! DESCRIPTION: - !! Modified for bgc-interface (wgs): 9/12/2015 - !! clm-bgc soil Module, can be called through clm_bgc_interface - !! ONLY includes SOM decomposition & nitrification/denitrification (if use_nitrif_denitrif) - !! CNAllocaiton is divided into 3 subroutines: - !! (1) CNAllocation1_PlantNPDemand is called in CNEcosystemDynNoLeaching1 - !! (2) CNAllocation2_ResolveNPLimit is called in CNDecompAlloc (this subroutine) - !! (3) CNAllocation3_PlantCNPAlloc is called in CNDecompAlloc2 - !!----------------------------------------------------------------------------- + !----------------------------------------------------------------------------- + ! DESCRIPTION: + ! Modified for clm_interface: 9/12/2015 + ! clm-bgc soil Module, can be called through clm_bgc_interface + ! ONLY includes SOM decomposition & nitrification/denitrification (if use_nitrif_denitrif) + ! CNAllocaiton is divided into 3 subroutines: + ! (1) CNAllocation1_PlantNPDemand is called in CNEcosystemDynNoLeaching1 + ! (2) CNAllocation2_ResolveNPLimit is called in CNDecompAlloc (this subroutine) + ! (3) CNAllocation3_PlantCNPAlloc is called in CNDecompAlloc2 + !----------------------------------------------------------------------------- ! !USES: ! use CNAllocationMod , only: CNAllocation - use CNAllocationMod , only: CNAllocation2_ResolveNPLimit !! Phase-2 of CNAllocation + use CNAllocationMod , only: CNAllocation2_ResolveNPLimit ! Phase-2 of CNAllocation ! ! !ARGUMENT: type(bounds_type) , intent(in) :: bounds @@ -132,7 +132,7 @@ subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & ! type(carbonflux_type) , intent(inout) :: c14_carbonflux_vars type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars - !! add phosphorus -- + ! add phosphorus -- type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars ! type(crop_type) , intent(in) :: crop_vars @@ -186,7 +186,7 @@ subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & net_nmin_vr => nitrogenflux_vars%net_nmin_vr_col , & ! Output: [real(r8) (:,:) ] gross_nmin => nitrogenflux_vars%gross_nmin_col , & ! Output: [real(r8) (:) ] gross rate of N mineralization (gN/m2/s) net_nmin => nitrogenflux_vars%net_nmin_col , & ! Output: [real(r8) (:) ] net rate of N mineralization (gN/m2/s) - !!! add phosphorus + ! add phosphorus decomp_cascade_ptransfer_vr => phosphorusflux_vars%decomp_cascade_ptransfer_vr_col , & ! Output: [real(r8) (:,:,:) ] vert-res transfer of P from donor to receiver pool along decomp. cascade (gP/m3/s) decomp_cascade_sminp_flux_vr => phosphorusflux_vars%decomp_cascade_sminp_flux_vr_col , & ! Output: [real(r8) (:,:,:) ] vert-res mineral P flux for transition along decomposition cascade (gP/m3/s) potential_immob_p_vr => phosphorusflux_vars%potential_immob_p_vr_col , & ! Output: [real(r8) (:,:) ] @@ -212,16 +212,9 @@ subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & actual_immob_p_vr => phosphorusflux_vars%actual_immob_p_vr_col & ) -!!------------------------------------------------------------------------------------------------- - ! calculate decomposition rates (originally called in CNEcosystemDynNoLeaching1) - if (use_century_decomp) then - call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & - canopystate_vars, soilstate_vars, temperature_vars, ch4_vars, carbonflux_vars) - else - call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc, & - canopystate_vars, soilstate_vars, temperature_vars, ch4_vars, carbonflux_vars, cnstate_vars) - end if -!!------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------------------------- + ! call decomp_rate_constants_bgc() or decomp_rate_constants_cn(): now called in CNEcosystemDynNoLeaching1 + !------------------------------------------------------------------------------------------------- ! set initial values for potential C and N fluxes p_decomp_cpool_loss(bounds%begc : bounds%endc, :, :) = 0._r8 @@ -391,13 +384,10 @@ subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & end do -!!------------------------------------------------------------------------------------------------- -!! 'decomp_vertprofiles' (calc nfixation_prof) is moved to CNEcosystemDynNoLeaching1 -!! 'nfixation_prof' is used to 'calc_nuptake_prof' & 'calc_puptake_prof', which are called in CNAllocation1,2,3 -! call decomp_vertprofiles(bounds, & -! num_soilc, filter_soilc, num_soilp, filter_soilp, & -! soilstate_vars, canopystate_vars, cnstate_vars) -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- +! 'call decomp_vertprofiles()' (calc nfixation_prof) is moved to CNEcosystemDynNoLeaching1 +! 'nfixation_prof' is used in 'calc_nuptake_prof' & 'calc_puptake_prof', which are called in CNAllocation1,2,3 +!------------------------------------------------------------------------------------------------- if (use_nitrif_denitrif) then ! calculate nitrification and denitrification rates call nitrif_denitrif(bounds, & @@ -424,54 +414,12 @@ subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & ! column loop to calculate actual immobilization and decomp rates, following ! resolution of plant/heterotroph competition for mineral N -!!------------------------------------------------------------------------------------------------- -!! comment out c:n,c:p ratios calculation, they have been calculated at the beginning of this subroutine -!!------------------------------------------------------------------------------------------------- - ! 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) -! 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 -! end do -! end do -! else -! do j = 1,nlevdecomp -! do fc = 1,num_soilc -! c = filter_soilc(fc) -! cn_decomp_pools(c,j,l) = initial_cn_ratio(l) -! end do -! end do -! end if -! end do -! -! -! !! calculate c:p ratios of applicable pools -! do l = 1, ndecomp_pools -! if ( floating_cp_ratio_decomp_pools(l) ) then -! do j = 1,nlevdecomp -! do fc = 1,num_soilc -! c = filter_soilc(fc) -! if ( decomp_ppools_vr(c,j,l) > 0._r8 ) then -! cp_decomp_pools(c,j,l) = decomp_cpools_vr(c,j,l) / decomp_ppools_vr(c,j,l) -! end if -! end do -! end do -! else -! do j = 1,nlevdecomp -! do fc = 1,num_soilc -! c = filter_soilc(fc) -! cp_decomp_pools(c,j,l) = initial_cp_ratio(l) -! end do -! end do -! end if -! end do -!!------------------------------------------------------------------------------------------------- - ! upon return from CNAllocation, the fraction of potential immobilization + !------------------------------------------------------------------------------------------------- + ! delete c:n,c:p ratios calculation, they have been calculated at the beginning of this subroutine + !------------------------------------------------------------------------------------------------- + + ! upon return from CNAllocation, the fraction of potential immobilization ! has been set (cnstate_vars%fpi_vr_col). now finish the decomp calculations. ! Only the immobilization steps are limited by fpi_vr (pmnf > 0) ! Also calculate denitrification losses as a simple proportion @@ -631,7 +579,7 @@ subroutine CNDecompAlloc (bounds, num_soilc, filter_soilc, & end subroutine CNDecompAlloc -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & photosyns_vars, canopystate_vars, soilstate_vars, temperature_vars, & @@ -639,16 +587,16 @@ subroutine CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_so carbonstate_vars, carbonflux_vars, c13_carbonflux_vars, c14_carbonflux_vars, & nitrogenstate_vars, nitrogenflux_vars, crop_vars, atm2lnd_vars, & phosphorusstate_vars,phosphorusflux_vars) - !!----------------------------------------------------------------------------- - !! DESCRIPTION: - !! bgc interface & pflotran: - !! (1) Simplified codes of CNDecompAlloc subroutine for coupling with pflotran - !! (2) call CNAllocation3_PlantCNPAlloc - !! (3) calculate net_nmin(c), gross_nmin(c), net_pmin(c), gross_pmin(c) - !!----------------------------------------------------------------------------- + !----------------------------------------------------------------------------- + ! DESCRIPTION: + ! bgc interface & pflotran: + ! (1) Simplified codes of CNDecompAlloc subroutine for coupling with pflotran + ! (2) call CNAllocation3_PlantCNPAlloc + ! (3) calculate net_nmin(c), gross_nmin(c), net_pmin(c), gross_pmin(c) + !----------------------------------------------------------------------------- ! !USES: - use CNAllocationMod , only: CNAllocation3_PlantCNPAlloc !! Phase-3 of CNAllocation + use CNAllocationMod , only: CNAllocation3_PlantCNPAlloc ! Phase-3 of CNAllocation use atm2lndType , only: atm2lnd_type use clm_time_manager, only: get_step_size ! use clm_varpar , only: nlevdecomp, ndecomp_pools @@ -682,7 +630,9 @@ subroutine CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_so ! !LOCAL VARIABLES: integer :: fc, c, j ! indices ! real(r8):: col_plant_ndemand(bounds%begc:bounds%endc) ! column-level vertically-integrated plant N demand (gN/m2/s) - real(r8):: dt ! time step (seconds) + real(r8) :: dt ! time step (seconds) + real(r8) :: smin_nh4_to_plant_vr_loc(bounds%begc:bounds%endc,1:nlevdecomp) + real(r8) :: smin_no3_to_plant_vr_loc(bounds%begc:bounds%endc,1:nlevdecomp) ! For methane code real(r8):: hrsum(bounds%begc:bounds%endc,1:nlevdecomp) !sum of HR (gC/m2/s) @@ -701,12 +651,19 @@ subroutine CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_so fpi_vr => cnstate_vars%fpi_vr_col , & ! Output: [real(r8) (:,:) ] fraction of potential immobilization (no units) + fpi => cnstate_vars%fpi_col , & ! Output: [real(r8) (:) ] fraction of potential immobilization (no units) potential_immob_vr => nitrogenflux_vars%potential_immob_vr_col , & ! Input: actual_immob_vr => nitrogenflux_vars%actual_immob_vr_col , & ! Input: + potential_immob => nitrogenflux_vars%potential_immob_col , & ! Output: [real(r8) (:) ] + actual_immob => nitrogenflux_vars%actual_immob_col , & ! Output: [real(r8) (:) ] fpg => cnstate_vars%fpg_col , & ! Output: [real(r8) (:) ] fraction of potential gpp (no units) sminn_to_plant => nitrogenflux_vars%sminn_to_plant_col , & ! Output: [real(r8) (:) ] col N uptake (gN/m2/s) sminn_to_plant_vr => nitrogenflux_vars%sminn_to_plant_vr_col , & ! Input: [real(r8) (:,:) ] vertically-resolved N uptake (gN/m3/s) + + smin_no3_to_plant_vr => nitrogenflux_vars%smin_no3_to_plant_vr_col , & ! Output: [real(r8) (:,:) ] + smin_nh4_to_plant_vr => nitrogenflux_vars%smin_nh4_to_plant_vr_col , & ! Output: [real(r8) (:,:) ] + col_plant_ndemand_vr => nitrogenflux_vars%plant_ndemand_vr_col , & ! Input: [real(r8) (:) ] col N uptake (gN/m2/s) plant_ndemand_col => nitrogenflux_vars%plant_ndemand_col , & ! Output: [real(r8) (:,:) ] @@ -718,97 +675,121 @@ subroutine CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_so decomp_k => carbonflux_vars%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) hr_vr => carbonflux_vars%hr_vr_col , & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) phr_vr => carbonflux_vars%phr_vr_col , & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) - fphr => carbonflux_vars%fphr_col & ! Output: [real(r8) (:,:) ] fraction of potential SOM + LITTER heterotrophic + fphr => carbonflux_vars%fphr_col , & ! Output: [real(r8) (:,:) ] fraction of potential SOM + LITTER heterotrophic + + smin_no3_vr => nitrogenstate_vars%smin_no3_vr_col , & + smin_nh4_vr => nitrogenstate_vars%smin_nh4_vr_col & ) ! set time steps dt = real( get_step_size(), r8 ) + !------------------------------------------------------------------ + ! 'call decomp_vertprofiles()' moved to EcosystemDynNoLeaching1 + !------------------------------------------------------------------ + smin_nh4_to_plant_vr_loc(:,:) = 0._r8 + smin_no3_to_plant_vr_loc(:,:) = 0._r8 + ! MUST have already updated needed bgc variables from PFLOTRAN by this point -!!------------------------------------------------------------------ -! moved to EcosystemDynNoLeaching1 -! call decomp_vertprofiles(bounds, & -! num_soilc, filter_soilc, num_soilp, filter_soilp, & -! soilstate_vars, canopystate_vars, cnstate_vars) - -!!------------------------------------------------------------------ - if(use_bgc_interface.and.use_pflotran.and.pf_cmode) then - ! fpg calculation - do fc=1,num_soilc - c = filter_soilc(fc) - sminn_to_plant(c) = 0._r8 - !! local var 'col_plant_ndemand' is replaced by fluxtype%plant_ndemand_col -! col_plant_ndemand(c) = 0._r8 - do j = 1, nlevdecomp ! sum up actual and potential column-level N fluxes to plant - sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) -! col_plant_ndemand(c) = col_plant_ndemand(c) + col_plant_ndemand_vr(c,j) * dzsoi_decomp(j) + if(use_clm_interface.and.use_pflotran.and.pf_cmode) then + ! fpg calculation + do fc=1,num_soilc + c = filter_soilc(fc) + sminn_to_plant(c) = 0._r8 + do j = 1, nlevdecomp ! sum up actual and potential column-level N fluxes to plant + sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) + end do + end do + do fc=1,num_soilc + c = filter_soilc(fc) + ! calculate the fraction of potential growth that can be + ! acheived with the N available to plants + if (plant_ndemand_col(c) > 0.0_r8) then + fpg(c) = max(0._r8,sminn_to_plant(c)) / plant_ndemand_col(c) + fpg(c) = min(1._r8, fpg(c)) + else + fpg(c) = 1.0_r8 + end if end do - end do - do fc=1,num_soilc - c = filter_soilc(fc) - ! calculate the fraction of potential growth that can be - ! acheived with the N available to plants - if (plant_ndemand_col(c) > 0.0_r8) then - fpg(c) = max(0._r8,sminn_to_plant(c)) / plant_ndemand_col(c) - fpg(c) = min(1._r8, fpg(c)) - else - fpg(c) = 1.0_r8 - end if - end do - ! fpi calculation - do fc=1,num_soilc - c = filter_soilc(fc) - do j = 1, nlevdecomp - if (potential_immob_vr(c,j) > 0.0_r8) then - fpi_vr(c,j) = actual_immob_vr(c,j) / potential_immob_vr(c,j) + ! fpi calculation + do fc=1,num_soilc + c = filter_soilc(fc) + potential_immob(c) = 0._r8 + actual_immob(c) = 0._r8 + do j = 1, nlevdecomp + if (potential_immob_vr(c,j) > 0.0_r8) then + fpi_vr(c,j) = actual_immob_vr(c,j) / potential_immob_vr(c,j) + potential_immob(c) = potential_immob(c) + potential_immob_vr(c,j)*dzsoi_decomp(j) + actual_immob(c) = actual_immob(c) + actual_immob_vr(c,j)*dzsoi_decomp(j) + else + fpi_vr(c,j) = 0.0_r8 + end if + end do + end do + do fc=1,num_soilc + c = filter_soilc(fc) + if (potential_immob(c) > 0.0_r8) then + fpi(c) = max(0._r8,actual_immob(c)) / potential_immob(c) + fpi(c) = min(1._r8, fpi(c)) else - fpi_vr(c,j) = 0.0_r8 + fpi(c) = 1.0_r8 end if end do - end do - if (use_lch4) then - ! Add up potential hr for methane calculations - ! potential hr is not available from PFLOTRAN, so here temporarily as actual hr - ! in the end, this methane module will be moving into PFLOTRAN as well + if (use_lch4) then + ! Add up potential hr for methane calculations + ! potential hr is not available from PFLOTRAN, so here temporarily as actual hr + ! in the end, this methane module will be moving into PFLOTRAN as well - do j = 1,nlevdecomp - do fc = 1, num_soilc - c = filter_soilc(fc) - phr_vr(c,j) = hr_vr(c,j) + do j = 1,nlevdecomp + do fc = 1, num_soilc + c = filter_soilc(fc) + phr_vr(c,j) = hr_vr(c,j) + end do end do - end do - ! Calculate total fraction of potential HR, for methane code - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - hrsum(c,j) = hr_vr(c,j) + ! Calculate total fraction of potential HR, for methane code + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + hrsum(c,j) = hr_vr(c,j) + end do end do - end do - ! Nitrogen limitation / (low)-moisture limitation - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_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 - else - fphr(c,j) = 1._r8 - end if + ! Nitrogen limitation / (low)-moisture limitation + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_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 + else + fphr(c,j) = 1._r8 + end if + end do + end do + end if + + ! needs to zero CLM-CNP variables NOT available from pflotran bgc coupling + call CNvariables_nan4pf(bounds, num_soilc, filter_soilc, & + num_soilp, filter_soilp, & + carbonflux_vars, nitrogenflux_vars, & + phosphorusstate_vars, phosphorusflux_vars) + + ! save variables before updating + do fc = 1,num_soilc + c = filter_soilc(fc) + do j = 1,nlevdecomp + smin_no3_to_plant_vr_loc(c,j) = smin_no3_to_plant_vr(c,j) + smin_nh4_to_plant_vr_loc(c,j) = smin_nh4_to_plant_vr(c,j) end do end do - end if - ! needs to zero CLM-CN variables NOT available from pflotran bgc coupling - call CNvariables_nan4pf(bounds, num_soilc, filter_soilc, & - carbonflux_vars, nitrogenflux_vars) - end if !!if(use_bgc_interface.and.use_pflotran.and.pf_cmode) + end if !if(use_clm_interface.and.use_pflotran.and.pf_cmode) -!!------------------------------------------------------------------ + !------------------------------------------------------------------ ! phase-3 Allocation for plants call t_startf('CNAllocation - phase-3') call CNAllocation3_PlantCNPAlloc (bounds , & @@ -819,9 +800,31 @@ subroutine CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_so nitrogenstate_vars, nitrogenflux_vars , & phosphorusstate_vars, phosphorusflux_vars) call t_stopf('CNAllocation - phase-3') -!!------------------------------------------------------------------ + !------------------------------------------------------------------ + if(use_pflotran.and.pf_cmode) then + ! in CNAllocation3_PlantCNPAlloc(): + ! smin_nh4_to_plant_vr(c,j), smin_no3_to_plant_vr(c,j), sminn_to_plant_vr(c,j) may be adjusted + ! therefore, we need to update smin_no3_vr(c,j) & smin_nh4_vr(c,j) + do fc = 1,num_soilc + c = filter_soilc(fc) + do j = 1,nlevdecomp + smin_no3_vr(c,j) = smin_no3_vr(c,j) - (smin_no3_to_plant_vr(c,j) - smin_no3_to_plant_vr_loc(c,j))*dt + smin_nh4_vr(c,j) = smin_nh4_vr(c,j) - (smin_nh4_to_plant_vr(c,j) - smin_nh4_to_plant_vr_loc(c,j))*dt + smin_no3_vr(c,j) = max(0._r8, smin_no3_vr(c,j)) + smin_nh4_vr(c,j) = max(0._r8, smin_nh4_vr(c,j)) + end do + end do + end if !(use_pflotran.and.pf_cmode) + !------------------------------------------------------------------ ! vertically integrate net and gross mineralization fluxes for diagnostic output + do fc=1,num_soilc + c = filter_soilc(fc) + net_nmin(c) = 0._r8 + gross_nmin(c) = 0._r8 + net_pmin(c) = 0._r8 + gross_pmin(c) = 0._r8 + end do do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) @@ -835,10 +838,10 @@ subroutine CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_so end associate end subroutine CNDecompAlloc2 -!!------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------------------------- ! - subroutine CNvariables_nan4pf (bounds, num_soilc, filter_soilc, & - carbonflux_vars, nitrogenflux_vars) + subroutine CNvariables_nan4pf (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + carbonflux_vars, nitrogenflux_vars, phosphorusstate_vars,phosphorusflux_vars) ! !DESCRIPTION: ! CN variables not available from PFLOTRAN, some of which may be output and may cause issues, @@ -846,14 +849,20 @@ subroutine CNvariables_nan4pf (bounds, num_soilc, filter_soilc, & ! !USES: + use clm_varctl , only: cnallocate_carbon_only, cnallocate_carbonnitrogen_only use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions ! !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(carbonflux_type) , intent(inout) :: carbonflux_vars type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars + !! add phosphorus -- + type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars + type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars ! !CALLED FROM: ! @@ -881,9 +890,21 @@ subroutine CNvariables_nan4pf (bounds, num_soilc, filter_soilc, & end do - end associate - end subroutine CNvariables_nan4pf + ! pflotran not yet support phosphous cycle + if (cnallocate_carbon_only() .or. & + cnallocate_carbonnitrogen_only() ) then + call phosphorusstate_vars%SetValues ( & + num_patch=num_soilp, filter_patch=filter_soilp, value_patch=0._r8, & + num_column=num_soilc, filter_column=filter_soilc, value_column=0._r8 ) + + call phosphorusflux_vars%SetValues ( & + num_patch=num_soilp, filter_patch=filter_soilp, value_patch=0._r8, & + num_column=num_soilc, filter_column=filter_soilc, value_column=0._r8 ) + end if + + end associate + end subroutine CNvariables_nan4pf -!!------------------------------------------------------------------------------------------------- + !------------------------------------------------------------------------------------------------- end module CNDecompMod diff --git a/components/clm/src/biogeochem/CNEcosystemDynMod.F90 b/components/clm/src/biogeochem/CNEcosystemDynMod.F90 index 048768f2c72a..a5bd39446028 100755 --- a/components/clm/src/biogeochem/CNEcosystemDynMod.F90 +++ b/components/clm/src/biogeochem/CNEcosystemDynMod.F90 @@ -34,7 +34,7 @@ module CNEcosystemDynMod use PhosphorusFluxType , only : phosphorusflux_type use PhosphorusStateType , only : phosphorusstate_type ! bgc interface & pflotran - use clm_varctl , only : use_bgc_interface, use_clm_bgc, use_pflotran, pf_cmode, pf_hmode + use clm_varctl , only : use_clm_interface, use_clm_bgc, use_pflotran, pf_cmode, pf_hmode use CNVerticalProfileMod , only : decomp_vertprofiles use CNAllocationMod , only : nu_com_nfix, nu_com_phosphatase use clm_varctl , only : nu_com @@ -45,11 +45,10 @@ module CNEcosystemDynMod ! ! !PUBLIC MEMBER FUNCTIONS: public :: CNEcosystemDynInit ! Ecosystem dynamics initialization -! public :: CNEcosystemDynNoLeaching ! Ecosystem dynamics: phenology, vegetation, before doing N leaching public :: CNEcosystemDynLeaching ! Ecosystem dynamics: phenology, vegetation, doing N leaching - !!---------------------------------------------------------------------- - !! bgc interface & pflotran: - !! CNEcosystemDynNoLeaching is divided into 2 subroutines: + !---------------------------------------------------------------------- + ! bgc&th interface & pflotran: + ! CNEcosystemDynNoLeaching is divided into 2 subroutines: public :: CNEcosystemDynNoLeaching1 ! Ecosystem dynamics: phenology, vegetation, before doing soil_bgc public :: CNEcosystemDynNoLeaching2 ! Ecosystem dynamics: phenology, vegetation, after doing soil_bgc & before doing N leaching !----------------------------------------------------------------------- @@ -103,8 +102,8 @@ subroutine CNEcosystemDynLeaching(bounds, num_soilc, filter_soilc, & ! ! !USES: use spmdMod , only: masterproc - use PDynamicsMod , only: PWeathering,PAdsorption,PDesorption,POcclusion - use PDynamicsMod , only: PBiochemMin,PLeaching + use PDynamicsMod , only: PWeathering,PAdsorption,PDesorption,POcclusion + use PDynamicsMod , only: PBiochemMin,PLeaching use CNNDynamicsMod , only: CNNLeaching use CNNStateUpdate3Mod , only: NStateUpdate3 use PStateUpdate3Mod , only: PStateUpdate3 @@ -145,7 +144,7 @@ subroutine CNEcosystemDynLeaching(bounds, num_soilc, filter_soilc, & ! only do if ed is off if( .not. use_ed) then - if(.not.(use_pflotran.and.pf_cmode)) then + !if(.not.(use_pflotran.and.pf_cmode)) then call t_startf('PWeathering') call PWeathering(num_soilc, filter_soilc, & cnstate_vars,phosphorusstate_vars,phosphorusflux_vars) @@ -178,18 +177,18 @@ subroutine CNEcosystemDynLeaching(bounds, num_soilc, filter_soilc, & cnstate_vars,nitrogenstate_vars,phosphorusstate_vars,phosphorusflux_vars) call t_stopf('PBiochemMin') end if - end if + !end if - !----------------------------------------------------------------------- - ! pflotran: when both 'pf-bgc' and 'pf-h' on, no need to call CLM-CN's N leaching module - if (.not. (pf_cmode .and. pf_hmode)) then - call CNNLeaching(bounds, num_soilc, filter_soilc, & + !----------------------------------------------------------------------- + ! pflotran: when both 'pf-bgc' and 'pf-h' on, no need to call CLM-CN's N leaching module + if (.not. (pf_cmode .and. pf_hmode)) then + call CNNLeaching(bounds, num_soilc, filter_soilc, & waterstate_vars, waterflux_vars, nitrogenstate_vars, nitrogenflux_vars) - call PLeaching(bounds, num_soilc, filter_soilc, & + call PLeaching(bounds, num_soilc, filter_soilc, & waterstate_vars, waterflux_vars, phosphorusstate_vars, phosphorusflux_vars) - end if !(.not. (pf_cmode .and. pf_hmode)) - !----------------------------------------------------------------------- + end if !(.not. (pf_cmode .and. pf_hmode)) + !----------------------------------------------------------------------- call t_startf('CNUpdate3') @@ -231,7 +230,7 @@ subroutine CNEcosystemDynLeaching(bounds, num_soilc, filter_soilc, & end subroutine CNEcosystemDynLeaching -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine CNEcosystemDynNoLeaching1(bounds, & num_soilc, filter_soilc, & num_soilp, filter_soilp, & @@ -243,11 +242,11 @@ subroutine CNEcosystemDynNoLeaching1(bounds, & canopystate_vars, soilstate_vars, temperature_vars, crop_vars, & ch4_vars, photosyns_vars, & phosphorusflux_vars,phosphorusstate_vars) - !!------------------------------------------------------------------- - !! bgc interface - !! Phase-1 of CNEcosystemDynNoLeaching - !! call CNAllocation1_PlantNPDemand before soil_bgc - !!------------------------------------------------------------------- + !------------------------------------------------------------------- + ! bgc interface + ! Phase-1 of CNEcosystemDynNoLeaching + ! call CNAllocation1_PlantNPDemand before soil_bgc + !------------------------------------------------------------------- ! !DESCRIPTION: ! The core CN code is executed here. Calculates fluxes for maintenance @@ -280,7 +279,7 @@ subroutine CNEcosystemDynNoLeaching1(bounds, & use CropType , only: crop_type ! use dynHarvestMod , only: CNHarvest use clm_varpar , only: crop_prog - use CNAllocationMod , only: CNAllocation1_PlantNPDemand !! Phase-1 of CNAllocation + use CNAllocationMod , only: CNAllocation1_PlantNPDemand ! Phase-1 of CNAllocation ! use CNDecompMod , only: CNDecompAlloc2 use CNNDynamicsMod , only: CNNLeaching use PDynamicsMod , only: PLeaching @@ -429,25 +428,25 @@ subroutine CNEcosystemDynNoLeaching1(bounds, & atm2lnd_vars, phosphorusflux_vars) call t_stopf('PDeposition') -!!------------------------------------------------------------------------------------------------- -!! 'decomp_rate_constants' is moved to CNDecompAlloc -! if (use_century_decomp) then -! call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & -! canopystate_vars, soilstate_vars, temperature_vars, ch4_vars, carbonflux_vars) -! else -! call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc, & -! canopystate_vars, soilstate_vars, temperature_vars, ch4_vars, carbonflux_vars) -! end if - -!!------------------------------------------------------------------------------------------------- -!! 'decomp_vertprofiles' (calc nfixation_prof) is moved from CNDecompAlloc: -!! 'nfixation_prof' is used to 'calc_nuptake_prof' & 'calc_puptake_prof', which are called in CNAllocation1,2,3 + !------------------------------------------------------------------------------------------------- + ! plfotran: 'decomp_rate_constants' must be calculated before entering "clm_interface" + if (use_century_decomp) then + call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & + canopystate_vars, soilstate_vars, temperature_vars, ch4_vars, carbonflux_vars) + else + call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc, & + canopystate_vars, soilstate_vars, temperature_vars, ch4_vars, carbonflux_vars, cnstate_vars) + end if + + !------------------------------------------------------------------------------------------------- + ! 'decomp_vertprofiles' (calc nfixation_prof) is moved from CNDecompAlloc: + ! 'nfixation_prof' is used to 'calc_nuptake_prof' & 'calc_puptake_prof', which are called in CNAllocation1,2,3 call decomp_vertprofiles(bounds, & num_soilc, filter_soilc, num_soilp, filter_soilp, & soilstate_vars, canopystate_vars, cnstate_vars) -!!------------------------------------------------------------------------------------------------- - !! CNAllocation1 is always called (w/ or w/o use_bgc_interface) - !! pflotran: call 'CNAllocation1' to obtain potential N demand for support initial GPP + !------------------------------------------------------------------------------------------------- + ! CNAllocation1 is always called (w/ or w/o use_clm_interface) + ! pflotran: call 'CNAllocation1' to obtain potential N demand for support initial GPP call t_startf('CNAllocation - phase-1') call CNAllocation1_PlantNPDemand (bounds , & num_soilc, filter_soilc, num_soilp, filter_soilp , & @@ -462,7 +461,7 @@ subroutine CNEcosystemDynNoLeaching1(bounds, & end subroutine CNEcosystemDynNoLeaching1 -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine CNEcosystemDynNoLeaching2(bounds, & num_soilc, filter_soilc, & num_soilp, filter_soilp, num_pcropp, filter_pcropp, doalb, & @@ -474,11 +473,11 @@ subroutine CNEcosystemDynNoLeaching2(bounds, & canopystate_vars, soilstate_vars, temperature_vars, crop_vars, ch4_vars, & dgvs_vars, photosyns_vars, soilhydrology_vars, energyflux_vars, & phosphorusflux_vars,phosphorusstate_vars) - !!------------------------------------------------------------------- - !! bgc interface - !! Phase-2 of CNEcosystemDynNoLeaching - !! call CNDecompAlloc (w/o bgc_interface) & CNDecompAlloc2 - !!------------------------------------------------------------------- + !------------------------------------------------------------------- + ! bgc interface + ! Phase-2 of CNEcosystemDynNoLeaching + ! call CNDecompAlloc (w/o bgc_interface) & CNDecompAlloc2 + !------------------------------------------------------------------- ! !DESCRIPTION: ! The core CN code is executed here. Calculates fluxes for maintenance @@ -515,7 +514,7 @@ subroutine CNEcosystemDynNoLeaching2(bounds, & ! use CNAllocationMod , only: cnallocation use CNDecompMod , only: CNDecompAlloc - use CNDecompMod , only: CNDecompAlloc2 !!after CNDecompAlloc + use CNDecompMod , only: CNDecompAlloc2 !after CNDecompAlloc ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -559,9 +558,9 @@ subroutine CNEcosystemDynNoLeaching2(bounds, & call t_startf('CNDecompAlloc') !---------------------------------------------------------------- - if(.not.use_bgc_interface) then - !! directly run clm-bgc - !! if (use_bgc_interface & use_clm_bgc), then CNDecomAlloc is called in clm_driver + if(.not.use_clm_interface) then + ! directly run clm-bgc + ! if (use_clm_interface & use_clm_bgc), then CNDecomAlloc is called in clm_driver call CNDecompAlloc (bounds, num_soilc, filter_soilc, & num_soilp, filter_soilp, & canopystate_vars, soilstate_vars, & @@ -570,11 +569,11 @@ subroutine CNEcosystemDynNoLeaching2(bounds, & carbonstate_vars, carbonflux_vars, & nitrogenstate_vars, nitrogenflux_vars, & phosphorusstate_vars,phosphorusflux_vars) - end if !!if(.not.use_bgc_interface) + end if !if(.not.use_clm_interface) !---------------------------------------------------------------- - !! CNDecompAlloc2 is called by both clm-bgc & pflotran - !! pflotran: call 'CNDecompAlloc2' to calculate some diagnostic variables and 'fpg' for plant N uptake - !! pflotran & clm-bgc : 'CNAllocation3_AG' and vertically integrate net and gross mineralization fluxes + ! CNDecompAlloc2 is called by both clm-bgc & pflotran + ! pflotran: call 'CNDecompAlloc2' to calculate some diagnostic variables and 'fpg' for plant N uptake + ! pflotran & clm-bgc : 'CNAllocation3_AG' and vertically integrate net and gross mineralization fluxes call CNDecompAlloc2 (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & photosyns_vars, canopystate_vars, soilstate_vars, temperature_vars, & waterstate_vars, cnstate_vars, ch4_vars, & diff --git a/components/clm/src/biogeochem/CNNStateUpdate1Mod.F90 b/components/clm/src/biogeochem/CNNStateUpdate1Mod.F90 index b9257b82eaee..0d78d3ea02cc 100644 --- a/components/clm/src/biogeochem/CNNStateUpdate1Mod.F90 +++ b/components/clm/src/biogeochem/CNNStateUpdate1Mod.F90 @@ -18,7 +18,7 @@ module CNNStateUpdate1Mod use CNNitrogenStateType , only : nitrogenstate_type use VegetationType , only : veg_pp use tracer_varcon , only : is_active_betr_bgc - !! bgc interface & pflotran: + ! bgc interface & pflotran: use clm_varctl , only : use_pflotran, pf_cmode ! implicit none diff --git a/components/clm/src/biogeochem/CNNStateUpdate2Mod.F90 b/components/clm/src/biogeochem/CNNStateUpdate2Mod.F90 index 51f7e1feccc9..92a2d377d05d 100644 --- a/components/clm/src/biogeochem/CNNStateUpdate2Mod.F90 +++ b/components/clm/src/biogeochem/CNNStateUpdate2Mod.F90 @@ -14,7 +14,7 @@ module CNNStateUpdate2Mod use CNNitrogenFLuxType , only : nitrogenflux_type use VegetationType , only : veg_pp use pftvarcon , only : npcropmin - !! bgc interface & pflotran: + ! bgc interface & pflotran: use clm_varctl , only : use_pflotran, pf_cmode ! implicit none diff --git a/components/clm/src/biogeochem/CNNStateUpdate3Mod.F90 b/components/clm/src/biogeochem/CNNStateUpdate3Mod.F90 index db4450e38f26..5619dd286cc1 100644 --- a/components/clm/src/biogeochem/CNNStateUpdate3Mod.F90 +++ b/components/clm/src/biogeochem/CNNStateUpdate3Mod.F90 @@ -13,7 +13,7 @@ module CNNStateUpdate3Mod use clm_varpar , only : i_cwd, i_met_lit, i_cel_lit, i_lig_lit use CNNitrogenStateType , only : nitrogenstate_type use CNNitrogenFLuxType , only : nitrogenflux_type - !! bgc interface & pflotran: + ! bgc interface & pflotran: use clm_varctl , only : use_pflotran, pf_cmode ! implicit none @@ -74,16 +74,21 @@ subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & ( nf%smin_no3_leached_vr_col(c,j) + nf%smin_no3_runoff_vr_col(c,j) ) * dt, 0._r8) ns%sminn_vr_col(c,j) = ns%smin_no3_vr_col(c,j) + ns%smin_nh4_vr_col(c,j) + if (use_pflotran .and. pf_cmode) then + ns%sminn_vr_col(c,j) = ns%sminn_vr_col(c,j) + ns%smin_nh4sorb_vr_col(c,j) + end if end if - ! column level nitrogen fluxes from fire - ! pft-level wood to column-level CWD (uncombusted wood) - ns%decomp_npools_vr_col(c,j,i_cwd) = ns%decomp_npools_vr_col(c,j,i_cwd) + nf%fire_mortality_n_to_cwdn_col(c,j) * dt - - ! pft-level wood to column-level litter (uncombusted wood) - ns%decomp_npools_vr_col(c,j,i_met_lit) = ns%decomp_npools_vr_col(c,j,i_met_lit) + nf%m_n_to_litr_met_fire_col(c,j)* dt - ns%decomp_npools_vr_col(c,j,i_cel_lit) = ns%decomp_npools_vr_col(c,j,i_cel_lit) + nf%m_n_to_litr_cel_fire_col(c,j)* dt - ns%decomp_npools_vr_col(c,j,i_lig_lit) = ns%decomp_npools_vr_col(c,j,i_lig_lit) + nf%m_n_to_litr_lig_fire_col(c,j)* dt + if (.not.(use_pflotran .and. pf_cmode)) then + ! column level nitrogen fluxes from fire + ! pft-level wood to column-level CWD (uncombusted wood) + ns%decomp_npools_vr_col(c,j,i_cwd) = ns%decomp_npools_vr_col(c,j,i_cwd) + nf%fire_mortality_n_to_cwdn_col(c,j) * dt + + ! pft-level wood to column-level litter (uncombusted wood) + ns%decomp_npools_vr_col(c,j,i_met_lit) = ns%decomp_npools_vr_col(c,j,i_met_lit) + nf%m_n_to_litr_met_fire_col(c,j)* dt + ns%decomp_npools_vr_col(c,j,i_cel_lit) = ns%decomp_npools_vr_col(c,j,i_cel_lit) + nf%m_n_to_litr_cel_fire_col(c,j)* dt + ns%decomp_npools_vr_col(c,j,i_lig_lit) = ns%decomp_npools_vr_col(c,j,i_lig_lit) + nf%m_n_to_litr_lig_fire_col(c,j)* dt + end if !(.not.(use_pflotran .and. pf_cmode)) end do ! end of column loop end do diff --git a/components/clm/src/biogeochem/CNNitrogenFluxType.F90 b/components/clm/src/biogeochem/CNNitrogenFluxType.F90 index ea7dadecdfca..c954cdb16efb 100644 --- a/components/clm/src/biogeochem/CNNitrogenFluxType.F90 +++ b/components/clm/src/biogeochem/CNNitrogenFluxType.F90 @@ -13,8 +13,8 @@ module CNNitrogenFluxType use LandunitType , only : lun_pp use ColumnType , only : col_pp use VegetationType , only : veg_pp - !! bgc interface & pflotran: - use clm_varctl , only : use_bgc_interface, use_pflotran, pf_cmode, pf_hmode, use_vertsoilc + ! bgc interface & pflotran: + use clm_varctl , only : use_clm_interface, use_pflotran, pf_cmode, pf_hmode, use_vertsoilc ! ! !PUBLIC TYPES: implicit none @@ -339,10 +339,10 @@ module CNNitrogenFluxType real(r8), pointer :: avail_retransn_patch (:) ! N flux available from retranslocation pool (gN/m2/s) real(r8), pointer :: plant_nalloc_patch (:) ! total allocated N flux (gN/m2/s) - ! bgc interfacepflotran + ! bgc interface/pflotran !------------------------------------------------------------------------ real(r8), pointer :: plant_ndemand_col (:) ! col N flux required to support initial GPP (gN/m2/s) - !! pflotran + ! pflotran real(r8), pointer :: plant_ndemand_vr_col (:,:) ! col vertically-resolved N flux required to support initial GPP (gN/m3/s) real(r8), pointer :: f_ngas_decomp_vr_col (:,:) ! col vertically-resolved N emission from excess mineral N pool due to mineralization (gN/m3/s) @@ -361,8 +361,8 @@ module CNNitrogenFluxType real(r8), pointer :: externaln_to_decomp_npools_col (:,:,:) ! col net N fluxes associated with litter/som-adding/removal to decomp pools (gN/m3/s) ! (sum of all external N additions and removals, excluding decomposition/hr). real(r8), pointer :: externaln_to_decomp_delta_col (:) ! col summarized net N i/o changes associated with litter/som-adding/removal to decomp pools btw time-step (gN/m2) - real(r8), pointer :: no3_net_transport_vr_col (:,:) ! col net NO3 transport associated with runoff/leaching (gN/m3/s) - real(r8), pointer :: no3_net_transport_delta_col (:) ! col summarized net change of column-level N leaching to NO3 bwtn time-step (for balance checking) (gN/m2) + real(r8), pointer :: no3_net_transport_vr_col (:,:) ! col net NO3 transport associated with runoff/leaching/diffusion (gN/m3/s) + real(r8), pointer :: nh4_net_transport_vr_col (:,:) ! col net NH4 transport associated with runoff/leaching/diffusion (gN/m3/s) !------------------------------------------------------------------------ real(r8), pointer :: smin_no3_to_plant_patch (:) ! pft level plant uptake of soil NO3 (gN/m2/s) BGC mode @@ -757,7 +757,7 @@ subroutine InitAllocate(this, bounds) allocate(this%externaln_to_decomp_npools_col (begc:endc, 1:nlevdecomp_full, 1:ndecomp_pools)); this%externaln_to_decomp_npools_col (:,:,:) = spval allocate(this%externaln_to_decomp_delta_col (begc:endc)) ; this%externaln_to_decomp_delta_col (:) = spval allocate(this%no3_net_transport_vr_col (begc:endc, 1:nlevdecomp_full)) ; this%no3_net_transport_vr_col (:,:) = spval - allocate(this%no3_net_transport_delta_col (begc:endc)) ; this%no3_net_transport_delta_col (:) = spval + allocate(this%nh4_net_transport_vr_col (begc:endc, 1:nlevdecomp_full)) ; this%nh4_net_transport_vr_col (:,:) = spval !------------------------------------------------------------------------ allocate(this%smin_no3_to_plant_patch (begp:endp)) ; this%smin_no3_to_plant_patch (:) = nan @@ -1464,14 +1464,14 @@ subroutine InitHistory(this, bounds) endif end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then this%f_nit_col(begc:endc) = spval call hist_addfld1d (fname='F_NIT', units='gN/m^2/s', & avgflag='A', long_name='nitrification flux', & ptr_col=this%f_nit_col) end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then this%f_denit_col(begc:endc) = spval call hist_addfld1d (fname='F_DENIT', units='gN/m^2/s', & avgflag='A', long_name='denitrification flux', & @@ -1492,28 +1492,30 @@ subroutine InitHistory(this, bounds) ptr_col=this%pot_f_denit_col) end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_leached_col(begc:endc) = spval call hist_addfld1d (fname='SMIN_NO3_LEACHED', units='gN/m^2/s', & avgflag='A', long_name='soil NO3 pool loss to leaching', & ptr_col=this%smin_no3_leached_col) end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_runoff_col(begc:endc) = spval call hist_addfld1d (fname='SMIN_NO3_RUNOFF', units='gN/m^2/s', & avgflag='A', long_name='soil NO3 pool loss to runoff', & ptr_col=this%smin_no3_runoff_col) end if - if (use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%f_nit_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='F_NIT'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='nitrification flux', & ptr_col=this%f_nit_vr_col) end if - if (use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%f_denit_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='F_DENIT'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='denitrification flux', & @@ -1534,14 +1536,16 @@ subroutine InitHistory(this, bounds) ptr_col=this%pot_f_denit_vr_col, default='inactive') end if - if (use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_leached_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SMIN_NO3_LEACHED'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='soil NO3 pool loss to leaching', & ptr_col=this%smin_no3_leached_vr_col, default='inactive') end if - if (use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_runoff_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SMIN_NO3_RUNOFF'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='soil NO3 pool loss to runoff', & @@ -1555,28 +1559,32 @@ subroutine InitHistory(this, bounds) ptr_col=this%n2_n2o_ratio_denit_vr_col, default='inactive') end if - if (use_nitrif_denitrif) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%actual_immob_no3_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='ACTUAL_IMMOB_NO3', units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='immobilization of NO3', & ptr_col=this%actual_immob_no3_vr_col, default='inactive') end if - if (use_nitrif_denitrif) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%actual_immob_nh4_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='ACTUAL_IMMOB_NH4', units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='immobilization of NH4', & ptr_col=this%actual_immob_nh4_vr_col, default='inactive') end if - if (use_nitrif_denitrif) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_to_plant_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SMIN_NO3_TO_PLANT', units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='plant uptake of NO3', & ptr_col=this%smin_no3_to_plant_vr_col, default='inactive') end if - if (use_nitrif_denitrif) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%smin_nh4_to_plant_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SMIN_NH4_TO_PLANT', units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='plant uptake of NH4', & @@ -1703,21 +1711,24 @@ subroutine InitHistory(this, bounds) end if - if ( use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%potential_immob_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='POTENTIAL_IMMOB'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='potential N immobilization', & ptr_col=this%potential_immob_vr_col, default='inactive') end if - if ( use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%actual_immob_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='ACTUAL_IMMOB'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='actual N immobilization', & ptr_col=this%actual_immob_vr_col, default='inactive') end if - if ( use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%sminn_to_plant_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SMINN_TO_PLANT'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='plant uptake of soil mineral N', & @@ -1725,21 +1736,24 @@ subroutine InitHistory(this, bounds) end if - if ( use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%supplement_to_sminn_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SUPPLEMENT_TO_SMINN'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='supplemental N supply', & ptr_col=this%supplement_to_sminn_vr_col, default='inactive') end if - if ( use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%gross_nmin_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='GROSS_NMIN'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='gross rate of N mineralization', & ptr_col=this%gross_nmin_vr_col, default='inactive') end if - if ( use_nitrif_denitrif .and. nlevdecomp_full > 1 ) then + if ((use_nitrif_denitrif .and. nlevdecomp_full > 1) & + .or. (use_pflotran .and. pf_cmode)) then this%net_nmin_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='NET_NMIN'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='net rate of N mineralization', & @@ -1902,8 +1916,8 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='total allocated N flux', & ptr_patch=this%plant_nalloc_patch, default='inactive') - !!----------------------------------------------------------- - !! bgc interface & pflotran + !----------------------------------------------------------- + ! bgc interface & pflotran this%plant_ndemand_col(begc:endc) = spval call hist_addfld1d (fname='PLANT_NDEMAND_COL', units='gN/m^2/s', & avgflag='A', long_name='N flux required to support initial GPP', & @@ -1944,7 +1958,7 @@ subroutine InitHistory(this, bounds) call hist_addfld1d (fname='SMIN_NO3_TO_PLANT', units='gN/m^2/s', & avgflag='A', long_name='plant uptake of NO3', & ptr_col=this%smin_no3_to_plant_col, default='inactive') - !!--------------------------------------------------------------- + !--------------------------------------------------------------- this%f_ngas_decomp_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='F_NGAS_DECOMP'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='n gas emission from excess mineral N pool due to mineralization', & @@ -1974,8 +1988,8 @@ subroutine InitHistory(this, bounds) call hist_addfld_decomp (fname='PLANT_NDEMAND'//trim(vr_suffix), units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name='plant N demand distribution via roots', & ptr_col=this%plant_ndemand_vr_col, default='inactive') - end if !! if (use_pflotran.and.pf_cmode) - !!----------------------------------------------------------- + end if ! if (use_pflotran.and.pf_cmode) + !----------------------------------------------------------- end subroutine InitHistory !----------------------------------------------------------------------- @@ -2147,7 +2161,7 @@ subroutine Restart (this, bounds, ncid, flag ) interpinic_flag='interp', readvar=readvar, data=this%grainn_storage_to_xfer_patch) end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then ! pot_f_nit_vr if (use_vertsoilc) then ptr2d => this%pot_f_nit_vr_col(:,:) @@ -2167,7 +2181,7 @@ subroutine Restart (this, bounds, ncid, flag ) end if end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then ! f_nit_vr if (use_vertsoilc) then ptr2d => this%f_nit_vr_col(:,:) @@ -2251,7 +2265,7 @@ subroutine Restart (this, bounds, ncid, flag ) end if end if - end if !! if (use_pflotran .and. pf_cmode) + end if ! if (use_pflotran .and. pf_cmode) !------------------------------------------------------------------------ end subroutine Restart @@ -2560,7 +2574,7 @@ subroutine SetValues ( this, & this%fire_nloss_col(i) = value_column this%wood_harvestn_col(i) = value_column - !! bgc-interface + ! bgc-interface this%plant_ndemand_col(i) = value_column end do @@ -2639,6 +2653,9 @@ subroutine SetValues ( this, & if ( this%no3_net_transport_vr_col(i,j) == spval ) then this%no3_net_transport_vr_col(i,j) = value_column end if + if ( this%nh4_net_transport_vr_col(i,j) == spval ) then + this%nh4_net_transport_vr_col(i,j) = value_column + end if end do end do @@ -2648,9 +2665,6 @@ subroutine SetValues ( this, & if ( this%externaln_to_decomp_delta_col(i) == spval ) then this%externaln_to_decomp_delta_col(i) = value_column end if - if ( this%no3_net_transport_delta_col(i) == spval ) then - this%no3_net_transport_delta_col(i) = value_column - end if end do !------------------------------------------------------------------------ @@ -2699,6 +2713,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil use subgridAveMod , only: p2c use pftvarcon , only : npcropmin use tracer_varcon , only: is_active_betr_bgc + use clm_varpar , only: nlevdecomp_full ! ! !ARGUMENTS: class (nitrogenflux_type) :: this @@ -2712,6 +2727,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil integer :: c,p,j,k,l ! indices integer :: fp,fc ! lake filter indices real(r8) :: maxdepth ! depth to integrate soil variables + integer :: nlev !----------------------------------------------------------------------- do fp = 1,num_soilp @@ -2764,6 +2780,9 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%wood_harvestn_patch(bounds%begp:bounds%endp), & this%wood_harvestn_col(bounds%begc:bounds%endc)) + nlev = nlevdecomp + if (use_pflotran .and. pf_cmode) nlev = nlevdecomp_full + do fc = 1,num_soilc c = filter_soilc(fc) this%denit_col(c) = 0._r8 @@ -2780,7 +2799,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil !soil mineral N fluxes associated with decomposition cascade do k = 1, ndecomp_cascade_transitions - do j = 1,nlevdecomp + do j = 1,nlev do fc = 1,num_soilc c = filter_soilc(fc) @@ -2798,7 +2817,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil if (.not. use_nitrif_denitrif) then ! vertically integrate each denitrification flux do l = 1, ndecomp_cascade_transitions - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%sminn_to_denit_decomp_cascade_col(c,l) = & @@ -2809,7 +2828,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil end do ! vertically integrate bulk denitrification and leaching flux - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%sminn_to_denit_excess_col(c) = & @@ -2842,7 +2861,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil else ! vertically integrate NO3 NH4 N2O fluxes and pools - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) @@ -2893,7 +2912,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! vertically integrate column-level fire N losses do k = 1, ndecomp_pools - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%m_decomp_npools_to_fire_col(c,k) = & @@ -2918,7 +2937,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil end do ! supplementary N supplement_to_sminn - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%supplement_to_sminn_col(c) = & @@ -2960,7 +2979,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%decomp_npools_leached_col(c,l) = 0._r8 end do - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%decomp_npools_leached_col(c,l) = & @@ -2986,7 +3005,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%smin_nh4_to_plant_col(c) = 0._r8 this%plant_to_litter_nflux(c) = 0._r8 this%plant_to_cwd_nflux(c) = 0._r8 - do j = 1, nlevdecomp + do j = 1, nlev this%plant_to_litter_nflux(c) = & this%plant_to_litter_nflux(c) + & this%phenology_n_to_litr_met_n_col(c,j)* dzsoi_decomp(j) + & @@ -3008,7 +3027,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil if (use_nitrif_denitrif) then do fc = 1,num_soilc c = filter_soilc(fc) - do j = 1, nlevdecomp + do j = 1, nlev this%smin_no3_to_plant_col(c)= this%smin_no3_to_plant_col(c) + & this%smin_no3_to_plant_vr_col(c,j) * dzsoi_decomp(j) this%smin_nh4_to_plant_col(c)= this%smin_nh4_to_plant_col(c) + & @@ -3019,23 +3038,23 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! bgc interface & pflotran !---------------------------------------------------------------- - if (use_bgc_interface) then + if (use_clm_interface .and. pf_cmode) then call NSummary_interface(this, bounds, num_soilc, filter_soilc) end if !---------------------------------------------------------------- end subroutine Summary -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- ! !INTERFACE: subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) ! ! !DESCRIPTION: -!! bgc interface & pflotran: -! On the radiation time step, perform olumn-level nitrogen +! bgc interface & pflotran: +! On the radiation time step, perform column-level nitrogen ! summary calculations, which mainly from PFLOTRAN bgc coupling ! ! !USES: - use clm_varpar , only: nlevdecomp, ndecomp_pools + use clm_varpar , only: nlevdecomp_full, ndecomp_pools use clm_varpar , only: i_met_lit, i_cel_lit, i_lig_lit, i_cwd use clm_time_manager , only : get_step_size @@ -3049,10 +3068,8 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) integer, intent(in) :: filter_soilc(:) ! filter for soil columns ! ! !CALLED FROM: -! subroutine NSummary (if pflotran coupled) +! subroutine NSummary (if pflotran coupled) vertically from 1 to 'nlevdecomp_full' (not 'nlevdecomp') ! -! !REVISION HISTORY: -!!06/17/2015: modified by Gangsheng Wang ! ! !LOCAL VARIABLES: integer :: c,j, l ! indices @@ -3063,12 +3080,14 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) dtime = real( get_step_size(), r8 ) if (use_pflotran .and. pf_cmode) then -! nitrification-denitrification rates (not yet passing out from PF, but will) + ! nitrification-denitrification rates (not yet passing out from PF, but will) + !------------------------------------------------ + ! NOT used currently do fc = 1,num_soilc c = filter_soilc(fc) this%f_nit_col(c) = 0._r8 this%f_denit_col(c) = 0._r8 - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full this%f_nit_vr_col(c,j) = 0._r8 this%f_nit_col(c) = this%f_nit_col(c) + & this%f_nit_vr_col(c,j)*dzsoi_decomp(j) @@ -3081,8 +3100,9 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) this%denit_col(c) = this%f_denit_col(c) end do + !end------------------------------------------------ - ! the following are from pflotran bgc + ! the following are from pflotran bgc, and vertically down to 'nlevdecomp_full' do fc = 1,num_soilc c = filter_soilc(fc) this%f_n2_soil_col(c) = 0._r8 @@ -3092,8 +3112,9 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) this%f_ngas_denit_col(c) = 0._r8 this%smin_no3_leached_col(c) = 0._r8 this%smin_no3_runoff_col(c) = 0._r8 + this%sminn_leached_col(c) = 0._r8 - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full ! all N2/N2O gas exchange between atm. and soil (i.e., dissolving - degassing) this%f_n2_soil_col(c) = this%f_n2_soil_col(c) + & @@ -3110,27 +3131,34 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) this%f_ngas_denit_col(c) = this%f_ngas_denit_col(c) + & this%f_ngas_denit_vr_col(c,j)*dzsoi_decomp(j) - ! leaching/runoff flux (if not hydroloy-coupled, from CLM-CN; otherwise from PF) + ! leaching/runoff fluxes summed vertically + ! (1) if not hydroloy-coupled, advection from CLM-CN, plus diffusion from PF + ! (2) if hydrology-coupled, all from PF (i.e. 'no3_net_transport_vr_col'); this%smin_no3_leached_col(c) = this%smin_no3_leached_col(c) + & + this%no3_net_transport_vr_col(c,j) * dzsoi_decomp(j) + + if(.not. pf_hmode) then ! this is from CLM-CN's leaching subroutine + this%smin_no3_leached_col(c) = this%smin_no3_leached_col(c) + & this%smin_no3_leached_vr_col(c,j) * dzsoi_decomp(j) - this%smin_no3_runoff_col(c) = this%smin_no3_runoff_col(c) + & + this%smin_no3_runoff_col(c) = this%smin_no3_runoff_col(c) + & this%smin_no3_runoff_vr_col(c,j) * dzsoi_decomp(j) + endif - ! assign all no3-N leaching/runoff to all mineral-N + ! assign all no3-N leaching/runof,including diffusion from PF, to all mineral-N this%sminn_leached_vr_col(c,j) = this%smin_no3_leached_vr_col(c,j) + & - this%smin_no3_runoff_vr_col(c,j) + this%smin_no3_runoff_vr_col(c,j) + & + this%nh4_net_transport_vr_col(c,j) * dzsoi_decomp(j) - end do + this%sminn_leached_col(c) = this%sminn_leached_col(c) + & + this%sminn_leached_vr_col(c,j)*dzsoi_decomp(j) + + end do !j = 1, nlevdecomp_full ! for balance-checking this%denit_col(c) = this%f_ngas_denit_col(c) this%f_n2o_nit_col(c) = this%f_ngas_decomp_col(c) + this%f_ngas_nitri_col(c) - ! assign all no3-N leaching/runoff to all mineral-N - this%sminn_leached_col(c) = this%smin_no3_leached_col(c) + this%smin_no3_runoff_col(c) - - end do - end if !! if (use_pflotran .and. pf_cmode) + end do !fc = 1,num_soilc ! summarize at column-level vertically-resolved littering/removal for PFLOTRAN bgc input needs @@ -3140,32 +3168,25 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) do fc = 1,num_soilc c = filter_soilc(fc) this%externaln_to_decomp_delta_col(c) = 0._r8 - this%no3_net_transport_delta_col(c) = 0._r8 - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full do l = 1, ndecomp_pools this%externaln_to_decomp_delta_col(c) = & this%externaln_to_decomp_delta_col(c) + & this%externaln_to_decomp_npools_col(c,j,l)*dzsoi_decomp(j) end do - ! NO3 leaching/runoff at previous time-step, which may be as source by PFLOTRAN - this%no3_net_transport_delta_col(c) = & - this%no3_net_transport_delta_col(c) + & - this%no3_net_transport_vr_col(c,j)*dzsoi_decomp(j) - end do end do - ! do the initialization for the following 2 variables here. + ! do the initialization for the following variable here. ! DON'T do so in the beginning of CLM-CN time-step (otherwise the above saved will not work) this%externaln_to_decomp_npools_col(:,:,:) = 0._r8 - this%no3_net_transport_vr_col(:,:) = 0._r8 ! add up all vertically-resolved addition/removal rates (gC/m3/s) of decomp_pools - do l = 1, ndecomp_pools - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_soilc + c = filter_soilc(fc) + do j = 1, nlevdecomp_full + do l = 1, ndecomp_pools ! for litter C pools if (l==i_met_lit) then @@ -3174,9 +3195,8 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) + this%phenology_n_to_litr_met_n_col(c,j) & + this%dwt_frootn_to_litr_met_n_col(c,j) & + this%gap_mortality_n_to_litr_met_n_col(c,j) & - + this%harvest_n_to_litr_met_n_col(c,j) !!& -! + this%m_n_to_litr_met_fire_col(c,j) & -! - this%m_decomp_npools_to_fire_vr_col(c,j,l) + + this%harvest_n_to_litr_met_n_col(c,j) & + + this%m_n_to_litr_met_fire_col(c,j) elseif (l==i_cel_lit) then this%externaln_to_decomp_npools_col(c,j,l) = & @@ -3184,9 +3204,8 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) + this%phenology_n_to_litr_cel_n_col(c,j) & + this%dwt_frootn_to_litr_cel_n_col(c,j) & + this%gap_mortality_n_to_litr_cel_n_col(c,j) & - + this%harvest_n_to_litr_cel_n_col(c,j) !!& -! + this%m_n_to_litr_cel_fire_col(c,j) & -! - this%m_decomp_npools_to_fire_vr_col(c,j,l) + + this%harvest_n_to_litr_cel_n_col(c,j) & + + this%m_n_to_litr_cel_fire_col(c,j) elseif (l==i_lig_lit) then this%externaln_to_decomp_npools_col(c,j,l) = & @@ -3194,9 +3213,8 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) + this%phenology_n_to_litr_lig_n_col(c,j) & + this%dwt_frootn_to_litr_lig_n_col(c,j) & + this%gap_mortality_n_to_litr_lig_n_col(c,j) & - + this%harvest_n_to_litr_lig_n_col(c,j) !!& -! + this%m_n_to_litr_lig_fire_col(c,j) & -! - this%m_decomp_npools_to_fire_vr_col(c,j,l) + + this%harvest_n_to_litr_lig_n_col(c,j) & + + this%m_n_to_litr_lig_fire_col(c,j) ! for cwd elseif (l==i_cwd) then @@ -3205,14 +3223,8 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) + this%dwt_livecrootn_to_cwdn_col(c,j) & + this%dwt_deadcrootn_to_cwdn_col(c,j) & + this%gap_mortality_n_to_cwdn_col(c,j) & - + this%harvest_n_to_cwdn_col(c,j) !!& -! + this%fire_mortality_n_to_cwdn_col(c,j) - - ! for som n -! else -! this%externaln_to_decomp_npools_col(c,j,l) = & -! this%externaln_to_decomp_npools_col(c,j,l) & -! - this%m_decomp_npools_to_fire_vr_col(c,j,l) + + this%harvest_n_to_cwdn_col(c,j) & + + this%fire_mortality_n_to_cwdn_col(c,j) end if @@ -3228,34 +3240,36 @@ subroutine NSummary_interface(this,bounds,num_soilc, filter_soilc) this%externaln_to_decomp_npools_col(c,j,l) = 0._r8 end if - end do - end do - end do + end do !l = 1, ndecomp_pools + end do !j = 1, nlevdecomp_full + end do !fc = 1,num_soilc + - ! if pflotran hydrology NOT coupled, need to do adjusting for NO3 leaching for balance error checking + ! if pflotran hydrology NOT coupled, need to do: + ! saving for (next time-step) possible including of RT mass-transfer in PFLOTRAN bgc coupling. + ! (NOT USED anymore - 04/26/2017) if (.not. pf_hmode) then - do j = 1, nlevdecomp + do j = 1, nlevdecomp_full do fc = 1,num_soilc c = filter_soilc(fc) - !! wgs: EXCLUDE leaching from external input - this%no3_net_transport_vr_col(c,j) = 0._r8 -! this%no3_net_transport_vr_col(c,j) = this%smin_no3_runoff_vr_col(c,j) + & -! this%smin_no3_leached_vr_col(c,j) - this%no3_net_transport_delta_col(c) = & - this%no3_net_transport_delta_col(c) - & - this%no3_net_transport_vr_col(c,j)*dzsoi_decomp(j) + this%no3_net_transport_vr_col(c,j) = this%smin_no3_runoff_vr_col(c,j) + & + this%smin_no3_leached_vr_col(c,j) end do end do + else + this%no3_net_transport_vr_col(:,:) = 0._r8 end if ! change the sign so that it is the increments from the previous time-step (unit: g/m2/s) do fc = 1, num_soilc c = filter_soilc(fc) this%externaln_to_decomp_delta_col(c) = -this%externaln_to_decomp_delta_col(c) - this%no3_net_transport_delta_col(c) = -this%no3_net_transport_delta_col(c) end do + + end if ! if (use_pflotran .and. pf_cmode) + end subroutine NSummary_interface -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- end module CNNitrogenFluxType diff --git a/components/clm/src/biogeochem/CNNitrogenStateType.F90 b/components/clm/src/biogeochem/CNNitrogenStateType.F90 index b1ef450047b2..dd4ff3aa1a00 100644 --- a/components/clm/src/biogeochem/CNNitrogenStateType.F90 +++ b/components/clm/src/biogeochem/CNNitrogenStateType.F90 @@ -618,7 +618,7 @@ subroutine InitHistory(this, bounds) vr_suffix = "" endif - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SMIN_NO3'//trim(vr_suffix), units='gN/m^3', type2d='levdcmp', & avgflag='A', long_name='soil mineral NO3 (vert. res.)', & @@ -630,10 +630,12 @@ subroutine InitHistory(this, bounds) ptr_col=this%smin_nh4_vr_col) ! pflotran - this%smin_nh4sorb_vr_col(begc:endc,:) = spval - call hist_addfld_decomp (fname='SMIN_NH4SORB'//trim(vr_suffix), units='gN/m^3', type2d='levdcmp', & + if(use_pflotran .and. pf_cmode) then + this%smin_nh4sorb_vr_col(begc:endc,:) = spval + call hist_addfld_decomp (fname='SMIN_NH4SORB'//trim(vr_suffix), units='gN/m^3', type2d='levdcmp', & avgflag='A', long_name='soil mineral NH4 absorbed (vert. res.)', & ptr_col=this%smin_nh4sorb_vr_col) + end if if ( nlevdecomp_full > 1 ) then this%smin_no3_col(begc:endc) = spval @@ -647,11 +649,13 @@ subroutine InitHistory(this, bounds) ptr_col=this%smin_nh4_col) ! pflotran - this%smin_nh4sorb_col(begc:endc) = spval - call hist_addfld1d (fname='SMIN_NH4SORB', units='gN/m^2', & + if(use_pflotran .and. pf_cmode) then + this%smin_nh4sorb_col(begc:endc) = spval + call hist_addfld1d (fname='SMIN_NH4SORB', units='gN/m^2', & avgflag='A', long_name='soil mineral NH4 absorbed', & ptr_col=this%smin_nh4sorb_col) - endif + end if + end if this%sminn_vr_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SMINN'//trim(vr_suffix), units='gN/m^3', type2d='levdcmp', & @@ -876,15 +880,19 @@ subroutine InitCold(this, bounds, & this%decomp_npools_col(c,k) = decomp_cpools_col(c,k) / decomp_cascade_con%initial_cn_ratio(k) this%decomp_npools_1m_col(c,k) = decomp_cpools_1m_col(c,k) / decomp_cascade_con%initial_cn_ratio(k) end do - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then do j = 1, nlevdecomp_full this%smin_nh4_vr_col(c,j) = 0._r8 this%smin_no3_vr_col(c,j) = 0._r8 - this%smin_nh4sorb_vr_col(c,j) = 0._r8 + if(use_pflotran .and. pf_cmode) then + this%smin_nh4sorb_vr_col(c,j) = 0._r8 + end if end do this%smin_nh4_col(c) = 0._r8 this%smin_no3_col(c) = 0._r8 - this%smin_nh4sorb_col(c) = 0._r8 + if(use_pflotran .and. pf_cmode) then + this%smin_nh4sorb_col(c) = 0._r8 + end if end if this%totlitn_col(c) = 0._r8 this%totsomn_col(c) = 0._r8 @@ -1135,7 +1143,7 @@ subroutine Restart ( this, bounds, ncid, flag, cnstate_vars ) interpinic_flag='interp' , readvar=readvar, data=ptr1d) end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then ! smin_no3_vr if (use_vertsoilc) then ptr2d => this%smin_no3_vr_col(:,:) @@ -1155,7 +1163,7 @@ subroutine Restart ( this, bounds, ncid, flag, cnstate_vars ) end if end if - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then ! smin_nh4 if (use_vertsoilc) then ptr2d => this%smin_nh4_vr_col(:,:) @@ -1237,7 +1245,7 @@ subroutine Restart ( this, bounds, ncid, flag, cnstate_vars ) decomp_cascade_state = 0 end if ! add info about the nitrification / denitrification state - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then decomp_cascade_state = decomp_cascade_state + 10 end if if (flag == 'write') itemp = decomp_cascade_state @@ -1419,7 +1427,7 @@ subroutine SetValues ( this, & this%sminn_col(i) = value_column this%ntrunc_col(i) = value_column this%cwdn_col(i) = value_column - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_col(i) = value_column this%smin_nh4_col(i) = value_column if(use_pflotran .and. pf_cmode) then @@ -1439,7 +1447,7 @@ subroutine SetValues ( this, & i = filter_column(fi) this%sminn_vr_col(i,j) = value_column this%ntrunc_vr_col(i,j) = value_column - if (use_nitrif_denitrif) then + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then this%smin_no3_vr_col(i,j) = value_column this%smin_nh4_vr_col(i,j) = value_column if(use_pflotran .and. pf_cmode) then @@ -1500,6 +1508,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil use clm_varpar , only: nlevdecomp,ndecomp_cascade_transitions,ndecomp_pools use clm_varctl , only: use_nitrif_denitrif use subgridAveMod , only: p2c + use clm_varpar , only: nlevdecomp_full ! ! !ARGUMENTS: class (nitrogenstate_type) :: this @@ -1513,6 +1522,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil integer :: c,p,j,k,l ! indices integer :: fp,fc ! lake filter indices real(r8) :: maxdepth ! depth to integrate soil variables + integer :: nlev !----------------------------------------------------------------------- do fp = 1,num_soilp @@ -1580,7 +1590,10 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%totpftn_col(bounds%begc:bounds%endc)) ! vertically integrate NO3 NH4 N2O pools - if (use_nitrif_denitrif) then + nlev = nlevdecomp + if (use_pflotran .and. pf_cmode) nlev = nlevdecomp_full + + if (use_nitrif_denitrif .or. (use_pflotran .and. pf_cmode)) then do fc = 1,num_soilc c = filter_soilc(fc) this%smin_no3_col(c) = 0._r8 @@ -1589,7 +1602,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%smin_nh4sorb_col(c) = 0._r8 end if end do - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%smin_no3_col(c) = & @@ -1615,7 +1628,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil c = filter_soilc(fc) this%decomp_npools_col(c,l) = 0._r8 end do - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%decomp_npools_col(c,l) = & @@ -1744,7 +1757,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil c = filter_soilc(fc) this%sminn_col(c) = 0._r8 end do - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%sminn_col(c) = & @@ -1758,7 +1771,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil c = filter_soilc(fc) this%ntrunc_col(c) = 0._r8 end do - do j = 1, nlevdecomp + do j = 1, nlev do fc = 1,num_soilc c = filter_soilc(fc) this%ntrunc_col(c) = & diff --git a/components/clm/src/biogeochem/CNPrecisionControlMod.F90 b/components/clm/src/biogeochem/CNPrecisionControlMod.F90 index 66cf3287d2f9..0969652f7b95 100644 --- a/components/clm/src/biogeochem/CNPrecisionControlMod.F90 +++ b/components/clm/src/biogeochem/CNPrecisionControlMod.F90 @@ -34,7 +34,7 @@ subroutine CNPrecisionControl(num_soilc, filter_soilc, num_soilp, filter_soilp, ! ! !USES: use clm_varctl , only : iulog, use_c13, use_c14, use_nitrif_denitrif, use_ed - use clm_varpar , only : nlevdecomp, crop_prog + use clm_varpar , only : nlevdecomp_full, crop_prog use pftvarcon , only : nc3crop use tracer_varcon , only : is_active_betr_bgc ! @@ -672,7 +672,7 @@ subroutine CNPrecisionControl(num_soilc, filter_soilc, num_soilp, filter_soilp, do fc = 1,num_soilc c = filter_soilc(fc) - do j = 1,nlevdecomp + do j = 1,nlevdecomp_full ! initialize the column-level C and N truncation terms cc = 0._r8 if ( use_c13 ) cc13 = 0._r8 @@ -728,7 +728,7 @@ subroutine CNPrecisionControl(num_soilc, filter_soilc, num_soilp, filter_soilp, do fc = 1,num_soilc c = filter_soilc(fc) - do j = 1,nlevdecomp + do j = 1,nlevdecomp_full if (abs(ns%smin_no3_vr_col(c,j)) < ncrit/1e4_r8) then if ( ns%smin_no3_vr_col(c,j) < 0._r8 ) then write(iulog, *) '-10^-12 < smin_no3 < 0. resetting to zero.' diff --git a/components/clm/src/biogeochem/PStateUpdate1Mod.F90 b/components/clm/src/biogeochem/PStateUpdate1Mod.F90 index df256c52e58f..f60ee26f8bf4 100644 --- a/components/clm/src/biogeochem/PStateUpdate1Mod.F90 +++ b/components/clm/src/biogeochem/PStateUpdate1Mod.F90 @@ -19,7 +19,7 @@ module PStateUpdate1Mod use PhosphorusStateType , only : phosphorusstate_type use VegetationType , only : veg_pp use tracer_varcon , only : is_active_betr_bgc - !! bgc interface & pflotran: + ! bgc interface & pflotran: use clm_varctl , only : use_pflotran, pf_cmode use clm_varctl , only : nu_com ! diff --git a/components/clm/src/biogeochem/PStateUpdate2Mod.F90 b/components/clm/src/biogeochem/PStateUpdate2Mod.F90 index 927c5b3caddf..fbdcd64eb840 100644 --- a/components/clm/src/biogeochem/PStateUpdate2Mod.F90 +++ b/components/clm/src/biogeochem/PStateUpdate2Mod.F90 @@ -15,7 +15,7 @@ module PStateUpdate2Mod use VegetationType , only : veg_pp use pftvarcon , only : npcropmin use tracer_varcon , only : is_active_betr_bgc - !! bgc interface & pflotran: + ! bgc interface & pflotran: use clm_varctl , only : use_pflotran, pf_cmode ! implicit none diff --git a/components/clm/src/biogeochem/PStateUpdate3Mod.F90 b/components/clm/src/biogeochem/PStateUpdate3Mod.F90 index accd872dda4f..85f715bf06b7 100644 --- a/components/clm/src/biogeochem/PStateUpdate3Mod.F90 +++ b/components/clm/src/biogeochem/PStateUpdate3Mod.F90 @@ -18,7 +18,7 @@ module PStateUpdate3Mod use PhosphorusFLuxType , only : phosphorusflux_type use soilorder_varcon , only : smax,ks_sorption use tracer_varcon , only : is_active_betr_bgc - !! bgc interface & pflotran: + ! bgc interface & pflotran: use clm_varctl , only : use_pflotran, pf_cmode use clm_varctl , only : nu_com use VegetationPropertiesType , only : veg_vp diff --git a/components/clm/src/biogeochem/PhosphorusFluxType.F90 b/components/clm/src/biogeochem/PhosphorusFluxType.F90 index 4c21c2ddcc23..df762ced93de 100755 --- a/components/clm/src/biogeochem/PhosphorusFluxType.F90 +++ b/components/clm/src/biogeochem/PhosphorusFluxType.F90 @@ -13,8 +13,8 @@ module PhosphorusFluxType use LandunitType , only : lun_pp use ColumnType , only : col_pp use VegetationType , only : veg_pp - !! bgc interface & pflotran: - use clm_varctl , only : use_bgc_interface, use_pflotran, pf_cmode, pf_hmode, use_vertsoilc + ! bgc interface & pflotran: + use clm_varctl , only : use_clm_interface, use_pflotran, pf_cmode, pf_hmode, use_vertsoilc ! ! !PUBLIC TYPES: implicit none @@ -282,7 +282,7 @@ module PhosphorusFluxType real(r8), pointer :: avail_retransp_patch (:) ! P flux available from retranslocation pool (gP/m2/s) real(r8), pointer :: plant_palloc_patch (:) ! total allocated P flux (gP/m2/s) - ! clm_bgc_interface & pflotran + ! clm_interface & pflotran !------------------------------------------------------------------------ real(r8), pointer :: plant_pdemand_col (:) ! col P flux required to support initial GPP (gN/m2/s) real(r8), pointer :: plant_pdemand_vr_col (:,:) ! col vertically-resolved P flux required to support initial GPP (gP/m3/s) @@ -322,7 +322,7 @@ module PhosphorusFluxType procedure , private :: InitAllocate procedure , private :: InitHistory procedure , private :: InitCold - !! bgc & pflotran interface + ! bgc & pflotran interface procedure , private :: PSummary_interface end type phosphorusflux_type @@ -645,7 +645,7 @@ subroutine InitAllocate(this, bounds) allocate(this%plant_to_litter_pflux (begc:endc )) ; this%plant_to_litter_pflux (:) = nan allocate(this%plant_to_cwd_pflux (begc:endc )) ; this%plant_to_cwd_pflux (:) = nan - ! clm_bgc_interface & pflotran + ! clm_interface & pflotran !------------------------------------------------------------------------ allocate(this%plant_pdemand_col (begc:endc)) ; this%plant_pdemand_col (:) = nan allocate(this%plant_pdemand_vr_col (begc:endc,1:nlevdecomp_full)) ; this%plant_pdemand_vr_col (:,:) = nan @@ -1496,7 +1496,7 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='total allocated P flux', & ptr_patch=this%plant_palloc_patch, default='active') - !! bgc interface + ! bgc interface this%plant_pdemand_col(begc:endc) = spval call hist_addfld1d (fname='PLANT_PDEMAND_COL', units='gN/m^2/s', & avgflag='A', long_name='P flux required to support initial GPP', & @@ -1694,7 +1694,7 @@ subroutine Restart (this, bounds, ncid, flag ) long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%plant_palloc_patch) - ! clm_bgc_interface & pflotran + ! clm_interface & pflotran !------------------------------------------------------------------------ if (use_pflotran .and. pf_cmode) then ! externalp_to_decomp_ppools_col @@ -1742,7 +1742,7 @@ subroutine Restart (this, bounds, ncid, flag ) end if end if - end if !! if (use_pflotran .and. pf_cmode) + end if ! if (use_pflotran .and. pf_cmode) !------------------------------------------------------------------------ end subroutine Restart @@ -1995,7 +1995,7 @@ subroutine SetValues ( this, & this%fire_ploss_col(i) = value_column this%wood_harvestp_col(i) = value_column - !! bgc-interface + ! bgc-interface this%plant_pdemand_col(i) = value_column this%fire_ploss_col(i) = value_column @@ -2047,6 +2047,7 @@ subroutine SetValues ( this, & do fi = 1,num_column i = filter_column(fi) this%decomp_ppools_sourcesink_col(i,j,k) = value_column + this%biochem_pmin_ppools_vr_col(i,j,k) = value_column ! this is needed, if no P cycle end do end do end do @@ -2221,7 +2222,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil end do end do end do - end if !!if (.not.(use_pflotran .and. pf_cmode)) + end if !if (.not.(use_pflotran .and. pf_cmode)) !----------------------------------------------------------------- ! vertically integrate inorganic P flux @@ -2405,21 +2406,21 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil end do end do - !! bgc interface & pflotran: + ! bgc interface & pflotran: !---------------------------------------------------------------- - if (use_bgc_interface) then + if (use_clm_interface) then call PSummary_interface(this, bounds, num_soilc, filter_soilc) end if !---------------------------------------------------------------- end subroutine Summary -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- ! !INTERFACE: subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) ! ! !DESCRIPTION: -!! bgc interface & pflotran: +! bgc interface & pflotran: ! On the radiation time step, perform olumn-level nitrogen ! summary calculations, which mainly from PFLOTRAN bgc coupling ! @@ -2436,10 +2437,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) 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 -! -! !REVISION HISTORY: -!!08/26/2015: created by Gangsheng Wang -! + ! !LOCAL VARIABLES: integer :: c,j, l ! indices integer :: fc ! column filter indices @@ -2448,7 +2446,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) ! set time steps dtime = real( get_step_size(), r8 ) if (use_pflotran .and. pf_cmode) then - !! TODO + ! TODO end if ! summarize at column-level vertically-resolved littering/removal for PFLOTRAN bgc input needs @@ -2492,9 +2490,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) + this%phenology_p_to_litr_met_p_col(c,j) & + this%dwt_frootp_to_litr_met_p_col(c,j) & + this%gap_mortality_p_to_litr_met_p_col(c,j) & - + this%harvest_p_to_litr_met_p_col(c,j) !!& -! + this%m_p_to_litr_met_fire_col(c,j) & -! - this%m_decomp_ppools_to_fire_vr_col(c,j,l) + + this%harvest_p_to_litr_met_p_col(c,j) elseif (l==i_cel_lit) then this%externalp_to_decomp_ppools_col(c,j,l) = & @@ -2502,9 +2498,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) + this%phenology_p_to_litr_cel_p_col(c,j) & + this%dwt_frootp_to_litr_cel_p_col(c,j) & + this%gap_mortality_p_to_litr_cel_p_col(c,j) & - + this%harvest_p_to_litr_cel_p_col(c,j) !!& -! + this%m_p_to_litr_cel_fire_col(c,j) & -! - this%m_decomp_ppools_to_fire_vr_col(c,j,l) + + this%harvest_p_to_litr_cel_p_col(c,j) elseif (l==i_lig_lit) then this%externalp_to_decomp_ppools_col(c,j,l) = & @@ -2512,9 +2506,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) + this%phenology_p_to_litr_lig_p_col(c,j) & + this%dwt_frootp_to_litr_lig_p_col(c,j) & + this%gap_mortality_p_to_litr_lig_p_col(c,j) & - + this%harvest_p_to_litr_lig_p_col(c,j) !!& -! + this%m_p_to_litr_lig_fire_col(c,j) & -! - this%m_decomp_ppools_to_fire_vr_col(c,j,l) + + this%harvest_p_to_litr_lig_p_col(c,j) ! for cwd elseif (l==i_cwd) then @@ -2523,14 +2515,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) + this%dwt_livecrootp_to_cwdp_col(c,j) & + this%dwt_deadcrootp_to_cwdp_col(c,j) & + this%gap_mortality_p_to_cwdp_col(c,j) & - + this%harvest_p_to_cwdp_col(c,j) !!& -! + this%fire_mortality_p_to_cwdp_col(c,j) -! - ! for som n -! else -! this%externalp_to_decomp_ppools_col(c,j,l) = & -! this%externalp_to_decomp_ppools_col(c,j,l) & -! - this%m_decomp_ppools_to_fire_vr_col(c,j,l) + + this%harvest_p_to_cwdp_col(c,j) end if @@ -2556,7 +2541,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) do fc = 1,num_soilc c = filter_soilc(fc) this%sminp_net_transport_vr_col(c,j) = 0._r8 -! this%sminp_net_transport_vr_col(c,j) = this%sminp_leached_vr_col(c,j) + this%sminp_net_transport_delta_col(c) = & this%sminp_net_transport_delta_col(c) - & this%sminp_net_transport_vr_col(c,j)*dzsoi_decomp(j) @@ -2571,7 +2556,7 @@ subroutine PSummary_interface(this,bounds,num_soilc, filter_soilc) this%sminp_net_transport_delta_col(c) = -this%sminp_net_transport_delta_col(c) end do end subroutine PSummary_interface -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- end module PhosphorusFluxType diff --git a/components/clm/src/biogeophys/EnergyFluxType.F90 b/components/clm/src/biogeophys/EnergyFluxType.F90 index 1a8ab01e6787..8105549aaf81 100644 --- a/components/clm/src/biogeophys/EnergyFluxType.F90 +++ b/components/clm/src/biogeophys/EnergyFluxType.F90 @@ -94,6 +94,13 @@ module EnergyFluxType ! Latent heat real(r8), pointer :: htvp_col (:) ! latent heat of vapor of water (or sublimation) [j/kg] + ! for couplig with pflotran + real(r8), pointer :: eflx_soil_grnd_col (:) ! col integrated soil ground heat flux (W/m2) [+ = into ground] + real(r8), pointer :: eflx_rnet_soil_col (:) ! col soil net (sw+lw) radiation flux (W/m2) [+ = into soil] + real(r8), pointer :: eflx_fgr0_soil_col (:) ! col soil-air heat flux (W/m2) [+ = into soil] + real(r8), pointer :: eflx_fgr0_snow_col (:) ! col soil-snow heat flux (W/m2) [+ = into soil] + real(r8), pointer :: eflx_fgr0_h2osfc_col (:) ! col soil-surfacewater heat flux (W/m2) [+ = into soil] + ! Balance Checks real(r8), pointer :: errsoi_patch (:) ! soil/lake energy conservation error (W/m**2) real(r8), pointer :: errsoi_col (:) ! soil/lake energy conservation error (W/m**2) @@ -222,6 +229,13 @@ subroutine InitAllocate(this, bounds) allocate( this%htvp_col (begc:endc)) ; this%htvp_col (:) = nan + ! for coupling with pflotran + allocate( this%eflx_soil_grnd_col (begc:endc)) ; this%eflx_soil_grnd_col (:) = nan + allocate( this%eflx_rnet_soil_col (begc:endc)) ; this%eflx_rnet_soil_col (:) = nan + allocate( this%eflx_fgr0_soil_col (begc:endc)) ; this%eflx_fgr0_soil_col (:) = nan + allocate( this%eflx_fgr0_snow_col (begc:endc)) ; this%eflx_fgr0_snow_col (:) = nan + allocate( this%eflx_fgr0_h2osfc_col (begc:endc)) ; this%eflx_fgr0_h2osfc_col (:) = nan + allocate(this%rresis_patch (begp:endp,1:nlevgrnd)) ; this%rresis_patch (:,:) = nan allocate(this%btran_patch (begp:endp)) ; this%btran_patch (:) = nan allocate(this%btran2_patch (begp:endp)) ; this%btran2_patch (:) = nan diff --git a/components/clm/src/biogeophys/HydrologyNoDrainageMod.F90 b/components/clm/src/biogeophys/HydrologyNoDrainageMod.F90 index 85244a692403..9cb4f458943e 100644 --- a/components/clm/src/biogeophys/HydrologyNoDrainageMod.F90 +++ b/components/clm/src/biogeophys/HydrologyNoDrainageMod.F90 @@ -35,6 +35,7 @@ Module HydrologyNoDrainageMod subroutine HydrologyNoDrainage(bounds, & num_nolakec, filter_nolakec, & num_hydrologyc, filter_hydrologyc, & + num_hydrononsoic, filter_hydrononsoic, & num_urbanc, filter_urbanc, & num_snowc, filter_snowc, & num_nosnowc, filter_nosnowc, & @@ -63,7 +64,7 @@ subroutine HydrologyNoDrainage(bounds, & use landunit_varcon , only : istice, istwet, istsoil, istice_mec, istcrop, istdlak use column_varcon , only : icol_roof, icol_road_imperv, icol_road_perv, icol_sunwall use column_varcon , only : icol_shadewall - use clm_varctl , only : use_cn, use_betr, use_ed + use clm_varctl , only : use_cn, use_betr, use_ed, use_pflotran, pf_hmode use clm_varpar , only : nlevgrnd, nlevsno, nlevsoi, nlevurb use clm_time_manager , only : get_step_size, get_nstep use SnowHydrologyMod , only : SnowCompaction, CombineSnowLayers, DivideSnowLayers @@ -83,6 +84,8 @@ subroutine HydrologyNoDrainage(bounds, & integer , intent(in) :: filter_nolakec(:) ! column filter for non-lake points integer , intent(in) :: num_hydrologyc ! number of column soil points in column filter integer , intent(in) :: filter_hydrologyc(:) ! column filter for soil points + integer , intent(in) :: num_hydrononsoic ! number of non-soil landunit points in hydrology filter + integer , intent(in) :: filter_hydrononsoic(:) ! column filter for non-soil hydrology points integer , intent(in) :: num_urbanc ! number of column urban points in column filter integer , intent(in) :: filter_urbanc(:) ! column filter for urban points integer , intent(inout) :: num_snowc ! number of column snow points @@ -183,8 +186,6 @@ subroutine HydrologyNoDrainage(bounds, & call SnowWater(bounds, num_snowc, filter_snowc, num_nosnowc, filter_nosnowc, & atm2lnd_vars, waterflux_vars, waterstate_vars, aerosol_vars) - - ! mapping soilmoist from CLM to VIC layers for runoff calculations if (use_vichydro) then call CLMVICMap(bounds, num_hydrologyc, filter_hydrologyc, & @@ -194,9 +195,24 @@ subroutine HydrologyNoDrainage(bounds, & call SurfaceRunoff(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filter_urbanc, & soilhydrology_vars, soilstate_vars, waterflux_vars, waterstate_vars) - call Infiltration(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filter_urbanc,& - energyflux_vars, soilhydrology_vars, soilstate_vars, temperature_vars, & - waterflux_vars, waterstate_vars) + !------------------------------------------------------------------------------------ + if (use_pflotran .and. pf_hmode) then + + call Infiltration(bounds, num_hydrononsoic, filter_hydrononsoic, & + num_urbanc, filter_urbanc, & + energyflux_vars, soilhydrology_vars, soilstate_vars, temperature_vars, & + waterflux_vars, waterstate_vars) + + else + !------------------------------------------------------------------------------------ + + call Infiltration(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filter_urbanc, & + energyflux_vars, soilhydrology_vars, soilstate_vars, temperature_vars, & + waterflux_vars, waterstate_vars) + + !------------------------------------------------------------------------------------ + end if + !------------------------------------------------------------------------------------ if (use_betr) then call ep_betr%BeTRSetBiophysForcing(bounds, col_pp, veg_pp, 1, nlevsoi, waterstate_vars=waterstate_vars) @@ -218,9 +234,25 @@ subroutine HydrologyNoDrainage(bounds, & if( use_ed ) call alm_fates%ComputeRootSoilFlux(bounds, num_hydrologyc, filter_hydrologyc, & soilstate_vars, waterflux_vars) - call SoilWater(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filter_urbanc, & + !------------------------------------------------------------------------------------ + if (use_pflotran .and. pf_hmode) then + + call SoilWater(bounds, num_hydrononsoic, filter_hydrononsoic, & + num_urbanc, filter_urbanc, & + soilhydrology_vars, soilstate_vars, waterflux_vars, waterstate_vars, temperature_vars, & + soil_water_retention_curve) + + else + !------------------------------------------------------------------------------------ + + call SoilWater(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filter_urbanc, & soilhydrology_vars, soilstate_vars, waterflux_vars, waterstate_vars, temperature_vars, & soil_water_retention_curve) + + !------------------------------------------------------------------------------------ + end if + !------------------------------------------------------------------------------------ + if (use_betr) then call ep_betr%BeTRSetBiophysForcing(bounds, col_pp, veg_pp, 1, nlevsoi, waterstate_vars=waterstate_vars, & @@ -237,9 +269,24 @@ subroutine HydrologyNoDrainage(bounds, & soilhydrology_vars, waterstate_vars) end if - call WaterTable(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filter_urbanc, & + !------------------------------------------------------------------------------------ + if (use_pflotran .and. pf_hmode) then + + call WaterTable(bounds, num_hydrononsoic, filter_hydrononsoic, & + num_urbanc, filter_urbanc, & + soilhydrology_vars, soilstate_vars, temperature_vars, waterstate_vars, waterflux_vars) + + else + !------------------------------------------------------------------------------------ + + call WaterTable(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filter_urbanc, & soilhydrology_vars, soilstate_vars, temperature_vars, waterstate_vars, waterflux_vars) + !------------------------------------------------------------------------------------ + end if + !------------------------------------------------------------------------------------ + + if (use_betr) then !apply dew and sublimation fluxes, this is a temporary work aroud for tracking water isotope !Jinyun Tang, Feb 4, 2015 @@ -406,7 +453,8 @@ subroutine HydrologyNoDrainage(bounds, & end do end do - if (use_cn .or. use_ed) then + if ( (use_cn .or. use_ed) .and. & + .not.(use_pflotran .and. pf_hmode) ) then ! Update soilpsi. ! ZMS: Note this could be merged with the following loop updating smp_l in the future. do j = 1, nlevgrnd diff --git a/components/clm/src/biogeophys/SoilHydrologyMod.F90 b/components/clm/src/biogeophys/SoilHydrologyMod.F90 index 6cf30c3410f1..28dcc56e0178 100644 --- a/components/clm/src/biogeophys/SoilHydrologyMod.F90 +++ b/components/clm/src/biogeophys/SoilHydrologyMod.F90 @@ -981,9 +981,9 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte qflx_snwcp_liq => waterflux_vars%qflx_snwcp_liq_col , & ! Output: [real(r8) (:) ] excess rainfall due to snow capping (mm H2O /s) [+] qflx_snwcp_ice => waterflux_vars%qflx_snwcp_ice_col , & ! Output: [real(r8) (:) ] excess snowfall due to snow capping (mm H2O /s) [+] - qflx_dew_grnd => waterflux_vars%qflx_dew_grnd_col , & ! Output: [real(r8) (:) ] ground surface dew formation (mm H2O /s) [+] - qflx_dew_snow => waterflux_vars%qflx_dew_snow_col , & ! Output: [real(r8) (:) ] surface dew added to snow pack (mm H2O /s) [+] - qflx_sub_snow => waterflux_vars%qflx_sub_snow_col , & ! Output: [real(r8) (:) ] sublimation rate from snow pack (mm H2O /s) [+] + !qflx_dew_grnd => waterflux_vars%qflx_dew_grnd_col , & ! Output: [real(r8) (:) ] ground surface dew formation (mm H2O /s) [+] + !qflx_dew_snow => waterflux_vars%qflx_dew_snow_col , & ! Output: [real(r8) (:) ] surface dew added to snow pack (mm H2O /s) [+] + !qflx_sub_snow => waterflux_vars%qflx_sub_snow_col , & ! Output: [real(r8) (:) ] sublimation rate from snow pack (mm H2O /s) [+] qflx_drain => waterflux_vars%qflx_drain_col , & ! Output: [real(r8) (:) ] sub-surface runoff (mm H2O /s) qflx_qrgwl => waterflux_vars%qflx_qrgwl_col , & ! Output: [real(r8) (:) ] qflx_surf at glaciers, wetlands, lakes (mm H2O /s) qflx_rsub_sat => waterflux_vars%qflx_rsub_sat_col , & ! Output: [real(r8) (:) ] soil saturation excess [mm h2o/s] diff --git a/components/clm/src/biogeophys/TemperatureType.F90 b/components/clm/src/biogeophys/TemperatureType.F90 index 0232cab3f240..103ab8b8407e 100755 --- a/components/clm/src/biogeophys/TemperatureType.F90 +++ b/components/clm/src/biogeophys/TemperatureType.F90 @@ -103,6 +103,9 @@ module TemperatureType ! For VSFM model real(r8), pointer :: t_soil_col_1d (:) ! 1D temperature of soil layers (Kelvin) + ! For coupling with pflotran + real(r8), pointer :: t_nearsurf_col (:) ! near-surface air temperature averaged over bare-veg as BC (Kelvin) + contains procedure, public :: Init @@ -237,7 +240,10 @@ subroutine InitAllocate(this, bounds) allocate(this%c_h2osfc_col (begc:endc)) ; this%c_h2osfc_col (:) = nan ! For VSFM model - allocate(this%t_soil_col_1d ((endc-begc+1)*nlevgrnd)) ; this%t_soil_col_1d (:) = nan + allocate(this%t_soil_col_1d ((endc-begc+1)*nlevgrnd)) ; this%t_soil_col_1d (:) = nan + + ! for coupling with pflotran + allocate(this%t_nearsurf_col (begc:endc)) ; this%t_nearsurf_col (:) = nan end subroutine InitAllocate diff --git a/components/clm/src/biogeophys/WaterfluxType.F90 b/components/clm/src/biogeophys/WaterfluxType.F90 index ae35adc69678..ce49a8415c37 100644 --- a/components/clm/src/biogeophys/WaterfluxType.F90 +++ b/components/clm/src/biogeophys/WaterfluxType.F90 @@ -52,12 +52,12 @@ module WaterfluxType real(r8), pointer :: qflx_prec_intr_patch (:) ! patch interception of precipitation [mm/s] real(r8), pointer :: qflx_prec_intr_col (:) ! col interception of precipitation [mm/s] - real(r8), pointer :: qflx_ev_snow_patch (:) ! patch evaporation heat flux from snow (W/m**2) [+ to atm] - real(r8), pointer :: qflx_ev_snow_col (:) ! col evaporation heat flux from snow (W/m**2) [+ to atm] - real(r8), pointer :: qflx_ev_soil_patch (:) ! patch evaporation heat flux from soil (W/m**2) [+ to atm] - real(r8), pointer :: qflx_ev_soil_col (:) ! col evaporation heat flux from soil (W/m**2) [+ to atm] - real(r8), pointer :: qflx_ev_h2osfc_patch (:) ! patch evaporation heat flux from soil (W/m**2) [+ to atm] - real(r8), pointer :: qflx_ev_h2osfc_col (:) ! col evaporation heat flux from soil (W/m**2) [+ to atm] + real(r8), pointer :: qflx_ev_snow_patch (:) ! patch evaporation heat flux from snow (W/m**2) [+ to atm] ! NOTE: unit shall be mm H2O/s for water NOT heat + real(r8), pointer :: qflx_ev_snow_col (:) ! col evaporation heat flux from snow (W/m**2) [+ to atm] ! NOTE: unit shall be mm H2O/s for water NOT heat + real(r8), pointer :: qflx_ev_soil_patch (:) ! patch evaporation heat flux from soil (W/m**2) [+ to atm] ! NOTE: unit shall be mm H2O/s for water NOT heat + real(r8), pointer :: qflx_ev_soil_col (:) ! col evaporation heat flux from soil (W/m**2) [+ to atm] ! NOTE: unit shall be mm H2O/s for water NOT heat + real(r8), pointer :: qflx_ev_h2osfc_patch (:) ! patch evaporation heat flux from soil (W/m**2) [+ to atm] ! NOTE: unit shall be mm H2O/s for water NOT heat + real(r8), pointer :: qflx_ev_h2osfc_col (:) ! col evaporation heat flux from soil (W/m**2) [+ to atm] ! NOTE: unit shall be mm H2O/s for water NOT heat real(r8), pointer :: qflx_gross_evap_soil_col (:) ! col gross infiltration from soil, this satisfies the relationship qflx_infl_col = qflx_gross_infl_soil_col-qflx_gross_evap_soil_col real(r8), pointer :: qflx_gross_infl_soil_col (:) ! col gross infiltration, before considering the evaporation diff --git a/components/clm/src/main/clm_driver.F90 b/components/clm/src/main/clm_driver.F90 index 45e3912c7af9..f47b3f5b4f3d 100644 --- a/components/clm/src/main/clm_driver.F90 +++ b/components/clm/src/main/clm_driver.F90 @@ -47,10 +47,10 @@ module clm_driver ! use SurfaceRadiationMod , only : SurfaceRadiation, CanopySunShadeFractions use UrbanRadiationMod , only : UrbanRadiation - !clm_bgc_interface + !clm_interface use CNEcosystemDynMod , only : CNEcosystemDynNoLeaching1, CNEcosystemDynNoLeaching2 - use CNEcosystemDynMod , only : CNEcosystemDynLeaching !!CNEcosystemDynNoLeaching, + use CNEcosystemDynMod , only : CNEcosystemDynLeaching use CNVegStructUpdateMod , only : CNVegStructUpdate use CNAnnualUpdateMod , only : CNAnnualUpdate use CNBalanceCheckMod , only : BeginCBalance, BeginNBalance, CBalanceCheck, NBalanceCheck @@ -125,20 +125,21 @@ module clm_driver use shr_sys_mod , only : shr_sys_flush use shr_log_mod , only : errMsg => shr_log_errMsg - !!---------------------------------------------------------------------------- - !! bgc interface & pflotran: - use clm_varctl , only : use_bgc_interface - use clm_instMod , only : clm_bgc_data - use clm_bgc_interfaceMod , only : get_clm_bgc_data - !! (1) clm_bgc through interface + !---------------------------------------------------------------------------- + ! bgc interface & pflotran: + use clm_varctl , only : use_clm_interface + use clm_instMod , only : clm_interface_data + use clm_interface_funcsMod , only : get_clm_data + ! (1) clm_bgc through interface use clm_varctl , only : use_clm_bgc - use clm_bgc_interfaceMod , only : clm_bgc_run, update_bgc_data_clm2clm - !! (2) pflotran - use clm_varctl , only : use_pflotran, pf_cmode, pf_hmode, pf_tmode - use clm_bgc_interfaceMod , only : update_bgc_data_pf2clm - use clm_pflotran_interfaceMod , only : clm_pf_run, clm_pf_write_restart -! use clm_pflotran_interfaceMod , only : clm_pf_finalize - !!---------------------------------------------------------------------------- + use clm_interface_funcsMod , only : clm_bgc_run, update_bgc_data_clm2clm + ! (2) pflotran + use clm_time_manager , only : nsstep, nestep + use clm_varctl , only : use_pflotran, pf_cmode, pf_hmode, pf_tmode + use clm_interface_funcsMod , only : update_bgc_data_pf2clm, update_th_data_pf2clm + use clm_interface_pflotranMod , only : clm_pf_run, clm_pf_write_restart + use clm_interface_pflotranMod , only : clm_pf_finalize + !---------------------------------------------------------------------------- ! ! !PUBLIC TYPES: @@ -645,6 +646,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) call HydrologyNoDrainage(bounds_clump, & filter(nc)%num_nolakec, filter(nc)%nolakec, & filter(nc)%num_hydrologyc, filter(nc)%hydrologyc, & + filter(nc)%num_hydrononsoic, filter(nc)%hydrononsoic, & filter(nc)%num_urbanc, filter(nc)%urbanc, & filter(nc)%num_snowc, filter(nc)%snowc, & filter(nc)%num_nosnowc, filter(nc)%nosnowc, & @@ -773,11 +775,11 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) ! - CNDV defined: prognostic biogeography; else prescribed ! - crop model: crop algorithms called from within CNEcosystemDyn - !!=========================================================================================== - !! clm_bgc_interface: 'CNEcosystemDynNoLeaching' is divided into 2 subroutines (1 & 2): BEGIN - !! CNEcosystemDynNoLeaching1 is called before clm_bgc_interface - !! CNEcosystemDynNoLeaching2 is called after clm_bgc_interface - !!=========================================================================================== + !=========================================================================================== + ! clm_interface: 'CNEcosystemDynNoLeaching' is divided into 2 subroutines (1 & 2): BEGIN + ! CNEcosystemDynNoLeaching1 is called before clm_interface + ! CNEcosystemDynNoLeaching2 is called after clm_interface + !=========================================================================================== call CNEcosystemDynNoLeaching1(bounds_clump, & filter(nc)%num_soilc, filter(nc)%soilc, & filter(nc)%num_soilp, filter(nc)%soilp, & @@ -790,40 +792,36 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) ch4_vars, photosyns_vars, & phosphorusflux_vars,phosphorusstate_vars) - !!-------------------------------------------------------------------------------- - if (use_bgc_interface) then - !! STEP-1: pass data from CLM to clm_bgc_data (INTERFACE DATA TYPE) - call get_clm_bgc_data(clm_bgc_data,bounds_clump, & + !-------------------------------------------------------------------------------- + if (use_clm_interface) then + ! STEP-1: pass data from CLM to clm_interface_data (INTERFACE DATA TYPE) + call get_clm_data(clm_interface_data,bounds_clump, & filter(nc)%num_soilc, filter(nc)%soilc, & filter(nc)%num_soilp, filter(nc)%soilp, & - atm2lnd_vars, waterstate_vars, waterflux_vars, & - soilstate_vars, temperature_vars, energyflux_vars, & - soilhydrology_vars, soil_water_retention_curve, & + atm2lnd_vars, soilstate_vars, & + waterstate_vars, waterflux_vars, & + temperature_vars, energyflux_vars, & cnstate_vars, carbonflux_vars, carbonstate_vars, & nitrogenflux_vars, nitrogenstate_vars, & phosphorusflux_vars, phosphorusstate_vars, & - canopystate_vars, ch4_vars) + ch4_vars) + if (use_pflotran .and. pf_cmode) then call t_startf('pflotran') ! ------------------------------------------------------------------------- ! PFLOTRAN calling for solving below-ground and ground-surface processes, ! including thermal, hydrological and biogeochemical processes - !! STEP-2: (1) pass data from clm_bgc_data to pflotran - !! STEP-2: (2) run pflotran - !! STEP-2: (3) update clm_bgc_data from pflotran + ! STEP-2: (1) pass data from clm_interface_data to pflotran + ! STEP-2: (2) run pflotran + ! STEP-2: (3) update clm_interface_data from pflotran ! ------------------------------------------------------------------------- - call clm_pf_run(clm_bgc_data,bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc) + call clm_pf_run(clm_interface_data, bounds_clump, filter, nc) - !! STEP-3: update CLM from clm_bgc_data - call update_bgc_data_pf2clm(clm_bgc_data,bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & + ! STEP-3: update CLM from clm_interface_data + call update_bgc_data_pf2clm(clm_interface_data%bgc, & + bounds_clump,filter(nc)%num_soilc, filter(nc)%soilc, & filter(nc)%num_soilp, filter(nc)%soilp, & - atm2lnd_vars, & - waterstate_vars, waterflux_vars, & - soilstate_vars, temperature_vars, energyflux_vars, & - soilhydrology_vars, soil_water_retention_curve, & cnstate_vars, carbonflux_vars, carbonstate_vars, & nitrogenflux_vars, nitrogenstate_vars, & phosphorusflux_vars, phosphorusstate_vars, & @@ -834,12 +832,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) elseif (use_clm_bgc) then call t_startf('clm-bgc via interface') ! ------------------------------------------------------------------------- - !! run clm-bgc (CNDecompAlloc) through interface - !! STEP-2: (1) pass data from clm_bgc_data to CNDecompAlloc - !! STEP-2: (2) run CNDecompAlloc - !! STEP-2: (3) update clm_bgc_data from CNDecompAlloc + ! run clm-bgc (CNDecompAlloc) through interface + ! STEP-2: (1) pass data from clm_interface_data to CNDecompAlloc + ! STEP-2: (2) run CNDecompAlloc + ! STEP-2: (3) update clm_interface_data from CNDecompAlloc ! ------------------------------------------------------------------------- - call clm_bgc_run(clm_bgc_data, bounds_clump, & + call clm_bgc_run(clm_interface_data, bounds_clump, & filter(nc)%num_soilc, filter(nc)%soilc, & filter(nc)%num_soilp, filter(nc)%soilp, & canopystate_vars, soilstate_vars, & @@ -849,22 +847,18 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) nitrogenstate_vars, nitrogenflux_vars, & phosphorusstate_vars,phosphorusflux_vars) - !! STEP-3: update CLM from clm_bgc_data - call update_bgc_data_clm2clm(clm_bgc_data, bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & + ! STEP-3: update CLM from clm_interface_data + call update_bgc_data_clm2clm(clm_interface_data%bgc, & + bounds_clump, filter(nc)%num_soilc, filter(nc)%soilc,& filter(nc)%num_soilp, filter(nc)%soilp, & - atm2lnd_vars, & - waterstate_vars, waterflux_vars, & - soilstate_vars, temperature_vars, energyflux_vars, & - soilhydrology_vars, soil_water_retention_curve, & cnstate_vars, carbonflux_vars, carbonstate_vars, & nitrogenflux_vars, nitrogenstate_vars, & phosphorusflux_vars, phosphorusstate_vars, & ch4_vars) call t_stopf('clm-bgc via interface') - end if !!if (use_pflotran .and. pf_cmode) - end if !!if (use_bgc_interface) - !!-------------------------------------------------------------------------------- + end if !if (use_pflotran .and. pf_cmode) + end if !if (use_clm_interface) + !-------------------------------------------------------------------------------- call CNEcosystemDynNoLeaching2(bounds_clump, & filter(nc)%num_soilc, filter(nc)%soilc, & @@ -879,9 +873,9 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) dgvs_vars, photosyns_vars, soilhydrology_vars, energyflux_vars, & phosphorusflux_vars,phosphorusstate_vars) - !!=========================================================================================== - !! clm_bgc_interface: 'CNEcosystemDynNoLeaching' is divided into 2 subroutines (1 & 2): END - !!=========================================================================================== + !=========================================================================================== + ! clm_interface: 'CNEcosystemDynNoLeaching' is divided into 2 subroutines (1 & 2): END + !=========================================================================================== call CNAnnualUpdate(bounds_clump, & filter(nc)%num_soilc, filter(nc)%soilc, & @@ -959,7 +953,20 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) call t_startf('hydro2 drainage') - call HydrologyDrainage(bounds_clump, & + if (use_clm_interface .and. (use_pflotran .and. pf_hmode)) then + ! pflotran only works on 'soilc' (already done above). + ! here for non-soil hydrology columns + call HydrologyDrainage(bounds_clump, & + filter(nc)%num_nolakec, filter(nc)%nolakec, & + filter(nc)%num_hydrononsoic, filter(nc)%hydrononsoic, & + filter(nc)%num_urbanc, filter(nc)%urbanc, & + filter(nc)%num_do_smb_c, filter(nc)%do_smb_c, & + atm2lnd_vars, glc2lnd_vars, temperature_vars, & + soilhydrology_vars, soilstate_vars, waterstate_vars, waterflux_vars,ep_betr) + + else + + call HydrologyDrainage(bounds_clump, & filter(nc)%num_nolakec, filter(nc)%nolakec, & filter(nc)%num_hydrologyc, filter(nc)%hydrologyc, & filter(nc)%num_urbanc, filter(nc)%urbanc, & @@ -967,6 +974,8 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) atm2lnd_vars, glc2lnd_vars, temperature_vars, & soilhydrology_vars, soilstate_vars, waterstate_vars, waterflux_vars,ep_betr) + end if + call t_stopf('hydro2 drainage') if (use_betr) then @@ -1279,13 +1288,6 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) soilstate_vars%bsw_col(bounds_proc%begc:bounds_proc%endc, 1:), & soilstate_vars%hksat_col(bounds_proc%begc:bounds_proc%endc, 1:)) - !---------------------------------------------- - ! pflotran - if (use_pflotran) then - call clm_pf_write_restart(rdate) - end if - !---------------------------------------------- - call t_stopf('clm_drv_io_htapes') ! Write to CNDV history buffer if appropriate @@ -1313,12 +1315,24 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate) phosphorusstate_vars,phosphorusflux_vars, & ep_betr, alm_fates, rdate=rdate ) + !---------------------------------------------- + ! pflotran (off now) + ! if (use_pflotran) then + ! call clm_pf_write_restart(rdate) + ! end if + !---------------------------------------------- + + call t_stopf('clm_drv_io_wrest') end if call t_stopf('clm_drv_io') end if + if (use_pflotran .and. nstep>=nestep) then + call clm_pf_finalize() + end if + end subroutine clm_drv !----------------------------------------------------------------------- diff --git a/components/clm/src/main/clm_initializeMod.F90 b/components/clm/src/main/clm_initializeMod.F90 index b52438bcae62..f4330c43347c 100644 --- a/components/clm/src/main/clm_initializeMod.F90 +++ b/components/clm/src/main/clm_initializeMod.F90 @@ -397,8 +397,8 @@ subroutine initialize2( ) use glc2lndMod , only : glc2lnd_type use lnd2glcMod , only : lnd2glc_type use SoilWaterRetentionCurveFactoryMod , only : create_soil_water_retention_curve - use clm_varctl , only : use_bgc_interface, use_pflotran - use clm_pflotran_interfaceMod , only : clm_pf_interface_init !!, clm_pf_set_restart_stamp + use clm_varctl , only : use_clm_interface, use_pflotran + use clm_interface_pflotranMod , only : clm_pf_interface_init !, clm_pf_set_restart_stamp use tracer_varcon , only : is_active_betr_bgc use clm_time_manager , only : is_restart use ALMbetrNLMod , only : betr_namelist_buffer @@ -531,9 +531,9 @@ subroutine initialize2( ) call clm_inst_biogeophys(bounds_proc) - !allocate memory for betr simulator - allocate(ep_betr, source=create_betr_simulation_alm()) if(use_betr)then + !allocate memory for betr simulator + allocate(ep_betr, source=create_betr_simulation_alm()) !set internal filters for betr call ep_betr%BeTRSetFilter(maxpft_per_col=max_patch_per_col, boffline=.false.) call ep_betr%InitOnline(bounds_proc, lun_pp, col_pp, veg_pp, waterstate_vars, betr_namelist_buffer, masterproc) @@ -890,16 +890,16 @@ subroutine initialize2( ) deallocate(topo_glc_mec) !------------------------------------------------------------ - !! initialize clm_bgc_interface_data_type - call t_startf('init_clm_bgc_interface_data & pflotran') - if (use_bgc_interface) then - call clm_bgc_data%Init(bounds_proc) + ! initialize clm_bgc_interface_data_type + call t_startf('init_clm_interface_data & pflotran') + if (use_clm_interface) then + call clm_interface_data%Init(bounds_proc) ! PFLOTRAN initialization if (use_pflotran) then call clm_pf_interface_init(bounds_proc) end if end if - call t_stopf('init_clm_bgc_interface_data & pflotran') + call t_stopf('init_clm_interface_data & pflotran') !------------------------------------------------------------ !------------------------------------------------------------ diff --git a/components/clm/src/main/clm_instMod.F90 b/components/clm/src/main/clm_instMod.F90 index f7fb9efc07d3..0d2b8b3f6e0e 100644 --- a/components/clm/src/main/clm_instMod.F90 +++ b/components/clm/src/main/clm_instMod.F90 @@ -48,14 +48,13 @@ module clm_instMod use SoilWaterRetentionCurveMod , only : soil_water_retention_curve_type use UrbanParamsType , only : urbanparams_type ! Constants use VegetationPropertiesType , only : veg_vp ! Ecophysical Constants - ! use VegetationPropertiesType , only : veg_vp ! Constants use SoilorderConType , only : soilordercon ! Constants use LandunitType , only : lun_pp use ColumnType , only : col_pp use VegetationType , only : veg_pp - use clm_bgc_interface_data , only : clm_bgc_interface_data_type + use clm_interface_dataType , only : clm_interface_data_type use ChemStateType , only : chemstate_type ! structure for chemical indices of the soil, such as pH and Eh use BeTRSimulationALM , only : betr_simulation_alm_type use PlantMicKineticsMod , only : PlantMicKinetics_type @@ -110,7 +109,7 @@ module clm_instMod class(soil_water_retention_curve_type), allocatable :: soil_water_retention_curve type(phosphorusstate_type) :: phosphorusstate_vars type(phosphorusflux_type) :: phosphorusflux_vars - type(clm_bgc_interface_data_type) :: clm_bgc_data + type(clm_interface_data_type) :: clm_interface_data type(chemstate_type) :: chemstate_vars type(hlm_fates_interface_type) :: alm_fates class(betr_simulation_alm_type), pointer :: ep_betr diff --git a/components/clm/src/main/clm_bgc_interface_data.F90 b/components/clm/src/main/clm_interface_bgcType.F90 similarity index 74% rename from components/clm/src/main/clm_bgc_interface_data.F90 rename to components/clm/src/main/clm_interface_bgcType.F90 index 64382b0bbda6..04c4998e5bae 100644 --- a/components/clm/src/main/clm_bgc_interface_data.F90 +++ b/components/clm/src/main/clm_interface_bgcType.F90 @@ -1,28 +1,22 @@ -module clm_bgc_interface_data -!!================================================================================================= +module clm_interface_bgcType +!================================================================================================= ! CLM BioGeoChemistry (BGC) Interface: Data Type (Variables) -! -! Created by wgs @ ORNL -! -! date: 8/25/2015 -!!================================================================================================= - !! USES: +! created: 8/25/2015 +! update: 9/16/2016, 2/2/2017, May-2017, June-2017 +!================================================================================================= + ! USES: use shr_log_mod , only : errMsg => shr_log_errMsg use shr_kind_mod , only : r8 => shr_kind_r8 use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : nlevsno, nlevgrnd - use clm_varpar , only : nlevdecomp_full, ndecomp_pools, ndecomp_cascade_transitions - use clm_varcon , only : spval - use decompMod , only : bounds_type implicit none -! save +! private - type, public :: clm_bgc_interface_data_type + type, public :: clm_interface_bgc_datatype ! clm_varpar - integer :: nlevdecomp ! num of CLM soil layers that are mapped to/from PFLOTRAN + integer :: nlevdecomp_full ! num of CLM soil layers that are mapped to/from PFLOTRAN integer :: ndecomp_pools ! num of decomposition pools ! decomp_cascade_con @@ -30,38 +24,7 @@ module clm_bgc_interface_data logical, pointer :: floating_cp_ratio (:) ! TRUE => pool has fixed C:P ratio character(len=8), pointer :: decomp_pool_name (:) ! name of pool real(r8), pointer :: initial_cn_ratio (:) ! c:n ratio for initialization of pools - real(r8), pointer :: initial_cp_ratio (:) ! c:n ratio for initialization of pools - - ! col: - real(r8), pointer :: z (:,:) ! layer depth (m) (-nlevsno+1:nlevgrnd) - real(r8), pointer :: dz (:,:) ! layer thickness (m) (-nlevsno+1:nlevgrnd) - - ! soilstate_vars: - real(r8), pointer :: bd_col (:,:) ! col bulk density of dry soil material [kg/m^3] (CN) - real(r8), pointer :: hksat_col (:,:) ! col hydraulic conductivity at saturation (mm H2O /s) - real(r8), pointer :: bsw_col (:,:) ! col Clapp and Hornberger "b" (nlevgrnd) - real(r8), pointer :: watsat_col (:,:) ! col volumetric soil water at saturation (porosity) - real(r8), pointer :: sucsat_col (:,:) ! col minimum soil suction (mm) (nlevgrnd) - real(r8), pointer :: watfc_col (:,:) ! col volumetric soil water at field capacity (nlevsoi) - real(r8), pointer :: porosity_col (:,:) ! col soil porisity (1-bulk_density/soil_density) (VIC) - real(r8), pointer :: eff_porosity_col (:,:) ! col effective porosity = porosity - vol_ice (nlevgrnd) - real(r8), pointer :: cellorg_col (:,:) ! col organic matter for gridcell containing column (1:nlevsoi) - real(r8), pointer :: soilpsi_col (:,:) ! col soil water potential in each soil layer (MPa) (CN) - real(r8), pointer :: rootfr_col (:,:) ! col fraction of roots in each soil layer (nlevgrnd) - - ! waterstate_vars: - real(r8), pointer :: h2osoi_liq_col (:,:) ! col liquid water (kg/m2) (new) (-nlevsno+1:nlevgrnd) - real(r8), pointer :: h2osoi_ice_col (:,:) ! col ice lens (kg/m2) (new) (-nlevsno+1:nlevgrnd) - real(r8), pointer :: frac_sno_eff_col (:) ! col fraction of ground covered by snow (0 to 1) - real(r8), pointer :: frac_h2osfc_col (:) ! col fractional area with surface water greater than zero - real(r8), pointer :: h2osoi_vol_col (:,:) ! col volumetric soil water (0<=h2osoi_vol<=watsat) [m3/m3] (nlevgrnd) - - ! temperature_vars: - real(r8), pointer :: t_soisno_col (:,:) ! col soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) - real(r8), pointer :: t_grnd_col (:) ! col ground temperature (Kelvin) - - ! canopystate_vars - integer , pointer :: alt_indx_col (:) ! col current depth of thaw + real(r8), pointer :: initial_cp_ratio (:) ! c:p ratio for initialization of pools ! ch4 real(r8), pointer :: finundated_col (:) ! col fractional inundated area (excluding dedicated wetland cols) @@ -72,6 +35,10 @@ module clm_bgc_interface_data real(r8), pointer :: o2_decomp_depth_sat_col (:,:) ! col O2 consumption during decomposition in each soil layer (nlevsoi) (mol/m3/s) real(r8), pointer :: o2_decomp_depth_unsat_col (:,:) ! col O2 consumption during decomposition in each soil layer (nlevsoi) (mol/m3/s) + ! cnstate_vars: + real(r8) , pointer :: rf_decomp_cascade_col (:,:,:) ! col respired fraction in decomposition step (frac) + real(r8) , pointer :: pathfrac_decomp_cascade_col (:,:,:) ! col what fraction of C leaving a given pool passes through a given + ! carbonstate_vars: real(r8), pointer :: decomp_cpools_vr_col (:,:,:) ! col (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools @@ -111,6 +78,10 @@ module clm_bgc_interface_data real(r8), pointer :: sminn_to_denit_decomp_cascade_vr_col (:,:,:) ! col vertically-resolved denitrification along decomp cascade (gN/m3/s) real(r8), pointer :: decomp_cascade_hr_vr_col (:,:,:) ! vertically-resolved het. resp. from decomposing C pools (gC/m3/s) + real(r8), pointer :: o_scalar_col (:,:) ! fraction by which decomposition is limited by anoxia + real(r8), pointer :: w_scalar_col (:,:) ! fraction by which decomposition is limited by moisture availability + real(r8), pointer :: t_scalar_col (:,:) ! fraction by which decomposition is limited by temperature + ! mineralization / immobilization / uptake flux real(r8), pointer :: gross_nmin_vr_col (:,:) ! col vertically-resolved gross rate of N mineralization (gN/m3/s) real(r8), pointer :: net_nmin_vr_col (:,:) ! col vertically-resolved net rate of N mineralization (gN/m3/s) @@ -177,21 +148,23 @@ module clm_bgc_interface_data real(r8) , pointer :: fpi_p_col (:) ! col fraction of potential immobilization (no units) real(r8), pointer :: fpg_p_col (:) ! col fraction of potential gpp (no units) - !!------------------------------------------------------------------------------------------ - !! pflotran variables: BEGIN - !!------------------------------------------------------------------------------------------ + !------------------------------------------------------------------------------------------ + ! pflotran variables: BEGIN + !------------------------------------------------------------------------------------------ ! bgc rates/fluxes (previous time-step) to decomposition pools real(r8), pointer :: externalc_to_decomp_cpools_col (:,:,:) ! col (gC/m3/s) net C fluxes associated with litter/som-adding/removal to decomp pools real(r8), pointer :: externaln_to_decomp_npools_col (:,:,:) ! col (gN/m3/s) net N fluxes associated with litter/som-adding/removal to decomp pools real(r8), pointer :: externalp_to_decomp_ppools_col (:,:,:) ! col (gP/m3/s) net P fluxes associated with litter/som-adding/removal to decomp pools - + real(r8), pointer :: decomp_k_pools (:) ! rate constant for each decomposition pool (1./sec) + real(r8), pointer :: sitefactor_kd_vr_col (:,:) ! a site factor for adjusting rate constant of all decomposition pools (-) (c,j) + real(r8), pointer :: adfactor_kd_pools (:) ! a speed-up factor for adjusting rate constant of individual decomposition pool (-) (k) + ! bgc rates/fluxes (previous time-step) to nh4 / no3 real(r8), pointer :: externaln_to_nh4_col (:,:) ! col (gN/m3/s) net N fluxes to nh4 pool: deposition + fertilization + supplement + nfix + soyfixn real(r8), pointer :: externaln_to_no3_col (:,:) ! col (gN/m3/s) net N fluxes to no3 pool: deposition + fertilization + supplement real(r8), pointer :: externaln_to_sminn_col (:,:) ! col (gN/m3/s) net N fluxes to sminn pool: deposition + fertilization + supplement + nfix + soyfixn real(r8), pointer :: smin_no3_leached_vr_col (:,:) ! col vertically-resolved soil mineral NO3 loss to leaching (gN/m3/s) real(r8), pointer :: smin_no3_runoff_vr_col (:,:) ! col vertically-resolved rate of mineral NO3 loss with runoff (gN/m3/s) - real(r8), pointer :: no3_net_transport_vr_col (:,:) ! col net NO3 transport associated with runoff/leaching (gN/m3/s) ! bgc rates/fluxes (previous time-step) to mineral P real(r8), pointer :: externalp_to_primp_col (:,:) ! pdep_to_sminp_col (:) ! col atmospheric P deposition to soil mineral P (gP/m2/s) @@ -205,62 +178,62 @@ module clm_bgc_interface_data real(r8), pointer :: f_ngas_nitri_vr_col (:,:) ! col vertically-resolved N emission from nitrification (gN/m3/s) real(r8), pointer :: f_ngas_denit_vr_col (:,:) ! col vertically-resolved N emission from denitrification (gN/m3/s) - ! waterflux_vars: - real(r8), pointer :: qflx_top_soil_col (:) ! col net water input into soil from top (mm/s) - real(r8), pointer :: qflx_sub_snow_col (:) ! col sublimation rate from snow pack (mm H2O /s) [+] - real(r8), pointer :: qflx_evap_soi_col (:) ! col soil evaporation (mm H2O/s) (+ = to atm) - real(r8), pointer :: qflx_ev_h2osfc_col (:) ! col evaporation heat flux from soil (W/m**2) [+ to atm] - real(r8), pointer :: qflx_tran_veg_col (:) ! col vegetation transpiration (mm H2O/s) (+ = to atm) - - ! energyflux_vars: - real(r8), pointer :: htvp_col (:) ! latent heat of vapor of water (or sublimation) [j/kg] - real(r8), pointer :: eflx_bot_col (:) ! col heat flux from beneath the soil or ice column (W/m**2) - real(r8), pointer :: eflx_gnet_col (:) ! col net heat flux into ground (W/m**2) - real(r8), pointer :: eflx_soil_grnd_col (:) ! col soil heat flux (W/m**2) [+ = into soil] + ! aq. phases: + real(r8), pointer :: no3_net_transport_vr_col (:,:) ! col net NO3 transport associated with runoff/leaching (gN/m3/s) - also store PF's N transport inc. diffusion at current time-step + real(r8), pointer :: nh4_net_transport_vr_col (:,:) ! col net NH4 transport associated with runoff/leaching (gN/m3/s) - also store PF's N transport inc. diffusion at current time-step ! atm2lnd: - real(r8), pointer :: forc_pbot_not_downscaled_grc (:) ! not downscaled atm pressure (Pa) real(r8), pointer :: forc_pco2_grc (:) ! CO2 partial pressure (Pa) real(r8), pointer :: forc_pch4_grc (:) ! CH4 partial pressure (Pa) - !!------------------------------------------------------------------------------------------ - !! pflotran variables: END - !!------------------------------------------------------------------------------------------ + ! mass balance check: + ! summary of layer 1:nlevdecomp_full + real(r8), pointer :: soil_begcb_col (:) ! soil organic carbon mass, beginning of time step (gC/m**2) + real(r8), pointer :: soil_begnb_col (:) ! soil nitrogen mass, beginning of time step (gN/m**2) + real(r8), pointer :: soil_begnb_org_col (:) ! soil organic nitrogen mass, beginning of time step (gN/m**2) + real(r8), pointer :: soil_begnb_min_col (:) ! soil mineral nitrogen mass, beginning of time step (gN/m**2) = no3 + nh4 + nh4sorb + !------------------------------------------------------------------------------------------ + ! pflotran variables: END + !------------------------------------------------------------------------------------------ -!!------------------------------------------------------------------------------------------------- + +!------------------------------------------------------------------------------------------------- contains procedure , public :: Init procedure , private :: InitAllocate - end type clm_bgc_interface_data_type -!!------------------------------------------------------------------------------------------------- + end type clm_interface_bgc_datatype +!------------------------------------------------------------------------------------------------- -!! type(clm_bgc_interface_data_type) , public, target , save :: clm_bgc_data contains -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine Init(this, bounds) - class(clm_bgc_interface_data_type) :: this + use decompMod , only : bounds_type + class(clm_interface_bgc_datatype) :: this type(bounds_type), intent(in) :: bounds call this%InitAllocate (bounds) end subroutine Init -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- subroutine InitAllocate(this, bounds) - !! USES - + ! USES + use clm_varpar , only : nlevsno, nlevgrnd + use clm_varpar , only : nlevdecomp_full, ndecomp_pools, ndecomp_cascade_transitions + use clm_varcon , only : spval + use decompMod , only : bounds_type - !! ARGUMENTS: + ! ARGUMENTS: real(r8) :: ival = 0.0_r8 ! initial value - class(clm_bgc_interface_data_type) :: this - type(bounds_type), intent(in) :: bounds + class(clm_interface_bgc_datatype) :: this + type(bounds_type), intent(in) :: bounds - !! LOCAL VARIABLES: + ! LOCAL VARIABLES: integer :: begg, endg integer :: begc, endc integer :: begp, endp @@ -276,36 +249,6 @@ subroutine InitAllocate(this, bounds) allocate(this%initial_cn_ratio (0:ndecomp_pools)) ; this%initial_cn_ratio (:) = nan allocate(this%initial_cp_ratio (0:ndecomp_pools)) ; this%initial_cp_ratio (:) = nan - ! col: - allocate(this%z (begc:endc,-nlevsno+1:nlevgrnd)) ; this%z (:,:) = nan - allocate(this%dz (begc:endc,-nlevsno+1:nlevgrnd)) ; this%dz (:,:) = nan - ! soilstate_vars: - allocate(this%bd_col (begc:endc,nlevgrnd)) ; this%bd_col (:,:) = nan - allocate(this%hksat_col (begc:endc,nlevgrnd)) ; this%hksat_col (:,:) = spval - allocate(this%bsw_col (begc:endc,nlevgrnd)) ; this%bsw_col (:,:) = nan - allocate(this%watsat_col (begc:endc,nlevgrnd)) ; this%watsat_col (:,:) = nan - allocate(this%sucsat_col (begc:endc,nlevgrnd)) ; this%sucsat_col (:,:) = spval - allocate(this%watfc_col (begc:endc,nlevgrnd)) ; this%watfc_col (:,:) = nan - allocate(this%porosity_col (begc:endc,nlevgrnd)) ; this%porosity_col (:,:) = spval - allocate(this%eff_porosity_col (begc:endc,nlevgrnd)) ; this%eff_porosity_col (:,:) = spval - allocate(this%cellorg_col (begc:endc,nlevgrnd)) ; this%cellorg_col (:,:) = nan - allocate(this%soilpsi_col (begc:endc,nlevgrnd)) ; this%soilpsi_col (:,:) = nan - allocate(this%rootfr_col (begc:endc,1:nlevgrnd)) ; this%rootfr_col (:,:) = nan - - ! waterstate_vars: - allocate(this%h2osoi_liq_col (begc:endc,-nlevsno+1:nlevgrnd)) ; this%h2osoi_liq_col (:,:) = nan - allocate(this%h2osoi_ice_col (begc:endc,-nlevsno+1:nlevgrnd)) ; this%h2osoi_ice_col (:,:) = nan - allocate(this%frac_sno_eff_col (begc:endc)) ; this%frac_sno_eff_col (:) = nan - allocate(this%frac_h2osfc_col (begc:endc)) ; this%frac_h2osfc_col (:) = nan - allocate(this%h2osoi_vol_col (begc:endc, 1:nlevgrnd)) ; this%h2osoi_vol_col (:,:) = nan - - ! temperature_vars: - allocate(this%t_soisno_col (begc:endc,-nlevsno+1:nlevgrnd)) ; this%t_soisno_col (:,:) = nan - allocate(this%t_grnd_col (begc:endc)) ; this%t_grnd_col (:) = nan - - ! canopystate_vars - allocate(this%alt_indx_col (begc:endc)) ; this%alt_indx_col (:) = huge(1) - ! ch4 allocate(this%finundated_col (begc:endc)) ; this%finundated_col (:) = nan allocate(this%o2stress_unsat_col (begc:endc,1:nlevgrnd)) ; this%o2stress_unsat_col (:,:) = nan @@ -315,6 +258,13 @@ subroutine InitAllocate(this, bounds) allocate(this%o2_decomp_depth_sat_col (begc:endc,1:nlevgrnd)) ; this%o2_decomp_depth_sat_col (:,:) = nan allocate(this%o2_decomp_depth_unsat_col (begc:endc,1:nlevgrnd)) ; this%o2_decomp_depth_unsat_col (:,:) = nan + ! cnstate_vars: + allocate(this%rf_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); + this%rf_decomp_cascade_col(:,:,:) = nan + + allocate(this%pathfrac_decomp_cascade_col(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); + this%pathfrac_decomp_cascade_col(:,:,:) = nan + ! carbonstate_vars: allocate(this%decomp_cpools_vr_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%decomp_cpools_vr_col(:,:,:)= ival allocate(this%decomp_npools_vr_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%decomp_npools_vr_col(:,:,:)= ival @@ -355,6 +305,11 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_cascade_hr_vr_col (begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)); this%decomp_cascade_hr_vr_col (:,:,:) = ival + allocate(this%t_scalar_col (begc:endc,1:nlevdecomp_full)); this%t_scalar_col (:,:)=spval + allocate(this%w_scalar_col (begc:endc,1:nlevdecomp_full)); this%w_scalar_col (:,:)=spval + allocate(this%o_scalar_col (begc:endc,1:nlevdecomp_full)); this%o_scalar_col (:,:)=spval + + ! mineralization / immobilization / uptake fluxes allocate(this%gross_nmin_vr_col (begc:endc,1:nlevdecomp_full)) ; this%gross_nmin_vr_col (:,:) = ival allocate(this%net_nmin_vr_col (begc:endc,1:nlevdecomp_full)) ; this%net_nmin_vr_col (:,:) = ival @@ -420,13 +375,17 @@ subroutine InitAllocate(this, bounds) allocate(this%fpi_p_col (begc:endc)) ; this%fpi_p_col (:) = nan allocate(this%fpg_p_col (begc:endc)) ; this%fpg_p_col (:) = nan - !!------------------------------------------------------------------------------------------ - !! pflotran variables: BEGIN - !!------------------------------------------------------------------------------------------ + !------------------------------------------------------------------------------------------ + ! pflotran variables: BEGIN + !------------------------------------------------------------------------------------------ ! bgc rates/fluxes to decomposition pools allocate(this%externalc_to_decomp_cpools_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%externalc_to_decomp_cpools_col(:,:,:) = spval allocate(this%externaln_to_decomp_npools_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%externaln_to_decomp_npools_col(:,:,:) = spval allocate(this%externalp_to_decomp_ppools_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%externalp_to_decomp_ppools_col(:,:,:) = spval + allocate(this%decomp_k_pools (1:ndecomp_pools)) ; this%decomp_k_pools (:) = spval + allocate(this%adfactor_kd_pools (1:ndecomp_pools)) ; this%adfactor_kd_pools (:) = spval + + allocate(this%sitefactor_kd_vr_col (begc:endc,1:nlevdecomp_full)) ; this%sitefactor_kd_vr_col (:,:) = spval ! bgc rates/fluxes to nh4 / no3 allocate(this%externaln_to_nh4_col (begc:endc,1:nlevdecomp_full)) ; this%externaln_to_nh4_col (:,:) = spval @@ -435,6 +394,7 @@ subroutine InitAllocate(this, bounds) allocate(this%smin_no3_leached_vr_col (begc:endc,1:nlevdecomp_full)) ; this%smin_no3_leached_vr_col (:,:) = ival allocate(this%smin_no3_runoff_vr_col (begc:endc,1:nlevdecomp_full)) ; this%smin_no3_runoff_vr_col (:,:) = ival allocate(this%no3_net_transport_vr_col (begc:endc,1:nlevdecomp_full)) ; this%no3_net_transport_vr_col (:,:) = spval + allocate(this%nh4_net_transport_vr_col (begc:endc,1:nlevdecomp_full)) ; this%nh4_net_transport_vr_col (:,:) = spval ! bgc rates/fluxes to mineral P allocate(this%externalp_to_primp_col (begc:endc,1:nlevdecomp_full)) ; this%externalp_to_primp_col (:,:) = spval @@ -448,28 +408,21 @@ subroutine InitAllocate(this, bounds) allocate(this%f_ngas_nitri_vr_col (begc:endc,1:nlevdecomp_full)) ; this%f_ngas_nitri_vr_col (:,:) = ival allocate(this%f_ngas_denit_vr_col (begc:endc,1:nlevdecomp_full)) ; this%f_ngas_denit_vr_col (:,:) = ival - ! waterflux_vars: - allocate(this%qflx_top_soil_col (begc:endc)) ; this%qflx_top_soil_col (:) = ival - allocate(this%qflx_ev_h2osfc_col (begc:endc)) ; this%qflx_ev_h2osfc_col (:) = ival - allocate(this%qflx_evap_soi_col (begc:endc)) ; this%qflx_evap_soi_col (:) = ival - allocate(this%qflx_sub_snow_col (begc:endc)) ; this%qflx_sub_snow_col (:) = ival - allocate(this%qflx_tran_veg_col (begc:endc)) ; this%qflx_tran_veg_col (:) = ival - - ! energyflux_vars: - allocate( this%htvp_col (begc:endc)) ; this%htvp_col (:) = ival - allocate( this%eflx_bot_col (begc:endc)) ; this%eflx_bot_col (:) = ival - allocate( this%eflx_gnet_col (begc:endc)) ; this%eflx_bot_col (:) = ival - allocate( this%eflx_soil_grnd_col (begc:endc)) ; this%eflx_soil_grnd_col (:) = ival - ! atm2lnd: - allocate(this%forc_pbot_not_downscaled_grc (begg:endg)) ; this%forc_pbot_not_downscaled_grc (:) = ival allocate(this%forc_pco2_grc (begg:endg)) ; this%forc_pco2_grc (:) = ival allocate(this%forc_pch4_grc (begg:endg)) ; this%forc_pch4_grc (:) = ival - !!------------------------------------------------------------------------------------------ - !! pflotran variables: END - !!------------------------------------------------------------------------------------------ + + ! mass balance check + allocate(this%soil_begcb_col (begc:endc)) ; this%soil_begcb_col (:) = ival + allocate(this%soil_begnb_col (begc:endc)) ; this%soil_begnb_col (:) = ival + allocate(this%soil_begnb_org_col (begc:endc)) ; this%soil_begnb_org_col (:) = ival + allocate(this%soil_begnb_min_col (begc:endc)) ; this%soil_begnb_min_col (:) = ival + + !------------------------------------------------------------------------------------------ + ! pflotran variables: END + !------------------------------------------------------------------------------------------ end subroutine InitAllocate -!!------------------------------------------------------------------------------------------------- +!------------------------------------------------------------------------------------------------- -end module clm_bgc_interface_data +end module clm_interface_bgcType diff --git a/components/clm/src/main/clm_interface_dataType.F90 b/components/clm/src/main/clm_interface_dataType.F90 new file mode 100644 index 000000000000..88df65bbcf7b --- /dev/null +++ b/components/clm/src/main/clm_interface_dataType.F90 @@ -0,0 +1,127 @@ +module clm_interface_dataType + +!================================================================================================= +! ALM Thermal(T)-Hydrology (H) & BioGeoChemistry (BGC) Interface: Data Type (Variables) +! created: 8/25/2015 +! update: 9/16/2016, 2/2/2017, May-2017, June-2017 +!================================================================================================= + ! USES: + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + + use clm_interface_thType + use clm_interface_bgcType + + implicit none + + private + +!------------------------------------------------------------------------------------------------- + type, public :: clm_interface_data_type + + ! col dimension + real(r8), pointer :: z (:,:) ! layer depth (m) (-nlevsno+1:nlevgrnd) + real(r8), pointer :: zi (:,:) ! layer depth (m) (-nlevsno+1:nlevgrnd) + real(r8), pointer :: dz (:,:) ! layer thickness (m) (-nlevsno+1:nlevgrnd) + + ! soilstate_vars: + real(r8), pointer :: bd_col (:,:) ! col bulk density of dry soil material [kg/m^3] (CN) + real(r8), pointer :: hksat_col (:,:) ! col hydraulic conductivity at saturation (mm H2O /s) + real(r8), pointer :: bsw_col (:,:) ! col Clapp and Hornberger "b" (nlevgrnd) + real(r8), pointer :: watsat_col (:,:) ! col volumetric soil water at saturation (porosity) + real(r8), pointer :: watmin_col (:,:) ! col minimum volumetric soil water (nlevsoi) + real(r8), pointer :: sucsat_col (:,:) ! col minimum soil suction (mm) (nlevgrnd) + real(r8), pointer :: sucmin_col (:,:) ! col minimum allowable soil liquid suction pressure (mm) [Note: sucmin_col is a negative value, while sucsat_col is a positive quantity] + real(r8), pointer :: watfc_col (:,:) ! col volumetric soil water at field capacity (nlevsoi) + real(r8), pointer :: porosity_col (:,:) ! col soil porisity (1-bulk_density/soil_density) (VIC) + real(r8), pointer :: eff_porosity_col (:,:) ! col effective porosity = porosity - vol_ice (nlevgrnd) + real(r8), pointer :: cellorg_col (:,:) ! col organic matter for gridcell containing column (1:nlevsoi) + real(r8), pointer :: rootfr_col (:,:) ! col fraction of roots in each soil layer (nlevgrnd) + + real(r8), pointer :: tkfrz_col (:,:) ! col thermal conductivity, frozen soil [W/m-K] (new) (nlevgrnd) + real(r8), pointer :: tkdry_col (:,:) ! col thermal conductivity, dry soil (W/m/Kelvin) (nlevgrnd) + real(r8), pointer :: tkwet_col (:,:) ! col thermal conductivity, saturated soil [W/m-K] (new) (nlevgrnd) + real(r8), pointer :: csol_col (:,:) ! col heat capacity, soil solids (J/m**3/Kelvin) (nlevgrnd) + + ! thermal-hydrology: + type(clm_interface_th_datatype) :: th + + ! biogeochemistry: + type(clm_interface_bgc_datatype):: bgc + + ! + contains + procedure , public :: Init + procedure , private :: InitAllocate + end type clm_interface_data_type +!------------------------------------------------------------------------------------------------- + + +contains + +!------------------------------------------------------------------------------------------------- + subroutine Init(this, bounds) + use decompMod , only : bounds_type + class(clm_interface_data_type) :: this + type(bounds_type), intent(in) :: bounds + + call this%InitAllocate (bounds) + + call this%th%Init(bounds) + + call this%bgc%Init(bounds) + + end subroutine Init +!------------------------------------------------------------------------------------------------- + +!------------------------------------------------------------------------------------------------- + + subroutine InitAllocate(this, bounds) + ! USES + use clm_varpar , only : nlevsno, nlevgrnd + use clm_varcon , only : spval + use decompMod , only : bounds_type + + ! ARGUMENTS: + real(r8) :: ival = 0.0_r8 ! initial value + class(clm_interface_data_type) :: this + type(bounds_type), intent(in) :: bounds + + ! LOCAL VARIABLES: + integer :: begg, endg + integer :: begc, endc + integer :: begp, endp + !------------------------------------------------------------------------ + begg = bounds%begg; endg= bounds%endg + begc = bounds%begc; endc= bounds%endc + begp = bounds%begp; endp= bounds%endp + + ! col: + allocate(this%z (begc:endc,-nlevsno+1:nlevgrnd)) ; this%z (:,:) = nan + allocate(this%zi (begc:endc,-nlevsno+0:nlevgrnd)) ; this%zi (:,:) = nan + allocate(this%dz (begc:endc,-nlevsno+1:nlevgrnd)) ; this%dz (:,:) = nan + + ! soilstate_vars: + allocate(this%bd_col (begc:endc,1:nlevgrnd)) ; this%bd_col (:,:) = nan + allocate(this%hksat_col (begc:endc,1:nlevgrnd)) ; this%hksat_col (:,:) = spval + allocate(this%bsw_col (begc:endc,1:nlevgrnd)) ; this%bsw_col (:,:) = nan + allocate(this%watsat_col (begc:endc,1:nlevgrnd)) ; this%watsat_col (:,:) = nan + allocate(this%watmin_col (begc:endc,1:nlevgrnd)) ; this%watmin_col (:,:) = nan + allocate(this%sucsat_col (begc:endc,1:nlevgrnd)) ; this%sucsat_col (:,:) = spval + allocate(this%sucmin_col (begc:endc,1:nlevgrnd)) ; this%sucmin_col (:,:) = spval + allocate(this%watfc_col (begc:endc,1:nlevgrnd)) ; this%watfc_col (:,:) = nan + allocate(this%porosity_col (begc:endc,1:nlevgrnd)) ; this%porosity_col (:,:) = spval + allocate(this%eff_porosity_col (begc:endc,1:nlevgrnd)) ; this%eff_porosity_col (:,:) = spval + allocate(this%cellorg_col (begc:endc,1:nlevgrnd)) ; this%cellorg_col (:,:) = nan + allocate(this%rootfr_col (begc:endc,1:nlevgrnd)) ; this%rootfr_col (:,:) = nan + + allocate(this%tkwet_col (begc:endc,1:nlevgrnd)) ; this%tkwet_col (:,:) = nan + allocate(this%tkdry_col (begc:endc,1:nlevgrnd)) ; this%tkdry_col (:,:) = nan + allocate(this%tkfrz_col (begc:endc,1:nlevgrnd)) ; this%tkfrz_col (:,:) = nan + allocate(this%csol_col (begc:endc,1:nlevgrnd)) ; this%csol_col (:,:) = nan + + end subroutine InitAllocate +!------------------------------------------------------------------------------------------------- + +end module clm_interface_dataType diff --git a/components/clm/src/main/clm_bgc_interfaceMod.F90 b/components/clm/src/main/clm_interface_funcsMod.F90 similarity index 64% rename from components/clm/src/main/clm_bgc_interfaceMod.F90 rename to components/clm/src/main/clm_interface_funcsMod.F90 index 3a7ba894214f..9244698bc0c1 100644 --- a/components/clm/src/main/clm_bgc_interfaceMod.F90 +++ b/components/clm/src/main/clm_interface_funcsMod.F90 @@ -1,29 +1,27 @@ -module clm_bgc_interfaceMod -!!================================================================================================= -! CLM BioGeoChemistry (BGC) Interface -! -! Created by wgs @ ORNL -! -! date: 8/25/2015 -!!================================================================================================= +module clm_interface_funcsMod +!================================================================================================= +! CLM Theraml-Hydrology (TH) & BioGeoChemistry (BGC) Interface: Modules +! created: 8/25/2015 +! updated: June-2017 +!================================================================================================= #include "shr_assert.h" - !! MODULE: clm_bgc_interfaceMod - !!-------------------------------------------------------------------------------------- - !! DESCRIPTION: - !! Coupling of CLM with any specific Soil BGC module Consists of 3 STEPS: - !! STEP-1: clm vars -> clm_bgc_data (i.e. clm_bgc_interface_data_type) ; pass clm vars to clm_bgc_data - !! STEP-2: clm_bgc_data -> soil bgc module -> clm_bgc_data - !! 2.1: clm_bgc_data -> soil bgc module - !! 2.2: run soil bgc module - !! 2.3: soil bgc module -> clm_bgc_data - !! STEP-3: clm_bgc_data -> clm vars - !!-------------------------------------------------------------------------------------- + ! MODULE: clm_interface_funcsMod + !-------------------------------------------------------------------------------------- + ! DESCRIPTION: + ! Coupling of CLM with any specific Soil BGC module Consists of 3 STEPS: + ! STEP-1: clm vars -> clm_interface_data (i.e. clm_interface_dataType) ; pass clm vars to clm_interface_data + ! STEP-2: clm_interface_data -> soil bgc module -> clm_interface_data + ! 2.1: clm_interface_data -> soil bgc module + ! 2.2: run soil bgc module + ! 2.3: soil bgc module -> clm_interface_data + ! STEP-3: clm_interface_data -> clm vars + !-------------------------------------------------------------------------------------- - !!-------------------------------------------------------------------------------------- + !-------------------------------------------------------------------------------------- ! !USES: ! clm g/l/c/p constants use shr_log_mod , only : errMsg => shr_log_errMsg @@ -31,7 +29,7 @@ module clm_bgc_interfaceMod use GridcellType , only : grc_pp use LandunitType , only : lun_pp use ColumnType , only : col_pp - use VegetationType , only : veg_pp + use VegetationType , only : veg_pp use decompMod , only : bounds_type @@ -59,18 +57,21 @@ module clm_bgc_interfaceMod use PhosphorusFluxType , only : phosphorusflux_type use SoilWaterRetentionCurveMod , only : soil_water_retention_curve_type - use clm_bgc_interface_data , only : clm_bgc_interface_data_type + + use clm_interface_dataType , only : clm_interface_data_type + use clm_interface_thType , only : clm_interface_th_datatype + use clm_interface_bgcType , only : clm_interface_bgc_datatype ! most used constants in this module - use clm_varpar , only : nlevsoi, nlevsno,nlevgrnd, nlevdecomp, nlevdecomp_full - use clm_varpar , only : ndecomp_pools + use clm_varpar , only : nlevsoi, nlevsno, nlevgrnd, nlevdecomp_full + use clm_varpar , only : ndecomp_pools, ndecomp_cascade_transitions use clm_varpar , only : max_patch_per_col use clm_varcon , only : denh2o, denice, tfrz, dzsoi_decomp use landunit_varcon , only : istsoil, istcrop ! misc. use abortutils , only : endrun - !!-------------------------------------------------------------------------------------- + !-------------------------------------------------------------------------------------- implicit none @@ -78,24 +79,24 @@ module clm_bgc_interfaceMod private ! By default everything is private - !! LOCAL VARIABLES: + ! LOCAL VARIABLES: - !!-------------------------------------------------------------------------------------- - !! (1) GENERIC SUBROUTINES: used by any specific soil BGC module - !! pass clm variables to clm_bgc_data - public :: get_clm_bgc_data !! STEP-1: clm vars -> clm_bgc_data + !-------------------------------------------------------------------------------------- + ! (1) GENERIC SUBROUTINES: used by any specific soil BGC module + ! pass clm variables to clm_bgc_data + public :: get_clm_data ! STEP-1: clm vars -> clm_interface_data - !! pass clm variables to clm_bgc_data, called by get_clm_bgc_data - private :: get_clm_soil_property !! STEP-1.1: soil properties - private :: get_clm_soil_thermohydro !! STEP-1.2: thermohydrology vars - private :: get_clm_bgc_state !! STEP-1.3: state vars - private :: get_clm_bgc_flux !! STEP-1.4: flux vars + ! pass clm variables to clm_interface_data, called by get_clm_data + private :: get_clm_soil_property ! STEP-1.1: soil properties + private :: get_clm_soil_th_state ! STEP-1.2: thermohydrology (TH) state vars + private :: get_clm_bgc_state ! STEP-1.3: state vars + private :: get_clm_bgc_flux ! STEP-1.4: flux vars - !! STEP-3.x: clm_bgc_data -> clm vars - !! update clm variables from clm_bgc_data, - !! e.g., called in 'update_bgc_data_clm2clm' and 'update_bgc_data_pf2clm' - !! specific bgc-module (e.g., PFLOTRAN) requires certain combination of these subroutines + ! STEP-3.x: clm_interface_data -> clm vars + ! update clm variables from clm_interface_data, + ! e.g., called in 'update_bgc_data_clm2clm' and 'update_bgc_data_pf2clm' + ! specific bgc-module (e.g., PFLOTRAN) requires certain combination of these subroutines private :: update_bgc_state_decomp private :: update_bgc_state_smin private :: update_bgc_flux_decomp_sourcesink @@ -106,37 +107,38 @@ module clm_bgc_interfaceMod private :: update_soil_moisture private :: update_soil_temperature - !!-------------------------------------------------------------------------------------- - !! (2) SPECIFIC SUBROUTINES: used by a specific soil BGC module - !! (2.1) Specific Subroutines for running clm-bgc (CN or BGC) through interface - !! if (use_bgc_interface .and. use_clm_bgc) - public :: clm_bgc_run !! STEP-2: clm_bgc_data -> clm-bgc module -> clm_bgc_data ; called in clm_driver - private :: clm_bgc_get_data !! STEP-2.1: clm_bgc_data -> clm-bgc module ; called in clm_bgc_run - !! STEP-2.2: run clm-bgc module ; see CNDecompAlloc in CNDecompMod - private :: clm_bgc_update_data !! STEP-2.3: clm-bgc module-> clm_bgc_data ; called in clm_bgc_run - public :: update_bgc_data_clm2clm !! STEP-3: clm_bgc_data -> clm vars ; called in clm_driver - - !! (2.2) Specific Subroutines for CLM-PFLOTRAN Coupling: update clm variables from pflotran - !! if (use_bgc_interface .and. use_pflotran) - public :: update_bgc_data_pf2clm !! STEP-3: clm_bgc_data -> clm vars ; called in clm_driver - !! STEP-2: see 'clm_pf_run' in clm_pflotran_interfaceMod - !!-------------------------------------------------------------------------------------- + !-------------------------------------------------------------------------------------- + ! (2) SPECIFIC SUBROUTINES: used by a specific soil BGC module + ! (2.1) Specific Subroutines for running clm-bgc (CN or BGC) through interface + ! if (use_clm_interface .and. use_clm_bgc) + public :: clm_bgc_run ! STEP-2: clm_interface_data -> clm-bgc module -> clm_interface_data ; called in clm_driver + private :: clm_bgc_get_data ! STEP-2.1: clm_interface_data -> clm-bgc module ; called in clm_bgc_run + ! STEP-2.2: run clm-bgc module ; see CNDecompAlloc in CNDecompMod + private :: clm_bgc_update_data ! STEP-2.3: clm-bgc module-> clm_interface_data ; called in clm_bgc_run + public :: update_bgc_data_clm2clm ! STEP-3: clm_interface_data -> clm vars ; called in clm_driver + + ! (2.2) Specific Subroutines for CLM-PFLOTRAN Coupling: update clm variables from pflotran + ! if (use_clm_interface .and. use_pflotran) + public :: update_bgc_data_pf2clm ! STEP-3: clm_interface_data -> clm vars ; called in clm_driver + ! STEP-2: see 'clm_pf_run' in clm_interface_pflotranMod + + public :: update_th_data_pf2clm + !-------------------------------------------------------------------------------------- contains -!!-------------------------------------------------------------------------------------- - subroutine get_clm_bgc_data(clm_bgc_data,bounds, & - num_soilc, filter_soilc, & +!-------------------------------------------------------------------------------------- + subroutine get_clm_data(clm_idata, & + bounds, num_soilc, filter_soilc, & num_soilp, filter_soilp, & - atm2lnd_vars, & + atm2lnd_vars, soilstate_vars, & waterstate_vars, waterflux_vars, & - soilstate_vars, temperature_vars, energyflux_vars, & - soilhydrology_vars, soil_water_retention_curve, & + temperature_vars, energyflux_vars, & cnstate_vars, carbonflux_vars, carbonstate_vars, & nitrogenflux_vars, nitrogenstate_vars, & phosphorusflux_vars, phosphorusstate_vars, & - canopystate_vars, ch4_vars & + ch4_vars & ) implicit none @@ -148,12 +150,11 @@ subroutine get_clm_bgc_data(clm_bgc_data,bounds, & integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches type(atm2lnd_type) , intent(in) :: atm2lnd_vars - type(canopystate_type) , intent(in) :: canopystate_vars + type(soilstate_type) , intent(in) :: soilstate_vars + type(waterstate_type) , intent(in) :: waterstate_vars type(waterflux_type) , intent(in) :: waterflux_vars - type(soilstate_type) , intent(in) :: soilstate_vars type(temperature_type) , intent(in) :: temperature_vars - type(soilhydrology_type) , intent(in) :: soilhydrology_vars type(energyflux_type) , intent(in) :: energyflux_vars type(cnstate_type) , intent(in) :: cnstate_vars @@ -165,45 +166,59 @@ subroutine get_clm_bgc_data(clm_bgc_data,bounds, & type(phosphorusstate_type) , intent(in) :: phosphorusstate_vars type(ch4_type) , intent(in) :: ch4_vars - class(soil_water_retention_curve_type) , intent(in) :: soil_water_retention_curve - type(clm_bgc_interface_data_type) , intent(inout) :: clm_bgc_data + type(clm_interface_data_type), intent(inout) :: clm_idata + + ! LOCAL + !type(clm_interface_th_datatype) , pointer :: clm_idata_th + !type(clm_interface_bgc_datatype), pointer :: clm_idata_bgc + + character(len=256) :: subname = "get_clm_data" !----------------------------------------------------------------------- - character(len=256) :: subname = "get_clm_bgc_data" + associate ( & + clm_idata_th => clm_idata%th, & + clm_idata_bgc => clm_idata%bgc & + ) - call get_clm_soil_property(clm_bgc_data, & + call get_clm_soil_property(clm_idata, & bounds, num_soilc, filter_soilc, & - soilstate_vars) + soilstate_vars, cnstate_vars) - call get_clm_soil_thermohydro(clm_bgc_data, & + call get_clm_soil_th_state(clm_idata_th, & bounds, num_soilc, filter_soilc, & atm2lnd_vars, soilstate_vars, & - waterstate_vars, waterflux_vars, & - temperature_vars, energyflux_vars, & - soil_water_retention_curve, & - canopystate_vars, ch4_vars) + waterstate_vars, temperature_vars) + + call get_clm_soil_th_flux(clm_idata_th, & + bounds, num_soilc, filter_soilc, & + waterflux_vars, energyflux_vars) - call get_clm_bgc_state(clm_bgc_data, & + call get_clm_bgc_state(clm_idata_bgc, & bounds, num_soilc, filter_soilc, & + atm2lnd_vars, soilstate_vars, & carbonstate_vars, nitrogenstate_vars, & - phosphorusstate_vars) + phosphorusstate_vars, & + ch4_vars) - call get_clm_bgc_flux(clm_bgc_data, & + call get_clm_bgc_flux(clm_idata_bgc, & bounds, num_soilc, filter_soilc, & cnstate_vars, carbonflux_vars, & - nitrogenflux_vars, phosphorusflux_vars) + nitrogenflux_vars, phosphorusflux_vars, & + ch4_vars) - end subroutine get_clm_bgc_data -!!-------------------------------------------------------------------------------------- + end associate + end subroutine get_clm_data +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- - subroutine get_clm_soil_property(clm_bgc_data, & +!-------------------------------------------------------------------------------------- + subroutine get_clm_soil_property(clm_idata, & bounds, num_soilc, filter_soilc, & - soilstate_vars) + soilstate_vars, cnstate_vars) + ! ! !DESCRIPTION: - ! get soil column physical properties + ! get soil column physical and biogeochemical properties ! ! !USES: use CNDecompCascadeConType, only : decomp_cascade_con @@ -218,18 +233,20 @@ subroutine get_clm_soil_property(clm_bgc_data, & integer , intent(in) :: num_soilc ! number of column soil points in column filter integer , intent(in) :: filter_soilc(:) ! column filter for soil points type(soilstate_type) , intent(in) :: soilstate_vars + type(cnstate_type) , intent(in) :: cnstate_vars - type(clm_bgc_interface_data_type), intent(inout) :: clm_bgc_data + type(clm_interface_data_type), intent(inout) :: clm_idata - integer :: fc, g, l, c, j ! indices + integer :: fc, g, l, c, j, k ! indices integer :: gcount, cellcount character(len= 32) :: subname = 'get_clm_soil_property' ! subroutine name - associate( & + associate ( & ! Assign local pointer to derived subtypes components (column-level) z => col_pp%z , & ! [real(r8) (:,:)] layer depth (m) dz => col_pp%dz , & ! [real(r8) (:,:)] layer thickness depth (m) + zi => col_pp%zi , & ! bd => soilstate_vars%bd_col , & ! bsw => soilstate_vars%bsw_col , & ! [real(r8) (:,:)] Clapp and Hornberger "b" (nlevgrnd) @@ -237,64 +254,80 @@ subroutine get_clm_soil_property(clm_bgc_data, & sucsat => soilstate_vars%sucsat_col , & ! [real(r8) (:,:)] minimum soil suction (mm) (nlevgrnd) watsat => soilstate_vars%watsat_col , & ! [real(r8) (:,:)] volumetric soil water at saturation (porosity) (nlevgrnd) watfc => soilstate_vars%watfc_col , & ! [real(r8) (:,:)] volumetric soil water at saturation (porosity) (nlevgrnd) - - cellorg => soilstate_vars%cellorg_col , & ! Input: [real(r8) (:,:) ] column 3D org (kg/m3 organic matter) (nlevgrnd) - + watmin => soilstate_vars%watmin_col , & ! col minimum volumetric soil water (nlevsoi) + sucmin => soilstate_vars%sucmin_col , & ! col minimum allowable soil liquid suction pressure (mm) [Note: sucmin_col is a negative value, while sucsat_col is a positive quantity] + ! + cellorg => soilstate_vars%cellorg_col , & ! Input: [real(r8) (:,:) ] column 3D org (kg/m3 organic matter) (nlevgrnd) + ! porosity => soilstate_vars%porosity_col , & eff_porosity => soilstate_vars%eff_porosity_col , & - + ! + rootfr => soilstate_vars%rootfr_col , & ! pft-level effective fraction of roots in each soil layer + ! initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & initial_cp_ratio => decomp_cascade_con%initial_cp_ratio , & - + ! decomp_pool_name => decomp_cascade_con%decomp_pool_name_history , & floating_cn_ratio => decomp_cascade_con%floating_cn_ratio_decomp_pools , & - floating_cp_ratio => decomp_cascade_con%floating_cp_ratio_decomp_pools & + floating_cp_ratio => decomp_cascade_con%floating_cp_ratio_decomp_pools , & + decomp_k_pools => decomp_cascade_con%decomp_k_pools , & + adfactor_kd_pools => decomp_cascade_con%spinup_factor , & + rf_decomp_cascade => cnstate_vars%rf_decomp_cascade_col , & + pathfrac_decomp_cascade => cnstate_vars%pathfrac_decomp_cascade_col & ) !------------------------------------------------------------------------------------- - !! constants: - clm_bgc_data%ndecomp_pools = ndecomp_pools - clm_bgc_data%decomp_pool_name(:) = decomp_pool_name(:) - clm_bgc_data%floating_cn_ratio(:) = floating_cn_ratio(:) - clm_bgc_data%floating_cp_ratio(:) = floating_cp_ratio(:) - - clm_bgc_data%initial_cn_ratio(:) = initial_cn_ratio(:) - clm_bgc_data%initial_cp_ratio(:) = initial_cp_ratio(:) - + ! constants: + clm_idata%bgc%ndecomp_pools = ndecomp_pools + clm_idata%bgc%decomp_pool_name(:) = decomp_pool_name(:) + clm_idata%bgc%floating_cn_ratio(:) = floating_cn_ratio(:) + clm_idata%bgc%floating_cp_ratio(:) = floating_cp_ratio(:) + clm_idata%bgc%initial_cn_ratio(:) = initial_cn_ratio(:) + clm_idata%bgc%initial_cp_ratio(:) = initial_cp_ratio(:) + clm_idata%bgc%decomp_k_pools(:) = decomp_k_pools(1:ndecomp_pools) + clm_idata%bgc%adfactor_kd_pools(:) = adfactor_kd_pools(1:ndecomp_pools) do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1,nlevsoi - clm_bgc_data%z(c,:) = z(c,:) - clm_bgc_data%dz(c,:) = dz(c,:) - clm_bgc_data%bd_col(c,:) = bd(c,:) - clm_bgc_data%bsw_col(c,:) = bsw(c,:) - clm_bgc_data%hksat_col(c,:) = hksat(c,:) - clm_bgc_data%sucsat_col(c,:) = sucsat(c,:) - clm_bgc_data%watsat_col(c,:) = watsat(c,:) - clm_bgc_data%watfc_col(c,:) = watfc(c,:) - - clm_bgc_data%porosity_col(c,:) = porosity(c,:) - clm_bgc_data%eff_porosity_col(c,:) = eff_porosity(c,:) - - clm_bgc_data%cellorg_col(c,:) = cellorg(c,:) -! end do + + clm_idata%z(c,:) = z(c,:) + clm_idata%zi(c,:) = zi(c,:) + clm_idata%dz(c,:) = dz(c,:) + clm_idata%bd_col(c,:) = bd(c,:) + clm_idata%bsw_col(c,:) = bsw(c,:) + clm_idata%hksat_col(c,:) = hksat(c,:) + clm_idata%sucsat_col(c,:) = sucsat(c,:) + clm_idata%watsat_col(c,:) = watsat(c,:) + clm_idata%watfc_col(c,:) = watfc(c,:) + clm_idata%watmin_col(c,:) = watmin(c,:) + clm_idata%sucmin_col(c,:) = sucmin(c,:) + + clm_idata%porosity_col(c,:) = porosity(c,:) + clm_idata%eff_porosity_col(c,:) = eff_porosity(c,:) + + clm_idata%cellorg_col(c,:) = cellorg(c,:) + + clm_idata%rootfr_col(c,:) = rootfr(c,:) + + ! + do k = 1, ndecomp_cascade_transitions + clm_idata%bgc%rf_decomp_cascade_col(c,:,k) = rf_decomp_cascade(c,:,k) + clm_idata%bgc%pathfrac_decomp_cascade_col(c,:,k) = pathfrac_decomp_cascade(c,:,k) + end do + end do - end associate + end associate end subroutine get_clm_soil_property -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- - subroutine get_clm_soil_thermohydro(clm_bgc_data, & +!-------------------------------------------------------------------------------------- + subroutine get_clm_soil_th_state(clm_idata_th, & bounds, num_soilc, filter_soilc, & atm2lnd_vars, soilstate_vars, & - waterstate_vars, waterflux_vars, & - temperature_vars, energyflux_vars, & - soil_water_retention_curve, & - canopystate_vars, ch4_vars) + waterstate_vars, temperature_vars) ! ! !DESCRIPTION: ! get soil temperature/saturation from CLM to soil BGC module @@ -313,199 +346,216 @@ subroutine get_clm_soil_thermohydro(clm_bgc_data, & type(atm2lnd_type) , intent(in) :: atm2lnd_vars type(soilstate_type) , intent(in) :: soilstate_vars type(waterstate_type) , intent(in) :: waterstate_vars - type(waterflux_type) , intent(in) :: waterflux_vars type(temperature_type) , intent(in) :: temperature_vars - type(energyflux_type) , intent(in) :: energyflux_vars - type(canopystate_type) , intent(in) :: canopystate_vars - type(ch4_type) , intent(in) :: ch4_vars - class(soil_water_retention_curve_type) , intent(in) :: soil_water_retention_curve - type(clm_bgc_interface_data_type) , intent(inout) :: clm_bgc_data + type(clm_interface_th_datatype) , intent(inout) :: clm_idata_th ! !LOCAL VARIABLES: - integer :: fc, c, j ! indices - integer :: pftindex, p -! real(r8) :: sattmp, psitmp, itheta -! real(r8) :: watmin(num_soilc, nlevsoi) -! real(r8) :: sucmin(num_soilc, nlevsoi) + integer :: fc, c, j ! indices !EOP !----------------------------------------------------------------------- associate ( & - gridcell => col_pp%gridcell , & ! column's gridcell - wtgcell => col_pp%wtgcell , & ! column's weight relative to gridcell - cactive => col_pp%active , & ! [logical (:)] column active or not - dz => col_pp%dz , & ! layer thickness depth (m) - zi => col_pp%zi , & ! interface depth (m) - - soilpsi => soilstate_vars%soilpsi_col , & ! soil water matric potential in each soil layer (MPa) - rootfr => soilstate_vars%rootfr_col , & ! pft-level effective fraction of roots in each soil layer - - h2osoi_vol => waterstate_vars%h2osoi_vol_col , & ! Input: [real(r8) (:,:) ] volumetric soil water (0<=h2osoi_vol<=watsat) [m3/m3] (nlevgrnd) - h2osoi_liq => waterstate_vars%h2osoi_liq_col , & ! liquid water (kg/m2) - h2osoi_ice => waterstate_vars%h2osoi_ice_col , & ! ice lens (kg/m2) - frac_sno => waterstate_vars%frac_sno_eff_col , & ! Input: fraction of ground covered by snow (0 to 1) - frac_h2osfc => waterstate_vars%frac_h2osfc_col , & ! Input: fraction of ground covered by surface water (0 to 1) - - t_soisno => temperature_vars%t_soisno_col , & ! snow-soil temperature (Kelvin) - t_grnd => temperature_vars%t_grnd_col , & ! Input: [real(r8) (:)] ground surface temperature [K] - - forc_pbot => atm2lnd_vars%forc_pbot_not_downscaled_grc, & ! atmospheric pressure (Pa) - forc_pco2 => atm2lnd_vars%forc_pco2_grc , & ! partial pressure co2 (Pa) - forc_pch4 => atm2lnd_vars%forc_pch4_grc , & ! partial pressure ch4 (Pa) - - alt_indx => canopystate_vars%alt_indx_col , & ! Input: [integer (:) ] current depth of thaw - o2stress_sat => ch4_vars%o2stress_sat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) - o2stress_unsat => ch4_vars%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) - finundated => ch4_vars%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area (excluding dedicated wetland columns) - o2_decomp_depth_unsat => ch4_vars%o2_decomp_depth_unsat_col , & ! Input: [real(r8) (:,:) ] O2 consumption during decomposition in each soil layer (nlevsoi) (mol/m3/s) - conc_o2_unsat => ch4_vars%conc_o2_unsat_col , & ! Input: [real(r8) (:,:) ] O2 conc in each soil layer (mol/m3) (nlevsoi) - o2_decomp_depth_sat => ch4_vars%o2_decomp_depth_sat_col , & ! Input: [real(r8) (:,:) ] O2 consumption during decomposition in each soil layer (nlevsoi) (mol/m3/s) - conc_o2_sat => ch4_vars%conc_o2_sat_col , & ! Input: [real(r8) (:,:) ] O2 conc in each soil layer (mol/m3) (nlevsoi) - - htvp => energyflux_vars%htvp_col , & ! Input: [real(r8) (:)] latent heat of vapor of water (or sublimation) [j/kg] - eflx_bot => energyflux_vars%eflx_bot_col , & ! heat flux from beneath column (W/m**2) [+ = upward] - eflx_gnet_patch => energyflux_vars%eflx_gnet_patch , & ! net ground heat flux into the surface (W/m**2) per patch - eflx_soil_grnd_patch => energyflux_vars%eflx_soil_grnd_patch , & ! soil heat flux (W/m**2) [+ = into soil] - - qflx_top_soil => waterflux_vars%qflx_top_soil_col , & ! Input: net water input into soil from top (mm/s) - qflx_ev_h2osfc => waterflux_vars%qflx_ev_h2osfc_col , & ! Input: column-level evaporation flux from h2osfc (W/m2) [+ to atm] : checking unit - qflx_evap_soi => waterflux_vars%qflx_evap_soi_col , & ! Input: column-level soil evaporation (mm H2O/s) (+ = to atm) - qflx_sub_snow => waterflux_vars%qflx_sub_snow_col , & ! Input: column-level evaporation flux from snow (mm H2O/s) [+ to atm] - qflx_tran_veg => waterflux_vars%qflx_tran_veg_col & ! Input: pft-level vegetation transpiration (mm H2O/s) (+ = to atm) + soilpsi => soilstate_vars%soilpsi_col , & ! + ! + frac_sno_eff => waterstate_vars%frac_sno_eff_col , & ! + frac_h2osfc => waterstate_vars%frac_h2osfc_col , & ! + h2osoi_vol => waterstate_vars%h2osoi_vol_col , & ! [real(r8) (:,:)] volumetric soil water (0<=h2osoi_vol<=watsat) [m3/m3] (nlevgrnd) + h2osoi_liq => waterstate_vars%h2osoi_liq_col , & ! [real(r8) (:,:)] liquid water (kg/m2) (-nlevsno+1:nlevgrnd) + h2osoi_ice => waterstate_vars%h2osoi_ice_col , & ! [real(r8) (:,:)] ice lens (kg/m2) (-nlevsno+1:nlevgrnd) + ! + t_soisno => temperature_vars%t_soisno_col , & ! [real(r8) (:,:)] snow-soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) + t_grnd => temperature_vars%t_grnd_col , & ! [real(r8) (:)] ground (snow/soil1/surfwater-mixed) temperature (Kelvin) + t_h2osfc => temperature_vars%t_h2osfc_col , & ! [real(r8) (:)] surface water temperature (Kelvin) + t_nearsurf => temperature_vars%t_nearsurf_col , & ! [real(r8) (:)] near surface air temperature (Kelvin) + ! + forc_pbot => atm2lnd_vars%forc_pbot_not_downscaled_grc & ! atmospheric pressure (Pa) + ) - ) !-------------------------------------------------------------------------------------- -! -! watmin(:,:) = 0.01_r8 -! sucmin(:,:) = 1.e8_r8 - - !! grid: - clm_bgc_data%forc_pbot_not_downscaled_grc(:) = forc_pbot(:) - clm_bgc_data%forc_pco2_grc(:) = forc_pco2(:) - clm_bgc_data%forc_pch4_grc(:) = forc_pch4(:) - + ! grid: + clm_idata_th%forc_pbot_grc = forc_pbot do fc = 1,num_soilc c = filter_soilc(fc) - clm_bgc_data%frac_sno_eff_col(c) = frac_sno(c) - clm_bgc_data%frac_h2osfc_col(c) = frac_h2osfc(c) + clm_idata_th%frac_sno_eff_col(c) = frac_sno_eff(c) + clm_idata_th%frac_h2osfc_col(c) = frac_h2osfc(c) - clm_bgc_data%t_grnd_col(c) = t_grnd(c) + clm_idata_th%t_grnd_col(c) = t_grnd(c) + clm_idata_th%t_h2osfc_col(c) = t_h2osfc(c) + clm_idata_th%t_nearsurf_col(c) = t_nearsurf(c) - clm_bgc_data%alt_indx_col(c) = alt_indx(c) - clm_bgc_data%finundated_col(c) = finundated(c) + do j = -nlevsno+1,nlevgrnd + if(j>=1) then + clm_idata_th%soilpsi_col(c,j) = soilpsi(c,j) + clm_idata_th%h2osoi_vol_col(c,j) = h2osoi_vol(c,j) + endif - clm_bgc_data%qflx_top_soil_col(c) = qflx_top_soil(c) - clm_bgc_data%qflx_ev_h2osfc_col(c) = qflx_ev_h2osfc(c) - clm_bgc_data%qflx_evap_soi_col(c) = qflx_evap_soi(c) - clm_bgc_data%qflx_sub_snow_col(c) = qflx_sub_snow(c) - clm_bgc_data%qflx_tran_veg_col(c) = qflx_tran_veg(c) + clm_idata_th%h2osoi_liq_col(c,j) = h2osoi_liq(c,j) + clm_idata_th%h2osoi_ice_col(c,j) = h2osoi_ice(c,j) + clm_idata_th%t_soisno_col(c,j) = t_soisno(c,j) + end do - clm_bgc_data%htvp_col(c) = htvp(c) - clm_bgc_data%eflx_bot_col(c) = eflx_bot(c) + end do -! do j = 1, nlevsoi - clm_bgc_data%soilpsi_col(c,:) = soilpsi(c,:) - clm_bgc_data%rootfr_col(c,:) = rootfr(c,:) + end associate + end subroutine get_clm_soil_th_state +!-------------------------------------------------------------------------------------- - clm_bgc_data%h2osoi_vol_col(c,:) = h2osoi_vol(c,:) - clm_bgc_data%h2osoi_liq_col(c,:) = h2osoi_liq(c,:) - clm_bgc_data%h2osoi_ice_col(c,:) = h2osoi_ice(c,:) +!-------------------------------------------------------------------------------------- + subroutine get_clm_soil_th_flux(clm_idata_th, & + bounds, num_soilc, filter_soilc, & + waterflux_vars, energyflux_vars) + ! + ! !DESCRIPTION: + ! get soil temperature/saturation from CLM to soil BGC module + ! + ! !USES: + use clm_time_manager , only : get_nstep + use shr_const_mod , only : SHR_CONST_G - clm_bgc_data%t_soisno_col(c,:) = t_soisno(c,:) - clm_bgc_data%o2stress_unsat_col(c,:) = o2stress_unsat(c,:) - clm_bgc_data%o2stress_sat_col(c,:) = o2stress_sat(c,:) - clm_bgc_data%o2_decomp_depth_unsat_col(c,:) = o2_decomp_depth_unsat(c,:) - clm_bgc_data%conc_o2_unsat_col(c,:) = conc_o2_unsat(c,:) - clm_bgc_data%o2_decomp_depth_sat_col(c,:) = o2_decomp_depth_sat(c,:) - clm_bgc_data%conc_o2_sat_col(c,:) = conc_o2_sat(c,:) + ! !ARGUMENTS: + implicit none -! end do - end do + type(bounds_type) , intent(in) :: bounds ! bounds + integer , intent(in) :: num_soilc ! number of column soil points in column filter + integer , intent(in) :: filter_soilc(:) ! column filter for soil points + type(waterflux_type) , intent(in) :: waterflux_vars + type(energyflux_type) , intent(in) :: energyflux_vars - ! CLM appears NO column-level ground-heat-flux variable, instead by 'patch' - do fc = 1, num_soilc + type(clm_interface_th_datatype) , intent(inout) :: clm_idata_th + + ! !LOCAL VARIABLES: + integer :: fc, c, j ! indices + + !EOP + !----------------------------------------------------------------------- + associate ( & + qflx_top_soil => waterflux_vars%qflx_top_soil_col , & ! [real(:,:)] net liq. water input into top of soil column (mmH2O/s) + qflx_evap_soil => waterflux_vars%qflx_ev_soil_col , & ! [real(:)] ! col soil surface evaporation (mm H2O/s) (+ = to atm) + qflx_evap_h2osfc => waterflux_vars%qflx_ev_h2osfc_col , & ! [real(:)] ! col water surface evaporation (mm H2O/s) (+ = to atm) + qflx_evap_snow => waterflux_vars%qflx_ev_snow_col , & ! [real(:)] ! col snow surface evaporation (mm H2O/s) (+ = to atm) + qflx_subl_snow => waterflux_vars%qflx_sub_snow_col , & ! [real(:)] ! col snow sublimation (mm H2O/s) (+ = to atm) + qflx_tran_veg => waterflux_vars%qflx_tran_veg_col , & ! [real(:)] ! col plant transpiration (mm H2O/s) (+ = to atm) + qflx_rootsoil => waterflux_vars%qflx_rootsoi_col , & ! [real(:,:)] ! col vertically-resolved root and soil water exchange [mm H2O/s] [+ into root] + ! + htvp => energyflux_vars%htvp_col , & ! [real(:) ! latent heat of vapor of water (or sublimation) [j/kg] + eflx_bot => energyflux_vars%eflx_bot_col , & ! [real(:) ! col heat flux from beneath the soil or ice column (W/m**2) + eflx_soil_grnd => energyflux_vars%eflx_soil_grnd_col , & ! [real(:) ! col soil (ground) heat flux (W/m**2) [+ = into ground] + eflx_fgr0_snow => energyflux_vars%eflx_fgr0_snow_col , & ! [real(:) ! col ground heat flux from snow bottom to first soil layer (W/m**2) [+ = into soil] + eflx_fgr0_h2osfc => energyflux_vars%eflx_fgr0_h2osfc_col , & ! [real(:) ! col ground heat flux from surface water bottom to first soil layer (W/m**2) [+ = into soil] + eflx_fgr0_soil => energyflux_vars%eflx_fgr0_soil_col , & ! [real(:) ! col ground heat flux from near-surface air to first soil layer (W/m**2) [+ = into soil] + eflx_rnet_soil => energyflux_vars%eflx_rnet_soil_col & ! [real(:) ! net radiation flux between soil layer 1 and above-air, excluding SH and LE (i.e. radiation form only ) (W/m2) [+ = into soil] + + ) + + ! a few notes: + ! - 'qflx_evap_soil' appears for total soil surface, esp. bare soil; 'qflx_ev_soil/snow/h2osfc' are actually applied for in soil water modules + ! - 'qflx_ev_snow' vs. 'qflx_sub_snow': the former is for total evap from both solid/liq., the latter is from solid snow pack (normally shall be same) + ! there is another variable 'qlfx_evap_grnd', which are those from liq. water when snow + !-------------------------------------------------------------------------------------- +! + do fc = 1,num_soilc c = filter_soilc(fc) - clm_bgc_data%eflx_soil_grnd_col(c) = 0._r8 - clm_bgc_data%eflx_gnet_col(c) = 0._r8 - do pftindex = 1, max_patch_per_col - if (pftindex <= col_pp%npfts(c)) then - p = col_pp%pfti(c) + pftindex - 1 - clm_bgc_data%eflx_soil_grnd_col(c) = clm_bgc_data%eflx_soil_grnd_col(c) & - + eflx_soil_grnd_patch(p) * veg_pp%wtcol(p) ! W/m2 - clm_bgc_data%eflx_gnet_col(c) = clm_bgc_data%eflx_gnet_col(c) & - + eflx_gnet_patch(p) * veg_pp%wtcol(p) - end if - end do + + clm_idata_th%qflx_top_soil_col(c) = qflx_top_soil(c) + clm_idata_th%qflx_evap_soil_col(c) = qflx_evap_soil(c) + clm_idata_th%qflx_evap_h2osfc_col(c) = qflx_evap_h2osfc(c) + clm_idata_th%qflx_evap_snow_col(c) = qflx_evap_snow(c) + clm_idata_th%qflx_subl_snow_col(c) = qflx_subl_snow(c) + clm_idata_th%qflx_tran_veg_col(c) = qflx_tran_veg(c) + + do j = 1,nlevgrnd + clm_idata_th%qflx_rootsoil_col(c,j) = qflx_rootsoil(c,j) + end do + + clm_idata_th%htvp_col(c) = htvp(c) + clm_idata_th%eflx_bot_col(c) = eflx_bot(c) + clm_idata_th%eflx_soil_grnd_col(c) = eflx_soil_grnd(c) + clm_idata_th%eflx_fgr0_snow_col(c) = eflx_fgr0_snow(c) + clm_idata_th%eflx_fgr0_h2osfc_col(c) = eflx_fgr0_h2osfc(c) + clm_idata_th%eflx_fgr0_soil_col(c) = eflx_fgr0_soil(c) + clm_idata_th%eflx_rnet_soil_col(c) = eflx_rnet_soil(c) + end do -! -!write(*,'(A30,12E14.6)')">>>DEBUG | soillsat=", soillsat_clmp_loc(1:10) -!write(*,'(A30,12E14.6)')">>>DEBUG | gsoilpsi[Pa]=", soilpsi_clmp_loc(1:10) -!write(*,'(A30,12E14.6)')">>>DEBUG | soilt[oC]=", soilt_clmp_loc(1:10) + end associate + end subroutine get_clm_soil_th_flux +!-------------------------------------------------------------------------------------- - end associate - end subroutine get_clm_soil_thermohydro -!!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine get_clm_bgc_state(clm_bgc_data, & bounds, num_soilc, filter_soilc, & + atm2lnd_vars, soilstate_vars, & carbonstate_vars, nitrogenstate_vars, & - phosphorusstate_vars) + phosphorusstate_vars, & + ch4_vars) - !! get clm bgc state variables + ! get clm bgc state variables implicit none 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 + type(atm2lnd_type) , intent(in) :: atm2lnd_vars + type(soilstate_type) , intent(in) :: soilstate_vars type(carbonstate_type) , intent(in) :: carbonstate_vars type(nitrogenstate_type) , intent(in) :: nitrogenstate_vars type(phosphorusstate_type) , intent(in) :: phosphorusstate_vars -! type(ch4_type) , intent(in) :: ch4_vars + type(ch4_type) , intent(in) :: ch4_vars ! not yet used, but will be. - type(clm_bgc_interface_data_type), intent(inout) :: clm_bgc_data + type(clm_interface_bgc_datatype), intent(inout) :: clm_bgc_data character(len=256) :: subname = "get_clm_bgc_state" ! Local variables integer :: fc, c, j, k -! integer :: gcount, cellcount -! real(r8) :: wtgcell, realc_gcell, realn_gcell - !------------------------------------------------------------------------------------------ ! associate ( & - decomp_cpools_vr=> carbonstate_vars%decomp_cpools_vr_col , & ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - decomp_npools_vr=> nitrogenstate_vars%decomp_npools_vr_col , & ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools + decomp_cpools_vr=> carbonstate_vars%decomp_cpools_vr_col , & ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools + decomp_npools_vr=> nitrogenstate_vars%decomp_npools_vr_col , & ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools decomp_ppools_vr=> phosphorusstate_vars%decomp_ppools_vr_col , & ! [real(r8) (:,:,:) ! col (gP/m3) vertically-resolved decomposing (litter, cwd, soil) P pools - - smin_no3_vr => nitrogenstate_vars%smin_no3_vr_col , & ! (gN/m3) vertically-resolved soil mineral NO3 - smin_nh4_vr => nitrogenstate_vars%smin_nh4_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 - smin_nh4sorb_vr => nitrogenstate_vars%smin_nh4sorb_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 absorbed - + smin_no3_vr => nitrogenstate_vars%smin_no3_vr_col , & ! (gN/m3) vertically-resolved soil mineral NO3 + smin_nh4_vr => nitrogenstate_vars%smin_nh4_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 + smin_nh4sorb_vr => nitrogenstate_vars%smin_nh4sorb_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 absorbed + ! solutionp_vr => phosphorusstate_vars%solutionp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil solution P labilep_vr => phosphorusstate_vars%labilep_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil labile mineral P secondp_vr => phosphorusstate_vars%secondp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil secondary mineralP sminp_vr => phosphorusstate_vars%sminp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil mineral P = solutionp + labilep + secondp occlp_vr => phosphorusstate_vars%occlp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil occluded mineral P - primp_vr => phosphorusstate_vars%primp_vr_col & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil primary mineral P + primp_vr => phosphorusstate_vars%primp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil primary mineral P + ! + forc_pco2 => atm2lnd_vars%forc_pco2_grc , & ! partial pressure co2 (Pa) + forc_pch4 => atm2lnd_vars%forc_pch4_grc , & ! partial pressure ch4 (Pa) + ! + o2stress_sat => ch4_vars%o2stress_sat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) + o2stress_unsat => ch4_vars%o2stress_unsat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) + finundated => ch4_vars%finundated_col , & ! Input: [real(r8) (:) ] fractional inundated area (excluding dedicated wetland columns) + o2_decomp_depth_unsat => ch4_vars%o2_decomp_depth_unsat_col , & ! Input: [real(r8) (:,:) ] O2 consumption during decomposition in each soil layer (nlevsoi) (mol/m3/s) + conc_o2_unsat => ch4_vars%conc_o2_unsat_col , & ! Input: [real(r8) (:,:) ] O2 conc in each soil layer (mol/m3) (nlevsoi) + o2_decomp_depth_sat => ch4_vars%o2_decomp_depth_sat_col , & ! Input: [real(r8) (:,:) ] O2 consumption during decomposition in each soil layer (nlevsoi) (mol/m3/s) + conc_o2_sat => ch4_vars%conc_o2_sat_col & ! Input: [real(r8) (:,:) ] O2 conc in each soil layer (mol/m3) (nlevsoi) ) ! + + clm_bgc_data%forc_pco2_grc(:) = forc_pco2(:) + clm_bgc_data%forc_pch4_grc(:) = forc_pch4(:) + do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp do k = 1, ndecomp_pools clm_bgc_data%decomp_cpools_vr_col(c,:,k) = decomp_cpools_vr(c,:,k) clm_bgc_data%decomp_npools_vr_col(c,:,k) = decomp_npools_vr(c,:,k) clm_bgc_data%decomp_ppools_vr_col(c,:,k) = decomp_ppools_vr(c,:,k) + end do clm_bgc_data%smin_no3_vr_col(c,:) = smin_no3_vr(c,:) @@ -518,30 +568,38 @@ subroutine get_clm_bgc_state(clm_bgc_data, & clm_bgc_data%sminp_vr_col(c,:) = solutionp_vr(c,:) + labilep_vr(c,:) + secondp_vr(c,:) clm_bgc_data%occlp_vr_col(c,:) = occlp_vr(c,:) clm_bgc_data%primp_vr_col(c,:) = primp_vr(c,:) -! end do + + clm_bgc_data%finundated_col(c) = finundated(c) + clm_bgc_data%o2stress_unsat_col(c,:) = o2stress_unsat(c,:) + clm_bgc_data%o2stress_sat_col(c,:) = o2stress_sat(c,:) + clm_bgc_data%o2_decomp_depth_unsat_col(c,:) = o2_decomp_depth_unsat(c,:) + clm_bgc_data%conc_o2_unsat_col(c,:) = conc_o2_unsat(c,:) + clm_bgc_data%o2_decomp_depth_sat_col(c,:) = o2_decomp_depth_sat(c,:) + clm_bgc_data%conc_o2_sat_col(c,:) = conc_o2_sat(c,:) + end do +!----------------------------------------------------------------------------- end associate end subroutine get_clm_bgc_state -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- - subroutine get_clm_bgc_flux(clm_bgc_data, & - bounds, num_soilc, filter_soilc, & - cnstate_vars, carbonflux_vars, nitrogenflux_vars, & - phosphorusflux_vars) +!-------------------------------------------------------------------------------------- + subroutine get_clm_bgc_flux(clm_bgc_data, & + bounds, num_soilc, filter_soilc, & + cnstate_vars, carbonflux_vars, & + nitrogenflux_vars, phosphorusflux_vars, & + ch4_vars) ! ! !DESCRIPTION: - !! get clm bgc flux variables: external inputs to bgc state variables (pools) + ! get clm bgc flux variables: external inputs to bgc state variables (pools) ! ! !USES: - -! use clm_time_manager, only : get_step_size, get_nstep - -! use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd - + use clm_time_manager , only : get_curr_date + use clm_varctl , only : spinup_state + use CNDecompCascadeConType, only : decomp_cascade_con ! !ARGUMENTS: implicit none @@ -554,17 +612,18 @@ subroutine get_clm_bgc_flux(clm_bgc_data, & type(carbonflux_type) , intent(in) :: carbonflux_vars type(nitrogenflux_type) , intent(in) :: nitrogenflux_vars type(phosphorusflux_type) , intent(in) :: phosphorusflux_vars - type(clm_bgc_interface_data_type) , intent(inout) :: clm_bgc_data + type(ch4_type) , intent(in) :: ch4_vars ! not yet used, but will be. + + type(clm_interface_bgc_datatype) , intent(inout) :: clm_bgc_data character(len=256) :: subname = "get_clm_bgc_flux" ! !LOCAL VARIABLES: integer :: fc, c, g, j, k ! do loop indices -! integer :: gcount, cellcount -! real(r8) :: wtgcell, realc_gcell, realn_gcell real(r8) :: dtime ! land model time step (sec) + integer :: year, mon, day, sec ! ratios of NH4:NO3 in N deposition and fertilization (temporarily set here, will be as inputs) real(r8) :: r_nh4_no3_dep(bounds%begc:bounds%endc) @@ -581,6 +640,9 @@ subroutine get_clm_bgc_flux(clm_bgc_data, & externalc_to_decomp_cpools_vr => carbonflux_vars%externalc_to_decomp_cpools_col , & externaln_to_decomp_npools_vr => nitrogenflux_vars%externaln_to_decomp_npools_col , & externalp_to_decomp_ppools_vr => phosphorusflux_vars%externalp_to_decomp_ppools_col , & + t_scalar => carbonflux_vars%t_scalar_col , & ! Output: [real(r8) (:,:) ] soil temperature scalar for decomp + w_scalar => carbonflux_vars%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp + o_scalar => carbonflux_vars%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia ! inorg. nitrogen source ndep_to_sminn => nitrogenflux_vars%ndep_to_sminn_col , & nfix_to_sminn => nitrogenflux_vars%nfix_to_sminn_col , & @@ -591,7 +653,10 @@ subroutine get_clm_bgc_flux(clm_bgc_data, & nfixation_prof => cnstate_vars%nfixation_prof_col , & ndep_prof => cnstate_vars%ndep_prof_col , & + decomp_k_scalar => cnstate_vars%scalaravg_col , & + no3_net_transport_vr => nitrogenflux_vars%no3_net_transport_vr_col , & + nh4_net_transport_vr => nitrogenflux_vars%nh4_net_transport_vr_col , & col_plant_ndemand_vr => nitrogenflux_vars%plant_ndemand_vr_col , & plant_ndemand_col => nitrogenflux_vars%plant_ndemand_col , & @@ -605,60 +670,78 @@ subroutine get_clm_bgc_flux(clm_bgc_data, & sminp_net_transport_vr => phosphorusflux_vars%sminp_net_transport_vr_col & ) -! dtime = get_step_size() - + ! + call get_curr_date(year, mon, day, sec) ! r_nh4_no3_dep(:) = 1.0_r8 ! temporarily assuming half of N dep is in NH4 and another half in NO3 r_nh4_no3_fert(:) = 1.0_r8 ! temporarily assiming half of N fertilization is in NH4 and another half in NO3 + ! do fc = 1,num_soilc c = filter_soilc(fc) + + clm_bgc_data%t_scalar_col(c,:) = t_scalar(c,:) + clm_bgc_data%w_scalar_col(c,:) = w_scalar(c,:) + clm_bgc_data%o_scalar_col(c,:) = o_scalar(c,:) + + clm_bgc_data%plant_ndemand_col(c) = plant_ndemand_col(c) clm_bgc_data%plant_pdemand_col(c) = plant_pdemand_col(c) fnh4_dep = max(0._r8, min(1.0_r8, 1._r8/(r_nh4_no3_dep(c)+1._r8))) fnh4_fert = max(0._r8, min(1.0_r8, 1._r8/(r_nh4_no3_fert(c)+1._r8))) -! do j = 1, nlevdecomp - do k = 1, ndecomp_pools - clm_bgc_data%externalc_to_decomp_cpools_col(c,:,k) = externalc_to_decomp_cpools_vr(c,:,k) - clm_bgc_data%externaln_to_decomp_npools_col(c,:,k) = externaln_to_decomp_npools_vr(c,:,k) - clm_bgc_data%externalp_to_decomp_ppools_col(c,:,k) = externalp_to_decomp_ppools_vr(c,:,k) - end do + do k = 1, ndecomp_pools + clm_bgc_data%externalc_to_decomp_cpools_col(c,:,k) = externalc_to_decomp_cpools_vr(c,:,k) + clm_bgc_data%externaln_to_decomp_npools_col(c,:,k) = externaln_to_decomp_npools_vr(c,:,k) + clm_bgc_data%externalp_to_decomp_ppools_col(c,:,k) = externalp_to_decomp_ppools_vr(c,:,k) + end do - clm_bgc_data%externaln_to_nh4_col(c,:) = fnh4_dep*ndep_to_sminn(c) * ndep_prof(c,:) + & - fnh4_fert*fert_to_sminn(c) * ndep_prof(c,:) + & - fnh4_fert*supplement_to_sminn_vr(c,:) + & - nfix_to_sminn(c) * nfixation_prof(c,:) + & - soyfixn_to_sminn(c) * nfixation_prof(c,:) + ! the following is for CTC ad-spinup. + ! There is a 'time' control here, so MUST be called each time-step, + ! and then better put the code here rather than in 'get_clm_bgc_state' + if (spinup_state == 1 .and. year >= 40) then + clm_bgc_data%sitefactor_kd_vr_col(c,:) = decomp_k_scalar(c) + else + clm_bgc_data%sitefactor_kd_vr_col(c,:) = 1.0_r8 + end if - clm_bgc_data%externaln_to_no3_col(c,:) = (1._r8-fnh4_dep)*ndep_to_sminn(c) * ndep_prof(c, :) + & - (1._r8-fnh4_fert)*fert_to_sminn(c) * ndep_prof(c, :) + & - (1._r8-fnh4_fert)*supplement_to_sminn_vr(c,:) - clm_bgc_data%externalp_to_primp_col(c,:) = pdep_to_sminp(c)*ndep_prof(c, :) - clm_bgc_data%externalp_to_labilep_col(c,:) = fert_p_to_sminp(c)*ndep_prof(c, :) - clm_bgc_data%externalp_to_solutionp_col(c,:) = supplement_to_sminp_vr(c,:) - !! net flux to no3 = externaln_to_no3_col(c,j) - no3_net_transport_vr_col(c,j) - clm_bgc_data%no3_net_transport_vr_col(c,:) = no3_net_transport_vr(c,:) - clm_bgc_data%sminp_net_transport_vr_col(c,:) = sminp_net_transport_vr(c,:) !!from solutionp + clm_bgc_data%externaln_to_nh4_col(c,:) = fnh4_dep*ndep_to_sminn(c) * ndep_prof(c,:) + & + fnh4_fert*fert_to_sminn(c) * ndep_prof(c,:) + & + fnh4_fert*supplement_to_sminn_vr(c,:) + & + nfix_to_sminn(c) * nfixation_prof(c,:) + & + soyfixn_to_sminn(c) * nfixation_prof(c,:) - clm_bgc_data%plant_ndemand_vr_col(c,:) = col_plant_ndemand_vr(c,:) - clm_bgc_data%plant_pdemand_vr_col(c,:) = col_plant_pdemand_vr(c,:) + clm_bgc_data%externaln_to_no3_col(c,:) = (1._r8-fnh4_dep)*ndep_to_sminn(c) * ndep_prof(c, :) + & + (1._r8-fnh4_fert)*fert_to_sminn(c) * ndep_prof(c, :) + & + (1._r8-fnh4_fert)*supplement_to_sminn_vr(c,:) -! end do - end do + + + clm_bgc_data%externalp_to_primp_col(c,:) = pdep_to_sminp(c)*ndep_prof(c, :) + clm_bgc_data%externalp_to_labilep_col(c,:) = fert_p_to_sminp(c)*ndep_prof(c, :) + clm_bgc_data%externalp_to_solutionp_col(c,:) = supplement_to_sminp_vr(c,:) + + clm_bgc_data%no3_net_transport_vr_col(c,:) = no3_net_transport_vr(c,:) + clm_bgc_data%nh4_net_transport_vr_col(c,:) = nh4_net_transport_vr(c,:) + clm_bgc_data%sminp_net_transport_vr_col(c,:) = sminp_net_transport_vr(c,:) !from solutionp + + clm_bgc_data%plant_ndemand_vr_col(c,:) = col_plant_ndemand_vr(c,:) + clm_bgc_data%plant_pdemand_vr_col(c,:) = col_plant_pdemand_vr(c,:) + + end do ! fc = 1,num_soilc end associate end subroutine get_clm_bgc_flux -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- - subroutine update_soil_moisture(clm_bgc_data, & +!-------------------------------------------------------------------------------------- + subroutine update_soil_moisture(clm_idata_th, & bounds, num_soilc, filter_soilc, & - waterstate_vars) + soilstate_vars, waterstate_vars) ! ! !DESCRIPTION: @@ -672,9 +755,10 @@ subroutine update_soil_moisture(clm_bgc_data, & type(bounds_type), intent(in) :: bounds integer, intent(in) :: num_soilc ! number of column soil points in column filter integer, intent(in) :: filter_soilc(:) ! column filter for soil points -! type(soilstate_type) , intent(in) :: soilstate_vars + type(soilstate_type), intent(inout) :: soilstate_vars type(waterstate_type), intent(inout) :: waterstate_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data + + type(clm_interface_th_datatype), intent(in) :: clm_idata_th ! !LOCAL VARIABLES: integer :: fc, c, j, g, gcount ! indices @@ -682,6 +766,8 @@ subroutine update_soil_moisture(clm_bgc_data, & !EOP !----------------------------------------------------------------------- associate ( & + soilpsi_col => soilstate_vars%soilpsi_col , & + ! h2osoi_liq_col => waterstate_vars%h2osoi_liq_col , & h2osoi_ice_col => waterstate_vars%h2osoi_ice_col , & h2osoi_vol_col => waterstate_vars%h2osoi_vol_col & @@ -689,20 +775,21 @@ subroutine update_soil_moisture(clm_bgc_data, & do fc = 1,num_soilc c = filter_soilc(fc) -! do j = 1, nlevsoi - h2osoi_liq_col(c,:) = clm_bgc_data%h2osoi_liq_col(c,:) - h2osoi_ice_col(c,:) = clm_bgc_data%h2osoi_ice_col(c,:) - h2osoi_vol_col(c,:) = clm_bgc_data%h2osoi_vol_col(c,:) -! end do + + soilpsi_col(c,:) = clm_idata_th%soilpsi_col(c,:) + + h2osoi_liq_col(c,:) = clm_idata_th%h2osoi_liq_col(c,:) + h2osoi_ice_col(c,:) = clm_idata_th%h2osoi_ice_col(c,:) + h2osoi_vol_col(c,:) = clm_idata_th%h2osoi_vol_col(c,:) end do end associate end subroutine update_soil_moisture -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- - subroutine update_soil_temperature(clm_bgc_data, & - bounds, num_soilc, filter_soilc, & +!-------------------------------------------------------------------------------------- + subroutine update_soil_temperature(clm_idata_th, & + bounds, num_soilc, filter_soilc, & temperature_vars) ! @@ -718,7 +805,7 @@ subroutine update_soil_temperature(clm_bgc_data, & integer , intent(in) :: num_soilc ! number of column soil points in column filter integer , intent(in) :: filter_soilc(:) ! column filter for soil points type(temperature_type) , intent(inout) :: temperature_vars - type(clm_bgc_interface_data_type) , intent(in) :: clm_bgc_data + type(clm_interface_th_datatype) , intent(in) :: clm_idata_th ! !LOCAL VARIABLES: integer :: fc, c, j, g, gcount ! indices @@ -728,30 +815,67 @@ subroutine update_soil_temperature(clm_bgc_data, & associate ( & t_soisno => temperature_vars%t_soisno_col & ! snow-soil temperature (Kelvin) ) + do fc = 1,num_soilc c = filter_soilc(fc) -! do j = 1, nlevsoi - t_soisno(c,:) = clm_bgc_data%t_soisno_col(c,:) -! end do + t_soisno(c,:) = clm_idata_th%t_soisno_col(c,:) end do end associate end subroutine update_soil_temperature -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- + subroutine update_th_data_pf2clm(clm_idata_th, & + bounds, num_soilc, filter_soilc, & + waterstate_vars, waterflux_vars, & + temperature_vars, energyflux_vars, & + soilstate_vars, soilhydrology_vars) + + ! USES + use clm_varctl , only : use_pflotran, pf_tmode, pf_hmode + + implicit none + + ! !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 + type(waterstate_type) , intent(inout) :: waterstate_vars + type(waterflux_type) , intent(inout) :: waterflux_vars + type(temperature_type) , intent(inout) :: temperature_vars + type(soilstate_type) , intent(inout) :: soilstate_vars + type(soilhydrology_type) , intent(inout) :: soilhydrology_vars + type(energyflux_type) , intent(inout) :: energyflux_vars + + type(clm_interface_th_datatype), intent(in) :: clm_idata_th -!!-------------------------------------------------------------------------------------- - subroutine update_bgc_state_decomp(clm_bgc_data, & + !----------------------------------------------------------------------- + + character(len=256) :: subname = "update_th_data_pf2clm" + + if (pf_tmode) then + call update_soil_temperature(clm_idata_th, & + bounds, num_soilc, filter_soilc, & + temperature_vars) + end if + + if (pf_hmode) then + call update_soil_moisture(clm_idata_th, & + bounds, num_soilc, filter_soilc, & + soilstate_vars, waterstate_vars) + end if + + end subroutine update_th_data_pf2clm +!-------------------------------------------------------------------------------------- + + +!-------------------------------------------------------------------------------------- + subroutine update_bgc_state_decomp(clm_bgc_data, & bounds, num_soilc, filter_soilc, & carbonstate_vars, nitrogenstate_vars, & phosphorusstate_vars & ) -! use CNDecompCascadeConType, only : decomp_cascade_con -! use clm_time_manager, only : get_step_size -!#ifndef FLEXIBLE_POOLS -! use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -!#endif - implicit none type(bounds_type) , intent(in) :: bounds @@ -762,51 +886,41 @@ subroutine update_bgc_state_decomp(clm_bgc_data, & type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars - type(clm_bgc_interface_data_type) , intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype) , intent(in) :: clm_bgc_data character(len=256) :: subname = "update_soil_bgc_state" integer :: fc,c,j,k -! integer :: gcount, cellcount -! real(r8) :: wtgcell - -! real(r8) :: dtime ! land model time step (sec) !------------------------------------------------------------------------------------ - ! - associate ( & - decomp_cpools_vr => carbonstate_vars%decomp_cpools_vr_col , & - decomp_npools_vr => nitrogenstate_vars%decomp_npools_vr_col , & - decomp_ppools_vr => phosphorusstate_vars%decomp_ppools_vr_col & - ) + ! + associate ( & + decomp_cpools_vr => carbonstate_vars%decomp_cpools_vr_col , & + decomp_npools_vr => nitrogenstate_vars%decomp_npools_vr_col , & + decomp_ppools_vr => phosphorusstate_vars%decomp_ppools_vr_col & + ) ! ------------------------------------------------------------------------ -! dtime = get_step_size() ! do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp do k = 1, ndecomp_pools decomp_cpools_vr(c,:,k) = clm_bgc_data%decomp_cpools_vr_col(c,:,k) decomp_npools_vr(c,:,k) = clm_bgc_data%decomp_npools_vr_col(c,:,k) decomp_ppools_vr(c,:,k) = clm_bgc_data%decomp_ppools_vr_col(c,:,k) end do -! end do end do end associate end subroutine update_bgc_state_decomp -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_state_smin(clm_bgc_data, & bounds, num_soilc, filter_soilc, & nitrogenstate_vars, phosphorusstate_vars) use CNDecompCascadeConType, only : decomp_cascade_con use clm_time_manager, only : get_step_size -!#ifndef FLEXIBLE_POOLS -! use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -!#endif implicit none @@ -817,15 +931,11 @@ subroutine update_bgc_state_smin(clm_bgc_data, & type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype), intent(in) :: clm_bgc_data character(len=256) :: subname = "update_bgc_state_smin" integer :: fc,c,j -! integer :: gcount, cellcount -! real(r8) :: wtgcell -! -! real(r8) :: dtime ! land model time step (sec) !------------------------------------------------------------------------------------ ! @@ -844,11 +954,9 @@ subroutine update_bgc_state_smin(clm_bgc_data, & ) ! ------------------------------------------------------------------------ -! dtime = get_step_size() ! do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp smin_no3_vr(c,:) = clm_bgc_data%smin_no3_vr_col(c,:) smin_nh4_vr(c,:) = clm_bgc_data%smin_nh4_vr_col(c,:) smin_nh4sorb_vr(c,:) = clm_bgc_data%smin_nh4sorb_vr_col(c,:) @@ -860,25 +968,19 @@ subroutine update_bgc_state_smin(clm_bgc_data, & sminp_vr(c,:) = clm_bgc_data%sminp_vr_col(c,:) occlp_vr(c,:) = clm_bgc_data%occlp_vr_col(c,:) primp_vr(c,:) = clm_bgc_data%primp_vr_col(c,:) -! end do end do -!write(*,'(A30,12E14.6)')"DEBUG | clm UPDATE no3=",smin_no3_vr(1,1:nlevdecomp) end associate end subroutine update_bgc_state_smin -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_flux_decomp_sourcesink(clm_bgc_data, & - bounds, num_soilc, filter_soilc, & - carbonflux_vars, nitrogenflux_vars, & + bounds, num_soilc, filter_soilc, & + carbonflux_vars, nitrogenflux_vars, & phosphorusflux_vars) use CNDecompCascadeConType, only : decomp_cascade_con - use clm_time_manager, only : get_step_size -!#ifndef FLEXIBLE_POOLS -! use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -!#endif implicit none @@ -890,7 +992,7 @@ subroutine update_bgc_flux_decomp_sourcesink(clm_bgc_data, & type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype), intent(in):: clm_bgc_data integer :: fc, c, j, k character(len=256) :: subname = "update_soil_bgc_pf2clm" @@ -903,29 +1005,23 @@ subroutine update_bgc_flux_decomp_sourcesink(clm_bgc_data, & do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp do k = 1, ndecomp_pools decomp_cpools_sourcesink_vr(c,:,k) = clm_bgc_data%decomp_cpools_sourcesink_col(c,:,k) decomp_npools_sourcesink_vr(c,:,k) = clm_bgc_data%decomp_npools_sourcesink_col(c,:,k) decomp_ppools_sourcesink_vr(c,:,k) = clm_bgc_data%decomp_ppools_sourcesink_col(c,:,k) end do -! end do end do end associate end subroutine update_bgc_flux_decomp_sourcesink -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_flux_decomp_cascade(clm_bgc_data, & bounds, num_soilc, filter_soilc, & carbonflux_vars, nitrogenflux_vars, & phosphorusflux_vars) use CNDecompCascadeConType, only : decomp_cascade_con - use clm_time_manager, only : get_step_size -!#ifndef FLEXIBLE_POOLS -! use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -!#endif implicit none @@ -937,7 +1033,7 @@ subroutine update_bgc_flux_decomp_cascade(clm_bgc_data, & type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype), intent(in):: clm_bgc_data integer :: fc, c, j, k character(len=256) :: subname = "update_soil_bgc_pf2clm" @@ -960,8 +1056,6 @@ subroutine update_bgc_flux_decomp_cascade(clm_bgc_data, & do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp - phr_vr(c,:) = clm_bgc_data%phr_vr_col(c,:) fphr(c,:) = clm_bgc_data%fphr_col(c,:) @@ -975,24 +1069,17 @@ subroutine update_bgc_flux_decomp_cascade(clm_bgc_data, & decomp_cascade_sminp_flux_vr_col(c,:,k) = clm_bgc_data%decomp_cascade_sminp_flux_vr_col(c,:,k) sminn_to_denit_decomp_cascade_vr_col(c,:,k) = clm_bgc_data%sminn_to_denit_decomp_cascade_vr_col(c,:,k) end do -! end do end do end associate end subroutine update_bgc_flux_decomp_cascade -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_flux_smin(clm_bgc_data, & bounds, num_soilc, filter_soilc, & cnstate_vars, & nitrogenflux_vars, phosphorusflux_vars) -! use CNDecompCascadeConType, only : decomp_cascade_con -! use clm_time_manager, only : get_step_size -!#ifndef FLEXIBLE_POOLS -! use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -!#endif - implicit none type(bounds_type) , intent(in) :: bounds @@ -1003,7 +1090,7 @@ subroutine update_bgc_flux_smin(clm_bgc_data, & type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars - type(clm_bgc_interface_data_type) , intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype) , intent(in) :: clm_bgc_data integer :: fc, c, j character(len=256) :: subname = "update_bgc_flux_smin" @@ -1033,6 +1120,9 @@ subroutine update_bgc_flux_smin(clm_bgc_data, & sminn_to_denit_excess_vr => nitrogenflux_vars%sminn_to_denit_excess_vr_col , & ! Output: [real(r8) (:,:) ] supplement_to_sminn_vr => nitrogenflux_vars%supplement_to_sminn_vr_col , & ! Output: [real(r8) (:,:) ] + no3_net_transport_vr => nitrogenflux_vars%no3_net_transport_vr_col , & ! Output: updated from PF, if coupled + nh4_net_transport_vr => nitrogenflux_vars%nh4_net_transport_vr_col , & ! Output: updated from PF, if coupled + potential_immob_p => phosphorusflux_vars%potential_immob_p_col , & ! Output: [real(r8) (:) ] actual_immob_p => phosphorusflux_vars%actual_immob_p_col , & ! Output: [real(r8) (:) ] sminp_to_plant => phosphorusflux_vars%sminp_to_plant_col , & ! Output: [real(r8) (:) ] @@ -1046,7 +1136,7 @@ subroutine update_bgc_flux_smin(clm_bgc_data, & net_pmin_vr => phosphorusflux_vars%net_pmin_vr_col & ! Output: [real(r8) (:,:) ] ) - do fc = 1, num_soilc + do fc = 1, num_soilc c = filter_soilc(fc) fpg(c) = clm_bgc_data%fpg_col(c) @@ -1062,49 +1152,44 @@ subroutine update_bgc_flux_smin(clm_bgc_data, & actual_immob_p(c) = clm_bgc_data%actual_immob_p_col(c) sminp_to_plant(c) = clm_bgc_data%sminp_to_plant_col(c) -! do j = 1, nlevdecomp - fpi_vr(c,:) = clm_bgc_data%fpi_vr_col(c,:) - fpi_p_vr(c,:) = clm_bgc_data%fpi_p_vr_col(c,:) + fpi_vr(c,:) = clm_bgc_data%fpi_vr_col(c,:) + fpi_p_vr(c,:) = clm_bgc_data%fpi_p_vr_col(c,:) - sminn_to_plant_vr(c,:) = clm_bgc_data%sminn_to_plant_vr_col(c,:) - smin_no3_to_plant_vr(c,:) = clm_bgc_data%smin_no3_to_plant_vr_col(c,:) - smin_nh4_to_plant_vr(c,:) = clm_bgc_data%smin_nh4_to_plant_vr_col(c,:) + sminn_to_plant_vr(c,:) = clm_bgc_data%sminn_to_plant_vr_col(c,:) + smin_no3_to_plant_vr(c,:) = clm_bgc_data%smin_no3_to_plant_vr_col(c,:) + smin_nh4_to_plant_vr(c,:) = clm_bgc_data%smin_nh4_to_plant_vr_col(c,:) - potential_immob_vr(c,:) = clm_bgc_data%potential_immob_vr_col(c,:) - actual_immob_vr(c,:) = clm_bgc_data%actual_immob_vr_col(c,:) - actual_immob_no3_vr(c,:) = clm_bgc_data%actual_immob_no3_vr_col(c,:) - actual_immob_nh4_vr(c,:) = clm_bgc_data%actual_immob_nh4_vr_col(c,:) - gross_nmin_vr(c,:) = clm_bgc_data%gross_nmin_vr_col(c,:) - net_nmin_vr(c,:) = clm_bgc_data%net_nmin_vr_col(c,:) !!NOT available in PF + potential_immob_vr(c,:) = clm_bgc_data%potential_immob_vr_col(c,:) + actual_immob_vr(c,:) = clm_bgc_data%actual_immob_vr_col(c,:) + actual_immob_no3_vr(c,:) = clm_bgc_data%actual_immob_no3_vr_col(c,:) + actual_immob_nh4_vr(c,:) = clm_bgc_data%actual_immob_nh4_vr_col(c,:) + gross_nmin_vr(c,:) = clm_bgc_data%gross_nmin_vr_col(c,:) + net_nmin_vr(c,:) = clm_bgc_data%net_nmin_vr_col(c,:) - sminn_to_denit_excess_vr(c,:)=clm_bgc_data%sminn_to_denit_excess_vr_col(c,:) - supplement_to_sminn_vr(c,:) = clm_bgc_data%supplement_to_sminn_vr_col(c,:) + sminn_to_denit_excess_vr(c,:)=clm_bgc_data%sminn_to_denit_excess_vr_col(c,:) + supplement_to_sminn_vr(c,:) = clm_bgc_data%supplement_to_sminn_vr_col(c,:) - supplement_to_sminp_vr(c,:) = clm_bgc_data%supplement_to_sminp_vr_col(c,:) + no3_net_transport_vr(c,:) = clm_bgc_data%no3_net_transport_vr_col(c,:) + nh4_net_transport_vr(c,:) = clm_bgc_data%nh4_net_transport_vr_col(c,:) - sminp_to_plant_vr(c,:) = clm_bgc_data%sminp_to_plant_vr_col(c,:) - potential_immob_p_vr(c,:) = clm_bgc_data%potential_immob_p_vr_col(c,:) - actual_immob_p_vr(c,:) = clm_bgc_data%actual_immob_p_vr_col(c,:) - gross_pmin_vr(c,:) = clm_bgc_data%gross_pmin_vr_col(c,:) - net_pmin_vr(c,:) = clm_bgc_data%net_pmin_vr_col(c,:) !!NOT available in PF + supplement_to_sminp_vr(c,:) = clm_bgc_data%supplement_to_sminp_vr_col(c,:) -! end do - end do + sminp_to_plant_vr(c,:) = clm_bgc_data%sminp_to_plant_vr_col(c,:) + potential_immob_p_vr(c,:) = clm_bgc_data%potential_immob_p_vr_col(c,:) + actual_immob_p_vr(c,:) = clm_bgc_data%actual_immob_p_vr_col(c,:) + gross_pmin_vr(c,:) = clm_bgc_data%gross_pmin_vr_col(c,:) + net_pmin_vr(c,:) = clm_bgc_data%net_pmin_vr_col(c,:) !NOT available in PF + + end do end associate end subroutine update_bgc_flux_smin -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_flux_nitdenit(clm_bgc_data, & - bounds, num_soilc, filter_soilc, & + bounds, num_soilc, filter_soilc, & nitrogenflux_vars, phosphorusflux_vars) -! use CNDecompCascadeConType, only : decomp_cascade_con -! use clm_time_manager, only : get_step_size -!#ifndef FLEXIBLE_POOLS -! use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -!#endif - implicit none type(bounds_type) , intent(in) :: bounds @@ -1113,7 +1198,7 @@ subroutine update_bgc_flux_nitdenit(clm_bgc_data, & type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars - type(clm_bgc_interface_data_type) , intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype) , intent(in) :: clm_bgc_data integer :: fc, c, j character(len=256) :: subname = "update_bgc_flux_nitdenit" @@ -1130,28 +1215,23 @@ subroutine update_bgc_flux_nitdenit(clm_bgc_data, & do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp - - pot_f_nit_vr(c,:) = clm_bgc_data%pot_f_nit_vr_col(c,:) - pot_f_denit_vr(c,:) = clm_bgc_data%pot_f_denit_vr_col(c,:) - f_nit_vr(c,:) = clm_bgc_data%f_nit_vr_col(c,:) - f_denit_vr(c,:) = clm_bgc_data%f_denit_vr_col(c,:) - n2_n2o_ratio_denit_vr(c,:) = clm_bgc_data%n2_n2o_ratio_denit_vr_col(c,:) - f_n2o_denit_vr(c,:) = clm_bgc_data%f_n2o_denit_vr_col(c,:) - f_n2o_nit_vr(c,:) = clm_bgc_data%f_n2o_nit_vr_col(c,:) -! end do + pot_f_nit_vr(c,:) = clm_bgc_data%pot_f_nit_vr_col(c,:) + pot_f_denit_vr(c,:) = clm_bgc_data%pot_f_denit_vr_col(c,:) + f_nit_vr(c,:) = clm_bgc_data%f_nit_vr_col(c,:) + f_denit_vr(c,:) = clm_bgc_data%f_denit_vr_col(c,:) + n2_n2o_ratio_denit_vr(c,:) = clm_bgc_data%n2_n2o_ratio_denit_vr_col(c,:) + f_n2o_denit_vr(c,:) = clm_bgc_data%f_n2o_denit_vr_col(c,:) + f_n2o_nit_vr(c,:) = clm_bgc_data%f_n2o_nit_vr_col(c,:) end do end associate end subroutine update_bgc_flux_nitdenit -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_flux_gas_pf(clm_bgc_data, & - bounds, num_soilc, filter_soilc, & + bounds, num_soilc, filter_soilc, & carbonflux_vars, nitrogenflux_vars) -! use clm_time_manager, only : get_step_size, get_nstep - ! PFLOTRAN gas fluxes implicit none @@ -1161,15 +1241,11 @@ subroutine update_bgc_flux_gas_pf(clm_bgc_data, & type(carbonflux_type) , intent(inout) :: carbonflux_vars type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars - type(clm_bgc_interface_data_type) , intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype) , intent(in) :: clm_bgc_data !character(len=256) :: subname = "get_pf_bgc_gaslosses" integer :: fc, c, g, j -! integer :: gcount, cellcount -! real(r8) :: dtime ! land model time step (sec) -! integer :: nstep - !------------------------------------------------------------------------------------ associate ( & @@ -1184,37 +1260,31 @@ subroutine update_bgc_flux_gas_pf(clm_bgc_data, & ! ------------------------------------------------------------------------ do fc = 1,num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp -! - f_co2_soil_vr(c,:) = clm_bgc_data%f_co2_soil_vr_col(c,:) - f_n2_soil_vr(c,:) = clm_bgc_data%f_n2_soil_vr_col(c,:) - f_n2o_soil_vr(c,:) = clm_bgc_data%f_n2o_soil_vr_col(c,:) - - hr_vr(c,:) = clm_bgc_data%hr_vr_col(c,:) - f_ngas_decomp_vr(c,:) = clm_bgc_data%f_ngas_decomp_vr_col(c,:) - f_ngas_nitri_vr(c,:) = clm_bgc_data%f_ngas_nitri_vr_col(c,:) - f_ngas_denit_vr(c,:) = clm_bgc_data%f_ngas_denit_vr_col(c,:) -! enddo + f_co2_soil_vr(c,:) = clm_bgc_data%f_co2_soil_vr_col(c,:) + f_n2_soil_vr(c,:) = clm_bgc_data%f_n2_soil_vr_col(c,:) + f_n2o_soil_vr(c,:) = clm_bgc_data%f_n2o_soil_vr_col(c,:) + + hr_vr(c,:) = clm_bgc_data%hr_vr_col(c,:) + f_ngas_decomp_vr(c,:) = clm_bgc_data%f_ngas_decomp_vr_col(c,:) + f_ngas_nitri_vr(c,:) = clm_bgc_data%f_ngas_nitri_vr_col(c,:) + f_ngas_denit_vr(c,:) = clm_bgc_data%f_ngas_denit_vr_col(c,:) + enddo ! do c = begc, endc ! end associate end subroutine update_bgc_flux_gas_pf -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_data_pf2clm(clm_bgc_data, bounds, & num_soilc, filter_soilc, & num_soilp, filter_soilp, & - atm2lnd_vars, & - waterstate_vars, waterflux_vars, & - soilstate_vars, temperature_vars, energyflux_vars, & - soilhydrology_vars, soil_water_retention_curve, & cnstate_vars, carbonflux_vars, carbonstate_vars, & nitrogenflux_vars, nitrogenstate_vars, & phosphorusflux_vars, phosphorusstate_vars, & ch4_vars) - !! USES - use clm_varctl , only : use_pflotran, pf_tmode, pf_hmode, pf_cmode + ! USES + use clm_varctl , only : use_pflotran, pf_cmode implicit none @@ -1224,13 +1294,6 @@ subroutine update_bgc_data_pf2clm(clm_bgc_data, bounds, & 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(atm2lnd_type) , intent(in) :: atm2lnd_vars - type(waterstate_type) , intent(inout) :: waterstate_vars - type(waterflux_type) , intent(inout) :: waterflux_vars - type(soilstate_type) , intent(inout) :: soilstate_vars - type(temperature_type) , intent(inout) :: temperature_vars - type(soilhydrology_type) , intent(inout) :: soilhydrology_vars - type(energyflux_type) , intent(inout) :: energyflux_vars type(cnstate_type) , intent(inout) :: cnstate_vars type(carbonflux_type) , intent(inout) :: carbonflux_vars @@ -1241,17 +1304,16 @@ subroutine update_bgc_data_pf2clm(clm_bgc_data, bounds, & type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars type(ch4_type) , intent(inout) :: ch4_vars - class(soil_water_retention_curve_type) , intent(in) :: soil_water_retention_curve - type(clm_bgc_interface_data_type) , intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype), intent(in):: clm_bgc_data !----------------------------------------------------------------------- - character(len=256) :: subname = "get_clm_bgc_data" + character(len=256) :: subname = "update_bgc_data_pf2clm" if (pf_cmode) then - !! bgc_state_decomp is updated in CLM - !! by passing bgc_flux_decomp_sourcesink into CNSoilLittVertTransp + ! bgc_state_decomp is updated in CLM + ! by passing bgc_flux_decomp_sourcesink into CNSoilLittVertTransp call update_bgc_flux_decomp_sourcesink(clm_bgc_data, & bounds, num_soilc, filter_soilc, & carbonflux_vars, nitrogenflux_vars, & @@ -1272,29 +1334,16 @@ subroutine update_bgc_data_pf2clm(clm_bgc_data, bounds, & end if - if (pf_tmode) then - call update_soil_temperature(clm_bgc_data, & - bounds, num_soilc, filter_soilc, & - temperature_vars) - end if - - if (pf_hmode) then - call update_soil_moisture(clm_bgc_data, & - bounds, num_soilc, filter_soilc, & - waterstate_vars) - end if - end subroutine update_bgc_data_pf2clm -!!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- ! BEG of CLM-bgc through interface -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- ! !INTERFACE: - subroutine clm_bgc_run(clm_bgc_data, bounds, & + subroutine clm_bgc_run(clm_interface_data, bounds, & num_soilc, filter_soilc, & num_soilp, filter_soilp, & canopystate_vars, soilstate_vars, & @@ -1304,16 +1353,15 @@ subroutine clm_bgc_run(clm_bgc_data, bounds, & nitrogenstate_vars, nitrogenflux_vars, & phosphorusstate_vars,phosphorusflux_vars) - !! USES: + ! USES: use CNDecompMod , only: CNDecompAlloc - !! ARGUMENTS: + ! 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(photosyns_type) , intent(in) :: photosyns_vars type(canopystate_type) , intent(inout) :: canopystate_vars type(soilstate_type) , intent(inout) :: soilstate_vars type(temperature_type) , intent(inout) :: temperature_vars @@ -1322,19 +1370,16 @@ subroutine clm_bgc_run(clm_bgc_data, bounds, & type(ch4_type) , intent(inout) :: ch4_vars type(carbonstate_type) , intent(inout) :: carbonstate_vars type(carbonflux_type) , intent(inout) :: carbonflux_vars -! type(carbonflux_type) , intent(inout) :: c13_carbonflux_vars -! type(carbonflux_type) , intent(inout) :: c14_carbonflux_vars type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars -! type(crop_type) , intent(inout) :: crop_vars type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars - type(clm_bgc_interface_data_type) , intent(inout) :: clm_bgc_data + type(clm_interface_data_type) , intent(inout) :: clm_interface_data - !!------------------------------------------------------------- - !! STEP-2: (i) pass data from clm_bgc_data to CNDecompAlloc - call clm_bgc_get_data(clm_bgc_data, bounds, & + !------------------------------------------------------------- + ! STEP-2: (i) pass data from clm_bgc_data to CNDecompAlloc + call clm_bgc_get_data(clm_interface_data, bounds, & num_soilc, filter_soilc, & canopystate_vars, soilstate_vars, & temperature_vars, waterstate_vars, & @@ -1343,7 +1388,7 @@ subroutine clm_bgc_run(clm_bgc_data, bounds, & nitrogenstate_vars, nitrogenflux_vars, & phosphorusstate_vars,phosphorusflux_vars) - !! STEP-2: (ii) run CNDecompAlloc + ! STEP-2: (ii) run CNDecompAlloc call CNDecompAlloc (bounds, num_soilc, filter_soilc, & num_soilp, filter_soilp, & canopystate_vars, soilstate_vars, & @@ -1353,20 +1398,20 @@ subroutine clm_bgc_run(clm_bgc_data, bounds, & nitrogenstate_vars, nitrogenflux_vars, & phosphorusstate_vars,phosphorusflux_vars) - !! STEP-2: (iii) update clm_bgc_data from CNDecompAlloc - call clm_bgc_update_data(clm_bgc_data, bounds, & - num_soilc, filter_soilc, & - cnstate_vars, carbonflux_vars, & + ! STEP-2: (iii) update clm_bgc_data from CNDecompAlloc + call clm_bgc_update_data(clm_interface_data%bgc, bounds, & + num_soilc, filter_soilc, & + cnstate_vars, carbonflux_vars, & nitrogenflux_vars, phosphorusflux_vars) end subroutine clm_bgc_run -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- ! !INTERFACE: - !! pass data from clm_bgc_data to clm original data-types that used by CNDecompAlloc - subroutine clm_bgc_get_data(clm_bgc_data, bounds, & - num_soilc, filter_soilc, & + ! pass data from clm_bgc_data to clm original data-types that used by CNDecompAlloc + subroutine clm_bgc_get_data(clm_interface_data, & + bounds, num_soilc, filter_soilc, & canopystate_vars, soilstate_vars, & temperature_vars, waterstate_vars, & cnstate_vars, ch4_vars, & @@ -1374,16 +1419,13 @@ subroutine clm_bgc_get_data(clm_bgc_data, bounds, & nitrogenstate_vars, nitrogenflux_vars, & phosphorusstate_vars,phosphorusflux_vars) - !! USES: + ! USES: - !! ARGUMENTS: + ! 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(photosyns_type) , intent(in) :: photosyns_vars type(canopystate_type) , intent(inout) :: canopystate_vars type(soilstate_type) , intent(inout) :: soilstate_vars type(temperature_type) , intent(inout) :: temperature_vars @@ -1392,23 +1434,18 @@ subroutine clm_bgc_get_data(clm_bgc_data, bounds, & type(ch4_type) , intent(inout) :: ch4_vars type(carbonstate_type) , intent(inout) :: carbonstate_vars type(carbonflux_type) , intent(inout) :: carbonflux_vars -! type(carbonflux_type) , intent(inout) :: c13_carbonflux_vars -! type(carbonflux_type) , intent(inout) :: c14_carbonflux_vars type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars -! type(crop_type) , intent(in) :: crop_vars type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars type(phosphorusflux_type) , intent(inout) :: phosphorusflux_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data + type(clm_interface_data_type), intent(in) :: clm_interface_data - !! LOCAL VARIABLES: + ! LOCAL VARIABLES: integer :: fc, c, j, k !----------------------------------------------------------------------- associate(& -! initial_cn_ratio => decomp_cascade_con%initial_cn_ratio , & ! Input: [real(r8) (:) ] c:n ratio for initialization of pools -! initial_cp_ratio => decomp_cascade_con%initial_cp_ratio , & ! Input: [real(r8) (:) ] c:p ratio for initialization of pools decomp_cpools_vr => carbonstate_vars%decomp_cpools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools decomp_npools_vr => nitrogenstate_vars%decomp_npools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools decomp_ppools_vr => phosphorusstate_vars%decomp_ppools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) vertically-resolved decomposing (litter, cwd, soil) P pools @@ -1423,12 +1460,12 @@ subroutine clm_bgc_get_data(clm_bgc_data, bounds, & sminp_vr => phosphorusstate_vars%sminp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil mineral P = solutionp + labilep + secondp occlp_vr => phosphorusstate_vars%occlp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil occluded mineral P primp_vr => phosphorusstate_vars%primp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil primary mineral P - + ! plant_ndemand_col => nitrogenflux_vars%plant_ndemand_col , & plant_pdemand_col => phosphorusflux_vars%plant_pdemand_col , & - - alt_indx => canopystate_vars%alt_indx_col , & ! Input: [integer (:) ] current depth of thaw - + ! + !alt_indx => canopystate_vars%alt_indx_col , & ! Input: [integer (:) ] current depth of thaw + ! watsat => soilstate_vars%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) (nlevgrnd) bd => soilstate_vars%bd_col , & ! Input: [real(r8) (:,:) ] bulk density of dry soil material [kg/m3] watfc => soilstate_vars%watfc_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at field capacity (nlevsoi) @@ -1450,97 +1487,88 @@ subroutine clm_bgc_get_data(clm_bgc_data, bounds, & o2stress_sat => ch4_vars%o2stress_sat_col , & ! Input: [real(r8) (:,:) ] Ratio of oxygen available to that demanded by roots, aerobes, & methanotrophs (nlevsoi) finundated => ch4_vars%finundated_col & ! Input: [real(r8) (:) ] fractional inundated area (excluding dedicated wetland columns) - ) + ) - !! soil properties & thermohydrology + ! soil properties & thermohydrology do fc = 1, num_soilc c = filter_soilc(fc) - plant_ndemand_col(c) = clm_bgc_data%plant_ndemand_col(c) - plant_pdemand_col(c) = clm_bgc_data%plant_pdemand_col(c) + plant_ndemand_col(c) = clm_interface_data%bgc%plant_ndemand_col(c) + plant_pdemand_col(c) = clm_interface_data%bgc%plant_pdemand_col(c) - alt_indx(c) = clm_bgc_data%alt_indx_col(c) - finundated(c) = clm_bgc_data%finundated_col(c) + finundated(c) = clm_interface_data%bgc%finundated_col(c) -! do j = 1,nlevsoi - bd(c,:) = clm_bgc_data%bd_col(c,:) - watsat(c,:) = clm_bgc_data%watsat_col(c,:) - bsw(c,:) = clm_bgc_data%bsw_col(c,:) - sucsat(c,:) = clm_bgc_data%sucsat_col(c,:) - watfc(c,:) = clm_bgc_data%watfc_col(c,:) - cellorg(c,:) = clm_bgc_data%cellorg_col(c,:) + bd(c,:) = clm_interface_data%bd_col(c,:) + watsat(c,:) = clm_interface_data%watsat_col(c,:) + bsw(c,:) = clm_interface_data%bsw_col(c,:) + sucsat(c,:) = clm_interface_data%sucsat_col(c,:) + watfc(c,:) = clm_interface_data%watfc_col(c,:) + cellorg(c,:) = clm_interface_data%cellorg_col(c,:) - soilpsi(c,:) = clm_bgc_data%soilpsi_col(c,:) - h2osoi_vol(c,:) = clm_bgc_data%h2osoi_vol_col(c,:) - h2osoi_liq(c,:) = clm_bgc_data%h2osoi_liq_col(c,:) + soilpsi(c,:) = clm_interface_data%th%soilpsi_col(c,:) + h2osoi_vol(c,:) = clm_interface_data%th%h2osoi_vol_col(c,:) + h2osoi_liq(c,:) = clm_interface_data%th%h2osoi_liq_col(c,:) - t_soisno(c,:) = clm_bgc_data%t_soisno_col(c,:) + t_soisno(c,:) = clm_interface_data%th%t_soisno_col(c,:) - o2stress_unsat(c,:) = clm_bgc_data%o2stress_unsat_col(c,:) - o2stress_sat(c,:) = clm_bgc_data%o2stress_sat_col(c,:) - o2_decomp_depth_unsat(c,:) = clm_bgc_data%o2_decomp_depth_unsat_col(c,:) - conc_o2_unsat(c,:) = clm_bgc_data%conc_o2_unsat_col(c,:) - o2_decomp_depth_sat(c,:) = clm_bgc_data%o2_decomp_depth_sat_col(c,:) - conc_o2_sat(c,:) = clm_bgc_data%conc_o2_sat_col(c,:) + o2stress_unsat(c,:) = clm_interface_data%bgc%o2stress_unsat_col(c,:) + o2stress_sat(c,:) = clm_interface_data%bgc%o2stress_sat_col(c,:) + o2_decomp_depth_unsat(c,:) = clm_interface_data%bgc%o2_decomp_depth_unsat_col(c,:) + conc_o2_unsat(c,:) = clm_interface_data%bgc%conc_o2_unsat_col(c,:) + o2_decomp_depth_sat(c,:) = clm_interface_data%bgc%o2_decomp_depth_sat_col(c,:) + conc_o2_sat(c,:) = clm_interface_data%bgc%conc_o2_sat_col(c,:) -! end do end do - !!state variables + !state variables do fc = 1, num_soilc c = filter_soilc(fc) -! do j = 1, nlevdecomp do k = 1, ndecomp_pools - decomp_cpools_vr(c,:,k) = clm_bgc_data%decomp_cpools_vr_col(c,:,k) - decomp_npools_vr(c,:,k) = clm_bgc_data%decomp_npools_vr_col(c,:,k) - decomp_ppools_vr(c,:,k) = clm_bgc_data%decomp_ppools_vr_col(c,:,k) + decomp_cpools_vr(c,:,k) = clm_interface_data%bgc%decomp_cpools_vr_col(c,:,k) + decomp_npools_vr(c,:,k) = clm_interface_data%bgc%decomp_npools_vr_col(c,:,k) + decomp_ppools_vr(c,:,k) = clm_interface_data%bgc%decomp_ppools_vr_col(c,:,k) end do - smin_no3_vr(c,:) = clm_bgc_data%smin_no3_vr_col(c,:) - smin_nh4_vr(c,:) = clm_bgc_data%smin_nh4_vr_col(c,:) - smin_nh4sorb_vr(c,:) = clm_bgc_data%smin_nh4sorb_vr_col(c,:) + smin_no3_vr(c,:) = clm_interface_data%bgc%smin_no3_vr_col(c,:) + smin_nh4_vr(c,:) = clm_interface_data%bgc%smin_nh4_vr_col(c,:) + smin_nh4sorb_vr(c,:) = clm_interface_data%bgc%smin_nh4sorb_vr_col(c,:) - solutionp_vr(c,:) = clm_bgc_data%solutionp_vr_col(c,:) - labilep_vr(c,:) = clm_bgc_data%labilep_vr_col(c,:) - secondp_vr(c,:) = clm_bgc_data%secondp_vr_col(c,:) - sminp_vr(c,:) = clm_bgc_data%sminp_vr_col(c,:) - occlp_vr(c,:) = clm_bgc_data%occlp_vr_col(c,:) - primp_vr(c,:) = clm_bgc_data%primp_vr_col(c,:) -! end do + solutionp_vr(c,:) = clm_interface_data%bgc%solutionp_vr_col(c,:) + labilep_vr(c,:) = clm_interface_data%bgc%labilep_vr_col(c,:) + secondp_vr(c,:) = clm_interface_data%bgc%secondp_vr_col(c,:) + sminp_vr(c,:) = clm_interface_data%bgc%sminp_vr_col(c,:) + occlp_vr(c,:) = clm_interface_data%bgc%occlp_vr_col(c,:) + primp_vr(c,:) = clm_interface_data%bgc%primp_vr_col(c,:) end do end associate end subroutine clm_bgc_get_data -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- ! !INTERFACE: - !! pass data from clm_bgc to clm_bgc_data + ! pass data from clm_bgc to clm_bgc_data subroutine clm_bgc_update_data(clm_bgc_data, bounds, & num_soilc, filter_soilc, & cnstate_vars, carbonflux_vars, & nitrogenflux_vars, phosphorusflux_vars) - !! USES: + ! USES: - !! ARGUMENTS: + ! 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(cnstate_type) , intent(in) :: cnstate_vars type(carbonflux_type) , intent(in) :: carbonflux_vars -! type(carbonflux_type) , intent(in) :: c13_carbonflux_vars -! type(carbonflux_type) , intent(in) :: c14_carbonflux_vars type(nitrogenflux_type) , intent(in) :: nitrogenflux_vars type(phosphorusflux_type) , intent(in) :: phosphorusflux_vars - type(clm_bgc_interface_data_type) , intent(inout) :: clm_bgc_data + type(clm_interface_bgc_datatype) , intent(inout) :: clm_bgc_data - !! LOCAL VARIABLES: + ! LOCAL VARIABLES: integer :: fc, c, j, k !----------------------------------------------------------------------- @@ -1587,7 +1615,8 @@ subroutine clm_bgc_update_data(clm_bgc_data, bounds, & net_nmin_vr => nitrogenflux_vars%net_nmin_vr_col , & ! Output: [real(r8) (:,:) ] gross_nmin => nitrogenflux_vars%gross_nmin_col , & ! Output: [real(r8) (:) ] gross rate of N mineralization (gN/m2/s) net_nmin => nitrogenflux_vars%net_nmin_col , & ! Output: [real(r8) (:) ] net rate of N mineralization (gN/m2/s) - !!! add phosphorus + + ! add phosphorus decomp_cascade_ptransfer_vr => phosphorusflux_vars%decomp_cascade_ptransfer_vr_col , & ! Output: [real(r8) (:,:,:) ] vert-res transfer of P from donor to receiver pool along decomp. cascade (gP/m3/s) decomp_cascade_sminp_flux_vr => phosphorusflux_vars%decomp_cascade_sminp_flux_vr_col , & ! Output: [real(r8) (:,:,:) ] vert-res mineral P flux for transition along decomposition cascade (gP/m3/s) potential_immob_p_vr => phosphorusflux_vars%potential_immob_p_vr_col , & ! Output: [real(r8) (:,:) ] @@ -1598,7 +1627,6 @@ subroutine clm_bgc_update_data(clm_bgc_data, bounds, & decomp_cascade_hr_vr => carbonflux_vars%decomp_cascade_hr_vr_col , & ! Output: [real(r8) (:,:,:) ] vertically-resolved het. resp. from decomposing C pools (gC/m3/s) decomp_cascade_ctransfer_vr => carbonflux_vars%decomp_cascade_ctransfer_vr_col , & ! Output: [real(r8) (:,:,:) ] vertically-resolved het. resp. from decomposing C pools (gC/m3/s) -! decomp_k => carbonflux_vars%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) phr_vr => carbonflux_vars%phr_vr_col , & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) fphr => carbonflux_vars%fphr_col & ! Output: [real(r8) (:,:) ] fraction of potential SOM + LITTER heterotrophic ) @@ -1644,7 +1672,7 @@ subroutine clm_bgc_update_data(clm_bgc_data, bounds, & clm_bgc_data%gross_nmin_vr_col = gross_nmin_vr clm_bgc_data%net_nmin_vr_col = net_nmin_vr - !! phosphorus + ! phosphorus clm_bgc_data%decomp_cascade_ptransfer_vr_col = decomp_cascade_ptransfer_vr clm_bgc_data%decomp_cascade_sminp_flux_vr_col = decomp_cascade_sminp_flux_vr clm_bgc_data%potential_immob_p_vr_col = potential_immob_p_vr @@ -1660,21 +1688,17 @@ subroutine clm_bgc_update_data(clm_bgc_data, bounds, & end associate end subroutine clm_bgc_update_data -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- subroutine update_bgc_data_clm2clm(clm_bgc_data,bounds, & num_soilc, filter_soilc, & num_soilp, filter_soilp, & - atm2lnd_vars, & - waterstate_vars, waterflux_vars, & - soilstate_vars, temperature_vars, energyflux_vars, & - soilhydrology_vars, soil_water_retention_curve, & cnstate_vars, carbonflux_vars, carbonstate_vars, & nitrogenflux_vars, nitrogenstate_vars, & phosphorusflux_vars, phosphorusstate_vars, & ch4_vars) - !! USES + ! USES implicit none @@ -1685,13 +1709,6 @@ subroutine update_bgc_data_clm2clm(clm_bgc_data,bounds, & 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(atm2lnd_type) , intent(in) :: atm2lnd_vars - type(waterstate_type) , intent(inout) :: waterstate_vars - type(waterflux_type) , intent(inout) :: waterflux_vars - type(soilstate_type) , intent(inout) :: soilstate_vars - type(temperature_type) , intent(inout) :: temperature_vars - type(soilhydrology_type) , intent(inout) :: soilhydrology_vars - type(energyflux_type) , intent(inout) :: energyflux_vars type(cnstate_type) , intent(inout) :: cnstate_vars type(carbonflux_type) , intent(inout) :: carbonflux_vars @@ -1702,15 +1719,14 @@ subroutine update_bgc_data_clm2clm(clm_bgc_data,bounds, & type(phosphorusstate_type) , intent(inout) :: phosphorusstate_vars type(ch4_type) , intent(inout) :: ch4_vars - class(soil_water_retention_curve_type) , intent(in) :: soil_water_retention_curve - type(clm_bgc_interface_data_type) , intent(in) :: clm_bgc_data + type(clm_interface_bgc_datatype), intent(in):: clm_bgc_data !----------------------------------------------------------------------- - character(len=256) :: subname = "get_clm_bgc_data" + character(len=256) :: subname = "update_bgc_data_clm2clm" - !! bgc_state_decomp is updated in CLM - !! by passing bgc_flux_decomp_sourcesink into CNSoilLittVertTransp + ! bgc_state_decomp is updated in CLM + ! by passing bgc_flux_decomp_sourcesink into CNSoilLittVertTransp call update_bgc_flux_decomp_cascade(clm_bgc_data, & bounds, num_soilc, filter_soilc, & carbonflux_vars, nitrogenflux_vars, & @@ -1726,9 +1742,10 @@ subroutine update_bgc_data_clm2clm(clm_bgc_data,bounds, & nitrogenflux_vars, phosphorusflux_vars) end subroutine update_bgc_data_clm2clm -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- ! END of CLM-bgc through interface -!!-------------------------------------------------------------------------------------- +!-------------------------------------------------------------------------------------- + -end module clm_bgc_interfaceMod +end module clm_interface_funcsMod diff --git a/components/clm/src/main/clm_interface_pflotranMod.F90 b/components/clm/src/main/clm_interface_pflotranMod.F90 new file mode 100644 index 000000000000..59a81f449880 --- /dev/null +++ b/components/clm/src/main/clm_interface_pflotranMod.F90 @@ -0,0 +1,4893 @@ +module clm_interface_pflotranMod + +!#define CLM_PFLOTRAN +! the above #directive IS for explicit coupling CLM and PFLOTRAN (i.e. this interface) + +!#define COLUMN_MODE +! the above #define IS for column-wised 1D grid CLM-PF coupling (i.e. 'VERTICAL_ONLY_FLOW/TRAN'). +! (1) active columns ('filter(:)%soilc', i.e. only including both 'istsoil' and 'istcrop'); +! (2) 'soilc' are arranged arbitrarily by 'clumps', following by orders in 'soilc', along X-direction; +! (3) The order/sequence in (2) are forced passing to over-ride PF's fakely reading input cards. +! (4) MUST with pflotran%option%flow%only_vertical_flow and %option%tran%only_vertical_transport TRUE. +! (5) Since PF fake mesh will be over-rided, mapping_files are NOT needed. + +!---------------------------------------------------------------------------------------------- +! NGEE-Arctic CLM-PFLOTRAN soil Thermal-Hydrology & bgC coupling interface +! authors: Fengming YUAN1, Gautam Bishit1,2, and Guoping Tang1 +! +! 1.Climate Change Science Institute & Environmental Science Division +! Oak Ridge National Laboratory +! +! 2.Lawrence Berkley National Laboratory +! +! date: 2012 - 2017 +! +! modified by Gangsheng Wang @ ORNL based on clm_interface: 8/28/2015, 2/2/2017 +! +! yfm: Added Thermal-Hydrology coupling subroutines: 04/2017 +!---------------------------------------------------------------------------------------------- + +#include "shr_assert.h" + + !----------------------------------------------------------------------- + !BOP + ! + ! !MODULE: clm_pflotran_interfaceMod + ! + ! !DESCRIPTION: + ! Performs + ! + ! !USES: + ! Most 'USES' are declaired in each subroutine + ! use shr_const_mod, only : SHR_CONST_G + use shr_kind_mod , only : r8 => shr_kind_r8 + use decompMod , only : bounds_type + use filterMod , only : clumpfilter + use abortutils , only : endrun + use shr_log_mod , only : errMsg => shr_log_errMsg + + ! currently only works with soil columns, i.e. luntype of 'istsoil/istcrop' + ! use landunit_varcon , only : istsoil, istcrop + + ! (dummy) variable definitions + ! ALM types/variables are replaced by clm_interface_data + use clm_interface_dataType, only : clm_interface_data_type + + +#ifdef CLM_PFLOTRAN + use clm_pflotran_interface_data + use pflotran_clm_main_module + use pflotran_clm_setmapping_module +#endif + + ! !PUBLIC TYPES: + implicit none + + save + + private ! By default everything is private + +#ifdef CLM_PFLOTRAN + type(pflotran_model_type), pointer, public :: pflotran_m + + logical, pointer, public :: mapped_gcount_skip(:) ! dim: inactive grid mask in (1:bounds%endg-bounds%begg+1), + ! or inactive column in (1:bounds%endc-bounds%endc+1) +#endif + ! + character(len=256), private:: pflotran_prefix = '' + character(len=32), private :: restart_stamp = '' + + real(r8), parameter :: rgas = 8.3144621d0 ! m3 Pa K-1 mol-1 + + ! !PUBLIC MEMBER FUNCTIONS: + public :: clm_pf_readnl + + ! wrappers around '#ifdef CLM_PFLOTRAN .... #endif' block statements to maintain sane runtime behavior + ! when pflotran is not available. + public :: clm_pf_interface_init + public :: clm_pf_set_restart_stamp + public :: clm_pf_run + public :: clm_pf_write_restart + public :: clm_pf_finalize + + private :: pflotran_not_available + +#ifdef CLM_PFLOTRAN + ! private work functions that truely require '#ifdef CLM_PFLOTRAN .... #endif' + ! + private :: interface_init + private :: pflotran_run_onestep + private :: pflotran_write_checkpoint + private :: pflotran_finalize + private :: clm_pf_checkerr + ! + private :: get_clm_soil_dimension + private :: get_clm_soil_properties + ! + private :: get_clm_soil_th + private :: get_clm_iceadj_porosity + ! + private :: get_clm_bgc_conc + private :: get_clm_bgc_rate + private :: update_soil_bgc_pf2clm + private :: update_bgc_gaslosses_pf2clm + ! pflotran mass balance check + private :: clm_pf_BeginCBalance + private :: clm_pf_BeginNBalance + private :: clm_pf_CBalanceCheck + private :: clm_pf_NBalanceCheck + ! + private :: get_clm_bcwflx + private :: get_clm_bceflx + private :: update_soil_temperature_pf2clm + private :: update_soil_moisture_pf2clm + private :: update_bcflow_pf2clm + +#endif + +contains + +!----------------------------------------------------------------------- +! +! public interface functions allowing runtime behavior regardless of +! whether pflotran is compiled in. +! +!----------------------------------------------------------------------- + + !----------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: clm_pf_readnl + ! + ! !INTERFACE: + subroutine clm_pf_readnl( NLFilename ) + ! + ! !DESCRIPTION: + ! Read namelist for clm-pflotran interface + ! + ! !USES: + use clm_varctl , only : iulog + use spmdMod , only : masterproc, mpicom + use fileutils , only : getavu, relavu, opnfil + use clm_nlUtilsMod, only : find_nlgroup_name + use shr_nl_mod , only : shr_nl_find_group_name + use shr_mpi_mod , only : shr_mpi_bcast + + implicit none + + ! !ARGUMENTS: + character(len=*), intent(IN) :: NLFilename ! Namelist filename + ! !LOCAL VARIABLES: + integer :: ierr ! error code + integer :: unitn ! unit for namelist file + character(len=32) :: subname = 'clm_pf_readnl' ! subroutine name + !EOP + !----------------------------------------------------------------------- + namelist / clm_pflotran_inparm / pflotran_prefix + + ! ---------------------------------------------------------------------- + ! Read namelist from standard namelist file. + ! ---------------------------------------------------------------------- + + if ( masterproc )then + + unitn = getavu() + write(iulog,*) 'Read in clm-pflotran namelist' + call opnfil (NLFilename, unitn, 'F') + call shr_nl_find_group_name(unitn, 'clm_pflotran_inparm', status=ierr) + if (ierr == 0) then + read(unitn, clm_pflotran_inparm, iostat=ierr) + if (ierr /= 0) then + call endrun(msg=subname //':: ERROR: reading clm_pflotran_inparm namelist.'//& + errMsg(__FILE__, __LINE__)) + end if + end if + call relavu( unitn ) + write(iulog, '(/, A)') " clm-pflotran namelist:" + write(iulog, '(A, " : ", A,/)') " pflotran_prefix", trim(pflotran_prefix) + end if + + ! Broadcast namelist variables read in + call shr_mpi_bcast(pflotran_prefix, mpicom) + + end subroutine clm_pf_readnl + + !----------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: clm_pf_set_restart_stamp + ! + ! !INTERFACE: + subroutine clm_pf_set_restart_stamp(clm_restart_filename) + ! + ! !DESCRIPTION: Set the pflotran restart date stamp. Note we do NOT + ! restart here, that gets handled by pflotran's internal + ! initialization during interface_init_clm_pf() + ! + ! !USES: + ! !ARGUMENTS: + character(len=256), intent(in) :: clm_restart_filename + ! !LOCAL VARIABLES: + integer :: name_length, start_pos, end_pos + character(len=32) :: clm_stamp + !EOP + !----------------------------------------------------------------------- + + ! clm restart file name is of the form: + ! ${CASE_NAME}.clm2.r.YYYY-MM-DD-SSSSS.nc + ! we need to extract the: YYYY-MM-DD-SSSSS + write(*, '("clm-pf : clm restart file name : ", A/)') trim(clm_restart_filename) + name_length = len(trim(clm_restart_filename)) + start_pos = name_length - 18 + end_pos = name_length - 3 + clm_stamp = clm_restart_filename(start_pos : end_pos) + write(*, '("clm-pf : clm date stamp : ", A/)') trim(clm_stamp) + restart_stamp = clm_stamp + + end subroutine clm_pf_set_restart_stamp + + + !----------------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: pflotran_not_available + ! + ! !INTERFACE: + subroutine pflotran_not_available(subname) + ! + ! !DESCRIPTION: + ! Print an error message and abort. + ! + ! !USES: + + ! !ARGUMENTS: + implicit none + character(len=*), intent(in) :: subname + ! !LOCAL VARIABLES: + !EOP + !----------------------------------------------------------------------- + call endrun(trim(subname) // ": ERROR: CLM-PFLOTRAN interface has not been compiled " // & + "into this version of ALM.") + end subroutine pflotran_not_available + + +!******************************************************************************************! +! +! public interface function wrappers +! +!------------------------------------------------------------------------------------------! + + !----------------------------------------------------------------------------- + subroutine clm_pf_interface_init(bounds) + + implicit none + + type(bounds_type), intent(in) :: bounds ! bounds + + character(len=256) :: subname = "clm_pf_interface_init()" + +#ifdef CLM_PFLOTRAN + call interface_init(bounds) +#else + call pflotran_not_available(subname) +#endif + end subroutine clm_pf_interface_init + + !-------------------------------------------------------------------------------------------- + + subroutine clm_pf_run(clm_interface_data, bounds, filters, ifilter) + use clm_time_manager, only : get_nstep + + implicit none + + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(inout) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(inout) :: clm_interface_data + + !----------------------------------------------------------------------- + + character(len=256) :: subname = "clm_pf_run" + integer :: nstep + +#ifdef CLM_PFLOTRAN + call clm_pf_BeginCBalance(clm_interface_data, bounds, filters, ifilter) + call clm_pf_BeginNBalance(clm_interface_data, bounds, filters, ifilter) + + call pflotran_run_onestep(clm_interface_data, bounds, filters, ifilter) + + nstep = get_nstep() + + if (nstep > 1 )then + call clm_pf_CBalanceCheck(clm_interface_data, bounds, filters, ifilter) + call clm_pf_NBalanceCheck(clm_interface_data, bounds, filters, ifilter) + end if +#else + call pflotran_not_available(subname) +#endif + end subroutine clm_pf_run + + !----------------------------------------------------------------------------- + subroutine clm_pf_write_restart(date_stamp) + + implicit none + character(len=*), intent(in) :: date_stamp + + character(len=32) :: subname = "clm_pf_write_restart" + +#ifdef CLM_PFLOTRAN + call pflotran_write_checkpoint(date_stamp) +#else + call pflotran_not_available(subname) +#endif + end subroutine clm_pf_write_restart + + + !----------------------------------------------------------------------------- + !BOP + ! + ! !ROUTINE: clm_pf_finalize + ! + ! !INTERFACE: + subroutine clm_pf_finalize() + + implicit none + character(len=256) :: subname = "clm_pf_finalize" + +#ifdef CLM_PFLOTRAN + call pflotran_finalize() +#else + call pflotran_not_available(subname) +#endif + end subroutine clm_pf_finalize + + + + + +!************************************************************************************! +! (BEGIN) +! Private interface subroutines, requiring explicit coupling between CLM and PFLOTRAN +! +#ifdef CLM_PFLOTRAN + + !==================================================================================================== + ! ! + ! Main Subroutines to Couple with PFLOTRAN ! + ! ! + !==================================================================================================== + + !----------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: interface_init + ! + ! !INTERFACE: + subroutine interface_init(bounds) + ! + ! !DESCRIPTION: + ! initialize the pflotran iterface + ! + ! !USES: + use clm_varctl , only : iulog + use GridcellType , only : grc_pp + use LandunitType , only : lun_pp + use ColumnType , only : col_pp + use landunit_varcon , only : istsoil, istcrop + use decompMod , only : get_proc_global, get_proc_clumps, ldecomp + use spmdMod , only : mpicom, masterproc, iam, npes + use domainMod , only : ldomain, lon1d, lat1d + + use clm_time_manager, only : get_nstep + use clm_varcon , only : dzsoi, zisoi + use clm_varpar , only : nlevsoi, nlevgrnd, nlevdecomp_full, ndecomp_pools + use clm_varctl , only : pf_hmode, pf_tmode, pf_cmode, pf_frzmode, & + initth_pf2clm, pf_clmnstep0, & + pf_surfaceflow + + + use CNDecompCascadeConType , only : decomp_cascade_con + + + ! pflotran + use Option_module, only : printErrMsg + use Simulation_Base_class, only : simulation_base_type + use Simulation_Subsurface_class, only : simulation_subsurface_type + use Realization_Base_class, only : realization_base_type + use Realization_Subsurface_class, only : realization_subsurface_type + + use PFLOTRAN_Constants_module + use pflotran_clm_setmapping_module + use Mapping_module + ! !ARGUMENTS: + + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + ! + ! !REVISION HISTORY: + ! Created by Gautam Bisht + ! Revised by Fengming Yuan, CCSI-ORNL + ! + !EOP + ! + ! LOCAL VARAIBLES: + + type(bounds_type), intent(in) :: bounds ! bounds + + integer :: global_numg ! total number of gridcells across all processors (active) + integer :: global_numc ! total number of columns across all processors (active) + integer :: g,l,c, pid ! indices + integer :: nc, nclumps, total_soilc, total_grid, start_mappedgid, nx, ny, npes_pf + integer, pointer :: total_soilc_pes(:) ! dim: npes + integer, pointer :: mapped_gid(:) ! dim: 'total_soilc' or 'total_grid' + integer :: gid, gcount, colcount, cellcount + integer :: gcolumns(1:bounds%endg-bounds%begg+1) + integer :: ierr + + character(len= 32) :: subname = 'interface_init' ! subroutine name + + integer, pointer :: clm_all_cell_ids_nindex(:) + integer, pointer :: clm_top_cell_ids_nindex(:) + integer, pointer :: clm_bot_cell_ids_nindex(:) + integer :: clm_all_npts + integer :: clm_top_npts + integer :: clm_bot_npts + real(r8):: x0, x1, y0, y1, dx_global(1:ldomain%ni), dy_global(1:ldomain%nj) + integer :: i, j + real(r8):: lon0, lat0 !origin of longitude/latitude + integer :: nv ! number of vertices + class(realization_subsurface_type), pointer :: realization + + associate( & + ! Assign local pointers to derived subtypes components (landunit-level) + ltype => lun_pp%itype , & ! [integer (:)] landunit type index + lgridcell => lun_pp%gridcell , & ! [integer (:)] gridcell index of landunit + ! Assign local pointer to derived subtypes components (column-level) + cgridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column + clandunit => col_pp%landunit , & ! [integer (:)] landunit index of column + cwtgcell => col_pp%wtgcell , & ! [real(r8) (:)] weight (relative to gridcell) + cactive => col_pp%active & ! [logic (:)] column active or not + ) + + + ! beg---------------------------------------------------------------- + ! lon0/lat0 have been added to ldomain + lon0 = ldomain%lon0 + lat0 = ldomain%lat0 + ! end---------------------------------------------------------------- + + ! (0) determines Total grids/columns and ids to be mapped between CLM and PFLOTRAN + +#ifdef COLUMN_MODE + ! counting 'soilc' in 'filters' + ! NOTE: only works for 'soilc', which actually includes natural soil and crop land units + ! + + total_soilc = 0 + + ! mark the inactive column (non-natveg/crop landunits) + ! will be used to skip inactive column index in 'bounds%begc:endc' + allocate(mapped_gcount_skip(1:bounds%endc-bounds%begc+1)) + mapped_gcount_skip(:) = .true. + + do c = bounds%begc, bounds%endc + l = clandunit(c) + g = cgridcell(c) + + if (.not.cactive(c) .or. cwtgcell(c)<=0._r8) then + !write (iulog,*) 'WARNING: SOIL/CROP column with wtgcell <= 0 or inactive... within the domain' + !write (iulog,*) 'CLM-- PFLOTRAN does not include such a SOIL/CROP column, AND will skip it' + + elseif ( .not.(ltype(l)==istsoil .or. ltype(l)==istcrop) ) then + !write (iulog,*) 'WARNING: non-SOIL/CROP column found in filter%num_soilc: nc, l, ltype', nc, l, ltype(l) + !write (iulog,*) 'CLM-- PFLOTRAN does not include such a SOIL/CROP column, AND will skip it' + + else + total_soilc = total_soilc + 1 + + mapped_gcount_skip(c-bounds%begc+1) = .false. + endif + + end do + + call mpi_barrier(mpicom, ierr) ! needs all processes done first + ! sum of all active soil columns across all processors (information only) + call mpi_allreduce(total_soilc, global_numc, 1, MPI_INTEGER,MPI_SUM,mpicom,ierr) + + ! (active) 'soilc' global indexing across all processes + allocate (total_soilc_pes(0:npes-1)) + call mpi_gather(total_soilc, 1, MPI_INTEGER, & + total_soilc_pes, 1, MPI_INTEGER, 0, mpicom, ierr) + call mpi_bcast(total_soilc_pes, npes, MPI_INTEGER, 0, mpicom, ierr) + + ! CLM's natural grid id, continued and ordered across processes, for mapping to PF mesh + ! will be assigned to calculate 'clm_cell_ids_nindex' below + allocate(mapped_gid(1:total_soilc)) + + start_mappedgid = 0 + do pid=0, npes-1 + if (pid==iam) then + + colcount = 0 + do c = bounds%begc, bounds%endc + if (.not.mapped_gcount_skip(c-bounds%begc+1)) then + colcount = colcount + 1 + mapped_gid(colcount) = start_mappedgid+colcount + endif + enddo + + exit ! do pid=0,npes-1 + + else + start_mappedgid = start_mappedgid + total_soilc_pes(pid) + ! cumulatively add-up active soil column no. by pid, + ! until 'pid==iam' at which globally-indexed 'id' (mapped_gid) then can be numberred continueously. + endif + + end do + + +#else + ! 'grid'-wised coupling + ! (1) grid without soil column IS allowed, but will be skipped. + ! This will allow exactly same grid domain for CLM and PFLOTRAN + ! (why? - we may be able to run CLM-PFLOTRAN for irregular mesh, by assigning non-soil grid in normally a CLM rectangulal surface domain.) + ! (2) if soil column within a grid, assumes that only 1 natural/cropped soil-column allowed per grid cell NOW + + ! count active soil columns for a gridcell to do checking below + gcolumns(:) = 0 + ! a note: grc%ncolumns NOT assigned values at all, so cannot be used here. + do c = bounds%begc, bounds%endc + l = clandunit(c) + g = cgridcell(c) + + gcount = g - bounds%begg + 1 + if ((.not.(ltype(l)==istsoil)) .and. (.not.(ltype(l)==istcrop)) ) then + !write (iulog,*) 'WARNING: Land Unit type of Non-SOIL/CROP... within the domain' + !write (iulog,*) 'CLM-- PFLOTRAN does not support this land unit at present, AND will skip it' + + else + if (cactive(c) .and. cwtgcell(c)>0._r8) then + gcolumns(gcount) = gcolumns(gcount)+1 + end if + endif + + enddo ! do c = bounds%begc, bounds%endc + + ! do checking on assumption: 1 soil col. (either natveg or crop, but not both) per grid + total_soilc = 0 + do g = bounds%begg, bounds%endg + if (gcolumns(g-bounds%begg+1) > 1) then + write (iulog,*) 'ERROR: More than 1 ACTIVE soil column found in gridcell:', g, gcolumns(g-bounds%begg+1) + write (iulog,*) 'CLM-PFLOTRAN does not support this at present, AND please check your surface data, then re-run' + write (iulog,*) ' i.e., this mode is used for user-defined CLM grid, which may be generated together with PF mesh' + + call endrun(trim(subname) // ": ERROR: Currently does not support multiple or inactive soil column per grid " // & + "in this version of CLM-PFLOTRAN.") + + else + total_soilc = total_soilc + gcolumns(g-bounds%begg+1) + + endif + enddo + + call mpi_barrier(mpicom, ierr) ! needs all processes done first + ! sum of all active-soil-column gridcells across all processors (information only) + call mpi_allreduce(total_soilc, global_numg, 1, MPI_INTEGER,MPI_SUM,mpicom,ierr) + + ! counting active gridcells in current pes + total_grid = bounds%endg-bounds%begg+1 + + ! CLM's natural grid id, continued and ordered across processors, for mapping to PF mesh + ! will be assigned to calculate 'clm_cell_ids_nindex' below + allocate(mapped_gid(1:total_grid)) + + ! mark the inactive grid (non-natveg/crop landunits) + ! will be used to skip inactive grids in 'bounds%begg:endg' + allocate(mapped_gcount_skip(1:bounds%endg-bounds%begg+1)) + mapped_gcount_skip(:) = .true. + ! ideally it's better to loop with grc%numcol, but which seems not assigned a value + do c=bounds%begc, bounds%endc + l = clandunit(c) + g = cgridcell(c) + gcount = g-bounds%begg+1 + + if( (ltype(l)==istsoil .or. ltype(l)==istcrop) .and. & + (cactive(c) .and. cwtgcell(c)>0._r8) ) then + mapped_gid(gcount) = grc_pp%gindex(g) ! this is the globally grid-index, i.e. 'an' in its original calculation + + mapped_gcount_skip(gcount) = .false. + endif + + end do + + +#endif + + + if (masterproc) then + write(iulog,*) '%%--------------------------------------------------------%%' + write(iulog,*) '%% %%' + write(iulog,*) '%% clm_pf_interface_init %%' + write(iulog,*) '%% %%' +#ifdef COLUMN_MODE + write(iulog,*) '%% --- 1D COLUMN-MODE --- %%' + write(iulog,*) '%% Total soil columns (natveg+crop): ',global_numc,' %%' +#else + write(iulog,*) '%% --- FULLY-3D COUPLED-MODE --- %%' + write(iulog,*) '%% Total grids with active soil columns: ',global_numg,' %%' +#endif + write(iulog,*) '%% %%' + write(iulog,*) '%%--------------------------------------------------------%%' + write(iulog,*) ' ' + endif + + + pf_clmnstep0 = get_nstep() + + !---------------------------------------------------------------------------------------- + ! (1) Initialize PETSc vector for data transfer between CLM and PFLOTRAN + call CLMPFLOTRANIDataInit() + + !---------------------------------------------------------------------------------------- + ! (2) passing grid/mesh info to interface_data so that PF mesh can be established/mapped + + !(2a) domain/decompose + clm_pf_idata%nzclm_mapped = nlevgrnd ! the soil layer no. mapped btw CLM and PF for data-passing + + if (masterproc) then + write(iulog,*) '%% %%' + write(iulog,*) '%% CLM-Layer-No. PF-Layer-NO. Thickness (m) %%' + do j=clm_pf_idata%nzclm_mapped, 1, -1 + write(iulog,*) j, clm_pf_idata%nzclm_mapped-j+1, dzsoi(j) + enddo + write(iulog,*) '%% %%' + write(iulog,*) ' ' + endif + + +#ifdef COLUMN_MODE + clm_pf_idata%nxclm_mapped = global_numc ! 1-D format, along X direction + clm_pf_idata%nyclm_mapped = 1 ! 1-D format + + clm_pf_idata%npx = npes + clm_pf_idata%npy = 1 + clm_pf_idata%npz = 1 + + if(.not.associated(clm_pf_idata%clm_lx)) & + allocate(clm_pf_idata%clm_lx(1:clm_pf_idata%npx)) + if(.not.associated(clm_pf_idata%clm_ly)) & + allocate(clm_pf_idata%clm_ly(1:clm_pf_idata%npy)) + if(.not.associated(clm_pf_idata%clm_lz)) & + allocate(clm_pf_idata%clm_lz(1:clm_pf_idata%npz)) + + ! + do pid=0, npes-1 + clm_pf_idata%clm_lx(pid+1) = total_soilc_pes(pid) + end do + clm_pf_idata%clm_ly = 1 + clm_pf_idata%clm_lz = clm_pf_idata%nzclm_mapped + + deallocate(total_soilc_pes) + +#else + clm_pf_idata%nxclm_mapped = ldomain%ni ! longitudial + clm_pf_idata%nyclm_mapped = ldomain%nj ! latidudial + + ! Currently, the following IS only good for user-defined non-global soil domain + ! AND, the CLM grids ONLY over-rides PF mesh, when 'mapping_files' not provided + ! i.e. only used for structured-grid. + + ! due to virtually 2-D surface-grid, along which PF structured-grids are decomposed, + !the 'npes' used by PF must be some specific number + nx = ldomain%ni + ny = ldomain%nj + if(npes pflotran_m%simulation) + class is (simulation_subsurface_type) + realization => simulation%realization + class default + pflotran_m%option%io_buffer = "This version of clm-pflotran only works with subsurface simulations." + write(*, '(/A/)') pflotran_m%option%io_buffer + call printErrMsg(pflotran_m%option) + end select + + if(pflotran_m%option%nsurfflowdof > 0) then + pflotran_m%option%io_buffer = "This version of clm-pflotran DOES NOT work with PF Surface simulation." + write(*, '(/A/)') pflotran_m%option%io_buffer + call printErrMsg(pflotran_m%option) + endif + pf_surfaceflow = .false. + + !------------------------------------------------ + + ! Number of cells and Indexing in CLM domain's clumps on current process ('bounds') + +#ifdef COLUMN_MODE + ! soil column-wised for mapping. + clm_all_npts = total_soilc*clm_pf_idata%nzclm_mapped + clm_top_npts = total_soilc + clm_bot_npts = total_soilc + allocate(clm_all_cell_ids_nindex(1:clm_all_npts)) + allocate(clm_top_cell_ids_nindex(1:clm_top_npts)) + allocate(clm_bot_cell_ids_nindex(1:clm_bot_npts)) + + cellcount = 0 + do colcount = 1, total_soilc + gid = mapped_gid(colcount) + + ! Save cell IDs (0-based) of CLM columns in 1D array on current process ('bounds') + clm_top_cell_ids_nindex(colcount) = (gid-1)*clm_pf_idata%nzclm_mapped + do j = 1,clm_pf_idata%nzclm_mapped + cellcount = cellcount + 1 + clm_all_cell_ids_nindex(cellcount) = (gid-1)*clm_pf_idata%nzclm_mapped + j - 1 + enddo + clm_bot_cell_ids_nindex(colcount) = gid*clm_pf_idata%nzclm_mapped - 1 + + end do + deallocate(mapped_gid) + +#else + !grid-wised for mapping. + clm_all_npts = total_grid*clm_pf_idata%nzclm_mapped + clm_top_npts = total_grid + clm_bot_npts = total_grid + allocate(clm_all_cell_ids_nindex(1:clm_all_npts)) + allocate(clm_top_cell_ids_nindex(1:clm_top_npts)) + allocate(clm_bot_cell_ids_nindex(1:clm_bot_npts)) + + cellcount = 0 + do gcount = 1, total_grid + + gid = mapped_gid(gcount) + + ! Save cell IDs of CLM grid + do j = 1,clm_pf_idata%nzclm_mapped + cellcount = cellcount + 1 + clm_all_cell_ids_nindex(cellcount) = (gid-1)*clm_pf_idata%nzclm_mapped + j-1 ! zero-based + enddo + clm_top_cell_ids_nindex(gcount) = (gid-1)*clm_pf_idata%nzclm_mapped ! zero-based + clm_bot_cell_ids_nindex(gcount) = gid*clm_pf_idata%nzclm_mapped-1 ! zero-based + + enddo + deallocate(mapped_gid) + +#endif + + + ! CLM: 3-D Subsurface domain (local and ghosted cells) + clm_pf_idata%nlclm_sub = clm_all_npts + clm_pf_idata%ngclm_sub = clm_all_npts + + ! CLM: Surface/Bottom cells of subsurface domain (local and ghosted cells) + clm_pf_idata%nlclm_2dtop = clm_top_npts + clm_pf_idata%ngclm_2dtop = clm_top_npts + + ! CLM: bottom face of subsurface domain + clm_pf_idata%nlclm_2dbot = clm_bot_npts + clm_pf_idata%ngclm_2dbot = clm_bot_npts + + ! PFLOTRAN: 3-D Subsurface domain (local and ghosted cells) + clm_pf_idata%nlpf_sub = realization%patch%grid%nlmax + clm_pf_idata%ngpf_sub = realization%patch%grid%ngmax + + ! For CLM/PF: ground surface NOT defined, so need to set the following to zero. + clm_pf_idata%nlclm_srf = 0 + clm_pf_idata%ngclm_srf = 0 + clm_pf_idata%nlpf_srf = 0 + clm_pf_idata%ngpf_srf = 0 + + ! Initialize maps for transferring data between CLM and PFLOTRAN. + if(associated(pflotran_m%map_clm_sub_to_pf_sub) .and. & + pflotran_m%map_clm_sub_to_pf_sub%id == CLM_3DSUB_TO_PF_3DSUB) then + call pflotranModelInitMapping(pflotran_m, clm_all_cell_ids_nindex, & + clm_all_npts, CLM_3DSUB_TO_PF_3DSUB) + endif + if(associated(pflotran_m%map_pf_sub_to_clm_sub) .and. & + pflotran_m%map_pf_sub_to_clm_sub%id == PF_3DSUB_TO_CLM_3DSUB) then + call pflotranModelInitMapping(pflotran_m, clm_all_cell_ids_nindex, & + clm_all_npts, PF_3DSUB_TO_CLM_3DSUB) + endif + ! + if(associated(pflotran_m%map_clm_2dtop_to_pf_2dtop) .and. & + pflotran_m%map_clm_2dtop_to_pf_2dtop%id == CLM_2DTOP_TO_PF_2DTOP) then + call pflotranModelInitMapping(pflotran_m, clm_top_cell_ids_nindex, & + clm_top_npts, CLM_2DTOP_TO_PF_2DTOP) + endif + if(associated(pflotran_m%map_pf_2dtop_to_clm_2dtop) .and. & + pflotran_m%map_pf_2dtop_to_clm_2dtop%id == PF_2DTOP_TO_CLM_2DTOP) then + call pflotranModelInitMapping(pflotran_m, clm_top_cell_ids_nindex, & + clm_top_npts, PF_2DTOP_TO_CLM_2DTOP) + endif + ! + if(associated(pflotran_m%map_clm_2dbot_to_pf_2dbot) .and. & + pflotran_m%map_clm_2dbot_to_pf_2dbot%id == CLM_2DBOT_TO_PF_2DBOT) then + call pflotranModelInitMapping(pflotran_m, clm_bot_cell_ids_nindex, & + clm_bot_npts, CLM_2DBOT_TO_PF_2DBOT) + endif + if(associated(pflotran_m%map_pf_2dbot_to_clm_2dbot) .and. & + pflotran_m%map_pf_2dbot_to_clm_2dbot%id == PF_2DBOT_TO_CLM_2DBOT) then + call pflotranModelInitMapping(pflotran_m, clm_bot_cell_ids_nindex, & + clm_bot_npts, PF_2DBOT_TO_CLM_2DBOT) + endif + + ! Allocate vectors for data transfer between CLM and PFLOTRAN. + call CLMPFLOTRANIDataCreateVec(MPI_COMM_WORLD) + +#ifdef COLUMN_MODE + ! if 'column-wised' mapping, vertical-flow/transport only mode IS ON by default + if(pflotran_m%option%nflowdof > 0) then + pflotran_m%option%flow%only_vertical_flow = PETSC_TRUE + endif + if(pflotran_m%option%ntrandof > 0) then + pflotran_m%option%transport%only_vertical_tran = PETSC_TRUE + endif + + ! checking if 'option%mapping_files' turned off by default + if(pflotran_m%option%mapping_files) then + pflotran_m%option%io_buffer = " COLUMN_MODE coupled clm-pflotran DOES NOT need MAPPING_FILES ON." + write(*, '(/A/)') pflotran_m%option%io_buffer + call printErrMsg(pflotran_m%option) + endif + +#endif + + ! if BGC is on + if(pflotran_m%option%ntrandof > 0) then + + ! the CLM-CN/BGC decomposing pools + clm_pf_idata%decomp_pool_name = decomp_cascade_con%decomp_pool_name_history(1:ndecomp_pools) + clm_pf_idata%floating_cn_ratio = decomp_cascade_con%floating_cn_ratio_decomp_pools(1:ndecomp_pools) + ! PF bgc species names/IDs + call pflotranModelGetRTspecies(pflotran_m) + endif + + deallocate(clm_all_cell_ids_nindex) + deallocate(clm_top_cell_ids_nindex) + deallocate(clm_bot_cell_ids_nindex) + +!------------------------------------------------------------------------------------- + ! coupled module controls betweeen PFLOTRAN and CLM45 (F.-M. Yuan, Aug. 2013) + if(pflotran_m%option%iflowmode==RICHARDS_MODE) then + pf_hmode = .true. + pf_tmode = .false. + pf_frzmode = .false. + + elseif(pflotran_m%option%iflowmode==TH_MODE) then + pf_hmode = .true. + pf_tmode = .true. + if (pflotran_m%option%use_th_freezing) then + pf_frzmode = .true. + else + pf_frzmode = .false. + endif + endif + + if(pflotran_m%option%ntrandof.gt.0) then + pf_cmode = .true. ! initialized as '.false.' in clm initialization + endif + + + ! Initialize PFLOTRAN states + call pflotranModelStepperRunInit(pflotran_m) + + end associate + end subroutine interface_init + + !----------------------------------------------------------------------------- + ! + ! !SUBROUTINE: pflotran_run_onestep + ! + ! !INTERFACE: + + subroutine pflotran_run_onestep(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! + ! F.-M. YUAN: based on Gautam's 'step_th_clm_pf', + ! 'chemistry' (PF_CMODE) added (Sept. 6, 2013) + ! + ! !USES: + use spmdMod , only : mpicom, masterproc, iam, npes + use clm_time_manager , only : get_step_size, get_nstep, nsstep, nestep, & + is_first_step, is_first_restart_step, calc_nestep + use clm_varctl , only : pf_tmode, pf_hmode, pf_cmode, & + pf_frzmode, pf_clmnstep0, initth_pf2clm + + ! + implicit none + + type(bounds_type) , intent(in) :: bounds + type(clumpfilter) , intent(inout) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operate + + type(clm_interface_data_type), intent(inout) :: clm_interface_data + + !LOCAL VARIABLES: + real(r8) :: dtime ! land model time step (sec) + integer :: nstep ! time step number + integer :: total_clmstep ! total clm time step number + logical :: ispfprint ! let PF printout or not + logical :: isinitpf = .FALSE. ! (re-)initialize PF from CLM or not + integer :: ierr + + !----------------------------------------------------------------------- + + nstep = get_nstep() - pf_clmnstep0 !nsstep + dtime = get_step_size() + + if (is_first_step() .or. is_first_restart_step()) then + isinitpf = .TRUE. + else + isinitpf = .FALSE. + endif + + + ! (0) + if (isinitpf) then + call calc_nestep() ! nestep + total_clmstep = nestep - pf_clmnstep0 !nestep - nsstep + ispfprint = .true. ! turn-on or shut-off PF's *.h5 output + + call pflotranModelUpdateFinalWaypoint(pflotran_m, total_clmstep*dtime, dtime, ispfprint) + + ! beg------------------------------------------------ + ! move from 'interface_init' + ! force CLM soil domain into PFLOTRAN subsurface grids + call get_clm_soil_dimension(clm_interface_data, bounds) + + ! Currently always set soil hydraulic/BGC properties from CLM to PF + call get_clm_soil_properties(clm_interface_data, bounds, filters) + + ! Get top surface area of 3-D pflotran subsurface domain + call pflotranModelGetTopFaceArea(pflotran_m) + + ! end------------------------------------------------ + + ! always initializing soil 'TH' states from CLM to pflotran + call get_clm_soil_th(clm_interface_data, .not.initth_pf2clm, .not.initth_pf2clm, bounds, filters, ifilter) + + call pflotranModelUpdateTHfromCLM(pflotran_m, .FALSE., .FALSE.) ! pass TH to global_auxvar + + endif + + + ! (1) + ! if PF T/H mode not available, have to pass those from CLM to global variable in PF to drive BGC/H + if (.not. isinitpf .and. (.not.pf_tmode .or. .not.pf_hmode)) then ! always initialize from CLM to pF, if comment out this 'if'block + call get_clm_soil_th(clm_interface_data, .TRUE., .TRUE., bounds, filters, ifilter) + + call pflotranModelUpdateTHfromCLM(pflotran_m, .FALSE., .FALSE.) ! pass TH to global_auxvar + + end if + + ! ice-len adjusted porostiy, if PF-ice mode off + if (.not.pf_frzmode) then + call get_clm_iceadj_porosity(clm_interface_data, bounds, filters, ifilter) + + call pflotranModelResetSoilPorosityFromCLM(pflotran_m) + + endif + + ! (2) CLM thermal BC to PFLOTRAN-CLM interface + if (pf_tmode) then + call get_clm_bceflx(clm_interface_data, bounds, filters, ifilter) + call pflotranModelUpdateSubsurfTCond( pflotran_m ) ! E-SrcSink and T bc + end if + + ! (3) pass CLM water fluxes to PFLOTRAN-CLM interface + if (pf_hmode) then !if coupled 'H' mode between CLM45 and PFLOTRAN + call get_clm_bcwflx(clm_interface_data, bounds, filters, ifilter) + + ! pass flux 'vecs' from CLM to pflotran + call pflotranModelUpdateHSourceSink( pflotran_m ) ! H SrcSink + call pflotranModelSetSoilHbcsFromCLM( pflotran_m ) ! H bc + end if + + ! (4) + if (pf_cmode) then + + ! (4a) always (re-)initialize PFLOTRAN soil bgc state variables from CLM-CN + ! (this will be easier to maintain balance error-free) + + call get_clm_bgc_conc(clm_interface_data, bounds, filters, ifilter) + call pflotranModelSetBgcConcFromCLM(pflotran_m) + if ((.not.pf_hmode .or. .not.pf_frzmode)) then + ! this is needed, because at step 0, PF's interface data is empty + ! which causes Aq. conc. adjustment balacne issue + call pflotranModelGetSaturationFromPF(pflotran_m) + endif + + + ! MUST reset PFLOTRAN soil aq. bgc state variables from CLM-CN due to liq. water volume change + ! when NOT coupled with PF Hydrology or NOT in freezing-mode (porosity will be forced to vary from CLM) + if (.not.pf_hmode .or. .not.pf_frzmode) then + call pflotranModelUpdateAqConcFromCLM(pflotran_m) + endif + + ! (4b) bgc rate (fluxes) from CLM to PFLOTRAN + call get_clm_bgc_rate(clm_interface_data, bounds, filters, ifilter) + call pflotranModelSetBgcRatesFromCLM(pflotran_m) + + endif + + ! (5) the main callings of PFLOTRAN + call mpi_barrier(mpicom, ierr) + + if(mod(nstep+1,48) == 0) then ! this will allow PFLOTRAN write out every 48 CLM time-step, if relevant option is ON. + ispfprint = .TRUE. + else + ispfprint = .FALSE. + endif + + call pflotranModelStepperRunTillPauseTime( pflotran_m, (nstep+1.0d0)*dtime, dtime, ispfprint ) + call mpi_barrier(mpicom, ierr) + + ! (6) update CLM variables from PFLOTRAN + + if (pf_hmode) then + call pflotranModelGetSaturationFromPF( pflotran_m ) ! hydrological states + call update_soil_moisture_pf2clm(clm_interface_data, bounds, filters, ifilter) + + ! the actual infiltration/runoff/drainage and solute flux with BC, if defined, + ! are retrieving from PFLOTRAN using 'update_bcflow_pf2clm' subroutine + call pflotranModelGetBCMassBalanceDeltaFromPF( pflotran_m ) + call update_bcflow_pf2clm(clm_interface_data, bounds, filters, ifilter) + + endif + + if (pf_tmode) then + call pflotranModelGetTemperatureFromPF( pflotran_m ) ! thermal states + call update_soil_temperature_pf2clm(clm_interface_data, bounds, filters, ifilter) + endif + + if (pf_cmode) then + call pflotranModelGetBgcVariablesFromPF( pflotran_m) ! bgc variables + + call update_soil_bgc_pf2clm(clm_interface_data, bounds, filters, ifilter) + + call update_bgc_bcflux_pf2clm(clm_interface_data, bounds, filters, ifilter) + + ! need to save the current time-step PF porosity/liq. saturation for bgc species mass conservation + ! if CLM forced changing them into PF at NEXT timestep + if (.not.pf_hmode .or. .not.pf_frzmode) then + call pflotranModelGetSaturationFromPF(pflotran_m) + endif + + endif + + end subroutine pflotran_run_onestep + + !----------------------------------------------------------------------- + !BOP + ! + ! !ROUTINE: write_checkpoint + ! + ! !INTERFACE: + subroutine pflotran_write_checkpoint(date_stamp) + ! + ! !DESCRIPTION: + ! Trigger a pflotran checkpoint file to be written + ! + ! !USES: + ! !ARGUMENTS: + character(len=32), intent(in) :: date_stamp ! file name date stamp + + ! !LOCAL VARIABLES: + + !EOP + !----------------------------------------------------------------------- + + ! temporarily OFF - it's not working well for BGC + ! So, now must initializing PF variables from CLM each start/restart. + + !call pflotranModelStepperCheckpoint(pflotran_m, date_stamp) + + end subroutine pflotran_write_checkpoint + + !----------------------------------------------------------------------------- + ! + ! !IROUTINE: pflotran_finalize + ! + ! !INTERFACE: + subroutine pflotran_finalize() + ! + ! !DESCRIPTION: + ! + ! finalizing pflotran runs and destroying objects + ! + ! !USES: + use clm_varctl , only : use_pflotran + + implicit none + + !----------------------------------------------------------------------- + + if (use_pflotran) then + call pflotranModelDestroy(pflotran_m) + endif + + deallocate(mapped_gcount_skip) + + end subroutine pflotran_finalize + + + !==================================================================================================== + ! ! + ! Subroutines to GET CLM Dimension & Properties to PFLOTRAN ! + ! ! + !==================================================================================================== + !BOP + ! + ! !IROUTINE: get_clm_soil_dimension + ! + ! !INTERFACE: + subroutine get_clm_soil_dimension(clm_interface_data, bounds) + ! + ! !DESCRIPTION: + ! get soil column dimension to PFLOTRAN + ! + ! !USES: + use GridcellType , only : grc_pp + use LandunitType , only : lun_pp + use ColumnType , only : col_pp + + use clm_varpar , only : nlevgrnd + use domainMod , only : ldomain + use landunit_varcon , only : istsoil, istcrop + use clm_varcon , only : re + + + ! + ! !ARGUMENTS: + + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + type(bounds_type) , intent(in) :: bounds + type(clm_interface_data_type) , intent(in) :: clm_interface_data + ! + ! !REVISION HISTORY: + ! Created by Gautam Bisht + ! Revised by Fengming Yuan, CCSI-ORNL, May 2015 + ! + !EOP + ! + ! LOCAL VARAIBLES: + + integer :: g,l,c,j ! indices + integer :: gcount, colcount, cellcount ! gcount: 0-based, colcount: 1-based, cellcount: 1-based + integer :: v, n1, n2 + real(r8) :: p1, p2 + real(r8) :: dxsoil_clm(1:bounds%endg-bounds%begg+1) + real(r8) :: dysoil_clm(1:bounds%endg-bounds%begg+1) +#ifdef COLUMN_MODE + real(r8) :: wtgcell_sum(1:bounds%endc-bounds%begc+1) +#else + real(r8) :: wtgcell_sum(1:bounds%endg-bounds%begg+1) + integer :: xwtgcell_c(1:bounds%endg-bounds%begg+1) +#endif + + character(len= 32) :: subname = 'get_clm_soil_dimension' ! subroutine name + + PetscScalar, pointer :: cellid_clm_loc(:) + PetscScalar, pointer :: zisoil_clm_loc(:) ! 3-D PF-cell's z-node coordinates (elevation-adjusted, unit: m) + PetscScalar, pointer :: dxsoil_clm_loc(:) ! 3-D PF-cell's soil length (unit: degrees) + PetscScalar, pointer :: dysoil_clm_loc(:) ! 3-D PF-cell's soil width (unit: degrees) + PetscScalar, pointer :: dzsoil_clm_loc(:) ! 3-D PF-cell's soil thickness (unit: m) + PetscScalar, pointer :: xsoil_clm_loc(:) ! 3-D PF-cell's center x coordinates (unit: m) + PetscScalar, pointer :: ysoil_clm_loc(:) ! 3-D PF-cell's center y coordinates (unit: m) + PetscScalar, pointer :: zsoil_clm_loc(:) ! 3-D PF-cell's soil depth from ground surface at the layer center (unit: m) + PetscScalar, pointer :: toparea_clm_loc(:) ! 3-D PF-cell (unit: m^2) + + PetscErrorCode :: ierr + + + ! for calling functions in 'geodesic.for' + double precision a, f, dummy1, dummy2 + double precision lats(4), lons(4) + a = 6378137.0d0 ! major-axis length of Earth Ellipsoid in metres in WGS-84 + f = 1.d0/298.257223563d0 ! flatening of Earth Ellipsoid in WGS-84 + + associate( & + ! Assign local pointers to derived subtypes components (gridcell-level) + latc => ldomain%latc , & ! [real(r8) (:)] + lonc => ldomain%lonc , & ! [real(r8) (:)] + ! latv/lonv missing in ACME1 + latv => ldomain%latv , & ! [real(r8) (:,:)] + lonv => ldomain%lonv , & ! [real(r8) (:,:)] + + lelev => ldomain%topo , & ! [real(r8) (:)] + larea => ldomain%area , & ! [real(r8) (:)] + ! landunit + ltype => lun_pp%itype , & ! [integer (:)] landunit type index + ! Assign local pointer to derived subtypes components (column-level) + clandunit => col_pp%landunit , & ! [integer (:)] landunit index of column + cgridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column + cwtgcell => col_pp%wtgcell , & ! [real(r8) (:)] weight (relative to gridcell) + cactive => col_pp%active , & ! [logic (:)] column active or not + ! + z => col_pp%z , & ! [real(r8) (:,:)] layer depth (m) (sort of centroid from surface 0 ) + zi => col_pp%zi , & ! [real(r8) (:,:)] layer interface depth (m) + dz => col_pp%dz & ! [real(r8) (:,:)] layer thickness (m) + ) + + +#ifdef COLUMN_MODE + wtgcell_sum(:) = 1._r8 ! this is a fake value for column because cannot use the real 'cwtgcell', which may be ZERO (but will skip when do data passing) + +#else + ! active column weight summation for 1 grid + wtgcell_sum(:) = 0._r8 + xwtgcell_c(:) = 0 + + do c = bounds%begc, bounds%endc + gcount = cgridcell(c) - bounds%begc + 1 + if (xwtgcell_c(gcount)<=0) xwtgcell_c(gcount) = c + if (cactive(c)) then + wtgcell_sum(gcount) = wtgcell_sum(gcount)+cwtgcell(c) + + if( (cwtgcell(c)>=cwtgcell(xwtgcell_c(gcount))) .or. & + (.not.cactive(xwtgcell_c(gcount))) ) then + xwtgcell_c(gcount) = c ! column index with max. weight in a gridcell + end if + + end if + + enddo +#endif + + do g = bounds%begg, bounds%endg + gcount = g - bounds%begg ! 0-based + ! re-calculating 2-D grid area if vertices are known from input file + ! NOTE: this will over-write the grid area read-in from either 'ldomain' file or 'surfdata' file + if (ldomain%nv==4 .or. ldomain%nv==3) then + if (ldomain%nv==4) then + lats = latv(g,1:4) + lons = lonv(g,1:4) + call area(a, f, lats, lons, 4, dummy1, dummy2) + else if (ldomain%nv==3) then + lats(1:3) = latv(g,1:3) + lons(1:3) = lonv(g,1:3) + call area(a, f, lats(1:3), lons(1:3), 3, dummy1, dummy2) + endif + + if (dummy1 < 1.d-20) then + call endrun(trim(subname) // ": ERROR: re-calculated ldomain%area is less than 0. " // & + "Please check the grid vertices lat/lon in ldomain file") + else + larea(g) = dummy1 * 1.e-6_r8 + endif + + ! for 1-D grid, either 'dx' or 'dy' may be variable and acceptable in the model + ! (though, currently NOT YET used for PF mesh) + ! (NOTE: for 2-D grid, dx/dy in lon/lat can NOT be variable) + if(.not.ldomain%isgrid2d) then + + p1 = 0._r8 + p2 = 0._r8 + n1 = 0 + n2 = 0 + do v = 1, ldomain%nv ! ldomain%nv missing in ACME1 + if (lonv(g,v)lonc(g)) then + p2 = p2 + lonv(g,v) + n2 = n2 + 1 + end if + end do + if (n1 > 0 .and. n2 > 0) then + dxsoil_clm(gcount+1) = abs(p2/n2-p1/n1) ! degs + endif + + p1 = 0._r8 + p2 = 0._r8 + n1 = 0 + n2 = 0 + do v = 1, ldomain%nv ! ldomain%nv missing in ACME1 + if (latv(g,v)latc(g)) then + p2 = p2 + latv(g,v) + n2 = n2 + 1 + end if + end do + if (n1 > 0 .and. n2 > 0) then + dysoil_clm(gcount+1) = abs(p2/n2-p1/n1) ! degs + endif + + endif !if(.not.ldomain%isgrid2d) + + endif !if (ldomain%nv==4 .or. 3) + + end do + + call VecGetArrayF90(clm_pf_idata%cellid_clmp, cellid_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%zisoil_clmp, zisoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%dxsoil_clmp, dxsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%dysoil_clmp, dysoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%dzsoil_clmp, dzsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%area_top_face_clmp, toparea_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%xsoil_clmp, xsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%ysoil_clmp, ysoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%zsoil_clmp, zsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + zisoil_clm_loc(:) = 0._r8 + dxsoil_clm_loc(:) = 0._r8 + dysoil_clm_loc(:) = 0._r8 + dzsoil_clm_loc(:) = 0._r8 + + toparea_clm_loc(:) = 0._r8 + xsoil_clm_loc(:) = 0._r8 + ysoil_clm_loc(:) = 0._r8 + zsoil_clm_loc(:) = 0._r8 + + +#ifdef COLUMN_MODE + gcount = -1 + do c = bounds%begc, bounds%endc + g = cgridcell(c) + l = clandunit(c) + + colcount = c - bounds%begc + 1 + ! note that filters%soilc includes 'istsoil' and 'istcrop' + ! (TODO: checking col%itype and lun%itype - appears not match with each other, and col%itype IS messy) + if (.not.mapped_gcount_skip(colcount) ) then + gcount = gcount + 1 ! 0-based: the active soil column count + + do j = 1, clm_pf_idata%nzclm_mapped + if (j <= nlevgrnd) then + + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + xsoil_clm_loc(cellcount) = lonc(g) + ysoil_clm_loc(cellcount) = latc(g) + ! + dzsoil_clm_loc(cellcount) = dz(c, j) ! cell vertical thickness (m) + zisoil_clm_loc(cellcount) = -zi(c, j-1) + lelev(g) ! cell-node (top) elevation (m) + zsoil_clm_loc(cellcount) = z(c, j) ! cell-center vertical depth from surface (m) + + ! top face area, scaled by active column weight and land fraction + toparea_clm_loc(cellcount) = wtgcell_sum(colcount) * ldomain%frac(g) * larea(g) * 1.e6_r8 ! m^2 + + + ! after knowing 'toparea', we may get a pseudo 'dx' and 'dy' so that PF will not crash + ! (note: PF needs these information otherwise throw-out error message, even with 'vertical_only' option) + + if (ldomain%nv == 4) then ! ldomain%nv missing in ACME1 + ! having 4 vertices + lats = latv(g,1:4) + lons = lonv(g,1:4) + dxsoil_clm_loc(cellcount) = abs(lons(1)+lons(4)-lons(2)-lons(3))/2.0_r8 & + * wtgcell_sum(colcount) * ldomain%frac(g) + ! note: since in 'column_wise' mode, the columns are in 1D array by x-axis, + ! only need to scale 'dx' by column area fraction + dysoil_clm_loc(cellcount) = abs(lats(1)+lats(2)-lats(3)-lats(4))/2.0_r8 + + else + dxsoil_clm_loc(cellcount) = larea(g)/(re**2) & ! in degrees of great circle length + * wtgcell_sum(colcount) * ldomain%frac(g) + dysoil_clm_loc(cellcount) = larea(g)/(re**2) + endif + + else + call endrun(trim(subname) // ": ERROR: CLM-PF mapped soil layer numbers is greater than " // & + " 'clm_varpar%nlevgrnd'. Please check") + + endif + + enddo ! do j=1,nzclm_mapped + + endif + enddo ! do c = bounds%begc, bounds%endc + +#else + + do g = bounds%begg, bounds%endg + gcount = g - bounds%begg ! 0-based + + do j = 1, clm_pf_idata%nzclm_mapped + + if (j <= nlevgrnd) then + + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + cellid_clm_loc(cellcount) = (grc_pp%gindex(g)-1)*clm_pf_idata%nzclm_mapped + j ! 1-based + + xsoil_clm_loc(cellcount) = lonc(g) + ysoil_clm_loc(cellcount) = latc(g) + dxsoil_clm_loc(cellcount) = -9999.d0 + dysoil_clm_loc(cellcount) = -9999.d0 + + ! + dzsoil_clm_loc(cellcount) = dz(xwtgcell_c(gcount+1), j) ! cell vertical thickness (m), by column of max. weight in a grid + zisoil_clm_loc(cellcount) = -zi(xwtgcell_c(gcount+1), j-1) + lelev(g) ! cell-node (top) elevation (m) + zsoil_clm_loc(cellcount) = z(xwtgcell_c(gcount+1), j) ! cell-center vertical depth from surface (m) + + ! top face area, scaled by active column weight (summed) and land fraction + toparea_clm_loc(cellcount) = wtgcell_sum(gcount+1) * ldomain%frac(g) * larea(g) * 1.e6_r8 ! m^2 + + else + call endrun(trim(subname) // ": ERROR: CLM-PF mapped soil layer numbers is greater than " // & + " 'clm_varpar%nlevgrnd'. Please check") + + endif + + enddo ! do j=1,nzclm_mapped + enddo ! do g = bounds%begg, bounds%endg + +#endif + + call VecRestoreArrayF90(clm_pf_idata%cellid_clmp, cellid_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%zisoil_clmp, zisoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%dxsoil_clmp, dxsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%dysoil_clmp, dysoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%dzsoil_clmp, dzsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%area_top_face_clmp, toparea_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%xsoil_clmp, xsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%ysoil_clmp, ysoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%zsoil_clmp, zsoil_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! Set CLM soil domain onto PFLOTRAN grid + call pflotranModelSetSoilDimension(pflotran_m) + + end associate + end subroutine get_clm_soil_dimension + + !----------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: get_clm_soil_properties + ! + ! !INTERFACE: + subroutine get_clm_soil_properties(clm_interface_data, bounds, filters) + ! + ! !DESCRIPTION: + ! get soil column physical properties to PFLOTRAN + ! + ! !USES: + use LandunitType , only : lun_pp + use ColumnType , only : col_pp + use landunit_varcon , only : istsoil, istcrop + + use clm_varpar , only : nlevgrnd, ndecomp_pools, ndecomp_cascade_transitions + use CNDecompCascadeConType , only : decomp_cascade_con + + ! pflotran + ! + ! !ARGUMENTS: + + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" +#include "petsc/finclude/petscviewer.h" + + ! + ! !REVISION HISTORY: + ! Created by Gautam Bisht + ! Revised by Fengming Yuan, CCSI-ORNL + ! + !EOP + ! + ! LOCAL VARAIBLES: + + type(bounds_type), intent(in) :: bounds ! bounds + type(clumpfilter), intent(in) :: filters(:) ! filters on current process + + type(clm_interface_data_type), intent(in) :: clm_interface_data + + ! LOCAL VARAIBLES: + + integer :: fc, c, l, g, j ! indices + integer :: k,ki,kj + integer :: gcount, cellcount ! gcount: 0-based, cellcount: 1-based + integer :: soilc1, layer1 + real(r8) :: CN_ratio_mass_to_mol + real(r8) :: wtgcount + + character(len= 32) :: subname = 'get_clm_soil_properties' ! subroutine name + + + PetscScalar, pointer :: hksat_x_clm_loc(:) ! hydraulic conductivity in x-dir at saturation (mm H2O /s) + PetscScalar, pointer :: hksat_y_clm_loc(:) ! hydraulic conductivity in y-dir at saturation (mm H2O /s) + PetscScalar, pointer :: hksat_z_clm_loc(:) ! hydraulic conductivity in z-dir at saturation (mm H2O /s) + PetscScalar, pointer :: watsat_clm_loc(:) ! minimum soil suction (mm) + PetscScalar, pointer :: sucsat_clm_loc(:) ! volumetric soil water at saturation (porosity) + PetscScalar, pointer :: bsw_clm_loc(:) ! Clapp and Hornberger "b" + PetscScalar, pointer :: watfc_clm_loc(:) + PetscScalar, pointer :: bulkdensity_dry_clm_loc(:) + + PetscScalar, pointer :: tkwet_clm_loc(:) + PetscScalar, pointer :: tkdry_clm_loc(:) + PetscScalar, pointer :: tkfrz_clm_loc(:) + PetscScalar, pointer :: hcvsol_clm_loc(:) + + PetscErrorCode :: ierr + + associate( & + ! Assign local pointer to derived subtypes components (column-level) + ltype => lun_pp%itype , & ! [integer (:)] landunit type index + ! Assign local pointer to derived subtypes components (column-level) + clandunit => col_pp%landunit , & ! [integer (:)] landunit index of column + cgridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column + cwtgcell => col_pp%wtgcell , & ! [real(r8) (:)] weight (relative to gridcell + cactive => col_pp%active , & ! + z => col_pp%z , & ! [real(r8) (:,:)] layer depth (m) + dz => col_pp%dz , & ! [real(r8) (:,:)] layer thickness depth (m) + zi => col_pp%zi , & ! [real(r8) (:,:)] interface level below a "z" level (m) + ! + bd => clm_interface_data%bd_col , & ! + bsw => clm_interface_data%bsw_col , & ! [real(r8) (:,:)] Clapp and Hornberger "b" (nlevgrnd) + hksat => clm_interface_data%hksat_col , & ! [real(r8) (:,:)] hydraulic conductivity at saturation (mm H2O /s) (nlevgrnd) + sucsat => clm_interface_data%sucsat_col , & ! [real(r8) (:,:)] minimum soil suction (mm) (nlevgrnd) + watsat => clm_interface_data%watsat_col , & ! [real(r8) (:,:)] volumetric soil water at saturation (porosity) (nlevgrnd) + watfc => clm_interface_data%watfc_col , & ! [real(r8) (:,:)] volumetric soil water at field capacity (nlevgrnd) + ! + tkwet => clm_interface_data%tkwet_col , & ! [real(r8) (:,:)] (nlevgrnd) + tkdry => clm_interface_data%tkdry_col , & ! [real(r8) (:,:)] (nlevgrnd) + tkfrz => clm_interface_data%tkfrz_col , & ! [real(r8) (:,:)] (nlevgrnd) + csol => clm_interface_data%csol_col , & ! [real(r8) (:,:)] (nlevgrnd) + ! + rf_decomp_cascade => clm_interface_data%bgc%rf_decomp_cascade_col , & + pathfrac_decomp_cascade => clm_interface_data%bgc%pathfrac_decomp_cascade_col , & + initial_cn_ratio => clm_interface_data%bgc%initial_cn_ratio , & + kd_decomp_pools => clm_interface_data%bgc%decomp_k_pools , & + kd_adfactor_pools => clm_interface_data%bgc%adfactor_kd_pools & + ) + +!------------------------------------------------------------------------------------- + if(pflotran_m%option%ntrandof > 0) then + ! the following assumes 'nclumps' in current process greater than 0 (at least 1) + + CN_ratio_mass_to_mol = clm_pf_idata%N_molecular_weight/clm_pf_idata%C_molecular_weight + clm_pf_idata%decomp_element_ratios(:,1) = 1.0_r8 + clm_pf_idata%decomp_element_ratios(:,2) = 1.0_r8/initial_cn_ratio(1:ndecomp_pools) & + /CN_ratio_mass_to_mol ! ratio in moles + + ! note: the following 'kd' and ad-factors for each pool are separated + clm_pf_idata%ck_decomp_c = kd_decomp_pools(1:ndecomp_pools) + clm_pf_idata%adfactor_ck_c = kd_adfactor_pools(1:ndecomp_pools) + + ! find the first active SOIL Column to pick up the decomposition constants + ! NOTE: this only is good for CLM-CN reaction-network; + ! for CLM-BGC (century-type), those constants are 'cell' dependent + ! So, here we do the data passing by cell (although only 1 now) that can be extended by adding two loops in the future + ! + soilc1 = filters(1)%soilc(1) + layer1 = 1 + + clm_pf_idata%fr_decomp_c = 0._r8 + do k = 1, ndecomp_cascade_transitions + ki=decomp_cascade_con%cascade_donor_pool(k) + kj=decomp_cascade_con%cascade_receiver_pool(k) + + if (ki>0) then + ! taking the first 'cell' as default ('pathfrac' is 'cell'-related, which will be adjusted if needed) + if (clm_pf_idata%fr_decomp_c(ki,ki) <=0._r8) then + ! not-yet assign 'co2' fraction for donor-pool + clm_pf_idata%fr_decomp_c(ki,ki) = rf_decomp_cascade(soilc1,layer1,k) ! CO2-C respiration fraction + elseif(clm_pf_idata%fr_decomp_c(ki,ki) .ne. rf_decomp_cascade(soilc1,layer1,k)) then + ! have assigned 'co2' fraction for same donor-pool with different receive-pool, + ! BUT 'co2' fraction inconsistent + call endrun(trim(subname) // ": ERROR: CLM-PFLOTRAN interface finds different respiration fraction for " // & + "same decomposition pool: " //trim(decomp_cascade_con%decomp_pool_name_history(ki)) ) + + endif + + if (kj>0) then + clm_pf_idata%fr_decomp_c(ki,kj) = (1.0_r8-rf_decomp_cascade(soilc1,layer1,k)) & + * pathfrac_decomp_cascade(soilc1,layer1,k) + else + if(clm_pf_idata%fr_decomp_c(ki,ki) .ne. 1.0) then + ! if no receivor, respiration fraction must be 1.0 + call endrun(trim(subname) // ": ERROR: CLM-PFLOTRAN interface finds respiration fraction not 1.0 for " // & + "no-down decomposition pool: " //trim(decomp_cascade_con%decomp_pool_name_history(ki)) ) + endif + + endif + + endif + + enddo + + call pflotranModelSetSOMKfromCLM(pflotran_m) + endif + + + call VecGetArrayF90(clm_pf_idata%hksat_x_clmp, hksat_x_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%hksat_y_clmp, hksat_y_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%hksat_z_clmp, hksat_z_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%sucsat_clmp, sucsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%watsat_clmp, watsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%bsw_clmp, bsw_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%watfc_clmp, watfc_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%bulkdensity_dry_clmp, bulkdensity_dry_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%tkwet_clmp, tkwet_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%tkdry_clmp, tkdry_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%tkfrz_clmp, tkfrz_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%hcvsol_clmp, hcvsol_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + hksat_x_clm_loc(:) = 0._r8 + hksat_y_clm_loc(:) = 0._r8 + hksat_z_clm_loc(:) = 0._r8 + sucsat_clm_loc(:) = 0._r8 + watsat_clm_loc(:) = 0._r8 + bsw_clm_loc(:) = 0._r8 + watfc_clm_loc(:) = 0._r8 + bulkdensity_dry_clm_loc(:) = 0._r8 + + tkwet_clm_loc(:) = 0._r8 + tkdry_clm_loc(:) = 0._r8 + tkfrz_clm_loc(:) = 0._r8 + hcvsol_clm_loc(:) = 0._r8 + + gcount = -1 + ! note: the following data-passing will be looping for all columns, instead of filters, + ! so that NO void grids in PF mesh even for inactive (and skipped) gridcell. + do c = bounds%begc, bounds%endc + ! Set gridcell and landunit indices + g = cgridcell(c) + l = clandunit(c) + + if ( (ltype(l)==istsoil .or. ltype(l)==istcrop) .and. & + (cactive(c) .and. cwtgcell(c)>0._r8) ) then ! skip inactive or zero-weighted column (may be not needed, but in case) + +#ifdef COLUMN_MODE + gcount = gcount + 1 ! 0-based column (fake grid) count + wtgcount = 1._r8 +#else + gcount = g - bounds%begg ! 0-based actual grid numbering + wtgcount = cwtgcell(c) +#endif + + do j = 1, clm_pf_idata%nzclm_mapped + + if (j <= nlevgrnd) then + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + ! CLM calculation of wet thermal-conductivity as following: + ! dksat = tkmg(c,j)*tkwat**(fl*watsat(c,j))*tkice**((1._r8-fl)*watsat(c,j)) + ! where, fl is the liq. saturation/total saturation + ! so, if fl=0, it's the frozen-wet thermal-conductitivity + ! if fl=1, it's the liq.-wet thermal-conductivity, i.e. 'tksatu' + + tkwet_clm_loc(cellcount ) = & !(W/m/K) + tkwet_clm_loc(cellcount ) + tkwet(c,j)*wtgcount + tkdry_clm_loc(cellcount ) = & + tkdry_clm_loc(cellcount ) + tkdry(c,j)*wtgcount + tkfrz_clm_loc(cellcount ) = & + tkfrz_clm_loc(cellcount ) + tkfrz(c,j)*wtgcount + hcvsol_clm_loc(cellcount ) = & + hcvsol_clm_loc(cellcount ) + csol(c,j)*wtgcount ! (J/m3/K) + + hksat_x_clm_loc(cellcount ) = & + hksat_x_clm_loc(cellcount ) + hksat(c,j)*wtgcount + hksat_y_clm_loc(cellcount ) = & + hksat_y_clm_loc(cellcount ) + hksat(c,j)*wtgcount + hksat_z_clm_loc(cellcount ) = & + hksat_z_clm_loc(cellcount ) + hksat(c,j)*wtgcount + + sucsat_clm_loc( cellcount ) = & + sucsat_clm_loc( cellcount ) + sucsat(c,j)*wtgcount + watsat_clm_loc( cellcount ) = & + watsat_clm_loc( cellcount ) + watsat(c,j)*wtgcount + bsw_clm_loc( cellcount ) = & + bsw_clm_loc( cellcount ) + bsw(c,j)*wtgcount + watfc_clm_loc( cellcount ) = & + watfc_clm_loc( cellcount ) + watfc(c,j)*wtgcount + bulkdensity_dry_clm_loc( cellcount ) = & + bulkdensity_dry_clm_loc( cellcount ) + bd(c,j)*wtgcount + + else + call endrun(trim(subname) // ": ERROR: CLM-PF mapped soil layer numbers is greater than " // & + " 'clm_varpar%nlevgrnd'. Please check") + + endif + enddo + endif + + enddo ! do c = bounds%begc, bounds%endc + + call VecRestoreArrayF90(clm_pf_idata%hksat_x_clmp, hksat_x_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%hksat_y_clmp, hksat_y_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%hksat_z_clmp, hksat_z_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%sucsat_clmp, sucsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%watsat_clmp, watsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%bsw_clmp, bsw_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%watfc_clmp, watfc_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%bulkdensity_dry_clmp, bulkdensity_dry_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) +! call VecRestoreArrayF90(clm_pf_idata%zsoi_clmp, zsoi_clm_loc, ierr) +! call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%tkwet_clmp, tkwet_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%tkdry_clmp, tkdry_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%tkfrz_clmp, tkfrz_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%hcvsol_clmp, hcvsol_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! Set CLM soil properties onto PFLOTRAN grid + call pflotranModelSetSoilProp(pflotran_m) + + end associate + end subroutine get_clm_soil_properties + + + !==================================================================================================== + ! ! + ! Subroutines to GET CLM initial/src-sink/BC to PFLOTRAN ! + ! ! + !==================================================================================================== + + !----------------------------------------------------------------------------- + !BOP + ! + ! !ROUTINE: get_clm_soil_th + ! + ! !INTERFACE: + subroutine get_clm_soil_th(clm_interface_data,initpftmode, initpfhmode, bounds, filters, ifilter) + + ! + ! !DESCRIPTION: + ! update soil temperature/saturation from CLM to PFLOTRAN for driving PF's BGC + ! if either NOT available inside PFLOTRAN + ! + ! !USES: + use clm_time_manager , only : get_nstep, is_first_step, is_first_restart_step + use shr_const_mod , only : SHR_CONST_G + use ColumnType , only : col_pp + use clm_varctl , only : iulog + use clm_varcon , only : denh2o, denice, tfrz + use clm_varpar , only : nlevgrnd + use shr_infnan_mod , only : shr_infnan_isnan + + use PFLOTRAN_Constants_module + use clm_varctl , only : pf_frzmode + + ! !ARGUMENTS: + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + logical , intent(in) :: initpftmode, initpfhmode + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(in) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(in) :: clm_interface_data + + ! !LOCAL VARIABLES: + integer :: fc, c, g, gcount, cellcount ! indices + + PetscScalar, pointer :: soilpress_clmp_loc(:) + PetscScalar, pointer :: soilpsi_clmp_loc(:) + PetscScalar, pointer :: soillsat_clmp_loc(:) + PetscScalar, pointer :: soilisat_clmp_loc(:) + PetscScalar, pointer :: soilvwc_clmp_loc(:) ! + PetscScalar, pointer :: soilt_clmp_loc(:) ! + PetscScalar, pointer :: t_scalar_clmp_loc(:) ! + PetscScalar, pointer :: w_scalar_clmp_loc(:) ! + PetscScalar, pointer :: o_scalar_clmp_loc(:) ! + PetscErrorCode :: ierr + integer :: j,nstep + real(r8):: sattmp, psitmp, itheta, sucmin_pa, psitmp0 + + character(len= 32) :: subname = 'get_clm_soil_th' ! subroutine name + + !EOP + !----------------------------------------------------------------------- + associate ( & + cgridcell => col_pp%gridcell , & ! column's gridcell + dz => col_pp%dz , & ! layer thickness depth (m) + ! + sucsat => clm_interface_data%sucsat_col , & ! minimum soil suction (mm) (nlevgrnd) + bsw => clm_interface_data%bsw_col , & ! Clapp and Hornberger "b" + watsat => clm_interface_data%watsat_col , & ! volumetric soil water at saturation (porosity) (nlevgrnd) + watmin => clm_interface_data%watmin_col , & ! col minimum volumetric soil water (nlevsoi) + sucmin => clm_interface_data%sucmin_col , & ! col minimum allowable soil liquid suction pressure (mm) [Note: sucmin_col is a negative value, while sucsat_col is a positive quantity] + ! + soilpsi => clm_interface_data%th%soilpsi_col , & ! soil water matric potential in each soil layer (MPa) + h2osoi_liq => clm_interface_data%th%h2osoi_liq_col, & ! liquid water (kg/m2) + h2osoi_ice => clm_interface_data%th%h2osoi_ice_col, & ! ice lens (kg/m2) + h2osoi_vol => clm_interface_data%th%h2osoi_vol_col, & ! volumetric soil water (0<=h2osoi_vol<=watsat) [m3/m3] + t_soisno => clm_interface_data%th%t_soisno_col , & ! snow-soil temperature (Kelvin) + ! + t_scalar => clm_interface_data%bgc%t_scalar_col , & ! soil temperature scalar for decomp + w_scalar => clm_interface_data%bgc%w_scalar_col , & ! soil water scalar for decomp + o_scalar => clm_interface_data%bgc%o_scalar_col & ! fraction by which decomposition is limited by anoxia + ) + + !-------------------------------------------------------------------------------------- + nstep = get_nstep() + + call VecGetArrayF90(clm_pf_idata%press_clmp, soilpress_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%soilpsi_clmp, soilpsi_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%soillsat_clmp, soillsat_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%soilt_clmp, soilt_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%h2osoi_vol_clmp, soilvwc_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%t_scalar_clmp, t_scalar_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%w_scalar_clmp, w_scalar_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%o_scalar_clmp, o_scalar_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + do j = 1, clm_pf_idata%nzclm_mapped + + if (j<=nlevgrnd) then + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + if (initpfhmode) then + ! this adjusting should be done first, if PF-freezing-mode off, + ! so that the following calculation can be done correctly + itheta = h2osoi_ice(c,j) / (dz(c,j) * denice) + itheta = min(itheta, watsat(c,j)-watmin(c,j)) + soilisat_clmp_loc(cellcount) = itheta/watsat(c,j) + + if(.not.pf_frzmode) then + ! porosity will be ice-adjusted for PF, if PF freezing-mode is off, + ! so need to adjust 'psi' so that 'saturation' in PF is correct + sattmp = h2osoi_liq(c,j) / ((watsat(c,j)-itheta)*dz(c,j)*denh2o) + sattmp = min(max(0.01d0, sattmp/(watsat(c,j)-itheta)),1._r8) + + ! soil matric potential re-done by Clapp-Hornburger method (this is the default used by CLM) + ! this value IS different from what CLM used (not ice-content adjusted) + ! So that in PF, if not ice-adjusted, the PSI is very small (negative) which implies possible water movement + + ! sucsat > 0, sucmin < 0, sucsat & sucmin have units of mm + ! psitmp = psitmp0, as denh2o*1.e-3_r8 = 1.0 + psitmp0 = sucsat(c,j) * (-SHR_CONST_G) * (sattmp**(-bsw(c,j))) ! -Pa + + psitmp = denh2o*(-SHR_CONST_G)*(sucsat(c,j)*1.e-3_r8)*(sattmp**(-bsw(c,j))) ! -Pa + sucmin_pa = denh2o*SHR_CONST_G*sucmin(c,j)*1.e-3_r8 ! -Pa + psitmp = min(max(psitmp,sucmin_pa),0._r8) !Pa + + else + sattmp = h2osoi_liq(c,j) / (watsat(c,j)*dz(c,j)*denh2o) + sattmp = min(max(0.01d0, sattmp/watsat(c,j)),1._r8) + + psitmp = soilpsi(c,j)*1.e6_r8 ! MPa -> Pa + if (shr_infnan_isnan(soilpsi(c,j)) .or. nstep<=0) then ! only for initialization, in which NOT assigned a value + psitmp0 = sucsat(c,j) * (-SHR_CONST_G) * ((sattmp+itheta)**(-bsw(c,j))) ! -Pa: included both ice and liq. water as CLM does + psitmp = denh2o*(-SHR_CONST_G)*(sucsat(c,j)*1.e-3_r8) * ((sattmp+itheta)**(-bsw(c,j))) + sucmin_pa = denh2o*SHR_CONST_G*sucmin(c,j)*1.e-3_r8 + psitmp = min(max(psitmp,sucmin_pa),0._r8) + endif + + endif !if(.not.pf_frzmode) + soillsat_clmp_loc(cellcount) = sattmp + + soilpsi_clmp_loc(cellcount) = psitmp + soilpress_clmp_loc(cellcount) = psitmp+clm_pf_idata%pressure_reference + + w_scalar_clmp_loc(cellcount) = w_scalar(c,j) + o_scalar_clmp_loc(cellcount) = o_scalar(c,j) + + soilvwc_clmp_loc(cellcount) = h2osoi_vol(c,j) + + endif !if (initpfhmode) then + + if (initpftmode) then + soilt_clmp_loc(cellcount)=t_soisno(c,j)-tfrz + t_scalar_clmp_loc(cellcount)=t_scalar(c,j) + endif + + else + call endrun(trim(subname) // ": ERROR: CLM-PF mapped soil layer numbers is greater than " // & + " 'clm_varpar%nlevgrnd'. Please check") + + endif !if (j<=nlevgrnd) then + + enddo !do j = 1, clm_pf_idata%nzclm_mapped + enddo !do fc = 1,filters(ifilter)%num_soilc + + call VecRestoreArrayF90(clm_pf_idata%press_clmp, soilpress_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%soilpsi_clmp, soilpsi_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%soillsat_clmp, soillsat_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%soilt_clmp, soilt_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%h2osoi_vol_clmp, soilvwc_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%t_scalar_clmp, t_scalar_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%w_scalar_clmp, w_scalar_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%o_scalar_clmp, o_scalar_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end associate + end subroutine get_clm_soil_th + + + !----------------------------------------------------------------------------- + !BOP + ! + ! !ROUTINE: get_clm_iceadj_porosity + ! + ! !INTERFACE: + subroutine get_clm_iceadj_porosity(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! update soil effective porosity from CLM to PFLOTRAN if PF freezing mode is off + ! + ! !USES: + use ColumnType , only : col_pp + use clm_varctl , only : iulog + use clm_varcon , only : denice + use clm_varpar , only : nlevgrnd + + use PFLOTRAN_Constants_module + use clm_varctl , only : pf_frzmode + + ! !ARGUMENTS: + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + type(bounds_type) , intent(in) :: bounds ! bounds + type(clumpfilter) , intent(in) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(in) :: clm_interface_data + + ! !LOCAL VARIABLES: + integer :: fc, c, g, j, gcount, cellcount ! indices + real(r8) :: itheta + + PetscScalar, pointer :: adjporosity_clmp_loc(:) ! + PetscScalar, pointer :: soilisat_clmp_loc(:) ! + PetscErrorCode :: ierr + + character(len= 32) :: subname = 'get_clm_iceadj_porosity' ! subroutine name + + !EOP + !----------------------------------------------------------------------- + associate ( & + cgridcell => col_pp%gridcell , & ! column's gridcell + dz => col_pp%dz , & ! layer thickness depth (m) + ! + watsat => clm_interface_data%watsat_col , & ! volumetric soil water at saturation (porosity) (nlevgrnd) + h2osoi_ice => clm_interface_data%th%h2osoi_ice_col & ! ice lens (kg/m2) + ) + + ! if 'pf_tmode' is NOT using freezing option, the phase-change of soil water done in 'SoilTemperatureMod.F90' in 'bgp2' + ! must be included to adjust porosity (effective porosity) in pflotran + ! This is doing prior to the real liquid water source/sink, because 'h2osoi_liq' will be updated during those calls after 'bgp2'. + if (.not. pf_frzmode) then + + ! re-calculate the effective porosity (CLM ice-len adjusted), which should be pass to pflotran + call VecGetArrayF90(clm_pf_idata%effporosity_clmp, adjporosity_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + do j = 1, clm_pf_idata%nzclm_mapped + if (j<=nlevgrnd) then + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + itheta = h2osoi_ice(c,j) / (dz(c,j) * denice) + itheta = min(itheta, 0.99_r8*watsat(c,j)) + adjporosity_clmp_loc(cellcount ) = watsat(c,j) - itheta + soilisat_clmp_loc(cellcount ) = itheta/watsat(c,j) + else + call endrun(trim(subname) // ": ERROR: CLM-PF mapped soil layer number is greater than " // & + " 'clm_varpar%nlevgrnd'. Please check") + + endif + + end do + end do + + call VecRestoreArrayF90(clm_pf_idata%effporosity_clmp, adjporosity_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end if + + end associate + end subroutine get_clm_iceadj_porosity + ! + +!----------------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: get_clm_bcwflx + ! + ! !INTERFACE: + subroutine get_clm_bcwflx(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! + ! F.-M. YUAN: the water fluxes in CLM4.5 are separately calculated in a few subroutines + ! in 'SoilHydrologyMod.F90'. When coupled with pflotran, it's hard to get those together + ! like GB does in 'step_th_clm_pf' subroutine. So, this subroutine is a collective call of + ! that and others in 'Hydrology2Mod.F90' so that pflotran can be called out of 'hydrology2'. + ! + ! !USES: + use ColumnType , only : col_pp + use clm_varcon , only : tfrz, denh2o + use clm_varpar , only : nlevsoi, nlevgrnd + use clm_time_manager, only : get_step_size, get_nstep + use shr_infnan_mod , only : shr_infnan_isnan + use shr_const_mod , only : SHR_CONST_G + + use clm_pflotran_interface_data + use clm_varctl , only : pf_clmnstep0 + + ! !ARGUMENTS: + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + type(bounds_type), intent(in) :: bounds ! bounds of current process + type(clumpfilter), intent(inout) :: filters(:) ! filters on current process + integer, intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(inout) :: clm_interface_data + + ! !LOCAL VARIABLES: + integer :: fc, g, c, j ! do loop indices + integer :: gcount, cellcount + real(r8) :: dtime ! land model time step (sec) + integer :: nstep ! time step number + real(r8) :: area + real(r8) :: qflx_evap(bounds%begc:bounds%endc) ! weighted soil surface evaporation (mmH2O/s) + real(r8) :: qflx, qflx_sink, qflx_source, soilvwc + real(r8) :: dsoilliq1 = 0._r8, dsoilliq2 = 0._r8, dsoilliq3 = 0._r8 + + real(r8) :: qflx_ground, kbot + real(r8) :: reference_pressure, ponding_pressure ! Pa + real(r8) :: pondmax(bounds%begc:bounds%endc) ! mm H2O: max. ponding depth for column + real(r8) :: sr = 0.10_r8 + real(r8) :: tempreal, reductor + + ! for PF --> CLM (seq.) + PetscScalar, pointer :: press_clms_loc(:) ! + PetscScalar, pointer :: soillsat_clms_loc(:) ! + PetscScalar, pointer :: soilisat_clms_loc(:) ! + PetscScalar, pointer :: porosity_clms_loc(:) ! + PetscScalar, pointer :: sr_pcwmax_clms_loc(:) ! + + PetscScalar, pointer :: area_clms_loc(:) ! + + ! for CLM (mpi) --> PF + PetscScalar, pointer :: qflw_clmp_loc(:) ! source/sink term for plant Transpiration: unit in mass rate (kgH2O/sec) + PetscScalar, pointer :: qflwt_clmp_loc(:) ! temperature of source/sink term for plant Transpiration: oC (ET water temperature for thermal contact with soil) + PetscScalar, pointer :: press_top_clmp_loc(:) ! BC in pressure type: unit in Pa + PetscScalar, pointer :: press_base_clmp_loc(:) ! + PetscScalar, pointer :: qfluxw_top_clmp_loc(:) ! BC in neumann flux type: unit in m/s (liq.) + PetscScalar, pointer :: qfluxev_top_clmp_loc(:) ! BC in neumann flux type: unit in m/s (evaporation) + PetscScalar, pointer :: qfluxw_base_clmp_loc(:) ! BC in neumann flux type: unit in m/s (liq.) + PetscScalar, pointer :: press_maxponding_clmp_loc(:) ! + PetscErrorCode :: ierr + + character(len= 32) :: subname = 'get_clm_bcwflx' ! subroutine name + !EOP + !----------------------------------------------------------------------- + associate ( & + cgridcell => col_pp%gridcell , & ! column's gridcell + cwtgcell => col_pp%wtgcell , & ! weight (relative to gridcell) + dz => col_pp%dz , & ! layer thickness depth (m) + ! + bsw => clm_interface_data%bsw_col , &! Clapp and Hornberger "b" (nlevgrnd) + hksat => clm_interface_data%hksat_col , &! hydraulic conductivity at saturation (mm H2O /s) (nlevgrnd) + watsat => clm_interface_data%watsat_col , &! volumetric soil water at saturation (porosity) (nlevgrnd) + sucsat => clm_interface_data%sucsat_col , &! minimum soil suction (mm) (nlevgrnd) + watmin => clm_interface_data%watmin_col , &! restriction for min of volumetric soil water, or, residual vwc (-) (nlevgrnd) + sucmin => clm_interface_data%sucmin_col , &! restriction for min of soil potential (mm) (nlevgrnd) + ! + frac_sno_eff => clm_interface_data%th%frac_sno_eff_col , &! [real(r8) (:) ] fraction of ground covered by snow (0 to 1) + frac_h2osfc => clm_interface_data%th%frac_h2osfc_col , &! [real(r8) (:) ] fraction of ground covered by surface water (0 to 1) + t_soisno => clm_interface_data%th%t_soisno_col , &! [real(r8) (:,:) ] snow-soil layered temperature [K] + t_grnd => clm_interface_data%th%t_grnd_col , &! [real(r8) (:) ] col ground(-air interface averaged) temperature (Kelvin) + t_nearsurf => clm_interface_data%th%t_nearsurf_col , &! [real(r8) (:) ] col mixed air/veg. temperature near surface (for coupling with PFLOTRAN as BC) + qflx_top_soil => clm_interface_data%th%qflx_top_soil_col , &! [real(r8) (:) ] column-level net liq. water input into soil from top (mm/s) + qflx_evap_h2osfc => clm_interface_data%th%qflx_evap_h2osfc_col , &! [real(r8) (:) ] column-level p-aggregated evaporation flux from h2osfc (mm H2O/s) [+ to atm] + qflx_evap_soil => clm_interface_data%th%qflx_evap_soil_col , &! [real(r8) (:) ] column-level p-aggregated evaporation flux from soil (mm H2O/s) [+ to atm] + qflx_evap_snow => clm_interface_data%th%qflx_evap_snow_col , &! [real(r8) (:) ] column-level p-aggregated evaporation (inc. subl.) flux from snow (mm H2O/s) [+ to atm] + qflx_rootsoil => clm_interface_data%th%qflx_rootsoil_col , &! [real(r8) (:,:) ] column-level p-aggregated vertically-resolved vegetation/soil water exchange (m H2O/s) (+ = to atm) + h2osoi_liq => clm_interface_data%th%h2osoi_liq_col , &! [real(r8) (:,:) ] liquid water (kg/m2) + h2osoi_ice => clm_interface_data%th%h2osoi_ice_col &! [real(r8) (:,:) ] ice lens (kg/m2) + ) + +!---------------------------------------------------------------------------- + nstep = get_nstep() + dtime = get_step_size() + + ! (1) pass the clm_qflx to the vecs + ! NOTE the following unit conversions: + ! qflx_soil_top and qflx_tran_veg are in [mm/sec] from CLM; + ! qflx_clm_loc is in [kgH2O/sec] as mass rate for pflotran (as input) + + ! previous time-step soil water pressure and saturation for adjusting qflx + ! note that this is a temporary workaround - waiting for PF's solution + call VecGetArrayF90(clm_pf_idata%press_clms, press_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%soillsat_clms, soillsat_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%soilisat_clms, soilisat_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%effporosity_clms, porosity_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%sr_pcwmax_clms, sr_pcwmax_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%area_top_face_clms, area_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%qflow_clmp, qflw_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%qflowt_clmp, qflwt_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%press_subsurf_clmp, press_top_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%press_subbase_clmp, press_base_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%qfluxw_subsurf_clmp, qfluxw_top_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%qfluxev_subsurf_clmp, qfluxev_top_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%qfluxw_subbase_clmp, qfluxw_base_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%press_maxponding_clmp, press_maxponding_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + + if (t_grnd(c) < tfrz .and. qflx_evap_soil(c)<0._r8) then + ! frozen ground, no dew contribution to subsurface infiltration (will likely cause trouble in PFLOTRAN) + ! (NOTE: this will modify 'qflx_evap_soil' globally) + qflx_evap_soil (c) = 0._r8 + endif + ! bare-soil fraction-weighted col-level evaporation (this is the actual water by EV from the whole 1st soil layer) + qflx_evap(c)=(1.0_r8 - frac_sno_eff(c) - frac_h2osfc(c))*qflx_evap_soil(c) + + + do j = 1, clm_pf_idata%nzclm_mapped + if(j<=nlevgrnd) then + + cellcount = gcount*clm_pf_idata%nzclm_mapped + j + + qflw_clmp_loc(cellcount ) = 0.0_r8 + qflwt_clmp_loc(cellcount ) = t_nearsurf(gcount+1) - tfrz + + if (j .eq. 1) then + qfluxw_top_clmp_loc(gcount+1) = 0.0_r8 + qfluxev_top_clmp_loc(gcount+1) = 0.0_r8 + press_top_clmp_loc(gcount+1) = press_clms_loc(cellcount) ! same as the first top layer + end if + + if (j .eq. clm_pf_idata%nzclm_mapped) then + qfluxw_base_clmp_loc(gcount+1) = 0.0_r8 + press_base_clmp_loc(gcount+1) = press_clms_loc((gcount+1)*clm_pf_idata%nzclm_mapped) ! same as the bottom layer + end if + + else + call endrun(trim(subname) // ": ERROR: CLM-PF mapped soil layer numbers is greater than " // & + " 'clm_varpar%nlevgrnd'. Please check") + + endif + end do + + end do + + pondmax(:) = 0.0_r8 ! this is temporarily set (not yet figure out how CLM get this value) + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + area = area_clms_loc(gcount*clm_pf_idata%nzclm_mapped+1) + reference_pressure = clm_pf_idata%pressure_reference + ponding_pressure = pondmax(c)*SHR_CONST_G ! max. ponding water depth (mm) ==> pressure (Pa) + + press_maxponding_clmp_loc(gcount+1) = reference_pressure+ponding_pressure + + do j = 1, clm_pf_idata%nzclm_mapped + + if (j<=nlevgrnd) then + + cellcount = gcount*clm_pf_idata%nzclm_mapped + j + + ! CLM soil hydrology ONLY works down to 'nlevsoi' (one exception for 'vwc_zwt' when tnlevsoi) cycle ! comment out so that it can be down to 'nlevgrnd', although NOT really now. + + ! previous time-step soil water saturation for adjusting qflx to avoid too wet or too dry to cause PF math issue + ! (this is a temporary workaround - waiting for PF's solution) + soilvwc = soillsat_clms_loc(cellcount) * & + porosity_clms_loc(cellcount) ! PF saturation ==> real vwc (using adjusted porosity???) + + dsoilliq1 = (0.99_r8*porosity_clms_loc(cellcount)-soilvwc) & + *dz(c,j)*area*denh2o/dtime ! mH2O ==> kgH2O/sec to be filled at most (1% for hard-accessible pore and error-handling ) + dsoilliq1 = max(0._r8, dsoilliq1) ! always + + + sr = 1.01_r8*sr_pcwmax_clms_loc(cellcount) * & ! '1.01' will give 1% for hard-accessible pore and holding error in the calculation + porosity_clms_loc(cellcount) ! PF saturation ==> 'real' vwc + dsoilliq2 = (sr-soilvwc)*dz(c,j)*area*denh2o/dtime ! mH2O ==> kgH2O/sec to be extracted at most (-) + dsoilliq2 = min(0._r8, dsoilliq2) ! always - + + ! top BC + if (j .eq. 1) then + + ! mmH2O/sec ==> mH2O/sec of soil evaporation as top BC (neumann): negative to soil + if (.not.shr_infnan_isnan(qflx_evap(c))) then + ! it's better to limit 'qflx_evap' (but not if dew formation), + ! although causes water/energy-balance errors which should be accounted for later on (NOT YET - TODO!) + reductor = 1.0_r8 + if( qflx_evap(c)>0._r8) then + reductor = min(qflx_evap(c), max(0._r8,-dsoilliq2/denh2o/area*1.e3)) + reductor = reductor/qflx_evap(c) + + ! frozen condition evaporation has issue, temperarily OFF (TODO - further thought needed) + if (t_soisno(c,1) mH2O/sec, - = out of soil + endif + + ! net liq water input/output to soil column + ! mmH2O/sec ==> mH2O/sec of potential infiltration (flux) rate as top BC (neumann): positive to soil + qflx_ground = 0._r8 + if (.not.shr_infnan_isnan(qflx_top_soil(c))) then + + qflx_ground = qflx_top_soil(c) ! unit: mm/sec + + if(qflx_ground>0._r8 ) then + if (t_soisno(c,1)=0.95_r8 .and. & + (soillsat_clms_loc(cellcount)+soilisat_clms_loc(cellcount)) >= 0.9999_r8) then ! ice-blocked first-layer + qflx_ground = 0._r8 + endif + + qfluxw_top_clmp_loc(gcount+1) = qflx_ground*1.e-3 ! mm/sec --> kg/m2/sec + endif + endif + + ! if net input potential, it's forming TOP BC of pressure type (water ponding potetial) + ! both waterhead and flux calcuated here, but not applied in PFLOTRAN in the same time (upon BC type picked-up by PF) + if ( qflx_ground .gt. 0._r8) then + ! Newly ADDED mmH2O ==> pressure (Pa) as top BC (dirichlet) by forming a layer of surface water column + ! AND, the actual infiltration/runoff are retrieving from PFLOTRAN using 'update_surflow_pf2clm' subroutine + if (soillsat_clms_loc(cellcount) >= 1._r8) then + ! water-head formed on saturated below-ground soil layer + press_top_clmp_loc(gcount+1) = press_clms_loc(gcount*clm_pf_idata%nzclm_mapped+1) + & + qflx_ground*dtime*SHR_CONST_G + else + ! ground-water-head discontinued from below-ground (atm. pressure applied at both ends) + press_top_clmp_loc(gcount+1) = reference_pressure + & + qflx_ground*dtime*SHR_CONST_G + endif + + end if + + end if + + ! plant root extraction of water (transpiration: negative to soil) + ! mmH2O/sec ==> kgH2O/sec of source rate + qflx = -qflx_rootsoil(c,j)*area*1.e-3*denh2o + qflx = qflx * cwtgcell(c) ! clm column fraction of grid-cell adjustment + + ! checking if over-filled when sinking (excluding infiltration) + qflx_sink = max(0._r8, qflx) ! sink (+) only (kgH2O/sec) + qflx_sink = min(qflx_sink, max(0._r8,dsoilliq1)) + + ! checking if too dry to be ETed (or other sourced): lower than 'sr_pcwmax' + qflx_source = min(0._r8, qflx) ! source (-) only (kgH2O/sec) + qflx_source = max(qflx_source, min(0._r8,dsoilliq2)) + + qflw_clmp_loc(cellcount) = (qflx_sink+qflx_source)/area/dz(c,j) ! source/sink unit: kg/m3/sec + qflwt_clmp_loc(cellcount)= t_soisno(c,j) - tfrz ! + + ! bottom BC (neumman type): m/sec + if (j .eq. clm_pf_idata%nzclm_mapped) then + ! available water flux-out rate (-) adjusted by source(-)/sink(+) term + dsoilliq3 = min(0._r8, dsoilliq2 - qflw_clmp_loc(cellcount)) & + /area/denh2o ! kgH2O/sec ==> mH2O/sec + + ! free drainage at bottom + tempreal = soilvwc/watsat(c,j) ! using 'real' saturation + kbot = hksat(c,j)*(tempreal**(2._r8*bsw(c,j)+3._r8))*1.e-3 ! mmH2O/sec ==> mH2O/sec + qfluxw_base_clmp_loc(gcount+1) = max(dsoilliq3, -kbot) ! mH2O/sec + + end if + + else !j>clm_varpar%nlevgrnd + call endrun(trim(subname) // ": ERROR: CLM-PF mapped soil layer numbers is greater than " // & + " 'clm_varpar%nlevgrnd'. Please check") + endif + + end do + + end do + + call VecRestoreArrayF90(clm_pf_idata%press_clms, press_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%soillsat_clms, soillsat_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%soilisat_clms, soilisat_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%sr_pcwmax_clms, sr_pcwmax_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%effporosity_clms, porosity_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%area_top_face_clms, area_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%qflow_clmp, qflw_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%qflowt_clmp, qflwt_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%press_subsurf_clmp, press_top_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%press_subbase_clmp, press_base_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%qfluxw_subsurf_clmp, qfluxw_top_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%qfluxev_subsurf_clmp, qfluxev_top_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%qfluxw_subbase_clmp, qfluxw_base_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%press_maxponding_clmp, press_maxponding_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end associate + end subroutine get_clm_bcwflx + + !----------------------------------------------------------------------------- + ! + ! + ! !INTERFACE: + subroutine get_clm_bceflx(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! + ! F.-M. YUAN: the boundary heat fluxes in CLM4.5 are extracted to drive pflotran TH mode. + ! GB only defined ground-heaf-flux. + ! So, this subroutine is a collective setting on either heat-flux (neumann type) + ! or interface thermal state (temperature) (dirichlet type) + ! at both ground and bottom interface (BC). + ! + ! !USES: + use ColumnType , only : col_pp + use clm_time_manager, only : get_step_size, get_nstep + use clm_varcon , only : tfrz + use clm_varpar , only : nlevgrnd + use shr_infnan_mod , only : shr_infnan_isnan + + use clm_pflotran_interface_data + use clm_varctl , only : pf_clmnstep0 + + ! !ARGUMENTS: + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + type(bounds_type), intent(in) :: bounds ! bounds of current process + type(clumpfilter), intent(in) :: filters(:) ! filters on current process + integer, intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(in) :: clm_interface_data + + ! !LOCAL VARIABLES: + integer :: fc, c, g, gcount ! do loop indices + real(r8) :: dtime ! land model time step (sec) + integer :: nstep ! time step number + real(r8) :: t_grnd0, eflx_fgr0, eflx_ev0, eflx_rnet0 + real(r8) :: area + + ! for CLM (mpi) --> PF + PetscScalar, pointer :: geflx_subsurf_clmp_loc(:) ! all-form energy flux: unit MJ/m2/s + PetscScalar, pointer :: geflxr_subsurf_clmp_loc(:) ! radiation energy flux: unit MJ/m2/s + PetscScalar, pointer :: geflxl_subsurf_clmp_loc(:) ! soil evap. LE flux: unit MJ/m2/s + PetscScalar, pointer :: gtemp_subsurf_clmp_loc(:) ! BC in dirichlet type: unit in degC + PetscScalar, pointer :: geflx_subbase_clmp_loc(:) ! all-form energy flux: unit MJ/m2/s + PetscScalar, pointer :: gtemp_subbase_clmp_loc(:) ! BC in dirichlet type: unit in degC + + PetscScalar, Pointer :: area_clms_loc(:) + + PetscErrorCode :: ierr + + character(len= 32) :: subname = 'get_clm_bceflx' ! subroutine name + + !EOP + !----------------------------------------------------------------------- + associate ( & + cgridcell => col_pp%gridcell , &! column's gridcell + dz => col_pp%dz , &! layer thickness depth (m) + snl => col_pp%snl , &! number of snow layers (negative) + ! + frac_sno_eff => clm_interface_data%th%frac_sno_eff_col , &! fraction of ground covered by snow (0 to 1) + frac_h2osfc => clm_interface_data%th%frac_h2osfc_col , &! fraction of ground covered by surface water (0 to 1) + ! + htvp => clm_interface_data%th%htvp_col , &! latent heat of vapor of water (or sublimation) [j/kg] + eflx_fgr0_snow => clm_interface_data%th%eflx_fgr0_snow_col , &! heat flux from snow column (W/m**2) [+ = into soil] + eflx_fgr0_h2osfc => clm_interface_data%th%eflx_fgr0_h2osfc_col , &! heat flux from surface water column (W/m**2) [+ = into soil] + eflx_fgr0_soil => clm_interface_data%th%eflx_fgr0_soil_col , &! heat flux from near-surface air (W/m**2) [+ = into soil] + eflx_rnet_soil => clm_interface_data%th%eflx_rnet_soil_col , &! heat flux between soil layer 1 and above-air, excluding SH and LE (i.e. radiation form) (W/m2) [+ = into soil] + eflx_bot => clm_interface_data%th%eflx_bot_col , &! heat flux from beneath column (W/m**2) [+ = upward] + t_soisno => clm_interface_data%th%t_soisno_col , &! snow-soil layered temperature [K] + t_h2osfc => clm_interface_data%th%t_h2osfc_col , &! surface-water temperature [K] + t_nearsurf => clm_interface_data%th%t_nearsurf_col , &! mixed air/veg. temperature near surface (for coupling with PFLOTRAN as BC) + qflx_evap_soil => clm_interface_data%th%qflx_evap_soil_col &! non-urban column-level p-aggregated evaporation flux from soil (mm H2O/s) [+ to atm] + ) + +!---------------------------------------------------------------------------- + nstep = get_nstep() + dtime = get_step_size() + + ! (1) pass the clm_gflux/gtemp to the vec + + call VecGetArrayF90(clm_pf_idata%eflux_subsurf_clmp, geflx_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%efluxr_subsurf_clmp, geflxr_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%efluxl_subsurf_clmp, geflxl_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%eflux_subbase_clmp, geflx_subbase_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%gtemp_subsurf_clmp, gtemp_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%gtemp_subbase_clmp, gtemp_subbase_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%area_top_face_clms, area_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + geflx_subsurf_clmp_loc(:) = 0._r8 + geflxr_subsurf_clmp_loc(:) = 0._r8 + geflxl_subsurf_clmp_loc(:) = 0._r8 + geflx_subbase_clmp_loc(:) = 0._r8 + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + area = area_clms_loc(gcount*clm_pf_idata%nzclm_mapped+1) + + ! (1) Dirichlet-Type BC for energy + ! near-surface/subsurface interface temperature + ! NOTE that this is not exactly ground temperature from CLM, which is for air/ground (snow/surfwater-1st soil) interface + + if (snl(c) < 0) then + if(frac_h2osfc(c) /= 0._r8) then + t_grnd0 = frac_sno_eff(c) * t_soisno(c,0) & ! a note here: 't_soisno(c,0)' NOT always has a meanful value + + (1.0_r8 - frac_sno_eff(c) - frac_h2osfc(c)) * t_nearsurf(c) & + + frac_h2osfc(c) * t_h2osfc(c) ! a note here: 't_h2osfc' NOT always has a meanful value + else + t_grnd0 = frac_sno_eff(c) * t_soisno(c,0) & + + (1.0_r8 - frac_sno_eff(c)) * t_nearsurf(c) + + endif + else + if(frac_h2osfc(c) /= 0._r8) then + t_grnd0 = (1.0_r8 - frac_h2osfc(c)) * t_nearsurf(c) & + + frac_h2osfc(c) * t_h2osfc(c) + else + t_grnd0 = t_nearsurf(c) + endif + endif + + gtemp_subsurf_clmp_loc(gcount+1) = t_grnd0 - tfrz + gtemp_subbase_clmp_loc(gcount+1) = -9999 ! not yet get it from CLM (i.e.,dirichlet type bottom BC not available) + + ! (2) Neumann-Type BC for energy + ! THREE (3) types: radiation flux, latent heat flux, and sensible heat flux + + ! net (sw+lw) radiation into soil, if not covered by surface water or snow + eflx_rnet0 = (1.0_r8 - frac_sno_eff(c) - frac_h2osfc(c))*eflx_rnet_soil(c) + + ! soil surface evaporation (NOTE which adjusted by liq. water available in the first soil layer in 'get_clm_wflx' subroutine) + eflx_ev0 = -qflx_evap_soil(c)*htvp(c)*(1.0_r8 - frac_sno_eff(c) - frac_h2osfc(c)) ! - = LE out of soil + + ! net heat flux into soil + eflx_fgr0 = (1.0_r8 - frac_sno_eff(c) - frac_h2osfc(c))*eflx_fgr0_soil(c) + + ! if snow/surface-water covered, need to add snow/water-soil interface heat flux + ! (in this case, no radiation/soil-evap) + if(snl(c) < 0) then + eflx_fgr0 = eflx_fgr0 + frac_sno_eff(c)*eflx_fgr0_snow(c) + endif + if(frac_h2osfc(c)>0._r8) then + eflx_fgr0 = eflx_fgr0 + frac_h2osfc(c)*eflx_fgr0_h2osfc(c) + endif + + ! for heat flux boundry only (i.e. NO thermal-state boundary or LE flux BC) + if (.not.shr_infnan_isnan(eflx_fgr0)) & ! when initializing, it's a NAN + geflx_subsurf_clmp_loc(gcount+1) = eflx_fgr0*1.0e-6_r8 ! positive = into soil, unit: MJ/m2/sec + + ! if thermal-state boundary (i.e. dirichlet-type, temperature) + ! it must include non-heat-conductance energy fluxes, such as radiation and LE, which usually occurs if not covered by snow or h2osfc. + if (.not.shr_infnan_isnan(eflx_ev0)) & + geflxl_subsurf_clmp_loc(gcount+1) = eflx_ev0*1.0e-6_r8 ! positive = into soil, unit: MJ/m2/sec + + if (.not.shr_infnan_isnan(eflx_rnet0)) & + geflxr_subsurf_clmp_loc(gcount+1) = eflx_rnet0*1.0e-6_r8 ! positive = into soil, unit: MJ/m2/sec + + if (.not.shr_infnan_isnan(eflx_bot(c))) & + geflx_subbase_clmp_loc(gcount+1) = eflx_bot(c)*1.0e-6_r8 ! positive = into soil + + end do + + call VecRestoreArrayF90(clm_pf_idata%eflux_subsurf_clmp, geflx_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%efluxr_subsurf_clmp, geflxr_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%efluxl_subsurf_clmp, geflxl_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%eflux_subbase_clmp, geflx_subbase_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%gtemp_subsurf_clmp, gtemp_subsurf_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%gtemp_subbase_clmp, gtemp_subbase_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%area_top_face_clms, area_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end associate + end subroutine get_clm_bceflx + + ! + !----------------------------------------------------------------------------- + ! + ! + !----------------------------------------------------------------------------- + !BOP + ! + ! !ROUTINE: get_clm_bgc_conc(clm_interface_data, bounds, filters, ifilter) + ! + ! !INTERFACE: + + subroutine get_clm_bgc_conc(clm_interface_data, bounds, filters, ifilter) + use ColumnType , only : col_pp + use clm_varctl , only : iulog + use clm_varpar , only : ndecomp_pools, nlevdecomp_full + + implicit none + + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(in) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(in) :: clm_interface_data + + character(len=256) :: subname = "get_clm_bgc_concentration" + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + ! Local variables + integer :: fc, c, g, j, k ! do loop indices + integer :: gcount, cellcount + real(r8) :: CN_ratio_mass_to_mol + + integer :: vec_offset + PetscScalar, pointer :: decomp_cpools_vr_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools + PetscScalar, pointer :: decomp_npools_vr_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools +! PetscScalar, pointer :: decomp_ppools_vr_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) P pools + + PetscScalar, pointer :: smin_no3_vr_clm_loc(:) ! (gN/m3) vertically-resolved soil mineral NO3 + PetscScalar, pointer :: smin_nh4_vr_clm_loc(:) ! (gN/m3) vertically-resolved soil mineral NH4 + PetscScalar, pointer :: smin_nh4sorb_vr_clm_loc(:) ! (gN/m3) vertically-resolved soil mineral NH4 absorbed + + PetscErrorCode :: ierr + ! + !------------------------------------------------------------------------------------------ + ! + associate ( & + cgridcell => col_pp%gridcell , & ! column's gridcell + ! + initial_cn_ratio => clm_interface_data%bgc%initial_cn_ratio , & + initial_cp_ratio => clm_interface_data%bgc%initial_cp_ratio , & + + decomp_cpools_vr => clm_interface_data%bgc%decomp_cpools_vr_col , & ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools + decomp_npools_vr => clm_interface_data%bgc%decomp_npools_vr_col , & ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools + smin_no3_vr => clm_interface_data%bgc%smin_no3_vr_col , & ! (gN/m3) vertically-resolved soil mineral NO3 + smin_nh4_vr => clm_interface_data%bgc%smin_nh4_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 + smin_nh4sorb_vr => clm_interface_data%bgc%smin_nh4sorb_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 absorbed + + decomp_ppools_vr => clm_interface_data%bgc%decomp_ppools_vr_col , & ! [real(r8) (:,:,:) ! col (gP/m3) vertically-resolved decomposing (litter, cwd, soil) P pools + solutionp_vr => clm_interface_data%bgc%solutionp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil solution P + labilep_vr => clm_interface_data%bgc%labilep_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil labile mineral P + secondp_vr => clm_interface_data%bgc%secondp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil secondary mineralP + occlp_vr => clm_interface_data%bgc%occlp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil occluded mineral P + primp_vr => clm_interface_data%bgc%primp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil primary mineral P + sminp_vr => clm_interface_data%bgc%sminp_vr_col & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil mineral P = solutionp + labilep + secondp + ) + + call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_clmp, decomp_cpools_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_clmp, decomp_npools_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%smin_no3_vr_clmp, smin_no3_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%smin_nh4_vr_clmp, smin_nh4_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%smin_nh4sorb_vr_clmp, smin_nh4sorb_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + CN_ratio_mass_to_mol = clm_pf_idata%N_molecular_weight/clm_pf_idata%C_molecular_weight + + ! + decomp_cpools_vr_clm_loc(:) = 0._r8 + decomp_npools_vr_clm_loc(:) = 0._r8 + smin_no3_vr_clm_loc(:) = 0._r8 + smin_nh4_vr_clm_loc(:) = 0._r8 + smin_nh4sorb_vr_clm_loc(:) = 0._r8 + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + + do j = 1, clm_pf_idata%nzclm_mapped + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + ! note: all clm-pf soil layers are 'clm_pf_idata%nzclm_mapped' for both TH/BGC, + ! but in CLM, T is within 'nlevgrnd', H is within 'nlevsoi', bgc within 'nlevdecomp' + + if(j <= nlevdecomp_full) then + + do k = 1, ndecomp_pools + vec_offset = (k-1)*clm_pf_idata%nlclm_sub ! 0-based + ! decomp_pool vec: 'cell' first, then 'species' (i.e. cell by cell for 1 species, then species by species) + ! Tips: then when doing 3-D data-mapping, no need to stride the vecs BUT to do segmentation. + + decomp_cpools_vr_clm_loc(vec_offset+cellcount) = decomp_cpools_vr(c,j,k) & + /clm_pf_idata%C_molecular_weight + + if (clm_pf_idata%floating_cn_ratio(k)) then + decomp_npools_vr_clm_loc(vec_offset+cellcount) = decomp_npools_vr(c,j,k) & + /clm_pf_idata%N_molecular_weight + else + decomp_npools_vr_clm_loc(vec_offset+cellcount) = & + decomp_cpools_vr_clm_loc(vec_offset+cellcount) & + /(initial_cn_ratio(k)*CN_ratio_mass_to_mol) ! initial_cn_ratio: in unit of mass + endif + + enddo ! do k=1, ndecomp_pools + + smin_no3_vr_clm_loc(cellcount) = smin_no3_vr(c,j) & + /clm_pf_idata%N_molecular_weight + smin_nh4_vr_clm_loc(cellcount) = smin_nh4_vr(c,j) & + /clm_pf_idata%N_molecular_weight + smin_nh4sorb_vr_clm_loc(cellcount) = smin_nh4sorb_vr(c,j) & + /clm_pf_idata%N_molecular_weight + + endif + + enddo ! do j = 1, clm_pf_idata%nzclm_mapped + + enddo ! do fc = 1, num_soilc + + call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_clmp, decomp_cpools_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_clmp, decomp_npools_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%smin_no3_vr_clmp, smin_no3_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%smin_nh4_vr_clmp, smin_nh4_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%smin_nh4sorb_vr_clmp, smin_nh4sorb_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end associate + end subroutine get_clm_bgc_conc + + !----------------------------------------------------------------------------- + ! + ! !IROUTINE: get_clm_bgc_rate() + ! + ! !INTERFACE: + subroutine get_clm_bgc_rate(clm_interface_data, bounds, filters, ifilter) +! TODO: add phosphorus vars + ! + ! !DESCRIPTION: + ! + ! + ! !USES: + use ColumnType , only : col_pp + use clm_time_manager , only : get_step_size, get_nstep, is_first_step, is_first_restart_step + use clm_varpar , only : ndecomp_pools, nlevdecomp_full + use clm_varctl , only : iulog, pf_hmode + + ! !ARGUMENTS: + implicit none + + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(in) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(in) :: clm_interface_data + + character(len=256) :: subname = "get_clm_bgc_rate" + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + ! !LOCAL VARIABLES: + integer :: fc, c, g, j, k ! do loop indices + integer :: gcount, cellcount + + real(r8) :: dtime ! land model time step (sec) + + ! C/N source/sink rates as inputs for pflotran: Units - moles/m3/s (note: do unit conversion here for input rates) + integer :: vec_offset + PetscScalar, pointer :: rate_decomp_c_clm_loc(:) ! + PetscScalar, pointer :: rate_decomp_n_clm_loc(:) ! +! PetscScalar, pointer :: rate_decomp_p_clm_loc(:) ! + + PetscScalar, pointer :: kscalar_decomp_c_clm_loc(:) ! + + PetscScalar, pointer :: rate_plantndemand_clm_loc(:) ! + PetscScalar, pointer :: rate_smin_no3_clm_loc(:) ! + PetscScalar, pointer :: rate_smin_nh4_clm_loc(:) ! + + PetscErrorCode :: ierr + + ! + !--------------------------------------------------------------------------- + ! + associate ( & + cgridcell => col_pp%gridcell , & ! column's gridcell + ! + decomp_cpools_vr => clm_interface_data%bgc%decomp_cpools_vr_col , & ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools + decomp_npools_vr => clm_interface_data%bgc%decomp_npools_vr_col , & ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools + decomp_k_scalar_vr => clm_interface_data%bgc%sitefactor_kd_vr_col , & ! (-) vertically-resolved decomposing rate adjusting factor relevant to location (site) + smin_no3_vr => clm_interface_data%bgc%smin_no3_vr_col , & ! (gN/m3) vertically-resolved soil mineral NO3 + smin_nh4_vr => clm_interface_data%bgc%smin_nh4_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 + smin_nh4sorb_vr => clm_interface_data%bgc%smin_nh4sorb_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 absorbed + ! plant litering and removal + SOM/LIT vertical transport + col_net_to_decomp_cpools_vr => clm_interface_data%bgc%externalc_to_decomp_cpools_col , & + col_net_to_decomp_npools_vr => clm_interface_data%bgc%externaln_to_decomp_npools_col , & + ! inorg. nitrogen sink potential + col_plant_ndemand_vr => clm_interface_data%bgc%plant_ndemand_vr_col , & + ! inorg. N source/sink + externaln_to_nh4_vr => clm_interface_data%bgc%externaln_to_nh4_col , & + externaln_to_no3_vr => clm_interface_data%bgc%externaln_to_no3_col , & + + col_net_to_decomp_ppools_vr => clm_interface_data%bgc%externalp_to_decomp_ppools_col , & + externalp_to_primp_vr => clm_interface_data%bgc%externalp_to_primp_col , & + externalp_to_labilep_vr => clm_interface_data%bgc%externalp_to_labilep_col , & + externalp_to_solutionp => clm_interface_data%bgc%externalp_to_solutionp_col , & + sminp_net_transport_vr => clm_interface_data%bgc%sminp_net_transport_vr_col , & + col_plant_pdemand_vr => clm_interface_data%bgc%plant_pdemand_vr_col & + ) + + dtime = get_step_size() + + + call VecGetArrayF90(clm_pf_idata%rate_decomp_c_clmp, rate_decomp_c_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%rate_decomp_n_clmp, rate_decomp_n_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%kscalar_decomp_c_clmp, kscalar_decomp_c_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%rate_plantndemand_clmp, rate_plantndemand_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%rate_smin_no3_clmp, rate_smin_no3_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%rate_smin_nh4_clmp, rate_smin_nh4_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! Initialize to ZERO + + rate_decomp_c_clm_loc(:) = 0.0_r8 + rate_decomp_n_clm_loc(:) = 0.0_r8 + + rate_smin_no3_clm_loc(:) = 0.0_r8 + rate_smin_nh4_clm_loc(:) = 0.0_r8 + rate_plantndemand_clm_loc(:) = 0.0_r8 + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + do j = 1, clm_pf_idata%nzclm_mapped + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + ! note: all clm-pf soil layers are 'clm_pf_idata%nzclm_mapped' for both TH/BGC, + ! but in CLM, T is within 'nlevgrnd', H is within 'nlevsoi', bgc within 'nlevdecomp' + ! (nlevdecomp_full = nlevgrnd) + + if(j <= nlevdecomp_full) then + ! just in case, we need to do some checking first (actually already done before) + do k = 1,ndecomp_pools + if (col_net_to_decomp_cpools_vr(c,j,k) < 0._r8) then + col_net_to_decomp_cpools_vr(c,j,k) = & + max(col_net_to_decomp_cpools_vr(c,j,k), & + -max(decomp_cpools_vr(c,j,k)/dtime, 0._r8)) + endif + + if (col_net_to_decomp_npools_vr(c,j,k) < 0._r8) then + col_net_to_decomp_npools_vr(c,j,k) = & + max(col_net_to_decomp_npools_vr(c,j,k), & + -max(decomp_npools_vr(c,j,k)/dtime, 0._r8)) + endif + end do + + do k = 1, ndecomp_pools + vec_offset = (k-1)*clm_pf_idata%nlclm_sub ! 0-based + ! decomp_pool vec: 'cell' first, then 'species' (i.e. cell by cell for 1 species, then species by species) + ! Tips: then when doing 3-D data-mapping, no need to stride the vecs BUT to do segmentation. + + rate_decomp_c_clm_loc(vec_offset+cellcount) = & + col_net_to_decomp_cpools_vr(c,j,k) & + /clm_pf_idata%C_molecular_weight + + if (rate_decomp_c_clm_loc(vec_offset+cellcount)<0._r8) then + rate_decomp_c_clm_loc(vec_offset+cellcount) = max( & + rate_decomp_c_clm_loc(vec_offset+cellcount), & + -max(decomp_cpools_vr(c,j,k)/clm_pf_idata%C_molecular_weight/dtime, 0._r8)) + endif + + if (clm_pf_idata%floating_cn_ratio(k)) then + rate_decomp_n_clm_loc(vec_offset+cellcount) = & + col_net_to_decomp_npools_vr(c,j,k) & + /clm_pf_idata%N_molecular_weight + + if (rate_decomp_n_clm_loc(vec_offset+cellcount)<0._r8) then + rate_decomp_n_clm_loc(vec_offset+cellcount) = max( & + rate_decomp_n_clm_loc(vec_offset+cellcount), & + -max(decomp_npools_vr(c,j,k)/clm_pf_idata%N_molecular_weight/dtime, 0._r8)) + endif + + endif + + enddo ! do k=1, ndecomp_pools + + ! site-scalar to adjust decomposition rate constants + ! note: (1) this only works for CTC, together with adspinup_factor(k)>1 + ! (2) coding here is because of its time (year)-dependent, which implies checking each time-step + kscalar_decomp_c_clm_loc(cellcount) = decomp_k_scalar_vr(c,j) + + rate_smin_nh4_clm_loc(cellcount) = externaln_to_nh4_vr(c,j)/ & + clm_pf_idata%N_molecular_weight + if (rate_smin_nh4_clm_loc(cellcount)<0._r8) then + rate_smin_nh4_clm_loc(cellcount) = max( & + rate_smin_nh4_clm_loc(cellcount), & + -max(smin_nh4_vr(c,j)/clm_pf_idata%N_molecular_weight/dtime, 0._r8)) + endif + + rate_smin_no3_clm_loc(cellcount) = externaln_to_no3_vr(c,j)/ & + clm_pf_idata%N_molecular_weight + if (rate_smin_no3_clm_loc(cellcount)<0._r8) then + rate_smin_no3_clm_loc(cellcount) = max( & + rate_smin_no3_clm_loc(cellcount), & + -max(smin_no3_vr(c,j)/clm_pf_idata%N_molecular_weight/dtime, 0._r8)) + endif + + ! plant N uptake rate here IS the N demand (potential uptake) + rate_plantndemand_clm_loc(cellcount) = & + col_plant_ndemand_vr(c,j)/clm_pf_idata%N_molecular_weight + + endif ! if (j<=nlevdecomp_full) + + enddo ! do j=1, clm_pf_idata%nzclm_mapped + + enddo ! do fc=1,numsoic + + call VecRestoreArrayF90(clm_pf_idata%rate_decomp_c_clmp, rate_decomp_c_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%rate_decomp_n_clmp, rate_decomp_n_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%kscalar_decomp_c_clmp, kscalar_decomp_c_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecRestoreArrayF90(clm_pf_idata%rate_plantndemand_clmp, rate_plantndemand_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%rate_smin_no3_clmp, rate_smin_no3_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayF90(clm_pf_idata%rate_smin_nh4_clmp, rate_smin_nh4_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end associate + end subroutine get_clm_bgc_rate + + + + !==================================================================================================== + ! ! + ! Subroutines to UPDATE PFLOTRAN evolving variables to CLM ! + ! ! + !==================================================================================================== + ! + ! !IROUTINE: update_soil_moisture_pf2clm + ! + ! !INTERFACE: + subroutine update_soil_moisture_pf2clm(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! + ! + ! !USES: + use ColumnType , only : col_pp + use clm_varcon , only : denh2o, denice + use clm_varctl , only : pf_frzmode + use clm_varpar , only : nlevgrnd + + ! !ARGUMENTS: + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + type(bounds_type), intent(in) :: bounds ! bounds of current process + type(clumpfilter), intent(in) :: filters(:) ! filters on current process + integer, intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(in) :: clm_interface_data + + ! !LOCAL VARIABLES: + integer :: fc, c, j, g ! indices + integer :: cellcount, gcount + + PetscScalar, pointer :: sat_ice_clm_loc(:) + PetscScalar, pointer :: sat_clm_loc(:) + PetscScalar, pointer :: effporo_clm_loc(:) + PetscScalar, pointer :: soilpsi_clm_loc(:) + PetscErrorCode :: ierr + + character(len=256) :: subname = "update_soil_moisture_pf2clm" + + !EOP + !----------------------------------------------------------------------- + associate ( & + cgridcell => col_pp%gridcell , & ! column's gridcell + dz => col_pp%dz , & ! layer thickness depth (m) + ! + watsat => clm_interface_data%watsat_col , & ! volumetric soil water at saturation (porosity) (nlevgrnd) + ! + soilpsi => clm_interface_data%th%soilpsi_col , & ! soil water matric potential in each soil layer (MPa) + h2osoi_liq => clm_interface_data%th%h2osoi_liq_col, & ! liquid water (kg/m2) + h2osoi_ice => clm_interface_data%th%h2osoi_ice_col, & ! ice lens (kg/m2) + h2osoi_vol => clm_interface_data%th%h2osoi_vol_col & ! volumetric soil water (0<=h2osoi_vol<=watsat) [m3/m3] + ) + ! + call VecGetArrayReadF90(clm_pf_idata%soillsat_clms, sat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%effporosity_clms, effporo_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%soilpsi_clms, soilpsi_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + if (pf_frzmode) then + call VecGetArrayReadF90(clm_pf_idata%soilisat_clms, sat_ice_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + do j = 1, nlevgrnd + + if (j<=clm_pf_idata%nzclm_mapped) then + cellcount = gcount*clm_pf_idata%nzclm_mapped + j + + h2osoi_liq(c,j) = sat_clm_loc(cellcount) * & + effporo_clm_loc(cellcount) * dz(c,j) * denh2o ! 'watsat_clm_loc' may be effective porosity + if (pf_frzmode) then + ! since 'effporo' may be expanding when freezing, and 'soilpsi' is actually what PF works on + ! it's better to use CLM's 'watsat' + h2osoi_liq(c,j) = sat_clm_loc(cellcount) * & + !effporo_clm_loc(cellcount) * dz(c,j) * denh2o + watsat(c,j) * dz(c,j) * denh2o + h2osoi_ice(c,j) = sat_ice_clm_loc(cellcount) * & + !effporo_clm_loc(cellcount) * dz(c,j) * denice + watsat(c,j) * dz(c,j) * denice + end if + + soilpsi(c,j) = soilpsi_clm_loc(cellcount)*1.e-6_r8 ! Pa --> MPa (negative) + + else + h2osoi_liq(c,j) = sat_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) * & + effporo_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) * & + dz(c,j) * denh2o ! 'watsat_clm_loc' may be effective porosity + if (pf_frzmode) then + h2osoi_liq(c,j) = sat_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) * & + !effporo_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) * dz(c,j) * denh2o ! 'watsat_clm_loc' may be effective porosity + watsat(c,clm_pf_idata%nzclm_mapped) * dz(c,j) * denh2o + h2osoi_ice(c,j) = sat_ice_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) * & + !effporo_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) * dz(c,j) * denice + watsat(c,clm_pf_idata%nzclm_mapped) * dz(c,j) * denice + end if + + soilpsi(c,j) = soilpsi(c,clm_pf_idata%nzclm_mapped) + end if + + h2osoi_vol(c,j) = h2osoi_liq(c,j) / dz(c,j) / denh2o + & + h2osoi_ice(c,j) / dz(c,j) / denice + h2osoi_vol(c,j) = min(h2osoi_vol(c,j), watsat(c,j)) + + enddo + + enddo + + call VecRestoreArrayReadF90(clm_pf_idata%soillsat_clms, sat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%effporosity_clms, effporo_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%soilpsi_clms, soilpsi_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + if (pf_frzmode) then + call VecRestoreArrayReadF90(clm_pf_idata%soilisat_clms, sat_ice_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + end associate + end subroutine update_soil_moisture_pf2clm + + !----------------------------------------------------------------------------- + ! + ! !IROUTINE: update_soil_temperature_pf2clm + ! + ! !INTERFACE: + subroutine update_soil_temperature_pf2clm(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! + ! + ! !USES: + use ColumnType , only : col_pp + use clm_varpar , only : nlevgrnd + use clm_varcon , only : tfrz + + ! !ARGUMENTS: + implicit none + + type(clm_interface_data_type), intent(in) :: clm_interface_data + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + type(bounds_type), intent(in) :: bounds ! bounds of current process + type(clumpfilter), intent(in) :: filters(:) ! filters on current process + integer, intent(in) :: ifilter ! which filter to be operated + + ! !LOCAL VARIABLES: + integer :: fc, c, j, g ! indices + integer :: cellcount, gcount + integer :: j_frz + + PetscScalar, pointer :: soilt_clms_loc(:) + PetscErrorCode :: ierr + + character(len=256) :: subname = "update_soil_temperature_pf2clm" + + !EOP + !----------------------------------------------------------------------- + associate ( & + cgridcell => col_pp%gridcell , & ! column's gridcell + z => col_pp%z , & ! [real(r8) (:,:) ] layer depth (m) + ! + t_soisno => clm_interface_data%th%t_soisno_col , & ! [real(r8)(:,:)] snow-soil temperature (Kelvin) [:, 1:nlevgrnd] + frost_table => clm_interface_data%th%frost_table_col & ! [real(r8)(:)] frost table depth (m) + ) + + ! + call VecGetArrayReadF90(clm_pf_idata%soilt_clms, soilt_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + do j = 1, nlevgrnd + + if (j<=clm_pf_idata%nzclm_mapped) then + cellcount = gcount*clm_pf_idata%nzclm_mapped + j + + t_soisno(c,j) = soilt_clms_loc(cellcount) + tfrz + else + t_soisno(c,j) = t_soisno(c, clm_pf_idata%nzclm_mapped) + end if + + ! a simple (and temporary) checking of TH mode fake convergence + if(t_soisno(c,j)<173.d0) then + print *, 'col: ', c, 'level: ', j, t_soisno(c,j) + call endrun(trim(subname) // ": ERROR: PF TH mode appears NOT correct - fake convergence: " // & + " 't_soisno(c,j)'. STOP!") + endif + + enddo + + enddo + + call VecRestoreArrayReadF90(clm_pf_idata%soilt_clms, soilt_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + + ! define frost table as first frozen layer with unfrozen layer above it + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + + if(t_soisno(c,1) > tfrz) then + j_frz = nlevgrnd + else + j_frz=1 + endif + + do j = 2, nlevgrnd + if (t_soisno(c,j-1) > tfrz .and. t_soisno(c,j) <= tfrz) then + j_frz=j + exit + endif + enddo + + frost_table(c)=z(c,j_frz) + enddo + + + end associate + end subroutine update_soil_temperature_pf2clm + + !----------------------------------------------------------------------------- + !BOP + ! + ! !IROUTINE: update_bcflow_pf2clm + ! + ! !INTERFACE: + subroutine update_bcflow_pf2clm(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! update qflx_surf, qflx_infl from PF's + ! 'mass_balance' retrieving from PFLOTRAN + ! + ! !USES: + use ColumnType , only : col_pp + use clm_varpar , only : nlevgrnd + use clm_varcon , only : tfrz, denh2o + use landunit_varcon , only : istsoil, istcrop + use clm_time_manager , only : get_step_size, get_nstep + + ! + type(bounds_type), intent(in) :: bounds ! bounds of current process + type(clumpfilter), intent(in) :: filters(:) ! filters on current process + integer, intent(in) :: ifilter ! which filter to be operated + type(clm_interface_data_type), intent(inout) :: clm_interface_data + + ! !LOCAL VARIABLES: +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + integer :: fc, c, g, gcount ! indices + real(r8) :: area ! top face area + real(r8) :: dtime ! land model time step (sec) + integer :: nstep + real(r8) :: qflx_evap ! bare-soil surface evaporation (mmH2O/s) + + PetscScalar, pointer :: area_clm_loc(:) + PetscScalar, pointer :: qinfl_subsurf_clm_loc(:) ! kgH2O/time-step + PetscScalar, pointer :: qsurf_subsurf_clm_loc(:) ! kgH2O/time-step + PetscScalar, pointer :: qflux_subbase_clm_loc(:) ! kgH2O/time-step + PetscErrorCode :: ierr + character(len=32) :: subname = 'update_bcflow_pf2clm' ! subroutine name + + !----------------------------------------------------------------------- + + associate(& + cgridcell => col_pp%gridcell , & ! gridcell index of column + ! + frac_sno_eff => clm_interface_data%th%frac_sno_eff_col , & ! fraction of ground covered by snow (0 to 1) + frac_h2osfc => clm_interface_data%th%frac_h2osfc_col , & ! fraction of ground covered by surface water (0 to 1) + ! + forc_pbot => clm_interface_data%th%forc_pbot_grc , & ! [real(r8) (:)] atmospheric pressure (Pa) + t_grnd => clm_interface_data%th%t_grnd_col , & ! [real(r8) (:)] ground surface temperature [K] + qflx_top_soil => clm_interface_data%th%qflx_top_soil_col , & ! [real(r8) (:)] net liq. water input into soil from top (mm/s) + qflx_ev_h2osfc => clm_interface_data%th%qflx_evap_h2osfc_col , & ! [real(r8) (:)] column-level evaporation flux from h2osfc (mm H2O/s) [+ to atm] + qflx_ev_soil => clm_interface_data%th%qflx_evap_soil_col , & ! [real(r8) (:)] column-level evaporation flux from soil (mm H2O/s) [+ to atm] + qflx_surf => clm_interface_data%th%qflx_surf_col , & ! [real(r8) (:)] surface runoff (mm H2O /s) + qflx_infl => clm_interface_data%th%qflx_infl_col , & ! [real(r8) (:)] soil infiltration (mm H2O /s) + qflx_drain => clm_interface_data%th%qflx_drain_col , & ! [real(r8) (:,:)] sub-surface runoff (drainage) (mm H2O /s) + qflx_drain_vr => clm_interface_data%th%qflx_drain_vr_col & ! [real(r8) (:)] vertically-resolved sub-surface runoff (drainage) (mm H2O /s) + ) + + dtime = get_step_size() + nstep = get_nstep() + + ! from PF==>CLM + call VecGetArrayReadF90(clm_pf_idata%area_top_face_clms, area_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayReadF90(clm_pf_idata%qinfl_subsurf_clms,qinfl_subsurf_clm_loc,ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%qsurf_subsurf_clms,qsurf_subsurf_clm_loc,ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%qflux_subbase_clms,qflux_subbase_clm_loc,ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + ! the following was actually duplicated from 'get_clm_bcwflx' to calculate total water evap from 'qflx_topsoil' + ! in order to get potential infiltration from CLM, because 'qflx_ev_soil' might be reduced due to water limits + qflx_evap = (1.0_r8 - frac_sno_eff(c) - frac_h2osfc(c))*qflx_ev_soil(c) + if (t_grnd(c) < tfrz .and. qflx_evap<0._r8) then + qflx_evap = 0._r8 + endif + + !'from PF: qinfl_subsurf_clm_loc: positive - in, negative - out + area = area_clm_loc(gcount*clm_pf_idata%nzclm_mapped+1) + qflx_infl(c) = qinfl_subsurf_clm_loc(gcount+1) & + /dtime/(area*denh2o*1.e-3) ! kgH2O/time-step ==> mmH2O/sec + + qflx_surf(c) = qflx_top_soil(c) - qflx_infl(c) - qflx_evap + qflx_surf(c) = max(0._r8, qflx_surf(c)) + + !'from PF: qflux_subbase_clm_loc: positive - in, negative - out) + area = area_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) ! note: this 'area_clm_loc' is in 3-D for all subsurface domain + qflx_drain(c) = -qflux_subbase_clm_loc(gcount+1) & + /dtime/(area*denh2o*1.e-3) ! kgH2O/time-step ==> mmH2O/sec (+ drainage, - upward-in) + + end do + + + call VecRestoreArrayReadF90(clm_pf_idata%area_top_face_clms, area_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%qinfl_subsurf_clms,qinfl_subsurf_clm_loc,ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%qsurf_subsurf_clms,qsurf_subsurf_clm_loc,ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%qflux_subbase_clms,qflux_subbase_clm_loc,ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end associate + end subroutine update_bcflow_pf2clm + + ! + !----------------------------------------------------------------------------- + ! + ! + !----------------------------------------------------------------------------- + ! !ROUTINE: update_soil_bgc_pf2clm() + ! + ! !INTERFACE: + ! + ! ! calculating BGC state variable changes over one time-step (rates) + ! NOTE: Don't update the organic C/N state variables, which will be updated in those 'update' subroutines + ! and the 'CNSoilLittVertTranspMod.F90' after 'update1'. + ! + subroutine update_soil_bgc_pf2clm(clm_interface_data, bounds, filters, ifilter) +! TODO: add phosphorus vars + use ColumnType , only : col_pp + use clm_varctl , only : iulog, use_ed + use CNDecompCascadeConType , only : decomp_cascade_con + use clm_varpar , only : ndecomp_pools, nlevdecomp_full + use clm_varctl , only : pf_hmode + use clm_time_manager , only : get_step_size,get_nstep + + use clm_varcon , only : dzsoi_decomp + + implicit none + + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(in) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(inout) :: clm_interface_data + + character(len=256) :: subname = "update_soil_bgc_pf2clm" + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + integer :: fc,c,g,j,k,l + integer :: gcount, cellcount + + real(r8) :: dtime ! land model time step (sec) + + integer :: vec_offset + PetscScalar, pointer :: decomp_cpools_vr_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools + PetscScalar, pointer :: decomp_npools_vr_clm_loc(:) ! (moleN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools + + PetscScalar, pointer :: smin_no3_vr_clm_loc(:) ! (moleN/m3) vertically-resolved soil mineral NO3 + PetscScalar, pointer :: smin_nh4_vr_clm_loc(:) ! (moleN/m3) vertically-resolved total soil mineral NH4 + PetscScalar, pointer :: smin_nh4sorb_vr_clm_loc(:) ! (moleN/m3) vertically-resolved absorbed soil mineral NH4 + + ! 'accextrn_vr' - accumulative (root) extracted N, i.e., actual plant N uptake from each soil layer, within a CLM timestep + PetscScalar, pointer :: accextrnh4_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil mineral N root-extraction (accumulated) + PetscScalar, pointer :: accextrno3_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil mineral N root-extraction (accumulated) + + ! 'accnmin_vr' - accumulative gross N mineralization within a CLM timestep + PetscScalar, pointer :: accnmin_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil N mineralization (accumulated) + + ! 'accnimm_vr' - accumulative N immobilization within a CLM timestep + PetscScalar, pointer :: accnimmp_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil N potential immoblilization (accumulated) + PetscScalar, pointer :: accnimm_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil N immoblilization (accumulated) + + PetscErrorCode :: ierr + +!------------------------------------------------------------------------------------ + ! + associate ( & + cgridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column + ! + initial_cn_ratio => clm_interface_data%bgc%initial_cn_ratio , & + decomp_cpools_vr => clm_interface_data%bgc%decomp_cpools_vr_col , & + decomp_npools_vr => clm_interface_data%bgc%decomp_npools_vr_col , & + sminn_vr => clm_interface_data%bgc%sminn_vr_col , & + smin_no3_vr => clm_interface_data%bgc%smin_no3_vr_col , & + smin_nh4_vr => clm_interface_data%bgc%smin_nh4_vr_col , & + smin_nh4sorb_vr => clm_interface_data%bgc%smin_nh4sorb_vr_col , & + + decomp_cpools_delta_vr => clm_interface_data%bgc%decomp_cpools_sourcesink_col , & + decomp_npools_delta_vr => clm_interface_data%bgc%decomp_npools_sourcesink_col , & + + sminn_to_plant_vr => clm_interface_data%bgc%sminn_to_plant_vr_col , & + smin_no3_to_plant_vr => clm_interface_data%bgc%smin_no3_to_plant_vr_col , & + smin_nh4_to_plant_vr => clm_interface_data%bgc%smin_nh4_to_plant_vr_col , & + potential_immob_vr => clm_interface_data%bgc%potential_immob_vr_col , & + actual_immob_vr => clm_interface_data%bgc%actual_immob_vr_col , & + gross_nmin_vr => clm_interface_data%bgc%gross_nmin_vr_col & + ) +! ------------------------------------------------------------------------ + dtime = get_step_size() + + ! soil C/N pool increments set to the previous timestep (i.e., not yet updated) + decomp_cpools_delta_vr = 0._r8-decomp_cpools_vr + decomp_npools_delta_vr = 0._r8-decomp_npools_vr + + ! clm-pf interface data updated + call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_clms, decomp_cpools_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%decomp_npools_vr_clms, decomp_npools_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + + call VecGetArrayReadF90(clm_pf_idata%smin_no3_vr_clms, smin_no3_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%smin_nh4_vr_clms, smin_nh4_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%smin_nh4sorb_vr_clms, smin_nh4sorb_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayReadF90(clm_pf_idata%accextrnh4_vr_clms, accextrnh4_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%accextrno3_vr_clms, accextrno3_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + if(clm_pf_idata%ispec_nmin>0) then + call VecGetArrayReadF90(clm_pf_idata%acctotnmin_vr_clms, accnmin_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecGetArrayReadF90(clm_pf_idata%accnmin_vr_clms, accnmin_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + if(clm_pf_idata%ispec_nimp>0) then + call VecGetArrayReadF90(clm_pf_idata%acctotnimmp_vr_clms, accnimmp_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecGetArrayReadF90(clm_pf_idata%accnimmp_vr_clms, accnimmp_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + if(clm_pf_idata%ispec_nimm>0) then + call VecGetArrayReadF90(clm_pf_idata%acctotnimm_vr_clms, accnimm_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecGetArrayReadF90(clm_pf_idata%accnimm_vr_clms, accnimm_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + do j = 1, nlevdecomp_full + + gross_nmin_vr(c,j) = 0._r8 + actual_immob_vr(c,j) = 0._r8 + potential_immob_vr(c,j) = 0._r8 + + if(j <= clm_pf_idata%nzclm_mapped) then + + cellcount = gcount*clm_pf_idata%nzclm_mapped + j ! 1-based + + do k=1, ndecomp_pools + + vec_offset = (k-1)*clm_pf_idata%ngclm_sub ! 0-based + ! decomp_pool vec: 'cell' first, then 'species' (i.e. cell by cell for 1 species, then species by species) + ! Tips: then when doing 3-D data-mapping, no need to stride the vecs BUT to do segmentation. + + decomp_cpools_delta_vr(c,j,k) = ( decomp_cpools_delta_vr(c,j,k) & + + decomp_cpools_vr_clm_loc(vec_offset+cellcount) & + * clm_pf_idata%C_molecular_weight ) !decomp_cpools_delta_vr=> clm_bgc_data%decomp_cpools_sourcesink_col + + if (clm_pf_idata%floating_cn_ratio(k)) then + decomp_npools_delta_vr(c,j,k) = ( decomp_npools_delta_vr(c,j,k) & + + decomp_npools_vr_clm_loc(vec_offset+cellcount) & + * clm_pf_idata%N_molecular_weight ) !/dtime + else + decomp_npools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k)/ & + initial_cn_ratio(k) ! initial_cn_ratio: already in unit of mass + endif + + if (abs(decomp_cpools_delta_vr(c,j,k))<=1.d-20) decomp_cpools_delta_vr(c,j,k)=0._r8 + if (abs(decomp_npools_delta_vr(c,j,k))<=1.d-21) decomp_npools_delta_vr(c,j,k)=0._r8 + + ! + if (clm_pf_idata%ispec_decomp_nmin(k)>0 .and. clm_pf_idata%ispec_nmin<=0) then + gross_nmin_vr(c,j) = gross_nmin_vr(c,j) & + + (accnmin_vr_clm_loc(vec_offset+cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + endif + + ! + if (clm_pf_idata%ispec_decomp_nimm(k)>0 .and. clm_pf_idata%ispec_nimm<=0) then + actual_immob_vr(c,j) = actual_immob_vr(c,j) & + + (accnimm_vr_clm_loc(vec_offset+cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + endif + + ! + if (clm_pf_idata%ispec_decomp_nimp(k)>0 .and. clm_pf_idata%ispec_nimp<=0) then + potential_immob_vr(c,j) = potential_immob_vr(c,j) & + + (accnimmp_vr_clm_loc(vec_offset+cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + endif + + enddo ! do k=1, ndecomp_pools + + if (clm_pf_idata%ispec_nmin>0) then + gross_nmin_vr(c,j) = gross_nmin_vr(c,j) & + + (accnmin_vr_clm_loc(cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + endif + if (clm_pf_idata%ispec_nimm>0) then + actual_immob_vr(c,j) = actual_immob_vr(c,j) & + + (accnimm_vr_clm_loc(cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + endif + if (clm_pf_idata%ispec_nimp>0) then + potential_immob_vr(c,j) = potential_immob_vr(c,j) & + + (accnimmp_vr_clm_loc(cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + endif + + ! beg:-------------------------------------------------------------------------------- + ! directly update the 'smin' N pools (SO, must bypass the 'CNNStateUpdate1,2,3' relevant to soil N) + smin_no3_vr(c,j) = & + smin_no3_vr_clm_loc(cellcount)*clm_pf_idata%N_molecular_weight + + smin_nh4_vr(c,j) = & + smin_nh4_vr_clm_loc(cellcount)*clm_pf_idata%N_molecular_weight + + smin_nh4sorb_vr(c,j) = & + smin_nh4sorb_vr_clm_loc(cellcount)*clm_pf_idata%N_molecular_weight + + sminn_vr(c,j) = smin_no3_vr(c,j) + smin_nh4_vr(c,j) + smin_nh4sorb_vr(c,j) + ! end:-------------------------------------------------------------------------------- + + ! flows or changes + smin_nh4_to_plant_vr(c,j) = (accextrnh4_vr_clm_loc(cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + smin_no3_to_plant_vr(c,j) = (accextrno3_vr_clm_loc(cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) + + else ! just in case 'clm_pf_idata%nzclm_mapped0) then + call VecRestoreArrayReadF90(clm_pf_idata%acctotnmin_vr_clms, accnmin_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecRestoreArrayReadF90(clm_pf_idata%accnmin_vr_clms, accnmin_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + if(clm_pf_idata%ispec_nimp>0) then + call VecRestoreArrayReadF90(clm_pf_idata%acctotnimmp_vr_clms, accnimmp_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecRestoreArrayReadF90(clm_pf_idata%accnimmp_vr_clms, accnimmp_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + if(clm_pf_idata%ispec_nimm>0) then + call VecRestoreArrayReadF90(clm_pf_idata%acctotnimm_vr_clms, accnimm_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecRestoreArrayReadF90(clm_pf_idata%accnimm_vr_clms, accnimm_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + ! update bgc gas losses + call update_bgc_gaslosses_pf2clm(clm_interface_data, bounds, filters, ifilter) + + end associate + end subroutine update_soil_bgc_pf2clm + + + !----------------------------------------------------------------------------- + ! + ! !ROUTINE: update_bgc_gaslosses_pf2clm() + ! + ! !INTERFACE: + ! + ! This is a temporary solution to estimate pflotran bgc gaseous emission and transport loss + ! from their aq. phase states + ! (due to not yet available in pflotran bgc) + ! + subroutine update_bgc_gaslosses_pf2clm(clm_interface_data, bounds, filters, ifilter) + + use ColumnType , only : col_pp + use clm_time_manager , only : get_step_size, get_nstep + use clm_varpar , only : nlevdecomp_full + use clm_varcon , only : tfrz + + use clm_varctl , only : pf_tmode, pf_hmode, pf_frzmode + + ! + implicit none + + type(bounds_type), intent(in) :: bounds ! bounds of current process + type(clumpfilter), intent(in) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(inout) :: clm_interface_data + + character(len=256) :: subname = "get_pf_bgc_gaslosses" + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + integer :: fc, c, g, j, k + integer :: gcount, cellcount + real(r8) :: dtime ! land model time step (sec) + integer :: nstep + + ! for gas species + real(r8) :: tc, tk, total_p ! temperature (oC, K), total air pressure (Pa) + real(r8) :: co2_p, n2_p, n2o_p ! partial pressure (Pa) of CO2, N2, N2O + real(r8) :: cgas, cgas_p ! mole-C(N)/m3(bulk soil) + real(r8) :: air_vol, air_molar, wfps + integer :: lair_barrier(bounds%begc:bounds%endc) ! toppest soil layer that little air space for air flow into deep soil (-1: no, 0: ground, >0: soil layer) + + ! gases from PFLOTRAN are timely accumulated, so gas fluxes are calculated here if over atm. partial pressure (no explicit transport available from PF now) + PetscScalar, pointer :: gco2_vr_clms_loc(:) ! (M: molC/m3 bulk soil) vertically-resolved soil gas CO2 from PF's evolution + PetscScalar, pointer :: gn2_vr_clms_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2 from PF's evolution + PetscScalar, pointer :: gn2o_vr_clms_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2O from PF's evolution + PetscScalar, pointer :: gco2_vr_clmp_loc(:) ! (M: molC/m3 bulk soil) vertically-resolved soil gas CO2 to reset PF's CO2g + PetscScalar, pointer :: gn2_vr_clmp_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2 to reset PF's N2g + PetscScalar, pointer :: gn2o_vr_clmp_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2O to reset PF's N2Og + + ! 'acchr_vr' - accumulative CO2 proudction from decompositon (for tracking HR, not involving mass-balance) + PetscScalar, pointer :: acchr_vr_clm_loc(:) ! (moleC/m3/timestep) vertically-resolved soil CO2 production (accumulated) + ! 'accngasmin_vr' - accumulative N gas proudction from mineralization (for tracking, not involving mass-balance) + PetscScalar, pointer :: accngasmin_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil gaseous N production (accumulated) + ! 'accngasnitr_vr' - accumulative N gas proudction from nitrification (for tracking) + PetscScalar, pointer :: accngasnitr_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil gaseous N production (accumulated) + ! 'accngasdeni_vr' - accumulative N gas proudction from denitrification (for tracking) + PetscScalar, pointer :: accngasdeni_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil gaseous N production (accumulated) + + ! + PetscScalar, pointer :: soillsat_clm_loc(:) + PetscScalar, pointer :: soilisat_clm_loc(:) + PetscScalar, pointer :: soilpor_clm_loc(:) + PetscScalar, pointer :: soilt_clm_loc(:) + PetscScalar, pointer :: soilpress_clm_loc(:) + PetscErrorCode :: ierr + + real(r8), parameter :: rgas = 8.3144621 ! m3 Pa K-1 mol-1 + +!------------------------------------------------------------------------------------ + associate ( & + cgridcell => col_pp%gridcell , & ! gridcell index of column + dz => col_pp%dz , & ! soil layer thickness depth (m) + ! + frac_sno_eff => clm_interface_data%th%frac_sno_eff_col , & ! fraction of ground covered by snow (0 to 1) + frac_h2osfc => clm_interface_data%th%frac_h2osfc_col , & ! fraction of ground covered by surface water (0 to 1) + forc_pbot => clm_interface_data%th%forc_pbot_grc , & ! atmospheric pressure (Pa) + ! + forc_pco2 => clm_interface_data%bgc%forc_pco2_grc , & ! partial pressure co2 (Pa) + hr_vr => clm_interface_data%bgc%hr_vr_col , & + f_co2_soil_vr => clm_interface_data%bgc%f_co2_soil_vr_col , & + f_n2o_soil_vr => clm_interface_data%bgc%f_n2o_soil_vr_col , & + f_n2_soil_vr => clm_interface_data%bgc%f_n2_soil_vr_col , & + f_ngas_decomp_vr => clm_interface_data%bgc%f_ngas_decomp_vr_col , & + f_ngas_nitri_vr => clm_interface_data%bgc%f_ngas_nitri_vr_col , & + f_ngas_denit_vr => clm_interface_data%bgc%f_ngas_denit_vr_col & + ) +! ------------------------------------------------------------------------ + dtime = get_step_size() + nstep = get_nstep() + + ! get the current time-step state variables of aq. phase of interested species + call VecGetArrayReadF90(clm_pf_idata%gco2_vr_clms, gco2_vr_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%gn2_vr_clms, gn2_vr_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%gn2o_vr_clms, gn2o_vr_clms_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + call VecGetArrayF90(clm_pf_idata%gco2_vr_clmp, gco2_vr_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%gn2_vr_clmp, gn2_vr_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayF90(clm_pf_idata%gn2o_vr_clmp, gn2o_vr_clmp_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + + call VecGetArrayReadF90(clm_pf_idata%accngasmin_vr_clms, accngasmin_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%accngasnitr_vr_clms, accngasnitr_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%accngasdeni_vr_clms, accngasdeni_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + if(clm_pf_idata%ispec_hrimm>0) then + call VecGetArrayReadF90(clm_pf_idata%acctothr_vr_clms, acchr_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecGetArrayReadF90(clm_pf_idata%acchr_vr_clms, acchr_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + ! env. variables to properties of gases + if (pf_tmode) then + call VecGetArrayReadF90(clm_pf_idata%soilt_clms, soilt_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! PF evolved 'soilt' + else + call VecGetArrayReadF90(clm_pf_idata%soilt_clmp, soilt_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! CLM evolved 'soilt' - for CLM, MPI vecs and Seq. vecs should be same + end if + + if (pf_frzmode) then + call VecGetArrayReadF90(clm_pf_idata%soilisat_clms, soilisat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! PF evolved 'soil ice saturation' + end if + + if (pf_hmode) then + call VecGetArrayReadF90(clm_pf_idata%soillsat_clms, soillsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! PF evolved 'soil liq. saturation' + call VecGetArrayReadF90(clm_pf_idata%press_clms, soilpress_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! PF evolved 'soil liq. saturation' + else + call VecGetArrayReadF90(clm_pf_idata%soillsat_clmp, soillsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__)! CLM evolved 'soilt liq. saturation' + call VecGetArrayReadF90(clm_pf_idata%press_clmp, soilpress_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__)! CLM evolved 'soilt liq. saturation' + endif + call VecGetArrayReadF90(clm_pf_idata%effporosity_clms, soilpor_clm_loc, ierr) ! PF evolved 'soil porosity' + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! find the toppest air barrier layer + lair_barrier(:) = -1 ! (-1: no barrier, 0: ground snow/ice/water-layer barrier, >=1: barrier in soil column) + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + ! find the toppest air barrier layer for the current column at first + + if((frac_sno_eff(c)+ frac_h2osfc(c))>=0.95_r8) then + lair_barrier(c) = 0 + endif + + do j = 1, clm_pf_idata%nzclm_mapped + + cellcount = gcount*clm_pf_idata%nzclm_mapped+j + + wfps = 0._r8 + if (lair_barrier(c) >= 0) exit + + if (pf_frzmode) then + wfps =soillsat_clm_loc(cellcount) & + + soilisat_clm_loc(cellcount) + else + wfps =soillsat_clm_loc(cellcount) ! note: 'lsat' from PF has been adjusted by 'isat' reduced porosity + endif + if (wfps > 0.95_r8) then ! 95% total saturation as a critical-point for air-flow into deep soil + lair_barrier(c) = j + endif + enddo + + + ! gas exchanges btw atm. and non-barrierred soil layer + ! only operating on soil column one by one, which then back to CLM-CN + + total_p = forc_pbot(g) + + do j = 1, nlevdecomp_full + + if(j <= clm_pf_idata%nzclm_mapped) then + cellcount = gcount*clm_pf_idata%nzclm_mapped+j + + tc = soilt_clm_loc(cellcount) ! soil layer tc (oC) + tk = tc+tfrz + + ! total_p is soil air pressure (soil water pressure if not less than atm. pressure) + total_p = max(total_p, soilpress_clm_loc(cellcount)) + + ! the following is for adjusting air space in soil (seems not right ?? -- off) + !air_vol = (1.0_r8 - soillsat_clm_loc(cellcount)) * & + ! soilpor_clm_loc(cellcount) ! m3 air/m3 soil + !air_vol = max(air_vol, 0.01d0) ! min. 0.01 to avoid math. issue + + air_vol = 1.0_r8 ! atm used if not commented out + air_molar = total_p*air_vol/rgas/tk ! moles of air in a cell + + ! gas fluxes from immobile PFLOTRAN evolving CO2imm, N2Oimm and N2imm, which are cumulative + ! CO2 - + cgas = gco2_vr_clms_loc(cellcount) ! mol/m3 soil (evolving in PF, but not yet transport) + co2_p = forc_pco2(g) ! assuming atm. pco2 (pa) as directly equilibrated with soil CO2(g) + cgas_p = co2_p/forc_pbot(g) * air_molar + + f_co2_soil_vr(c,j) = cgas-cgas_p + cgas = cgas - f_co2_soil_vr(c,j) + if (j <= lair_barrier(c) .or. lair_barrier(c) < 0) then ! above barrier OR no-barrier(-1) + gco2_vr_clmp_loc(cellcount) = cgas_p ! this refreshed-air will pass back to PF + else + gco2_vr_clmp_loc(cellcount) = cgas ! currently don't have air transport (TODO) + endif + + f_co2_soil_vr(c,j) = f_co2_soil_vr(c,j)*clm_pf_idata%C_molecular_weight ! moleCO2/m3 --> gC/m3 soil + f_co2_soil_vr(c,j) = f_co2_soil_vr(c,j)/dtime ! gC/m3/s + + ! N2 + cgas = gn2_vr_clms_loc(cellcount) ! mol/m3 soil (evolving in PF, but not yet transport) + n2_p = 0.78084_r8 ! assuming atm. pn2 as directly equilibrated with soil n2(g) + cgas_p = n2_p * air_molar ! moleN2/m3 + + f_n2_soil_vr(c,j) = cgas-cgas_p + cgas = cgas - f_n2_soil_vr(c,j) + if (j <= lair_barrier(c) .or. lair_barrier(c) < 0) then ! above barrier OR no-barrier(-1) + gn2_vr_clmp_loc(cellcount) = cgas_p ! this refreshed-air will pass back to PF + else + gn2_vr_clmp_loc(cellcount) = cgas ! currently don't have air transport (TODO) + endif + + f_n2_soil_vr(c,j) = f_n2_soil_vr(c,j)*clm_pf_idata%N_molecular_weight*2._r8 ! mole-N2/m3 --> g-N/m3 soil + f_n2_soil_vr(c,j) = f_n2_soil_vr(c,j)/dtime ! gN/m3/s + + ! N2O + cgas = gn2o_vr_clms_loc(cellcount) + n2o_p = 310e-9_r8 ! assuming general atm. pN2O (310ppbv in 1990) as directly equilibrated with soil N2(aq) + cgas_p = n2o_p * air_molar ! moleN2O/m3 + + f_n2o_soil_vr(c,j) = cgas-cgas_p + cgas = cgas - f_n2o_soil_vr(c,j) + if (j <= lair_barrier(c) .or. lair_barrier(c) < 0) then ! above barrier OR no-barrier(-1) + gn2o_vr_clmp_loc(cellcount) = cgas_p ! this refreshed-air will pass back to PF + else + gn2o_vr_clmp_loc(cellcount) = cgas ! currently don't have air transport (TODO) + endif + + f_n2o_soil_vr(c,j) = f_n2o_soil_vr(c,j)*clm_pf_idata%N_molecular_weight*2._r8 ! mole-N2O/m3 --> g-N/m3 soil + f_n2o_soil_vr(c,j) = f_n2o_soil_vr(c,j)/dtime ! gN/m3/s + + ! tracking HR from SOM-C reaction network + hr_vr(c,j) = (acchr_vr_clm_loc(cellcount) & + * clm_pf_idata%C_molecular_weight)/dtime + + ! tracking gaseous N production from N reaction network + f_ngas_decomp_vr(c,j)= (accngasmin_vr_clm_loc (cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + + f_ngas_nitri_vr(c,j) = (accngasnitr_vr_clm_loc(cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + + f_ngas_denit_vr(c,j) = (accngasdeni_vr_clm_loc(cellcount) & + * clm_pf_idata%N_molecular_weight)/dtime + + else ! just in case 'clm_pf_idata%nzclm_mapped0) then + call VecRestoreArrayReadF90(clm_pf_idata%acctothr_vr_clms, acchr_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecRestoreArrayReadF90(clm_pf_idata%acchr_vr_clms, acchr_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + endif + + call VecRestoreArrayReadF90(clm_pf_idata%accngasmin_vr_clms, accngasmin_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%accngasnitr_vr_clms, accngasnitr_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%accngasdeni_vr_clms, accngasdeni_vr_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + if (pf_tmode) then + call VecRestoreArrayReadF90(clm_pf_idata%soilt_clms, soilt_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + else + call VecRestoreArrayReadF90(clm_pf_idata%soilt_clmp, soilt_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! for CLM, MPI vecs and Seq. vecs should be same + end if + if (pf_frzmode) then + call VecRestoreArrayReadF90(clm_pf_idata%soilisat_clms, soilisat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + end if + + if (pf_hmode) then + call VecRestoreArrayReadF90(clm_pf_idata%soillsat_clms, soillsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! PF evolved 'soil liq. saturation' + call VecRestoreArrayReadF90(clm_pf_idata%press_clms, soilpress_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) ! PF evolved 'soil liq. saturation' + else + call VecRestoreArrayReadF90(clm_pf_idata%soillsat_clmp, soillsat_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__)! CLM evolved 'soil liq. saturation' + call VecRestoreArrayReadF90(clm_pf_idata%press_clmp, soilpress_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__)! CLM evolved 'soil liq. saturation' + endif + call VecRestoreArrayReadF90(clm_pf_idata%effporosity_clms, soilpor_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + ! need to reset the PF's internal gas concentration (CLM ==> PF) + call pflotranModelUpdateAqGasesfromCLM(pflotran_m) + + end associate + end subroutine update_bgc_gaslosses_pf2clm + + !----------------------------------------------------------------------------- + ! + ! !ROUTINE: update_bgc_bcflux_pf2clm() + ! + ! !INTERFACE: + ! + ! This is to estimate pflotran bgc boundary aq. transport fluxes + ! for (1) diagnostic purpose and (2) mass-balance error checking for whole domain ONLY. + ! i.e. it's NOT for mass state updating, + ! because PFLOTRAN had already updated state variables. + ! + subroutine update_bgc_bcflux_pf2clm(clm_interface_data, bounds, filters, ifilter) + + use ColumnType , only : col_pp + use clm_time_manager , only : get_step_size + use clm_varpar , only : nlevdecomp_full + + ! + implicit none + + type(bounds_type), intent(in) :: bounds ! bounds of current process + type(clumpfilter), intent(in) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + + type(clm_interface_data_type), intent(inout) :: clm_interface_data + + character(len=256) :: subname = "get_pf_bgc_bcfluxes" + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + integer :: fc, c, g, j + integer :: gcount, cellcount + real(r8) :: dtime ! land model time step (sec) + ! + ! actual aqeuous N mass flow rate(moleN/m2/sec) at the top (runoff)/bottom (leaching) of 3-D subsurface domain + ! (+ in, - out) + PetscScalar, pointer :: f_nh4_subsurf_clm_loc(:) + PetscScalar, pointer :: f_nh4_subbase_clm_loc(:) + PetscScalar, pointer :: f_no3_subsurf_clm_loc(:) + PetscScalar, pointer :: f_no3_subbase_clm_loc(:) + + PetscErrorCode :: ierr + + +!------------------------------------------------------------------------------------ + associate ( & + cgridcell => col_pp%gridcell , & ! gridcell index of column + dz => col_pp%dz , & ! soil layer thickness depth (m) + ! + no3_net_transport_vr => clm_interface_data%bgc%no3_net_transport_vr_col , & ! output: [c,j] (gN/m3/s) + nh4_net_transport_vr => clm_interface_data%bgc%nh4_net_transport_vr_col & ! output: [c,j] (gN/m3/s) + ) +! ------------------------------------------------------------------------ + dtime = get_step_size() + + call VecGetArrayReadF90(clm_pf_idata%f_nh4_subsurf_clms, f_nh4_subsurf_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%f_no3_subsurf_clms, f_no3_subsurf_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%f_nh4_subbase_clms, f_nh4_subbase_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecGetArrayReadF90(clm_pf_idata%f_no3_subbase_clms, f_no3_subbase_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + no3_net_transport_vr(:,:) = 0._r8 + nh4_net_transport_vr(:,:) = 0._r8 + + ! operating via 'filters' + gcount = -1 + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + g = cgridcell(c) + +#ifdef COLUMN_MODE + if (mapped_gcount_skip(c-bounds%begc+1)) cycle ! skip inactive column (and following numbering) + gcount = gcount + 1 ! 0-based: cumulatively by not-skipped column +#else + gcount = g - bounds%begg ! 0-based + if (mapped_gcount_skip(gcount+1)) cycle ! skip inactive grid, but not numbering +#endif + + ! add actual BC mass fluxes ( in gN/m2/s) from PFLOTRAN + no3_net_transport_vr(c,clm_pf_idata%nzclm_mapped) = & + no3_net_transport_vr(c,clm_pf_idata%nzclm_mapped) - & + f_no3_subbase_clm_loc(gcount) * & !( - is out in PF) + clm_pf_idata%N_molecular_weight + + nh4_net_transport_vr(c,clm_pf_idata%nzclm_mapped) = & + nh4_net_transport_vr(c,clm_pf_idata%nzclm_mapped) - & + f_nh4_subbase_clm_loc(gcount) * & + clm_pf_idata%N_molecular_weight + + no3_net_transport_vr(c,1) = no3_net_transport_vr(c,1) - & + f_no3_subsurf_clm_loc(gcount) * & + clm_pf_idata%N_molecular_weight + nh4_net_transport_vr(c,1) = nh4_net_transport_vr(c,1) - & + f_nh4_subsurf_clm_loc(gcount) * & + clm_pf_idata%N_molecular_weight + + ! (TODO) not yet considering lateral transport (although data structure is here) + + enddo ! do fc = 1,filters(ifilter)%num_soilc + + call VecRestoreArrayReadF90(clm_pf_idata%f_nh4_subsurf_clms, f_nh4_subsurf_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%f_no3_subsurf_clms, f_no3_subsurf_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%f_nh4_subbase_clms, f_nh4_subbase_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + call VecRestoreArrayReadF90(clm_pf_idata%f_no3_subbase_clms, f_no3_subbase_clm_loc, ierr) + call clm_pf_checkerr(ierr, subname, __FILE__, __LINE__) + + end associate + end subroutine update_bgc_bcflux_pf2clm + + !----------------------------------------------------------------------------- + !BOP + ! + ! !SUBROUTINE: clm_pf_checkerr(ierr) + ! + ! !INTERFACE: + subroutine clm_pf_checkerr(ierr, subname, filename, line) + ! + ! !DESCRIPTION: + ! When using PETSc functions, it usually throws an error code for checking. + ! BUT it won't show where the error occurs in the first place, therefore it's hardly useful. + ! + ! !USES: + use clm_varctl , only : iulog + use spmdMod , only : iam + + implicit none + +#include "petsc/finclude/petscsys.h" +#include "petsc/finclude/petscvec.h" +#include "petsc/finclude/petscvec.h90" + + ! !ARGUMENTS: + character(len=*), intent(IN) :: subname ! subroutine name called this + character(len=*), intent(IN) :: filename ! filename called this + integer, intent(IN) :: line ! line number triggered this + PetscErrorCode, intent(IN) :: ierr ! petsc error code + + !EOP + !----------------------------------------------------------------------- + + if (ierr /= 0) then + write (iulog,*) 'PETSc ERROR: Subroutine - ' // & + trim(subname), ' @Rank -', iam + write (iulog,*) 'PETSc ERROR: File - ' // & + trim(filename), ' @Line -', line + end if + + CHKERRQ(ierr) + + end subroutine clm_pf_checkerr + +!-------------------------------------------------------------------------------------- + subroutine clm_pf_BeginCBalance(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! On the radiation time step, calculate the beginning carbon balance for mass + ! conservation checks. + + use clm_varpar , only : ndecomp_pools, nlevdecomp,nlevdecomp_full + use clm_varcon , only : dzsoi_decomp + ! + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(inout) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + type(clm_interface_data_type), intent(inout) :: clm_interface_data + ! + ! !LOCAL VARIABLES: + integer :: c,j,l ! indices + integer :: fc ! soil filter indices + + !----------------------------------------------------------------------- + + associate( & + decomp_cpools_vr => clm_interface_data%bgc%decomp_cpools_vr_col , & + soil_begcb => clm_interface_data%bgc%soil_begcb_col & ! Output: [real(r8) (:)] carbon mass, beginning of time step (gC/m**2) + ) + ! calculate beginning column-level soil carbon balance, for mass conservation check + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + soil_begcb(c) = 0._r8 + do j = 1, nlevdecomp_full + do l = 1, ndecomp_pools + soil_begcb(c) = soil_begcb(c) + decomp_cpools_vr(c,j,l)*dzsoi_decomp(j) + end do + end do + end do + + end associate + + end subroutine clm_pf_BeginCBalance + +!-------------------------------------------------------------------------------------- + + subroutine clm_pf_BeginNBalance(clm_interface_data, bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! On the radiation time step, calculate the beginning carbon balance for mass + ! conservation checks. + + use clm_varpar , only : ndecomp_pools, nlevdecomp, nlevdecomp_full + use clm_varcon , only : dzsoi_decomp + ! + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(inout) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + type(clm_interface_data_type), intent(inout) :: clm_interface_data + ! + ! !LOCAL VARIABLES: + integer :: c,j,l ! indices + integer :: fc ! soil filter indices + integer :: nlev + + !----------------------------------------------------------------------- + + associate( & + decomp_npools_vr => clm_interface_data%bgc%decomp_npools_vr_col , & + smin_no3_vr => clm_interface_data%bgc%smin_no3_vr_col , & + smin_nh4_vr => clm_interface_data%bgc%smin_nh4_vr_col , & + smin_nh4sorb_vr => clm_interface_data%bgc%smin_nh4sorb_vr_col , & + soil_begnb => clm_interface_data%bgc%soil_begnb_col , & ! Output: [real(r8) (:)] carbon mass, beginning of time step (gC/m**2) + soil_begnb_org => clm_interface_data%bgc%soil_begnb_org_col , & ! + soil_begnb_min => clm_interface_data%bgc%soil_begnb_min_col & ! + ) + ! calculate beginning column-level soil carbon balance, for mass conservation check + nlev = nlevdecomp_full + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + soil_begnb(c) = 0._r8 + soil_begnb_org(c) = 0._r8 + soil_begnb_min(c) = 0._r8 + + do j = 1, nlev + !do NOT directly use sminn_vr(c,j), it does NOT always equal to (no3+nh4+nh4sorb) herein + soil_begnb_min(c) = soil_begnb_min(c) + smin_no3_vr(c,j)*dzsoi_decomp(j) & + + smin_nh4_vr(c,j)*dzsoi_decomp(j) & + + smin_nh4sorb_vr(c,j)*dzsoi_decomp(j) + do l = 1, ndecomp_pools + soil_begnb_org(c) = soil_begnb_org(c) & + + decomp_npools_vr(c,j,l)*dzsoi_decomp(j) + end do + end do !j = 1, nlevdecomp + + soil_begnb(c) = soil_begnb_org(c) + soil_begnb_min(c) + end do + end associate + end subroutine clm_pf_BeginNBalance +!-------------------------------------------------------------------------------------- + + subroutine clm_pf_CBalanceCheck(clm_interface_data,bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! On the radiation time step, perform carbon mass conservation check for column and pft + ! + ! !USES: + use clm_time_manager, only : get_step_size, get_nstep + use clm_varctl , only : iulog, use_ed + use clm_varpar , only : ndecomp_pools, nlevdecomp, nlevdecomp_full + use clm_varcon , only : dzsoi_decomp + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(inout) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + type(clm_interface_data_type), intent(inout) :: clm_interface_data + ! + ! !LOCAL VARIABLES: + integer :: c,j,l ! indices + integer :: fc ! lake filter indices + real(r8) :: dtime ! land model time step (sec) + integer :: err_index ! indices + logical :: err_found ! error flag + ! balance check varialbes: + real(r8) :: pf_cinputs(1:filters(ifilter)%num_soilc) + real(r8) :: pf_coutputs(1:filters(ifilter)%num_soilc) + real(r8) :: pf_cdelta(1:filters(ifilter)%num_soilc) + real(r8) :: pf_errcb(1:filters(ifilter)%num_soilc) + real(r8) :: pf_cbeg(1:filters(ifilter)%num_soilc) + real(r8) :: pf_cend(1:filters(ifilter)%num_soilc) + !----------------------------------------------------------------------- + + associate( & + externalc => clm_interface_data%bgc%externalc_to_decomp_cpools_col , & ! Input: [real(r8) (:) ] (gC/m2) total column carbon, incl veg and cpool + decomp_cpools_delta_vr => clm_interface_data%bgc%decomp_cpools_sourcesink_col , & + hr_vr => clm_interface_data%bgc%hr_vr_col , & + soil_begcb => clm_interface_data%bgc%soil_begcb_col & ! Output: [real(r8) (:) ] carbon mass, beginning of time step (gC/m**2) + ) + + ! ------------------------------------------------------------------------ + dtime = real( get_step_size(), r8 ) + ! pflotran mass blance check-Carbon + err_found = .false. + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + pf_cbeg(fc) = soil_begcb(c) + pf_cend(fc) = 0._r8 + pf_errcb(fc) = 0._r8 + + pf_cinputs(fc) = 0._r8 + pf_coutputs(fc) = 0._r8 + pf_cdelta(fc) = 0._r8 + + do j = 1, nlevdecomp_full + pf_coutputs(fc) = pf_coutputs(fc) + hr_vr(c,j)*dzsoi_decomp(j) + do l = 1, ndecomp_pools + pf_cinputs(fc) = pf_cinputs(fc) + externalc(c,j,l)*dzsoi_decomp(j) + pf_cdelta(fc) = pf_cdelta(fc) + decomp_cpools_delta_vr(c,j,l)*dzsoi_decomp(j) + end do + end do + + pf_cend(fc) = pf_cbeg(fc) + pf_cdelta(fc) + pf_errcb(fc) = (pf_cinputs(fc) - pf_coutputs(fc))*dtime - pf_cdelta(fc) + + ! check for significant errors + if (abs(pf_errcb(fc)) > 1e-8_r8) then + err_found = .true. + err_index = fc + end if + end do + + if (.not. use_ed) then + if (err_found) then + fc = err_index + write(iulog,'(A,70(1h-))')">>>-------- PFLOTRAN Mass Balance Check:beg " + write(iulog,'(A35,I15,A10,I20)')"Carbon Balance Error in Column = ",filters(ifilter)%soilc(fc), " @ nstep=",get_nstep() + write(iulog,'(10A15)')"errcb", "C_in-out", "Cdelta","Cinputs","Coutputs","Cbeg","Cend" + write(iulog,'(10E15.6)')pf_errcb(fc), (pf_cinputs(fc) - pf_coutputs(fc))*dtime, pf_cdelta(fc), & + pf_cinputs(fc)*dtime,pf_coutputs(fc)*dtime,pf_cbeg(fc),pf_cend(fc) + write(iulog,'(A,70(1h-))')">>>-------- PFLOTRAN Mass Balance Check:end " + end if + end if !(.not. use_ed) + end associate + end subroutine clm_pf_CBalanceCheck +!-------------------------------------------------------------------------------------- + + subroutine clm_pf_NBalanceCheck(clm_interface_data,bounds, filters, ifilter) + ! + ! !DESCRIPTION: + ! On the radiation time step, perform carbon mass conservation check for column and pft + ! + ! !USES: + use clm_time_manager, only : get_step_size,get_nstep + use clm_varctl , only : iulog, use_ed + use clm_varpar , only : ndecomp_pools, nlevdecomp, nlevdecomp_full + use clm_varcon , only : dzsoi_decomp + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds ! bounds of current process + type(clumpfilter) , intent(inout) :: filters(:) ! filters on current process + integer , intent(in) :: ifilter ! which filter to be operated + type(clm_interface_data_type), intent(inout) :: clm_interface_data + ! + ! !LOCAL VARIABLES: + integer :: nlev + integer :: c,j,l ! indices + integer :: fc ! lake filter indices + real(r8) :: dtime ! land model time step (sec) + integer :: err_index ! indices + logical :: err_found ! error flag + + real(r8) :: pf_ninputs(1:filters(ifilter)%num_soilc) + real(r8) :: pf_noutputs(1:filters(ifilter)%num_soilc) + real(r8) :: pf_ndelta(1:filters(ifilter)%num_soilc) ! _ndelta: difference in pool sizes between end & beginning + real(r8) :: pf_errnb(1:filters(ifilter)%num_soilc) ! _errnb: mass balance error; + real(r8) :: pf_noutputs_gas(1:filters(ifilter)%num_soilc) + real(r8) :: pf_noutputs_veg(1:filters(ifilter)%num_soilc) ! _gas:nitrogen gases; _veg:plant uptake of NO3/NH4 + real(r8) :: pf_noutputs_nit(1:filters(ifilter)%num_soilc) + real(r8) :: pf_noutputs_denit(1:filters(ifilter)%num_soilc) ! _gas = _nit + _denit + real(r8) :: pf_ninputs_org(1:filters(ifilter)%num_soilc) ! _org:organic; _min:mineral nitrogen + real(r8) :: pf_ninputs_min(1:filters(ifilter)%num_soilc) + real(r8) :: pf_ndelta_org(1:filters(ifilter)%num_soilc) + real(r8) :: pf_ndelta_min(1:filters(ifilter)%num_soilc) + real(r8) :: pf_nbeg(1:filters(ifilter)%num_soilc) ! _nbeg: Nitrogen mass at the beginning of time-step + real(r8) :: pf_nbeg_org(1:filters(ifilter)%num_soilc) + real(r8) :: pf_nbeg_min(1:filters(ifilter)%num_soilc) + real(r8) :: pf_nend(1:filters(ifilter)%num_soilc) ! _end: Nitrogen mass at the end of time-step + real(r8) :: pf_nend_org(1:filters(ifilter)%num_soilc) + real(r8) :: pf_nend_min(1:filters(ifilter)%num_soilc) + real(r8) :: pf_nend_no3(1:filters(ifilter)%num_soilc) ! 3 mineral N pools at the end of time-step + real(r8) :: pf_nend_nh4(1:filters(ifilter)%num_soilc) + real(r8) :: pf_nend_nh4sorb(1:filters(ifilter)%num_soilc) + real(r8) :: plant_ndemand(1:filters(ifilter)%num_soilc) + real(r8) :: potential_immob(1:filters(ifilter)%num_soilc) + real(r8) :: actual_immob(1:filters(ifilter)%num_soilc) + real(r8) :: gross_nmin(1:filters(ifilter)%num_soilc) ! _immob: N immobilization; _nmin: N mineralization + real(r8) :: pf_ngas_dec(1:filters(ifilter)%num_soilc) ! _ngas_dec: N gas from decomposition-mineralization + real(r8) :: pf_ngas_min(1:filters(ifilter)%num_soilc) ! _ngas_min: N gas from nitrification & denitrification + real(r8) :: pf_errnb_org(1:filters(ifilter)%num_soilc) + real(r8) :: pf_errnb_min(1:filters(ifilter)%num_soilc) + + real(r8) :: pf_errnb_org_vr (1:filters(ifilter)%num_soilc, 1:nlevdecomp_full) + real(r8) :: pf_ndelta_org_vr (1:filters(ifilter)%num_soilc, 1:nlevdecomp_full) + real(r8) :: pf_ninputs_org_vr(1:filters(ifilter)%num_soilc, 1:nlevdecomp_full) + !----------------------------------------------------------------------- + + associate( & + externaln_to_decomp_npools => clm_interface_data%bgc%externaln_to_decomp_npools_col, & ! Input: [real(r8) (:) ] (gC/m2) total column carbon, incl veg and cpool + externaln_to_no3_vr => clm_interface_data%bgc%externaln_to_no3_col , & + externaln_to_nh4_vr => clm_interface_data%bgc%externaln_to_nh4_col , & + decomp_npools_delta_vr => clm_interface_data%bgc%decomp_npools_sourcesink_col , & + decomp_npools_vr => clm_interface_data%bgc%decomp_npools_vr_col , & + smin_no3_vr => clm_interface_data%bgc%smin_no3_vr_col , & + smin_nh4_vr => clm_interface_data%bgc%smin_nh4_vr_col , & + smin_nh4sorb_vr => clm_interface_data%bgc%smin_nh4sorb_vr_col , & + f_ngas_decomp_vr => clm_interface_data%bgc%f_ngas_decomp_vr_col , & + f_ngas_nitri_vr => clm_interface_data%bgc%f_ngas_nitri_vr_col , & + f_ngas_denit_vr => clm_interface_data%bgc%f_ngas_denit_vr_col , & + sminn_to_plant_vr => clm_interface_data%bgc%sminn_to_plant_vr_col , & + + plant_ndemand_vr => clm_interface_data%bgc%plant_ndemand_vr_col , & + potential_immob_vr => clm_interface_data%bgc%potential_immob_vr_col , & + actual_immob_vr => clm_interface_data%bgc%actual_immob_vr_col , & + gross_nmin_vr => clm_interface_data%bgc%gross_nmin_vr_col , & + + soil_begnb => clm_interface_data%bgc%soil_begnb_col , & ! Output: [real(r8) (:) ] carbon mass, beginning of time step (gC/m**2) + soil_begnb_org => clm_interface_data%bgc%soil_begnb_org_col , & ! + soil_begnb_min => clm_interface_data%bgc%soil_begnb_min_col & ! + ) + + ! ------------------------------------------------------------------------ + dtime = real( get_step_size(), r8 ) + nlev = nlevdecomp_full + ! pflotran mass blance check-Carbon + err_found = .false. + do fc = 1,filters(ifilter)%num_soilc + c = filters(ifilter)%soilc(fc) + pf_nbeg_org(fc) = soil_begnb_org(c) + pf_nbeg_min(fc) = soil_begnb_min(c) + pf_nbeg(fc) = soil_begnb(c) + + pf_nend_org(fc) = 0._r8 + pf_nend_min(fc) = 0._r8 + pf_nend_no3(fc) = 0._r8 + pf_nend_nh4(fc) = 0._r8 + pf_nend_nh4sorb(fc) = 0._r8 + pf_nend(fc) = 0._r8 + + pf_ninputs_org(fc) = 0._r8 + pf_ninputs_min(fc) = 0._r8 + pf_ninputs(fc) = 0._r8 + + pf_noutputs_nit(fc) = 0._r8 + pf_noutputs_denit(fc) = 0._r8 + pf_noutputs_gas(fc) = 0._r8 + pf_noutputs_veg(fc) = 0._r8 + pf_noutputs(fc) = 0._r8 + + pf_ndelta_org(fc) = 0._r8 + pf_ndelta_min(fc) = 0._r8 + pf_ndelta(fc) = 0._r8 + + plant_ndemand(fc) = 0._r8 + potential_immob(fc) = 0._r8 + actual_immob(fc) = 0._r8 + gross_nmin(fc) = 0._r8 + + pf_ngas_dec(fc) = 0._r8 + pf_ngas_min(fc) = 0._r8 + pf_errnb_org(fc) = 0._r8 + pf_errnb_min(fc) = 0._r8 + + do j = 1, nlev + ! sminn_vr(c,j) has been calculated above + pf_nend_no3(fc) = pf_nend_no3(fc) + smin_no3_vr(c,j)*dzsoi_decomp(j) + pf_nend_nh4(fc) = pf_nend_nh4(fc) + smin_nh4_vr(c,j)*dzsoi_decomp(j) + pf_nend_nh4sorb(fc) = pf_nend_nh4sorb(fc) + smin_nh4sorb_vr(c,j)*dzsoi_decomp(j) + + pf_ninputs_min(fc) = pf_ninputs_min(fc) + externaln_to_nh4_vr(c,j)*dzsoi_decomp(j) & + + externaln_to_no3_vr(c,j)*dzsoi_decomp(j) + + pf_noutputs_nit(fc) = pf_noutputs_nit(fc) + f_ngas_decomp_vr(c,j)*dzsoi_decomp(j) & + + f_ngas_nitri_vr(c,j)*dzsoi_decomp(j) + pf_noutputs_denit(fc) = pf_noutputs_denit(fc) + f_ngas_denit_vr(c,j)*dzsoi_decomp(j) + pf_noutputs_veg(fc) = pf_noutputs_veg(fc) + sminn_to_plant_vr(c,j)*dzsoi_decomp(j) + + pf_ngas_dec(fc) = pf_ngas_dec(fc) + f_ngas_decomp_vr(c,j)*dzsoi_decomp(j) + pf_ngas_min(fc) = pf_ngas_min(fc) + f_ngas_denit_vr(c,j)*dzsoi_decomp(j) & + + f_ngas_nitri_vr(c,j)*dzsoi_decomp(j) + do l = 1, ndecomp_pools + pf_ndelta_org(fc) = pf_ndelta_org(fc) + decomp_npools_delta_vr(c,j,l)*dzsoi_decomp(j) + pf_ninputs_org(fc) = pf_ninputs_org(fc) + externaln_to_decomp_npools(c,j,l)*dzsoi_decomp(j) + end do + + plant_ndemand(fc) = plant_ndemand(fc) + plant_ndemand_vr(c,j)*dzsoi_decomp(j) + potential_immob(fc) = potential_immob(fc) + potential_immob_vr(c,j)*dzsoi_decomp(j) + actual_immob(fc) = actual_immob(fc) + actual_immob_vr(c,j)*dzsoi_decomp(j) + gross_nmin(fc) = gross_nmin(fc) + gross_nmin_vr(c,j)*dzsoi_decomp(j) + end do !j = 1, nlevdecomp + + pf_nend_org(fc) = pf_nbeg_org(fc) + pf_ndelta_org(fc) !pf_ndelta_org has been calculated + pf_nend_min(fc) = pf_nend_no3(fc) + pf_nend_nh4(fc) + pf_nend_nh4sorb(fc) + pf_nend(fc) = pf_nend_org(fc) + pf_nend_min(fc) + pf_ndelta_min(fc) = pf_nend_min(fc) - pf_nbeg_min(fc) + pf_ndelta(fc) = pf_nend(fc) - pf_nbeg(fc) !pf_ndelta_org + pf_ndelta_min + pf_ninputs(fc) = pf_ninputs_org(fc) + pf_ninputs_min(fc) + pf_noutputs_gas(fc) = pf_noutputs_nit(fc) + pf_noutputs_denit(fc) + pf_noutputs(fc) = pf_noutputs_gas(fc) + pf_noutputs_veg(fc) + pf_errnb(fc) = (pf_ninputs(fc) - pf_noutputs(fc))*dtime - pf_ndelta(fc) + + pf_errnb_org(fc) = (pf_ninputs_org(fc) & + - gross_nmin(fc) + actual_immob(fc))*dtime & + - pf_ndelta_org(fc) + pf_errnb_min(fc) = (pf_ninputs_min(fc) - pf_ngas_min(fc) - pf_ngas_dec(fc) & + + gross_nmin(fc) - actual_immob(fc) - pf_noutputs_veg(fc))*dtime & + - pf_ndelta_min(fc) + ! check for significant errors + if (abs(pf_errnb(fc)) > 1e-8_r8) then + err_found = .true. + err_index = fc + end if + + ! check SON balance at each layer, + pf_errnb_org_vr(fc,:) = 0._r8 + pf_ndelta_org_vr(fc,:) = 0._r8 + pf_ninputs_org_vr(fc,:) = 0._r8 + do j = 1, nlev + do l = 1, ndecomp_pools + pf_ndelta_org_vr(fc,j) = pf_ndelta_org_vr(fc,j) + decomp_npools_delta_vr(c,j,l) + pf_ninputs_org_vr(fc,j) = pf_ninputs_org_vr(fc,j) + externaln_to_decomp_npools(c,j,l) + end do + pf_errnb_org_vr(fc,j) = (pf_ninputs_org_vr(fc,j) & + - gross_nmin_vr(c,j) + actual_immob_vr(c,j))*dtime & + - pf_ndelta_org_vr(fc,j) + pf_errnb_org_vr(fc,j) = pf_errnb_org_vr(fc,j)*dzsoi_decomp(j) + end do + end do + + if (.not. use_ed) then + if (err_found) then + fc = err_index + write(iulog,'(A,70(1h-))')">>>-------- PFLOTRAN Mass Balance Check:beg " + write(iulog,'(A35,I15,A10,I20)')"Nitrogen Balance Error in Column = ",filters(ifilter)%soilc(fc), " @ nstep = ",get_nstep() + write(iulog,'(10A15)') "errnb", "N_in-out", "Ndelta", & + "Ninputs","Noutputs", "Nbeg","Nend" + write(iulog,'(10E15.6)')pf_errnb(fc), (pf_ninputs(fc) - pf_noutputs(fc))*dtime, pf_ndelta(fc), & + pf_ninputs(fc)*dtime,pf_noutputs(fc)*dtime,pf_nbeg(fc),pf_nend(fc) + write(iulog,*) + write(iulog,'(10A15)') "errnb_org","Ndelta_org","Nbeg_org","Nend_org", & + "gross_nmin", "actual_immob", "pot_immob" + write(iulog,'(10E15.6)')pf_errnb_org(fc),pf_ndelta_org(fc),pf_nbeg_org(fc),pf_nend_org(fc), & + gross_nmin(fc)*dtime,actual_immob(fc)*dtime,potential_immob(fc)*dtime + write(iulog,*) + write(iulog,'(10A15)') "errnb_min","Ndelta_min","Nbeg_min","Nend_min", & + "Nend_no3","Nend_nh4", "Nend_nh4sorb" + write(iulog,'(10E15.6)')pf_errnb_min(fc), pf_ndelta_min(fc),pf_nbeg_min(fc),pf_nend_min(fc), & + pf_nend_no3(fc),pf_nend_nh4(fc),pf_nend_nh4sorb(fc) + write(iulog,*) + write(iulog,'(10A15)') "Ninputs_org","Ninputs_min", & + "Noutputs_nit","Noutputs_denit", & + "Noutputs_gas","Noutputs_veg", & + "plant_Ndemand","Ngas_dec","Ngas_min" + write(iulog,'(10E15.6)')pf_ninputs_org(fc)*dtime,pf_ninputs_min(fc)*dtime, & + pf_noutputs_nit(fc)*dtime,pf_noutputs_denit(fc)*dtime, & + pf_noutputs_gas(fc)*dtime,pf_noutputs_veg(fc)*dtime, & + plant_ndemand(fc)*dtime,pf_ngas_dec(fc)*dtime,pf_ngas_min(fc)*dtime +! ! close output currently +! write(iulog,*) +! write(iulog,'(A10,20A15)') "Layer","errbn_org","ndelta_org","ninputs","gross_nmin","actual_immob" +! do j = 1, nlev +! write(iulog,'(I10,15E15.6)')j,pf_errnb_org_vr(fc,j), & +! pf_ndelta_org_vr(fc,j)*dzsoi_decomp(j), & +! pf_ninputs_org_vr(fc,j)*dtime*dzsoi_decomp(j), & +! f_ngas_decomp_vr(c,j)*dtime*dzsoi_decomp(j), & +! gross_nmin_vr(c,j)*dtime*dzsoi_decomp(j), & +! actual_immob_vr(c,j)*dtime*dzsoi_decomp(j) + +! end do + write(iulog,'(A,70(1h-))')">>>-------- PFLOTRAN Mass Balance Check:end " + end if + end if !(.not. use_ed) + end associate + end subroutine clm_pf_NBalanceCheck +!-------------------------------------------------------------------------------------- + + + !----------------------------------------------------------------------------- + +#endif +! +! Private interface subroutines, requiring explicit coupling between CLM and PFLOTRAN +! (END) +!************************************************************************************! + + +end module clm_interface_pflotranMod + diff --git a/components/clm/src/main/clm_interface_thType.F90 b/components/clm/src/main/clm_interface_thType.F90 new file mode 100644 index 000000000000..6b76a3f01c7a --- /dev/null +++ b/components/clm/src/main/clm_interface_thType.F90 @@ -0,0 +1,169 @@ +module clm_interface_thType + +!================================================================================================= +! ALM Thermal(T)-Hydrology (H) Interface: Data Type (Variables) +! created: 8/25/2015 +! updated: 9/16/2016, 2/2/2017, June-2017 +!================================================================================================= + ! USES: + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + + implicit none + + private + + type, public :: clm_interface_th_datatype + + ! soilstate_vars: + real(r8), pointer :: soilpsi_col (:,:) ! col soil water potential in each soil layer (MPa) (CN) + + ! waterstate_vars: + real(r8), pointer :: frac_sno_eff_col (:) ! col fraction of ground covered by snow (0 to 1) + real(r8), pointer :: frac_h2osfc_col (:) ! col fractional area with surface water greater than zero + real(r8), pointer :: h2osoi_vol_col (:,:) ! col volumetric soil water (0<=h2osoi_vol<=watsat) [m3/m3] (nlevgrnd) + real(r8), pointer :: h2osoi_liq_col (:,:) ! col liquid water (kg/m2) (new) (-nlevsno+1:nlevgrnd) + real(r8), pointer :: h2osoi_ice_col (:,:) ! col ice lens (kg/m2) (new) (-nlevsno+1:nlevgrnd) + + ! temperature_vars: + real(r8), pointer :: t_soisno_col (:,:) ! col soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) + real(r8), pointer :: t_grnd_col (:) ! col ground(-air interface averaged) temperature (Kelvin) + real(r8), pointer :: t_h2osfc_col (:) ! col surface-water temperature [Kelvin] + real(r8), pointer :: t_nearsurf_col (:) ! col mixed air/veg. temperature near ground surface (for coupling with PFLOTRAN as BC) + + ! canopystate_vars + integer , pointer :: alt_indx_col (:) ! col current depth of thaw + + + ! waterflux_vars: + real(r8), pointer :: qflx_top_soil_col (:) ! col net water input into soil from top (mm/s) + real(r8), pointer :: qflx_subl_snow_col (:) ! col sublimation rate from snow pack (mm H2O /s) [+] + real(r8), pointer :: qflx_evap_soil_col (:) ! col soil surface evaporation (mm H2O/s) (+ = to atm) + real(r8), pointer :: qflx_evap_snow_col (:) ! col snow surface evaporation (mm H2O/s) (+ = to atm) + real(r8), pointer :: qflx_evap_h2osfc_col (:) ! col evaporation flux from surface water (mm H2O /s) [+ to atm] ! note: the energy unit of orginal definition incorrect + real(r8), pointer :: qflx_tran_veg_col (:) ! col vegetation transpiration (mm H2O/s) (+ = to atm) + real(r8), pointer :: qflx_rootsoil_col (:,:) ! col p-aggregated vertically-resolved vegetation/soil water exchange (m H2O/s) (+ = to atm) + + real(r8), pointer :: qflx_infl_col (:) ! col infiltration (mm H2O/s) + real(r8), pointer :: qflx_surf_col (:) ! col surface runoff (mm H2O/s) + real(r8), pointer :: qflx_drain_col (:) ! col sub-surface runoff (mm H2O/s) + real(r8), pointer :: qflx_drain_vr_col (:,:) ! col liquid water losted as drainage (mm H2O/s) + + ! energyflux_vars: + real(r8), pointer :: htvp_col (:) ! latent heat of vapor of water (or sublimation) [j/kg] + real(r8), pointer :: eflx_bot_col (:) ! col heat flux from beneath the soil or ice column (W/m**2) + real(r8), pointer :: eflx_soil_grnd_col (:) ! col soil heat flux (W/m**2) [+ = into soil] + real(r8), pointer :: eflx_fgr0_snow_col (:) ! col heat flux from snow bottom to first soil layer (W/m**2) [+ = into soil] + real(r8), pointer :: eflx_fgr0_h2osfc_col (:) ! col heat flux from surface water bottom to first soil layer (W/m**2) [+ = into soil] + real(r8), pointer :: eflx_fgr0_soil_col (:) ! col heat flux from near-surface air to first soil layer (W/m**2) [+ = into soil] + real(r8), pointer :: eflx_rnet_soil_col (:) ! net radiation flux between soil layer 1 and above-air, excluding SH and LE (i.e. radiation form only ) (W/m2) [+ = into soil] + + ! soilhydrology_vars: + real(r8), pointer :: frost_table_col (:) ! col frost table depth + real(r8), pointer :: zwt_col (:) ! col water table depth + real(r8), pointer :: zwt_perched_col (:) ! col perched water table depth + real(r8), pointer :: qcharge_col (:) ! col aquifer recharge rate (mm/s) + + ! atm2lnd: + real(r8), pointer :: forc_pbot_grc (:) ! grid atm pressure (Pa) + + contains + procedure , public :: Init + procedure , private :: InitAllocate + end type clm_interface_th_datatype +!------------------------------------------------------------------------------------------------- + + +contains + +!------------------------------------------------------------------------------------------------- + subroutine Init(this, bounds) + use decompMod , only : bounds_type + class(clm_interface_th_datatype) :: this + type(bounds_type), intent(in) :: bounds + + call this%InitAllocate (bounds) + end subroutine Init +!------------------------------------------------------------------------------------------------- + +!------------------------------------------------------------------------------------------------- + + subroutine InitAllocate(this, bounds) + ! USES + use clm_varpar , only : nlevsno, nlevgrnd + use clm_varcon , only : spval + use decompMod , only : bounds_type + + ! ARGUMENTS: + real(r8) :: ival = 0.0_r8 ! initial value + class(clm_interface_th_datatype) :: this + type(bounds_type), intent(in) :: bounds + + ! LOCAL VARIABLES: + integer :: begg, endg + integer :: begc, endc + integer :: begp, endp + !------------------------------------------------------------------------ + begg = bounds%begg; endg= bounds%endg + begc = bounds%begc; endc= bounds%endc + begp = bounds%begp; endp= bounds%endp + + !soilstate_vars: + allocate(this%soilpsi_col (begc:endc, 1:nlevgrnd)) ; this%soilpsi_col (:,:) = nan + + ! waterstate_vars: + allocate(this%frac_sno_eff_col (begc:endc)) ; this%frac_sno_eff_col (:) = nan + allocate(this%frac_h2osfc_col (begc:endc)) ; this%frac_h2osfc_col (:) = nan + allocate(this%h2osoi_liq_col (begc:endc,-nlevsno+1:nlevgrnd)) ; this%h2osoi_liq_col (:,:) = nan + allocate(this%h2osoi_ice_col (begc:endc,-nlevsno+1:nlevgrnd)) ; this%h2osoi_ice_col (:,:) = nan + allocate(this%h2osoi_vol_col (begc:endc, 1:nlevgrnd)) ; this%h2osoi_vol_col (:,:) = nan + + ! temperature_vars: + allocate(this%t_soisno_col (begc:endc,-nlevsno+1:nlevgrnd)) ; this%t_soisno_col (:,:) = nan + allocate(this%t_grnd_col (begc:endc)) ; this%t_grnd_col (:) = nan + allocate(this%t_h2osfc_col (begc:endc)) ; this%t_h2osfc_col (:) = nan + allocate(this%t_nearsurf_col (begc:endc)) ; this%t_nearsurf_col (:) = nan + + ! canopystate_vars: + allocate(this%alt_indx_col (begc:endc)) ; this%alt_indx_col (:) = huge(1) + + !------------------------------------------------------------------------------------------ + ! pflotran variables: BEGIN + !------------------------------------------------------------------------------------------ + ! waterflux_vars: + allocate(this%qflx_top_soil_col (begc:endc)) ; this%qflx_top_soil_col (:) = ival + allocate(this%qflx_evap_h2osfc_col (begc:endc)) ; this%qflx_evap_h2osfc_col (:) = ival + allocate(this%qflx_evap_soil_col (begc:endc)) ; this%qflx_evap_soil_col (:) = ival + allocate(this%qflx_evap_snow_col (begc:endc)) ; this%qflx_evap_snow_col (:) = ival + allocate(this%qflx_subl_snow_col (begc:endc)) ; this%qflx_subl_snow_col (:) = ival + allocate(this%qflx_tran_veg_col (begc:endc)) ; this%qflx_tran_veg_col (:) = ival + allocate(this%qflx_rootsoil_col (begc:endc,1:nlevgrnd)) ; this%qflx_rootsoil_col (:,:) = ival + allocate(this%qflx_infl_col (begc:endc)) ; this%qflx_infl_col (:) = ival + allocate(this%qflx_surf_col (begc:endc)) ; this%qflx_surf_col (:) = ival + allocate(this%qflx_drain_col (begc:endc)) ; this%qflx_drain_col (:) = ival + allocate(this%qflx_drain_vr_col (begc:endc,1:nlevgrnd)) ; this%qflx_drain_vr_col (:,:) = ival + + + ! energyflux_vars: + allocate( this%htvp_col (begc:endc)) ; this%htvp_col (:) = ival + allocate( this%eflx_bot_col (begc:endc)) ; this%eflx_bot_col (:) = ival + allocate( this%eflx_soil_grnd_col (begc:endc)) ; this%eflx_soil_grnd_col (:) = ival + allocate( this%eflx_fgr0_soil_col (begc:endc)) ; this%eflx_fgr0_soil_col (:) = ival + allocate( this%eflx_fgr0_snow_col (begc:endc)) ; this%eflx_fgr0_snow_col (:) = ival + allocate( this%eflx_fgr0_h2osfc_col (begc:endc)) ; this%eflx_fgr0_h2osfc_col (:) = ival + allocate( this%eflx_rnet_soil_col (begc:endc)) ; this%eflx_rnet_soil_col (:) = ival + + ! atm2lnd: + allocate(this%forc_pbot_grc (begg:endg)) ; this%forc_pbot_grc (:) = ival + + ! soilhydrology_vars: + allocate( this%frost_table_col (begc:endc)) ; this%frost_table_col (:) = ival + allocate( this%zwt_col (begc:endc)) ; this%zwt_col (:) = ival + allocate( this%zwt_perched_col (begc:endc)) ; this%zwt_perched_col (:) = ival + allocate( this%qcharge_col (begc:endc)) ; this%qcharge_col (:) = ival + + end subroutine InitAllocate +!------------------------------------------------------------------------------------------------- + +end module clm_interface_thType diff --git a/components/clm/src/main/clm_pflotran_interfaceMod.F90 b/components/clm/src/main/clm_pflotran_interfaceMod.F90 deleted file mode 100644 index 0912c6c9dcc0..000000000000 --- a/components/clm/src/main/clm_pflotran_interfaceMod.F90 +++ /dev/null @@ -1,3657 +0,0 @@ -module clm_pflotran_interfaceMod -!#define FLEXIBLE_POOLS -!---------------------------------------------------------------------------------------------- -! CLM-PFLOTRAN soil bgc coupling interface -! authors: Fengming YUAN1, Gautam Bishit1,2, and Guoping Tang1 -! -! 1.Climate Change Science Institute & Environmental Science Division -! Oak Ridge National Laboratory -! -! 2.Lawrence Berkley National Laboratory -! -! date: 2012 - 2015 -! modified (based on clm_bgc_interface): 8/28/2015, wgs -!---------------------------------------------------------------------------------------------- - -#include "shr_assert.h" - - !----------------------------------------------------------------------- - !BOP - ! - ! !MODULE: clm_pflotran_interfaceMod - ! - ! !DESCRIPTION: - ! Performs - ! - ! !USES: - - ! clm g/l/c/p constants - use shr_log_mod , only : errMsg => shr_log_errMsg - use shr_kind_mod , only : r8 => shr_kind_r8 - use GridcellType , only : grc_pp - use LandunitType , only : lun_pp - use ColumnType , only : col_pp - use VegetationType , only : veg_pp - - use decompMod , only : bounds_type - - ! (dummy) variable definitions - !! (wgs,8/28/2015): variables below are replaced by clm_bgc_data - -! use atm2lndType , only : atm2lnd_type -! use SoilStateType , only : soilstate_type -! use WaterStateType , only : waterstate_type -! use WaterFluxType , only : waterflux_type -! use SoilHydrologyType , only : soilhydrology_type -! use TemperatureType , only : temperature_type -! use EnergyFluxType , only : energyflux_type -! use SoilWaterRetentionCurveMod, only : soil_water_retention_curve_type -! -! use CNStateType , only : cnstate_type -! use CNCarbonFluxType , only : carbonflux_type -! use CNCarbonStateType , only : carbonstate_type -! use CNNitrogenFluxType , only : nitrogenflux_type -! use CNNitrogenStateType , only : nitrogenstate_type -! -! use ch4Mod , only : ch4_type -! -! use PhotosynthesisType , only : photosyns_type -! use cropType , only : crop_type -! use CanopyStateType , only : canopystate_type -! use PhosphorusStateType , only : phosphorusstate_type -! use PhosphorusFluxType , only : phosphorusflux_type - - - ! PFLOTRAN thc module switchs for coupling with CLM45-CN - use clm_varctl , only : use_pflotran, pf_tmode, pf_hmode, pf_cmode - use clm_varctl , only : pf_surfaceflow, pf_frzmode - use clm_varctl , only : initth_pf2clm - - ! most used constants in this module - use clm_varpar , only : nlevsoi, nlevgrnd, nlevdecomp, nlevdecomp_full - use clm_varpar , only : ndecomp_pools - use clm_varpar , only : max_patch_per_col - use clm_varcon , only : denh2o, denice, tfrz, dzsoi_decomp - use landunit_varcon , only : istsoil, istcrop - - ! misc. - use abortutils , only : endrun - -! use clm_bgc_interfaceMod - use clm_bgc_interface_data, only : clm_bgc_interface_data_type - - -#ifdef CLM_PFLOTRAN - use clm_pflotran_interface_data - use pflotran_clm_main_module - use pflotran_clm_setmapping_module -#endif - - ! !PUBLIC TYPES: - implicit none - - save - - private ! By default everything is private - -#ifdef CLM_PFLOTRAN - type(pflotran_model_type), pointer, public :: pflotran_m -#endif - ! - character(len=256), private:: pflotran_prefix = '' - character(len=32), private :: restart_stamp = '' - - real(r8), parameter :: rgas = 8.3144621d0 ! m3 Pa K-1 mol-1 - - ! !PUBLIC MEMBER FUNCTIONS: - public :: clm_pf_readnl - - ! wrappers around '#ifdef CLM_PFLOTRAN .... #endif' block statements to maintain sane runtime behavior - ! when pflotran is not available. - public :: clm_pf_interface_init - public :: clm_pf_set_restart_stamp - public :: clm_pf_run - public :: clm_pf_write_restart - public :: clm_pf_finalize - - -#ifdef CLM_PFLOTRAN - ! private work functions that truely require '#ifdef CLM_PFLOTRAN .... #endif' - private :: interface_init - private :: pflotran_run_onestep - private :: pflotran_write_checkpoint - private :: pflotran_finalize - private :: get_clm_soil_properties - private :: get_clm_soil_th - private :: get_clm_iceadj_porosity - private :: get_clm_bcwflx - private :: get_clm_bceflx - private :: get_clm_bgc_conc - private :: get_clm_bgc_rate - private :: update_soil_temperature_pf2clm - private :: update_soil_moisture_pf2clm - private :: update_soil_bgc_pf2clm - private :: update_bgc_gaslosses_pf2clm -! private :: update_bcflow_pf2clm !!comment out currently for bgc-only - -#endif - -contains - -!----------------------------------------------------------------------- -! -! public interface functions allowing runtime behavior regardless of -! whether pflotran is compiled in. -! -!----------------------------------------------------------------------- - - !----------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: clm_pf_readnl - ! - ! !INTERFACE: - subroutine clm_pf_readnl( NLFilename ) - ! - ! !DESCRIPTION: - ! Read namelist for clm-pflotran interface - ! - ! !USES: - use clm_varctl , only : iulog - use spmdMod , only : masterproc, mpicom - use fileutils , only : getavu, relavu, opnfil - use clm_nlUtilsMod, only : find_nlgroup_name - use shr_nl_mod , only : shr_nl_find_group_name - use shr_mpi_mod , only : shr_mpi_bcast - - implicit none - - ! !ARGUMENTS: - character(len=*), intent(IN) :: NLFilename ! Namelist filename - ! !LOCAL VARIABLES: - integer :: ierr ! error code - integer :: unitn ! unit for namelist file - character(len=32) :: subname = 'clm_pf_readnl' ! subroutine name - !EOP - !----------------------------------------------------------------------- - namelist / clm_pflotran_inparm / pflotran_prefix - - ! ---------------------------------------------------------------------- - ! Read namelist from standard namelist file. - ! ---------------------------------------------------------------------- - - if ( masterproc )then - - unitn = getavu() - write(iulog,*) 'Read in clm-pflotran namelist' - call opnfil (NLFilename, unitn, 'F') - call shr_nl_find_group_name(unitn, 'clm_pflotran_inparm', status=ierr) - if (ierr == 0) then - read(unitn, clm_pflotran_inparm, iostat=ierr) - if (ierr /= 0) then - call endrun(msg=subname //':: ERROR: reading clm_pflotran_inparm namelist.'//& - errMsg(__FILE__, __LINE__)) - end if - end if - call relavu( unitn ) - write(iulog, '(/, A)') " clm-pflotran namelist:" - write(iulog, '(A, " : ", A,/)') " pflotran_prefix", trim(pflotran_prefix) - end if - - ! Broadcast namelist variables read in - call shr_mpi_bcast(pflotran_prefix, mpicom) - - end subroutine clm_pf_readnl - - !----------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: clm_pf_set_restart_stamp - ! - ! !INTERFACE: - subroutine clm_pf_set_restart_stamp(clm_restart_filename) - ! - ! !DESCRIPTION: Set the pflotran restart date stamp. Note we do NOT - ! restart here, that gets handled by pflotran's internal - ! initialization during interface_init_clm_pf() - ! - ! !USES: - ! !ARGUMENTS: - character(len=256), intent(in) :: clm_restart_filename - ! !LOCAL VARIABLES: - integer :: name_length, start_pos, end_pos - character(len=32) :: clm_stamp - !EOP - !----------------------------------------------------------------------- - - ! clm restart file name is of the form: - ! ${CASE_NAME}.clm2.r.YYYY-MM-DD-SSSSS.nc - ! we need to extract the: YYYY-MM-DD-SSSSS - write(*, '("clm-pf : clm restart file name : ", A/)') trim(clm_restart_filename) - name_length = len(trim(clm_restart_filename)) - start_pos = name_length - 18 - end_pos = name_length - 3 - clm_stamp = clm_restart_filename(start_pos : end_pos) - write(*, '("clm-pf : clm date stamp : ", A/)') trim(clm_stamp) - restart_stamp = clm_stamp - - end subroutine clm_pf_set_restart_stamp - - - !----------------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: pflotran_not_available - ! - ! !INTERFACE: - subroutine pflotran_not_available(subname) - ! - ! !DESCRIPTION: - ! Print an error message and abort. - ! - ! !USES: - - ! !ARGUMENTS: - implicit none - character(len=*), intent(in) :: subname - ! !LOCAL VARIABLES: - !EOP - !----------------------------------------------------------------------- - call endrun(trim(subname) // ": ERROR: CLM-PFLOTRAN interface has not been compiled " // & - "into this version of CLM.") - end subroutine pflotran_not_available - - -!******************************************************************************************! -! -! public interface function wrappers -! -!------------------------------------------------------------------------------------------! - - !----------------------------------------------------------------------------- - subroutine clm_pf_interface_init(bounds) - - implicit none - - type(bounds_type), intent(in) :: bounds ! bounds - - character(len=256) :: subname = "clm_pf_interface_init()" - -#ifdef CLM_PFLOTRAN - call interface_init(bounds) -#else - call pflotran_not_available(subname) -#endif - end subroutine clm_pf_interface_init - - !-------------------------------------------------------------------------------------------- - - subroutine clm_pf_run(clm_bgc_data,bounds, & - num_soilc, filter_soilc) - - implicit none - - ! !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(atm2lnd_type) , intent(in) :: atm2lnd_vars -! type(waterstate_type) , intent(inout) :: waterstate_vars -! type(waterflux_type) , intent(inout) :: waterflux_vars -! type(soilstate_type) , intent(inout) :: soilstate_vars -! type(temperature_type) , intent(inout) :: temperature_vars -! type(soilhydrology_type) , intent(inout) :: soilhydrology_vars -! type(energyflux_type) , intent(inout) :: energyflux_vars -! class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve -! -! type(cnstate_type) , intent(inout) :: cnstate_vars -! type(carbonflux_type) , intent(inout) :: carbonflux_vars -! type(carbonstate_type) , intent(inout) :: carbonstate_vars -! type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars -! type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars -! type(ch4_type) , intent(inout) :: ch4_vars - type(clm_bgc_interface_data_type), intent(inout) :: clm_bgc_data - - !----------------------------------------------------------------------- - - character(len=256) :: subname = "clm_pf_run" - -#ifdef CLM_PFLOTRAN - call pflotran_run_onestep(clm_bgc_data,bounds, & - num_soilc, filter_soilc) -#else - call pflotran_not_available(subname) -#endif - end subroutine clm_pf_run - - !----------------------------------------------------------------------------- - subroutine clm_pf_write_restart(date_stamp) - - implicit none - character(len=*), intent(in) :: date_stamp - - character(len=32) :: subname = "clm_pf_write_restart" - -#ifdef CLM_PFLOTRAN - call pflotran_write_checkpoint(date_stamp) -#else - call pflotran_not_available(subname) -#endif - end subroutine clm_pf_write_restart - - - !----------------------------------------------------------------------------- - !BOP - ! - ! !ROUTINE: clm_pf_finalize - ! - ! !INTERFACE: - subroutine clm_pf_finalize() - - implicit none - character(len=256) :: subname = "clm_pf_finalize" - -#ifdef CLM_PFLOTRAN - call pflotran_finalize() -#else - call pflotran_not_available(subname) -#endif - end subroutine clm_pf_finalize - - - - -#ifdef CLM_PFLOTRAN - -!************************************************************************************! -! The following is private and requires explicit coupling between CLM and PFLOTRAN -! -!------------------------------------------------------------------------------------! -! - - !----------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: interface_init - ! - ! !INTERFACE: - subroutine interface_init(bounds) - ! - ! !DESCRIPTION: - ! initialize the pflotran iterface - ! - ! !USES: - use clm_varctl , only : iulog - use decompMod , only : get_proc_global, ldecomp - use spmdMod , only : mpicom, masterproc - use domainMod , only : ldomain - - use CNDecompCascadeConType , only : decomp_cascade_con - - use abortutils , only : endrun - - use clm_time_manager, only : nsstep, nestep - - ! pflotran - use Option_module!, only : printErrMsg - use Simulation_Base_class, only : simulation_base_type - use Simulation_Subsurface_class, only : subsurface_simulation_type - use Realization_class, only : realization_type - use PFLOTRAN_Constants_module - ! - ! !ARGUMENTS: - - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" -#include "finclude/petscviewer.h" - - ! - ! !REVISION HISTORY: - ! Created by Gautam Bisht - ! Revised by Fengming Yuan, CCSI-ORNL - ! - !EOP - ! - ! LOCAL VARAIBLES: - - type(bounds_type), intent(in) :: bounds ! bounds - - integer :: numg ! total number of gridcells across all processors - integer :: numl ! total number of landunits across all processors - integer :: numc ! total number of columns across all processors - integer :: nump ! total number of pfts across all processors - integer :: g,l,c,j ! indices - integer :: gcount, cellcount - - integer, pointer :: clm_cell_ids_nindex(:) - integer, pointer :: clm_2dtop_cell_ids_nindex(:) - integer, pointer :: clm_2dbot_cell_ids_nindex(:) - integer :: clm_cell_npts - integer :: clm_2dtop_npts - integer :: clm_2dbot_npts - - !type(pflotran_model_type), pointer:: pflotran_m - class(realization_type), pointer :: realization - type(option_type), pointer :: option - PetscErrorCode :: ierr - - character(len= 32) :: subname = 'interface_init' ! subroutine name - - associate( & - ! Assign local pointers to derived subtypes components (gridcell-level) - latdeg => grc_pp%latdeg , & ! [real(r8) (:)] latitude (degree) - londeg => grc_pp%londeg , & ! [real(r8) (:)] longitude (degree) - area => grc_pp%area , & ! [real(r8) (:)] total land area per gridcell (km^2) - gindex => grc_pp%gindex , & ! [real(r8) (:)] longitude (degree) - ! Assign local pointers to derived subtypes components (landunit-level) - ltype => lun_pp%itype , & ! [integer (:)] landunit type index - ! Assign local pointer to derived subtypes components (column-level) - cgridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column - clandunit => col_pp%landunit , & ! [integer (:)] landunit index of column - cwtgcell => col_pp%wtgcell , & ! [real(r8) (:)] weight (relative to gridcell - ctype => col_pp%itype , & ! [integer (:)] column type index - topo => col_pp%glc_topo , & ! surface elevation (m) - micro_sigma=> col_pp%micro_sigma, & ! microtopography pdf sigma (m) - slope => col_pp%topo_slope , & ! gridcell topographic slope - topo_std => col_pp%topo_std & ! gridcell elevation standard deviation - ) - - !------------------------------------------------------------------------ - - do c = bounds%begc, bounds%endc - l = col_pp%landunit(c) - if (.not.(ltype(l)==istsoil .or. ltype(l)==istcrop) .and. col_pp%active(c)) then - write (iulog,*) 'WARNING: Land Unit type of active Columns of non-soil/crop type found within the domain' - write (iulog,*) 'CLM-CN -- PFLOTRAN does not support this land unit presently' - write (iulog,*) 'So, DEactive the column: ', c - - col_pp%active(c) = .false. - - endif - - enddo ! do c = bounds%begc, bounds%endc - - if (masterproc) then - write(iulog,*) '%%-----------------------------------------------------%%' - write(iulog,*) '%% clm_pf_interface_init %%' - write(iulog,*) '%%-----------------------------------------------------%%' - write(iulog,*) ' ' - endif - - - ! Determine necessary indices - call get_proc_global(numg, numl, numc, nump) - - !------------------------------------------------------------------------ - allocate(pflotran_m) - - ! Create PFLOTRAN model - call pflotranModelCreate(mpicom, pflotran_prefix, pflotran_m) - option => pflotran_m%option - - call pflotranModelSetupMappingfiles(pflotran_m) - - ! initialize pflotran model - call pflotranModelStepperRunInit(pflotran_m) - - ! PFLOTRAN ck file NOT works well when coupling with CLM. - ! So it's off now and restart PF from CLM. - !restart_stamp = "" - !call pflotranModelSetupRestart(pflotran_m, restart_stamp) - initth_pf2clm = .false. - !if (restart_stamp .ne. "") then - ! initth_pf2clm = .true. - !endif - - ! Initialize PETSc vector for data transfer between CLM and PFLOTRAN - call CLMPFLOTRANIDataInit() - - clm_pf_idata%nzclm_mapped = nlevsoi ! the soil layer no. mapped btw CLM and PF for data-passing - - select type (simulation => pflotran_m%simulation) - class is (subsurface_simulation_type) - realization => simulation%realization - class default - pflotran_m%option%io_buffer = "This version of clm-pflotran only works with subsurface simulations." - write(*, '(/A/)') pflotran_m%option%io_buffer - call printErrMsg(pflotran_m%option) - end select - - if (pflotran_m%option%iflowmode == TH_MODE .or. pflotran_m%option%iflowmode == Richards_MODE) then - pflotran_m%option%io_buffer = "This version of clm-pflotran Richards_mode or TH_mode has NOT yet well tested." - write(*, '(/A/)') pflotran_m%option%io_buffer - call printErrMsg(pflotran_m%option) - endif - - if(pflotran_m%option%nsurfflowdof > 0) then - pflotran_m%option%io_buffer = "This version of clm-pflotran DOES NOT work with PF Surface simulation." - write(*, '(/A/)') pflotran_m%option%io_buffer - call printErrMsg(pflotran_m%option) - endif - pf_surfaceflow = .false. - - !------------------------------------------------ - - ! Compute number of cells in CLM domain. - clm_cell_npts = (bounds%endg - bounds%begg + 1)*clm_pf_idata%nzclm_mapped - clm_2dtop_npts = (bounds%endg - bounds%begg + 1) - clm_2dbot_npts = (bounds%endg - bounds%begg + 1) - allocate(clm_cell_ids_nindex( 1:clm_cell_npts)) - allocate(clm_2dtop_cell_ids_nindex(1:clm_2dtop_npts)) - allocate(clm_2dbot_cell_ids_nindex(1:clm_2dbot_npts)) - - ! Save cell IDs of CLM grid - cellcount = 0 - do g = bounds%begg, bounds%endg - gcount = g - bounds%begg + 1 - - do j = 1, clm_pf_idata%nzclm_mapped - cellcount = cellcount + 1 - !clm_cell_ids_nindex(cellcount) = (ldecomp%gdc2glo(g)-1)*nlevsoi + j - 1 - ! maintain CLM each processor's grids to match up with PF (this appears saving a lot of data communications) - clm_cell_ids_nindex(cellcount) = (g-1)*clm_pf_idata%nzclm_mapped + j - 1 - enddo - - clm_2dtop_cell_ids_nindex(gcount) = (g-1)*clm_pf_idata%nzclm_mapped - - clm_2dbot_cell_ids_nindex(gcount) = g*clm_pf_idata%nzclm_mapped-1 - enddo - - ! CLM: 3-D Subsurface domain (local and ghosted cells) - clm_pf_idata%nlclm_sub = clm_cell_npts - clm_pf_idata%ngclm_sub = clm_cell_npts - - ! CLM: Surface/Bottom cells of subsurface domain (local and ghosted cells) - clm_pf_idata%nlclm_2dtop = (bounds%endg - bounds%begg + 1) - clm_pf_idata%ngclm_2dtop = (bounds%endg - bounds%begg + 1) - - ! CLM: bottom face of subsurface domain - clm_pf_idata%nlclm_2dbot = (bounds%endg - bounds%begg + 1) - clm_pf_idata%ngclm_2dbot = (bounds%endg - bounds%begg + 1) - - ! PFLOTRAN: 3-D Subsurface domain (local and ghosted cells) - clm_pf_idata%nlpf_sub = realization%patch%grid%nlmax - clm_pf_idata%ngpf_sub = realization%patch%grid%ngmax - - ! PFLOTRAN: surface of subsurface domain (local and ghosted cells) - !if (pflotran_m%option%iflowmode == RICHARDS_MODE) then - ! clm_pf_idata%nlpf_2dtop = pflotranModelNSurfCells3DDomain(pflotran_m) ! this will be overwritten in Mapping below - ! clm_pf_idata%ngpf_2dtop = pflotranModelNSurfCells3DDomain(pflotran_m) - !endif - - ! For CLM/PF: ground surface NOT defined, so need to set the following to zero. - clm_pf_idata%nlclm_srf = 0 - clm_pf_idata%ngclm_srf = 0 - clm_pf_idata%nlpf_srf = 0 - clm_pf_idata%ngpf_srf = 0 - - ! Initialize maps for transferring data between CLM and PFLOTRAN. - call pflotranModelInitMapping(pflotran_m, clm_cell_ids_nindex, & - clm_cell_npts, CLM_SUB_TO_PF_SUB) - call pflotranModelInitMapping(pflotran_m, clm_cell_ids_nindex, & - clm_cell_npts, PF_SUB_TO_CLM_SUB) - - ! - if (pflotran_m%option%iflowmode == RICHARDS_MODE .or. & - pflotran_m%option%iflowmode == TH_MODE) then - call pflotranModelInitMapping(pflotran_m, clm_2dtop_cell_ids_nindex, & - clm_2dtop_npts, CLM_2DTOP_TO_PF_2DTOP) - call pflotranModelInitMapping(pflotran_m, clm_2dtop_cell_ids_nindex, & - clm_2dtop_npts, PF_2DTOP_TO_CLM_2DTOP) - - call pflotranModelInitMapping(pflotran_m, clm_2dbot_cell_ids_nindex, & - clm_2dbot_npts, CLM_2DBOT_TO_PF_2DBOT) - call pflotranModelInitMapping(pflotran_m, clm_2dbot_cell_ids_nindex, & - clm_2dbot_npts, PF_2DBOT_TO_CLM_2DBOT) - endif - - ! the CLM-CN/BGC decomposing pool size - clm_pf_idata%ndecomp_pools = ndecomp_pools - - ! Allocate vectors for data transfer between CLM and PFLOTRAN. - call CLMPFLOTRANIDataCreateVec(MPI_COMM_WORLD) - - ! the CLM-CN/BGC decomposing pool if varying cn ratios, and names. - clm_pf_idata%floating_cn_ratio = decomp_cascade_con%floating_cn_ratio_decomp_pools(1:ndecomp_pools) - clm_pf_idata%decomp_pool_name = decomp_cascade_con%decomp_pool_name_history(1:ndecomp_pools) - - ! if BGC is on - if(pflotran_m%option%ntrandof > 0) then - call pflotranModelGetRTspecies(pflotran_m) - endif - - ! Get pflotran top surface area - call pflotranModelGetTopFaceArea(pflotran_m) - - deallocate(clm_cell_ids_nindex) - deallocate(clm_2dtop_cell_ids_nindex) - deallocate(clm_2dbot_cell_ids_nindex) - -!------------------------------------------------------------------------------------- - ! coupled module controls betweeen PFLOTRAN and CLM45 (F.-M. Yuan, Aug. 2013) - if(pflotran_m%option%iflowmode==RICHARDS_MODE) then - pf_hmode = .true. - pf_tmode = .false. - pf_frzmode = .false. - - elseif(pflotran_m%option%iflowmode==TH_MODE) then - pf_hmode = .true. - pf_tmode = .true. - if (pflotran_m%option%use_th_freezing) then - pf_frzmode = .true. - else - pf_frzmode = .false. - endif - - endif - - if(pflotran_m%option%ntrandof.gt.0) then - pf_cmode = .true. ! initialized as '.false.' in clm initialization - endif - -!------------------------------------------------------------------------------------- - - end associate - end subroutine interface_init - - !----------------------------------------------------------------------------- - ! - ! !SUBROUTINE: pflotran_run_onestep - ! - ! !INTERFACE: - - subroutine pflotran_run_onestep(clm_bgc_data,bounds, & - num_soilc, filter_soilc) - ! - ! !DESCRIPTION: - ! - ! F.-M. YUAN: based on Gautam's 'step_th_clm_pf', - ! 'chemistry' (PF_CMODE) added (Sept. 6, 2013) - ! - ! !USES: - - -! use clm_pflotran_interface_data - use PFLOTRAN_Constants_module - - use clm_time_manager , only : get_step_size, get_nstep, nsstep, nestep, & - is_first_step, is_first_restart_step - - !use clm_varctl , only : use_century_decomp - !use CNDecompCascadeCNMod , only : decomp_rate_constants_cn - !use CNDecompCascadeBGCMod, only : decomp_rate_constants_bgc - - implicit none - - 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 pfts in filter -! integer, intent(in) :: filter_soilp(:) ! filter for soil pfts - - type(clm_bgc_interface_data_type), intent(inout) :: clm_bgc_data - - !LOCAL VARIABLES: - real(r8) :: dtime ! land model time step (sec) - integer :: nstep ! time step number - integer :: total_clmstep ! total clm time step number - logical :: ispfprint= .TRUE. ! let PF printout or not - logical :: isinitpf = .FALSE. ! (re-)initialize PF from CLM or not - -#ifdef CLM_PF_DEBUG - real(r8) :: t0, t1, t2, t3 -#endif - - !----------------------------------------------------------------------- - - nstep = get_nstep() - nsstep - dtime = get_step_size() - - if (is_first_step() .or. is_first_restart_step()) then - isinitpf = .TRUE. - else - isinitpf = .FALSE. - endif - -#ifdef CLM_PF_DEBUG -if(nstep>=48*210 .and. nstep<=48*211) then - call cpu_time(t0) - if(pflotran_m%option%myrank .eq. pflotran_m%option%io_rank) then - write(pflotran_m%option%myrank+200,*) '------------------------------------------------------- ' - write(pflotran_m%option%myrank+200,*) '------- checking CLM-PFLOTRAN timing - nstep = ', nstep - write(pflotran_m%option%myrank+200,*) 'CPU_time @check-point 0: ', t0 - endif -endif -#endif - - - ! (0) - if (isinitpf) then - total_clmstep = nestep - nsstep - ispfprint = .true. ! turn-on or shut-off PF's *.h5 output - call pflotranModelUpdateFinalWaypoint(pflotran_m, total_clmstep*dtime, ispfprint) - - ! Set CLM soil properties onto PFLOTRAN grid - - call get_clm_soil_properties(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - call pflotranModelSetSoilProp(pflotran_m) - - ! if initializing soil 'TH' states from CLM to pflotran - if (.not.initth_pf2clm) then - call get_clm_soil_th(clm_bgc_data,initth_pf2clm, initth_pf2clm, & - bounds, num_soilc, filter_soilc) - - if (pf_hmode) then - ! directly pass TH to internal PF vec (field%, work%) - call pflotranModelSetInternalTHStatesfromCLM(pflotran_m) - else - ! pass TH to global_auxvar - call pflotranModelUpdateTHfromCLM(pflotran_m, pf_hmode, pf_tmode) - end if - - ! if initializaing CLM's H states from pflotran (only H mode now) - else - call pflotranModelGetSaturationFromPF(pflotran_m) ! hydrological states - call update_soil_moisture_pf2clm(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - end if - - ! the following is for some specific PF's hydrological parameters useful to constrain H source/sink or BC - if (pf_hmode) then - call pflotranModelGetSoilPropFromPF(pflotran_m) - end if - - endif !!if (isinitpf) - - ! (1) passing TH states from CLM to PF, if not H/TH mode NOT on in PF, every CLM time-step - - ! if PF T/H mode not available, have to pass those from CLM to global variable in PF to drive BGC/H - if ((.not.pf_tmode .or. .not.pf_hmode) .and. (.not.isinitpf)) then - call get_clm_soil_th(clm_bgc_data,pf_tmode, pf_hmode, & - bounds, num_soilc, filter_soilc) - - call pflotranModelUpdateTHfromCLM(pflotran_m, pf_hmode, pf_tmode) - endif - - ! ice-len adjusted porostiy - if (.not.pf_frzmode) then - call get_clm_iceadj_porosity(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - call pflotranModelResetSoilPorosityFromCLM(pflotran_m) - endif - - ! (2) pass CLM water fluxes to CLM-PFLOTRAN interface - if (pf_hmode) then !if coupled 'H' mode between CLM45 and PFLOTRAN - call get_clm_bcwflx(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - - ! pass flux 'vecs' from CLM to pflotran - call pflotranModelUpdateHSourceSink(pflotran_m) ! H SrcSink - call pflotranModelSetSoilHbcsFromCLM(pflotran_m) ! H BC - end if - - ! (3) CLM thermal BC to PFLOTRAN - if (pf_tmode) then - call get_clm_bceflx(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - - call pflotranModelUpdateSubsurfTCond(pflotran_m) ! SrcSink and T bc - end if - - ! (4) - if (pf_cmode) then - ! (4a) for checking CLM's T/H response functions (TODO - also for passing decomposition rate to PF if needed) - !if (use_century_decomp) then - ! call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc) - !else - ! call decomp_rate_constants_cn(bounds, num_soilc, filter_soilc) - !end if - - ! (4b) reset PFLOTRAN bgc state variables from CLM-CN, every CLM time-step -! if (isinitpf) then ! NOTE: if only initialize ONCE, uncomment this 'if...endif' block - - call get_clm_bgc_conc(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - - call pflotranModelSetBgcConcFromCLM(pflotran_m) - - if ( (.not.pf_hmode .or. .not.pf_frzmode)) then - ! this is needed, because at step 0, PF's interface data is empty - !which causes Aq. conc. adjustment balance issue - call pflotranModelGetSaturationFromPF(pflotran_m) - endif -! endif ! NOTE: if only initialize ONCE, uncomment this 'if...endif' block - - ! MUST reset PFLOTRAN soil aq. bgc state variables due to liq. water volume change - ! when NOT coupled with PF Hydrology or NOT in freezing-mode (porosity will be forced to vary from CLM) - if (.not.pf_hmode .or. .not.pf_frzmode) then - call pflotranModelUpdateAqConcFromCLM(pflotran_m) - endif - - ! (4c) bgc rate (source/sink) from CLM to PFLOTRAN - call get_clm_bgc_rate(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - - call pflotranModelSetBgcRatesFromCLM(pflotran_m) -!write(*,*)">>>DEBUG | pflotranModelSetBgcRatesFromCLM" - endif - -#ifdef CLM_PF_DEBUG -if(nstep>=48*210 .and. nstep<=48*211) then - call cpu_time(t1) - if(pflotran_m%option%myrank .eq. pflotran_m%option%io_rank) then - write(pflotran_m%option%myrank+200,*) 'CPU_time elapsed @check-point 1 - 0: ', t1-t0 - endif -endif -#endif - -write(*,*)">>>DEBUG | pflotranModelStepperRunTillPauseTime: BEG...PFLOTRAN" - ! (5) the main callings of PFLOTRAN - call pflotranModelStepperRunTillPauseTime( pflotran_m, (nstep+1.0d0)*dtime, dtime, .false. ) - -write(*,*)">>>DEBUG | pflotranModelStepperRunTillPauseTime: END...CONTINUE..." - -#ifdef CLM_PF_DEBUG -if(nstep>=48*210 .and. nstep<=48*211) then - call cpu_time(t2) - if(pflotran_m%option%myrank .eq. pflotran_m%option%io_rank) then - write(pflotran_m%option%myrank+200,*) 'CPU_time elapsed @check-point 2 - 1: ', t2-t1 - endif -endif -#endif - - ! (6) update CLM variables from PFLOTRAN - if (pf_hmode) then - call pflotranModelGetSaturationFromPF(pflotran_m) ! hydrological states - - call update_soil_moisture_pf2clm(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - endif - - if (pf_tmode) then - call pflotranModelGetTemperatureFromPF(pflotran_m) ! thermal states - - call update_soil_temperature_pf2clm(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - endif - - ! bgc variables - if (pf_cmode) then - call pflotranModelGetBgcVariablesFromPF(pflotran_m) - - call update_soil_bgc_pf2clm(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - - ! need to save the current time-step PF porosity/liq. saturation for bgc species mass conservation - ! if CLM forced changing them into PF at NEXT timestep - if (.not.pf_hmode .or. .not.pf_frzmode) then - call pflotranModelGetSaturationFromPF(pflotran_m) - endif - endif - - ! the actual infiltration/runoff/drainage and solute flux with BC, if defined, - ! are retrieving from PFLOTRAN using 'update_bcflow_pf2clm' subroutine - ! TODO: comment out 'update_bcflow_pf2clm' currently -! if (pf_hmode) then -! call pflotranModelGetBCMassBalanceDeltaFromPF(pflotran_m ) - -! call update_bcflow_pf2clm( & -! bounds, num_soilc, filter_soilc, & -! atm2lnd_vars, & -! temperature_vars, energyflux_vars, & -! waterstate_vars, waterflux_vars) - -! !(TODO) bgc BC flows (e.g. runoff/leaching) -! endif - - -#ifdef CLM_PF_DEBUG -if(nstep>=48*210 .and. nstep<=48*211) then - call cpu_time(t3) - if(pflotran_m%option%myrank .eq. pflotran_m%option%io_rank) then - write(pflotran_m%option%myrank+200,*) 'CPU_time elapsed @check-point 3 - 2: ', t3-t2 - write(pflotran_m%option%myrank+200,*) 'CPU_time elapsed @check-point 3 - 0: ', t3-t0 - write(pflotran_m%option%myrank+200,*) '------------------------------------------------------- ' - endif -endif -#endif - - end subroutine pflotran_run_onestep - - !----------------------------------------------------------------------- - !BOP - ! - ! !ROUTINE: write_checkpoint - ! - ! !INTERFACE: - subroutine pflotran_write_checkpoint(date_stamp) - ! - ! !DESCRIPTION: - ! Trigger a pflotran checkpoint file to be written - ! - ! !USES: - ! !ARGUMENTS: - character(len=32), intent(in) :: date_stamp ! file name date stamp - - ! !LOCAL VARIABLES: - - !EOP - !----------------------------------------------------------------------- - - ! temporarily OFF - it's not working well for BGC - ! So, now must initializing PF variables from CLM each start/restart. - - !call pflotranModelStepperCheckpoint(pflotran_m, date_stamp) - - end subroutine pflotran_write_checkpoint - - !----------------------------------------------------------------------------- - ! - ! !IROUTINE: pflotran_finalize - ! - ! !INTERFACE: - subroutine pflotran_finalize() - ! - ! !DESCRIPTION: - ! - ! finalizing pflotran runs and destroying objects - ! - ! !USES: - - implicit none - - !----------------------------------------------------------------------- - - if (use_pflotran) then - call pflotranModelDestroy(pflotran_m) - endif - - end subroutine pflotran_finalize - - - ! ============================= GET CLM initial/src-sink/BC to PFLOTRAN ================================== - - !----------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: get_clm_soil_properties - ! - ! !INTERFACE: - subroutine get_clm_soil_properties(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - ! - ! !DESCRIPTION: - ! get soil column physical properties to PFLOTRAN - ! - ! !USES: - - ! pflotran - ! - ! !ARGUMENTS: - - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" -#include "finclude/petscviewer.h" - - ! - ! !REVISION HISTORY: - ! Created by Gautam Bisht - ! Revised by Fengming Yuan, CCSI-ORNL - ! - !EOP - ! - ! LOCAL VARAIBLES: - - type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilc ! number of column soil points in column filter - integer , intent(in) :: filter_soilc(:) ! column filter for soil points -! type(soilstate_type) , intent(in) :: soilstate_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data - - integer :: fc, g, l, c, j ! indices - integer :: gcount, cellcount - - character(len= 32) :: subname = 'get_clm_soil_properties' ! subroutine name - - - PetscScalar, pointer :: hksat_x_clm_loc(:) ! hydraulic conductivity in x-dir at saturation (mm H2O /s) - PetscScalar, pointer :: hksat_y_clm_loc(:) ! hydraulic conductivity in y-dir at saturation (mm H2O /s) - PetscScalar, pointer :: hksat_z_clm_loc(:) ! hydraulic conductivity in z-dir at saturation (mm H2O /s) - PetscScalar, pointer :: watsat_clm_loc(:) ! minimum soil suction (mm) - PetscScalar, pointer :: sucsat_clm_loc(:) ! volumetric soil water at saturation (porosity) - PetscScalar, pointer :: bsw_clm_loc(:) ! Clapp and Hornberger "b" - PetscScalar, pointer :: watfc_clm_loc(:) - PetscScalar, pointer :: bulkdensity_dry_clm_loc(:) - PetscScalar, pointer :: zsoi_clm_loc(:) - - PetscErrorCode :: ierr - - associate( & - ! Assign local pointer to derived subtypes components (column-level) - clandunit => col_pp%landunit , & ! [integer (:)] landunit index of column - cgridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column - wtgcell => col_pp%wtgcell , & ! [real(r8) (:)] weight (relative to gridcell - cactive => col_pp%active , & ! [logical (:)] column active or not - z => clm_bgc_data%z , & ! [real(r8) (:,:)] layer depth (m) - dz => clm_bgc_data%dz , & ! [real(r8) (:,:)] layer thickness depth (m) - zi => col_pp%zi , & ! [real(r8) (:,:)] interface level below a "z" level (m) - ! - bd => clm_bgc_data%bd_col , & ! - bsw => clm_bgc_data%bsw_col , & ! [real(r8) (:,:)] Clapp and Hornberger "b" (nlevgrnd) - hksat => clm_bgc_data%hksat_col , & ! [real(r8) (:,:)] hydraulic conductivity at saturation (mm H2O /s) (nlevgrnd) - sucsat => clm_bgc_data%sucsat_col , & ! [real(r8) (:,:)] minimum soil suction (mm) (nlevgrnd) - watsat => clm_bgc_data%watsat_col , & ! [real(r8) (:,:)] volumetric soil water at saturation (porosity) (nlevgrnd) - watfc => clm_bgc_data%watfc_col & ! [real(r8) (:,:)] volumetric soil water at saturation (porosity) (nlevgrnd) - ) - -!------------------------------------------------------------------------------------- - - call VecGetArrayF90(clm_pf_idata%hksat_x_clmp, hksat_x_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%hksat_y_clmp, hksat_y_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%hksat_z_clmp, hksat_z_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%sucsat_clmp, sucsat_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%watsat_clmp, watsat_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%bsw_clmp, bsw_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%watfc_clmp, watfc_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%bulkdensity_dry_clmp, bulkdensity_dry_clm_loc, ierr) - CHKERRQ(ierr) - - call VecGetArrayF90(clm_pf_idata%zsoi_clmp, zsoi_clm_loc, ierr) - CHKERRQ(ierr) - - do fc = 1, num_soilc - c = filter_soilc(fc) - if ( wtgcell(c) <= 0._r8 .or. (.not.cactive(c)) ) cycle ! don't assign data to PF for inactive cell - - ! Set gridcell and landunit indices - g = cgridcell(c) - l = clandunit(c) - gcount = g - bounds%begg - - do j = 1,nlevsoi - cellcount = gcount*clm_pf_idata%nzclm_mapped + j - - if (j <= clm_pf_idata%nzclm_mapped) then - hksat_x_clm_loc(cellcount) = hksat_x_clm_loc(cellcount) & - + hksat(c,j)*wtgcell(c) - hksat_y_clm_loc(cellcount) = hksat_y_clm_loc(cellcount) & - + hksat(c,j)*wtgcell(c) - hksat_z_clm_loc(cellcount) = hksat_z_clm_loc(cellcount) & - + hksat(c,j)*wtgcell(c) - sucsat_clm_loc(cellcount) = sucsat_clm_loc(cellcount) & - + sucsat(c,j)*wtgcell(c) - watsat_clm_loc(cellcount) = watsat_clm_loc(cellcount) & - + watsat(c,j)*wtgcell(c) - bsw_clm_loc(cellcount) = bsw_clm_loc(cellcount) & - + bsw(c,j)*wtgcell(c) - watfc_clm_loc(cellcount) = watfc_clm_loc(cellcount) & - + watfc(c,j)*wtgcell(c) - bulkdensity_dry_clm_loc(cellcount) = bulkdensity_dry_clm_loc(cellcount) & - + bd(c,j)*wtgcell(c) - - zsoi_clm_loc(cellcount) = z(c, j) ! make sure this is right for multiple columns' situation - - else - ! may need to further checking here - endif - - enddo - - enddo ! do c = 1, numsoilc - -!write(*,'(A40,10E14.6)')">>>DEBUG | hksat_x=",(hksat_x_clm_loc(1:10)) -!write(*,'(A40,10E14.6)')">>>DEBUG | hksat_y=",(hksat_y_clm_loc(1:10)) -!write(*,'(A40,10E14.6)')">>>DEBUG | hksat_z=",(hksat_z_clm_loc(1:10)) -!write(*,'(A40,10E14.6)')">>>DEBUG | sucsat=",(sucsat_clm_loc(1:10)) -!write(*,'(A40,10E14.6)')">>>DEBUG | watsat=",(watsat_clm_loc(1:10)) -!write(*,'(A40,10E14.6)')">>>DEBUG | watfc=",(watfc_clm_loc(1:10)) -!write(*,'(A40,10E14.6)')">>>DEBUG | bulkdensity=",(bulkdensity_dry_clm_loc(1:10)) - - call VecRestoreArrayF90(clm_pf_idata%hksat_x_clmp, hksat_x_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%hksat_y_clmp, hksat_y_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%hksat_z_clmp, hksat_z_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%sucsat_clmp, sucsat_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%watsat_clmp, watsat_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%bsw_clmp, bsw_clm_loc, ierr) - CHKERRQ(ierr) - - call VecRestoreArrayF90(clm_pf_idata%watfc_clmp, watfc_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%bulkdensity_dry_clmp, bulkdensity_dry_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%zsoi_clmp, zsoi_clm_loc, ierr) - CHKERRQ(ierr) - - end associate - end subroutine get_clm_soil_properties - - - !----------------------------------------------------------------------------- - !BOP - ! - ! !ROUTINE: get_clm_soil_th - ! - ! !INTERFACE: - subroutine get_clm_soil_th(clm_bgc_data,pftmode, pfhmode, & - bounds, num_soilc, filter_soilc) - - ! - ! !DESCRIPTION: - ! update soil temperature/saturation from CLM to PFLOTRAN for driving PF's BGC - ! if either NOT available inside PFLOTRAN - ! - ! !USES: - use clm_time_manager , only : get_nstep - use shr_const_mod , only : SHR_CONST_G - - use PFLOTRAN_Constants_module - - ! !ARGUMENTS: - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - logical , intent(in) :: pftmode, pfhmode - type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilc ! number of column soil points in column filter - integer , intent(in) :: filter_soilc(:) ! column filter for soil points -! type(atm2lnd_type) , intent(in) :: atm2lnd_vars -! type(soilstate_type) , intent(in) :: soilstate_vars -! type(waterstate_type) , intent(in) :: waterstate_vars -! type(temperature_type) , intent(in) :: temperature_vars -! class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data - - ! !LOCAL VARIABLES: - integer :: fc, c, g, j, gcount, cellcount ! indices - real(r8) :: sattmp, psitmp, itheta - real(r8) :: watmin(num_soilc, nlevsoi) - real(r8) :: sucmin(num_soilc, nlevsoi) - - PetscScalar, pointer :: soilpress_clmp_loc(:) - PetscScalar, pointer :: soilpsi_clmp_loc(:) - PetscScalar, pointer :: soillsat_clmp_loc(:) - PetscScalar, pointer :: soilisat_clmp_loc(:) - PetscScalar, pointer :: soilt_clmp_loc(:) - PetscErrorCode :: ierr - - !EOP - !----------------------------------------------------------------------- - associate ( & - gridcell => col_pp%gridcell , & ! column's gridcell - wtgcell => col_pp%wtgcell , & ! column's weight relative to gridcell - cactive => col_pp%active , & ! [logical (:)] column active or not - dz => clm_bgc_data%dz , & ! layer thickness depth (m) -! zi => clm_bgc_data%zi , & ! interface depth (m) - ! - sucsat => clm_bgc_data%sucsat_col , & ! minimum soil suction (mm) (nlevgrnd) - bsw => clm_bgc_data%bsw_col , & ! Clapp and Hornberger "b" - watsat => clm_bgc_data%watsat_col , & ! volumetric soil water at saturation (porosity) (nlevgrnd) - soilpsi => clm_bgc_data%soilpsi_col , & ! soil water matric potential in each soil layer (MPa) - ! - h2osoi_liq => clm_bgc_data%h2osoi_liq_col , & ! liquid water (kg/m2) - h2osoi_ice => clm_bgc_data%h2osoi_ice_col , & ! ice lens (kg/m2) - ! - t_soisno => clm_bgc_data%t_soisno_col & ! snow-soil temperature (Kelvin) -! ! -! forc_pbot => atm2lnd_vars%forc_pbot_not_downscaled_grc & ! atmospheric pressure (Pa) - ) - - !-------------------------------------------------------------------------------------- - - call VecGetArrayF90(clm_pf_idata%press_clmp, soilpress_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%soilpsi_clmp, soilpsi_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%soillsat_clmp, soillsat_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%soilt_clmp, soilt_clmp_loc, ierr) - CHKERRQ(ierr) - - watmin(:,:) = 0.01_r8 - sucmin(:,:) = 1.e8_r8 - - soilisat_clmp_loc(:) = 0._r8 - soillsat_clmp_loc(:) = 0._r8 - soilpsi_clmp_loc(:) = 0._r8 - soilpress_clmp_loc(:)= clm_pf_idata%pressure_reference - soilt_clmp_loc(:) = 0._r8 - - do fc = 1,num_soilc - c = filter_soilc(fc) - if ( wtgcell(c) <= 0._r8 .or. (.not.cactive(c)) ) cycle ! don't assign data from PF for inactive cell - - g = gridcell(c) - gcount = g - bounds%begg - do j = 1, nlevsoi - cellcount = gcount*clm_pf_idata%nzclm_mapped + j - - if (j<=clm_pf_idata%nzclm_mapped) then - ! this adjusting should be done first, if PF-freezing-mode off, so that the following calculation can be done correctly - itheta = 0._r8 - if(.not.pf_frzmode) then - itheta = h2osoi_ice(c,j) / (dz(c,j) * denice) - itheta = min(itheta, watsat(c,j)-watmin(c,j)/(dz(c,j)*denh2o)) - soilisat_clmp_loc(cellcount) = soilisat_clmp_loc(cellcount) + itheta/watsat(c,j)*wtgcell(c) - endif - - if (.not.pfhmode) then - ! porosity will be ice-adjusted for PF, if PF freezing-mode is off, - ! so need to adjust 'psi' so that 'saturation' in PF is correct - sattmp = h2osoi_liq(c,j) / ((watsat(c,j)-itheta)*dz(c,j)*denh2o) - sattmp = min(max(sattmp, watmin(c,j)/watsat(c,j)),1._r8) - soillsat_clmp_loc(cellcount) = soillsat_clmp_loc(cellcount) + sattmp*wtgcell(c) - - ! soil matric potential by Clapp-Hornburger method (this is the default used by CLM) - ! but, this value IS different from what CLM used (not ice-content adjusted) - ! So that in PF, if not ice-adjusted, the PSI is very small (negative) which implies possible water movement - psitmp = sucsat(c,j) * (-SHR_CONST_G) * (sattmp**(-bsw(c,j))) ! -Pa - psitmp = min(max(psitmp,-sucmin(c,j)/SHR_CONST_G),0._r8) - soilpsi_clmp_loc(cellcount) = soilpsi_clmp_loc(cellcount) + psitmp*wtgcell(c) - soilpress_clmp_loc(cellcount) = soilpress_clmp_loc(cellcount) + psitmp*wtgcell(c) - - endif - - if (.not.pftmode) then - soilt_clmp_loc(cellcount) = soilt_clmp_loc(cellcount) + (t_soisno(c,j)-tfrz)*wtgcell(c) - endif - - endif - - enddo - enddo - -!----------------------------------------------------------------------------- -!write(*,'(A30,12E14.6)')">>>DEBUG | soillsat=", soillsat_clmp_loc(1:10) -!write(*,'(A30,12E14.6)')">>>DEBUG | gsoilpsi[Pa]=", soilpsi_clmp_loc(1:10) -!write(*,'(A30,12E14.6)')">>>DEBUG | soilt[oC]=", soilt_clmp_loc(1:10) -!----------------------------------------------------------------------------- - - call VecRestoreArrayF90(clm_pf_idata%press_clmp, soilpress_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%soilpsi_clmp, soilpsi_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%soillsat_clmp, soillsat_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%soilt_clmp, soilt_clmp_loc, ierr) - CHKERRQ(ierr) - - end associate - end subroutine get_clm_soil_th - - - !----------------------------------------------------------------------------- - !BOP - ! - ! !ROUTINE: get_clm_iceadj_porosity - ! - ! !INTERFACE: - subroutine get_clm_iceadj_porosity(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - ! - ! !DESCRIPTION: - ! update soil effective porosity from CLM to PFLOTRAN if PF freezing mode is off - ! - ! !USES: - - use PFLOTRAN_Constants_module - use clm_varctl , only : pf_frzmode - - ! !ARGUMENTS: - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilc ! number of column soil points in column filter - integer , intent(in) :: filter_soilc(:) ! column filter for soil points -! type(soilstate_type) , intent(in) :: soilstate_vars -! type(waterstate_type) , intent(in) :: waterstate_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data - - ! !LOCAL VARIABLES: - integer :: fc, c, g, j, gcount, cellcount ! indices - real(r8) :: itheta - - PetscScalar, pointer :: adjporosity_clmp_loc(:) ! - PetscScalar, pointer :: soilisat_clmp_loc(:) ! - PetscErrorCode :: ierr - - !EOP - !----------------------------------------------------------------------- - associate ( & - gridcell => col_pp%gridcell , & ! column's gridcell - wtgcell => col_pp%wtgcell , & ! column's weight relative to gridcell - cactive => col_pp%active , & ! column's active or not - dz => col_pp%dz , & ! layer thickness depth (m) - watsat => clm_bgc_data%watsat_col , & ! volumetric soil water at saturation (porosity) (nlevgrnd) - h2osoi_ice => clm_bgc_data%h2osoi_ice_col & ! ice lens (kg/m2) - ) - - ! if 'pf_tmode' is NOT using freezing option, the phase-change of soil water done in 'SoilTemperatureMod.F90' in 'bgp2' - ! must be included to adjust porosity (effective porosity) in pflotran - ! This is doing prior to the real liquid water source/sink, because 'h2osoi_liq' will be updated during those calls after 'bgp2'. - if (.not. pf_frzmode) then - - ! re-calculate the effective porosity (CLM ice-len adjusted), which should be pass to pflotran - call VecGetArrayF90(clm_pf_idata%effporosity_clmp, adjporosity_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) - CHKERRQ(ierr) - - adjporosity_clmp_loc(:) = 0._r8 - soilisat_clmp_loc(:) = 0._r8 - do fc = 1,num_soilc - c = filter_soilc(fc) - if ( wtgcell(c) <= 0._r8 .or. (.not.cactive(c)) ) cycle ! don't assign data from PF for inactive cell - - g = gridcell(c) - gcount = g - bounds%begg - do j = 1, nlevsoi - cellcount = gcount*clm_pf_idata%nzclm_mapped + j - - if (j<=clm_pf_idata%nzclm_mapped) then - itheta = h2osoi_ice(c,j) / (dz(c,j) * denice) - itheta = min(itheta, 0.99_r8*watsat(c,j)) - adjporosity_clmp_loc(cellcount) = adjporosity_clmp_loc(cellcount) & - + (watsat(c,j) - itheta) * wtgcell(c) - soilisat_clmp_loc(cellcount) = soilisat_clmp_loc(cellcount) & - + itheta * wtgcell(c) - endif - end do - end do - call VecRestoreArrayF90(clm_pf_idata%effporosity_clmp, adjporosity_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%soilisat_clmp, soilisat_clmp_loc, ierr) - CHKERRQ(ierr) - - end if - - end associate - end subroutine get_clm_iceadj_porosity - - - !----------------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: get_clm_bcwflx - ! - ! !INTERFACE: - subroutine get_clm_bcwflx(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - ! - ! !DESCRIPTION: - ! - ! F.-M. YUAN: the water fluxes in CLM4.5 are separately calculated in a few subroutines - ! in 'SoilHydrologyMod.F90'. When coupled with pflotran, it's hard to get those together - ! like GB does in 'step_th_clm_pf' subroutine. So, this subroutine is a collective call of - ! that and others in 'Hydrology2Mod.F90' so that pflotran can be called out of 'hydrology2'. - ! - ! !USES: - - use shr_const_mod , only : SHR_CONST_G - use clm_time_manager, only : get_step_size, get_nstep - - ! !ARGUMENTS: - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - type(bounds_type) , intent(in) :: bounds - integer, intent(in) :: num_soilc ! number of column non-lake points in column filter - integer, intent(in) :: filter_soilc(:) ! column filter for non-lake points - -! type(atm2lnd_type) , intent(in) :: clm_a2l -! type(soilstate_type) , intent(in) :: soils_vars -! type(temperature_type) , intent(in) :: ces_vars -! type(energyflux_type) , intent(in) :: cef_vars -! type(waterstate_type) , intent(in) :: cws_vars -! type(waterflux_type) , intent(in) :: cwf_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data - - ! !LOCAL VARIABLES: - integer :: fc, g, c, j, p ! do loop indices - integer :: gcount ! gridcell index (0-based) - integer :: pftindex ! pft index - real(r8) :: dtime ! land model time step (sec) - integer :: nstep ! time step number - real(r8) :: area - integer :: cellcount ! 3-D cell index (1-based) - - real(r8) :: rootfr_col(bounds%begc:bounds%endc, nlevsoi) - real(r8) :: rootfr_sum(bounds%begc:bounds%endc) ! accumulator for rootr weighting - real(r8) :: qflx_evap_col(bounds%begc:bounds%endc) ! soil surface evaporation (mmH2O/s) - real(r8) :: qflx_tran_col(bounds%begc:bounds%endc) ! veg. transpiration (mmH2O/s) - - real(r8) :: qflx, qflx_sink, qflx_source, soilvwc - real(r8) :: dsoilliq1 = 0._r8, dsoilliq2 = 0._r8, dsoilliq3 = 0._r8 - - real(r8) :: qflx_ground, kbot - real(r8) :: reference_pressure, ponding_pressure ! Pa - real(r8) :: pondmax(bounds%begc:bounds%endc) ! mm H2O: max. ponding depth for column - real(r8) :: sr = 0.10_r8 - real(r8) :: tempreal - - ! for PF --> CLM (seq.) - PetscScalar, pointer :: press_clms_loc(:) ! - PetscScalar, pointer :: soillsat_clms_loc(:) ! - PetscScalar, pointer :: porosity_clms_loc(:) ! - PetscScalar, pointer :: sr_pcwmax_clms_loc(:) ! - - PetscScalar, pointer :: area_clms_loc(:) ! - - ! for CLM (mpi) --> PF - PetscScalar, pointer :: zsoi_clmp_loc(:) ! - PetscScalar, pointer :: qflx_clmp_loc(:) ! source/sink term for plant Transpiration: unit in mass rate (kgH2O/sec) - PetscScalar, pointer :: press_top_clmp_loc(:) ! BC in pressure type: unit in Pa - PetscScalar, pointer :: press_base_clmp_loc(:) ! - PetscScalar, pointer :: qflux_top_clmp_loc(:) ! BC in neumann flux type: unit in m/s - PetscScalar, pointer :: qflux_base_clmp_loc(:) ! - PetscScalar, pointer :: press_maxponding_clmp_loc(:) ! - PetscErrorCode :: ierr - - !EOP - !----------------------------------------------------------------------- - associate ( & - ltype => lun_pp%itype , & ! landunit type - cgridcell => col_pp%gridcell , & ! column's gridcell - clandunit => col_pp%landunit , & ! column's landunit - zi => col_pp%zi , & ! Input: (:,:) soil layer interface depth (m) - dz => col_pp%dz , & ! Input: (:,:) soil layer thickness (m) - pfti => col_pp%pfti , &! beginning pft index for each column - pwtgcell => veg_pp%wtgcell , &! weight relative to gridcell for each pft - pwtcol => veg_pp%wtcol , &! weight relative to column for each pft - ! - bsw => clm_bgc_data%bsw_col , &! Clapp and Hornberger "b" (nlevgrnd) - hksat => clm_bgc_data%hksat_col , &! hydraulic conductivity at saturation (mm H2O /s) (nlevgrnd) - watsat => clm_bgc_data%watsat_col , &! volumetric soil water at saturation (porosity) (nlevgrnd) - sucsat => clm_bgc_data%sucsat_col , &! minimum soil suction (mm) (nlevgrnd) - rootfr => clm_bgc_data%rootfr_col , & -! rootfr_pft => soils_vars%rootfr_patch , & ! pft-level effective fraction of roots in each soil layer - - forc_pbot => clm_bgc_data%forc_pbot_not_downscaled_grc , & ! Input: [real(r8) (:)] atmospheric pressure (Pa) - t_grnd => clm_bgc_data%t_grnd_col , & ! Input: [real(r8) (:)] ground surface temperature [K] - htvp => clm_bgc_data%htvp_col , & ! Input: [real(r8) (:)] latent heat of vapor of water (or sublimation) [j/kg] - ! - frac_sno => clm_bgc_data%frac_sno_eff_col , & ! Input: fraction of ground covered by snow (0 to 1) - frac_h2osfc => clm_bgc_data%frac_h2osfc_col , & ! Input: fraction of ground covered by surface water (0 to 1) - h2osoi_liq => clm_bgc_data%h2osoi_liq_col , & ! Input: liquid water (kg/m2) - h2osoi_ice => clm_bgc_data%h2osoi_ice_col , & ! Input: ice lens (kg/m2) - ! - qflx_top_soil => clm_bgc_data%qflx_top_soil_col , & ! Input: net water input into soil from top (mm/s) - qflx_ev_h2osfc => clm_bgc_data%qflx_ev_h2osfc_col , & ! Input: column-level evaporation flux from h2osfc (W/m2) [+ to atm] : checking unit - qflx_evap_soil => clm_bgc_data%qflx_evap_soi_col , & ! Input: column-level soil evaporation (mm H2O/s) (+ = to atm) - qflx_subl_snow => clm_bgc_data%qflx_sub_snow_col , & ! Input: column-level evaporation flux from snow (mm H2O/s) [+ to atm] -! qflx_tran_veg_pft => cwf_vars%qflx_tran_veg_patch & ! Input: pft-level vegetation transpiration (mm H2O/s) (+ = to atm) - qflx_tran_veg => clm_bgc_data%qflx_tran_veg_col & - - ) - -!---------------------------------------------------------------------------- - nstep = get_nstep() - dtime = get_step_size() - - ! (1) soil surface evaporation: needs further checking here? - - do fc = 1, num_soilc - c = filter_soilc(fc) - if (ltype(clandunit(c)) == istsoil .or. ltype(clandunit(c))==istcrop) then - ! not sure if using 'qflx_evap_soi' as a whole ground-surface better than individual surfaces, i.e. 'qflx_ev_snow/soi/h2osfc' - ! all of those 4 variables are calculated in 'BareGroundFluxesMod', 'CanopyFluxesMod', and then adjusted in 'Biogeophysics2' after soil temperature call - ! note that: all 4 variables could be negative (i.e., dew formation on ground) - qflx_evap_col(c)=(1.0_r8 - frac_sno(c) - frac_h2osfc(c))*qflx_evap_soil(c) + & - frac_h2osfc(c)*qflx_ev_h2osfc(c)/htvp(c) - !frac_sno(c)*qflx_ev_snow(c) ! snow-covered area should be excluded (see SoilHydrologyMod:: infiltration) - else - ! for other types of landunits - qflx_evap_col(c) = (1.0_r8 - frac_sno(c))*qflx_evap_soil(c) - end if - - if (t_grnd(c) <= tfrz) qflx_evap_col(c) = max(0._r8, qflx_evap_col(c)) ! frozen ground, no dew contribution to subsurface infiltration - end do - - ! (3) Compute the vegetation Transpiration (originally those are in 'SoilHydrologyMod.F90') - do j = 1, nlevsoi - do fc = 1, num_soilc - c = filter_soilc(fc) - rootfr_col(c,j) = 0._r8 - end do - end do - rootfr_sum(:) = 0._r8 - qflx_tran_col(:) = 0._r8 - -! do pftindex = 1, max_patch_per_col -! do fc = 1, num_soilc -! c = filter_soilc(fc) -! if (pftindex <= col_pp%npfts(c)) then -! p = pfti(c) + pftindex - 1 -! -! if (pwtgcell(p)>0._r8) then -! do j = 1,nlevsoi -! rootfr_col(c,j) = rootfr_col(c,j) + & -! rootfr_pft(p,j) * qflx_tran_veg_pft(p) * pwtcol(p) -! rootfr_sum(c) = rootfr_sum(c) + qflx_tran_veg_pft(p) * pwtcol(p) -! end do -! end if -! -! qflx_tran_col(c) = qflx_tran_col(c) + qflx_tran_veg_pft(p) * pwtcol(p) -! end if -! -! end do -! end do -! ! Compute the Transpiration sink vertical distribution -! do j = 1, nlevsoi -! do fc = 1, num_soilc -! c = filter_soilc(fc) -! if (rootfr_sum(c) /= 0._r8) then -! rootfr_col(c,j) = rootfr_col(c,j)/rootfr_sum(c) -! end if -! end do -! end do - - do fc = 1, num_soilc - c = filter_soilc(fc) - qflx_tran_col(c) = qflx_tran_veg(c) - do j = 1, nlevsoi - rootfr_col(c,j) = rootfr(c,j) - end do - - end do - -!---------------------------------------------------------------------------------------------------------- - ! (4) pass the clm_qflx to the vecs - ! NOTE the following unit conversions: - ! qflx_soil_top and qflx_tran_veg are in [mm/sec] from CLM; - ! qflx_clm_loc is in [kgH2O/sec] as mass rate for pflotran (as input) - - ! previous time-step soil water pressure and saturation for adjusting qflx - ! note that this is a temporary workaround - waiting for PF's solution - call VecGetArrayF90(clm_pf_idata%press_clms, press_clms_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%soillsat_clms, soillsat_clms_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%effporosity_clms, porosity_clms_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%sr_pcwmax_clms, sr_pcwmax_clms_loc, ierr) - CHKERRQ(ierr) - - call VecGetArrayF90(clm_pf_idata%area_top_face_clms, area_clms_loc, ierr) - CHKERRQ(ierr) - - call VecGetArrayF90(clm_pf_idata%zsoi_clmp, zsoi_clmp_loc, ierr) - CHKERRQ(ierr) - - call VecGetArrayF90(clm_pf_idata%qflux_clmp, qflx_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%press_subsurf_clmp, press_top_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%press_subbase_clmp, press_base_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%qflux_subsurf_clmp, qflux_top_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%qflux_subbase_clmp, qflux_base_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%press_maxponding_clmp, press_maxponding_clmp_loc, ierr) - CHKERRQ(ierr) - - ! Initialize flux variables and bcs - do fc = 1, num_soilc - - c = filter_soilc(fc) - g = cgridcell(c) - gcount = g - bounds%begg - - do j = 1, nlevsoi - cellcount = gcount*clm_pf_idata%nzclm_mapped + j - - if(j<=clm_pf_idata%nzclm_mapped) then - qflx_clmp_loc(cellcount) = 0.0_r8 - - if (j .eq. 1) then - press_top_clmp_loc(gcount+1) = press_clms_loc(cellcount) ! same as the first top layer - end if - - if (j .eq. clm_pf_idata%nzclm_mapped) then - press_base_clmp_loc(gcount+1) = press_clms_loc(cellcount) ! same as the bottom layer - end if - - endif - end do - - end do - - pondmax(:) = 0._r8 ! this is temporarily set (not yet figure out how CLM get this value) - do fc = 1, num_soilc - - c = filter_soilc(fc) - g = cgridcell(c) - gcount = g - bounds%begg - area = area_clms_loc(gcount*clm_pf_idata%nzclm_mapped+1) - reference_pressure = clm_pf_idata%pressure_reference - ponding_pressure = pondmax(c)*SHR_CONST_G ! max. ponding water depth (mm) ==> pressure (Pa) - - press_maxponding_clmp_loc(gcount+1) = reference_pressure+ponding_pressure*col_pp%wtgcell(c) - - do j = 1, nlevsoi - cellcount = gcount*clm_pf_idata%nzclm_mapped + j - - if(j<=clm_pf_idata%nzclm_mapped) then - qflx = 0._r8 - ! top BC - if (j .eq. 1) then - - ! net liq water input/output to soil column - qflx_ground = qflx_top_soil(c) - qflx_evap_col(c) ! unit: mm/sec - - ! if net input potential, it's forming TOP BC of pressure type (water ponding potetial) - ! both waterhead and flux calcuated here, but not applied in PFLOTRAN in the same time (upon BC type picked-up by PF) - if ( qflx_ground .gt. 0._r8) then - ! Newly ADDED mmH2O ==> pressure (Pa) as top BC (dirichlet) by forming a layer of surface water column - ! AND, the actual infiltration/runoff are retrieving from PFLOTRAN using 'update_surflow_pf2clm' subroutine - if (soillsat_clms_loc(cellcount) >= 1._r8) then - ! water-head formed on saturated below-ground soil layer - press_top_clmp_loc(gcount+1) = press_clms_loc(cellcount) + & - qflx_ground*col_pp%wtgcell(c)*dtime*SHR_CONST_G - else - ! ground-water-head discontinued from below-ground (atm. pressure applied at both ends) - press_top_clmp_loc(gcount+1) = press_top_clmp_loc(gcount+1) + & - qflx_ground*col_pp%wtgcell(c)*dtime*SHR_CONST_G - endif - - ! mmH2O/sec ==> mH2O/sec of potential infiltration (flux) rate as top BC (neumann) - ! must be used together with 'seepage' as top BC in the meantime to removing upwarding water - ! AND, the actual infiltration/runoff are retrieving from PFLOTRAN using 'update_bcflow_pf2clm' subroutine - qflux_top_clmp_loc(gcount+1) = qflx_ground*1.e-3 - - ! if net loss potential, it's as source/sink term of soil column - else - qflx = qflx + min(0._r8, qflx_ground) ! unit here: mmH2O/sec - qflux_top_clmp_loc(gcount+1) = 0._r8 - end if - end if - - ! adding plant root extraction of water (transpiration) - qflx = qflx - qflx_tran_col(c)*rootfr_col(c,j) ! by this point: unit: mmH2O/sec for CLM column - - qflx = qflx * col_pp%wtgcell(c) ! from now on: per PF 3-D cells - qflx = qflx * area * 1.e-3 *denh2o ! unit: mmH2O/sec ==> kgH2O/sec - - ! previous time-step soil water saturation for adjusting qflx to avoid too wet or too dry to cause PF math issue - ! (this is a temporary workaround - waiting for PF's solution) - soilvwc = soillsat_clms_loc(cellcount) * & - porosity_clms_loc(cellcount) ! PF saturation ==> real vwc (using adjusted porosity???) - - ! checking if over-filled when sinking (excluding infiltration) - qflx_sink = max(0._r8, qflx) ! sink (+) only (kgH2O/sec) - dsoilliq1 = (0.99_r8*porosity_clms_loc(cellcount)-soilvwc) & - * zsoi_clmp_loc(cellcount) & - * area * denh2o /dtime ! mH2O ==> kgH2O/sec to be filled at most (1% for error) - qflx_sink = min(qflx_sink, max(0._r8,dsoilliq1)) - - ! checking if too dry to be ETed (or other sourced): lower than 'sr_pcwmax' - qflx_source = min(0._r8, qflx) ! source (-) only (kgH2O/sec) - sr = 1.001_r8*sr_pcwmax_clms_loc(cellcount) * & ! '1.001' will give 0.1% for holding error in the calculation - watsat(c,j) ! PF saturation ==> 'real' vwc - dsoilliq2 = (sr-soilvwc)*zsoi_clmp_loc(cellcount)*area*denh2o/dtime ! mH2O ==> kgH2O/sec to be extracted at most (-) - qflx_source = max(qflx_source, min(0._r8,dsoilliq2)) - - qflx_clmp_loc(cellcount) = qflx_clmp_loc(cellcount)+ (qflx_sink+qflx_source) ! source/sink unit: kg/sec - - ! bottom BC (neumman type): m/sec - if (j .eq. clm_pf_idata%nzclm_mapped) then - ! available water flux-out rate (-) adjusted by source(-)/sink(+) term - dsoilliq3 = min(0._r8, dsoilliq2 - qflx_clmp_loc(cellcount)) & - /area/denh2o ! kgH2O/sec ==> mH2O/sec - - ! free drainage at bottom - tempreal = soilvwc/watsat(c,j) ! using 'real' saturation - kbot = hksat(c,j)*(tempreal**(2._r8*bsw(c,j)+3._r8))*1.e-3 ! mmH2O/sec ==> mH2O/sec - qflux_base_clmp_loc(gcount+1) = qflux_base_clmp_loc(gcount+1) & - + max(dsoilliq3, -kbot * col_pp%wtgcell(c)) ! mH2O/sec - - end if - - endif !if(j<=clm_pf_idata%nzclm_mapped) - - end do ! do j=1,nlevsoi - - end do ! do c=1, num_soilc - - call VecRestoreArrayF90(clm_pf_idata%press_clms, press_clms_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%soillsat_clms, soillsat_clms_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%sr_pcwmax_clms, sr_pcwmax_clms_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%effporosity_clms, porosity_clms_loc, ierr) - CHKERRQ(ierr) - - call VecRestoreArrayF90(clm_pf_idata%area_top_face_clms, area_clms_loc, ierr) - CHKERRQ(ierr) - - call VecRestoreArrayF90(clm_pf_idata%zsoi_clmp, zsoi_clmp_loc, ierr) - CHKERRQ(ierr) - - call VecRestoreArrayF90(clm_pf_idata%qflux_clmp, qflx_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%press_subsurf_clmp, press_top_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%press_subbase_clmp, press_base_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%qflux_subsurf_clmp, qflux_top_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%qflux_subbase_clmp, qflux_base_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%press_maxponding_clmp, press_maxponding_clmp_loc, ierr) - CHKERRQ(ierr) - -!---------------------------------------------------------------------------------------------------------- - - end associate - end subroutine get_clm_bcwflx - - !----------------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: get_clm_bceflx - ! - ! !INTERFACE: - subroutine get_clm_bceflx(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - ! - ! !DESCRIPTION: - ! - ! F.-M. YUAN: the boundary heat fluxes in CLM4.5 are extracted to drive pflotran TH mode. - ! GB only defined ground-heaf-flux. - ! So, this subroutine is a collective setting on either heat-flux (neumann type) - ! or interface thermal state (temperature) (dirichlet type) - ! at both ground and bottom interface (BC). - ! - ! !USES: - - ! !ARGUMENTS: - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - type(bounds_type) , intent(in) :: bounds - integer, intent(in) :: num_soilc ! number of column non-lake points in column filter - integer, intent(in) :: filter_soilc(:) ! column filter for non-lake points - -! type(atm2lnd_type) , intent(in) :: clm_a2l -! type(waterstate_type) , intent(in) :: cws_vars -! type(temperature_type) , intent(in) :: ces_vars -! type(energyflux_type) , intent(in) :: cef_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data - - ! !LOCAL VARIABLES: - integer :: fc, c, g, p, gcount ! do loop indices - integer :: pftindex - - ! for CLM (mpi) --> PF - PetscScalar, pointer :: gflux_subsurf_clmp_loc(:) ! BC in neumman type: unit W/m2 - PetscScalar, pointer :: gtemp_subsurf_clmp_loc(:) ! BC in dirichlet type: unit in degC - PetscScalar, pointer :: gflux_subbase_clmp_loc(:) ! BC in neumman type: unit W/m2 - PetscScalar, pointer :: gtemp_subbase_clmp_loc(:) ! BC in dirichlet type: unit in degC - PetscErrorCode :: ierr - - !EOP - !----------------------------------------------------------------------- - associate ( & - cgridcell => col_pp%gridcell , &! column's gridcell - clandunit => col_pp%landunit , &! column's landunit - dz => col_pp%dz , &! layer thickness depth (m) - pfti => col_pp%pfti , &! beginning pft index for each column - pwtgcell => veg_pp%wtgcell , &! weight relative to gridcell for each pft - pwtcol => veg_pp%wtcol , &! weight relative to column for each pft - ! - frac_sno => clm_bgc_data%frac_sno_eff_col , & ! Input: fraction of ground covered by snow (0 to 1) - frac_h2osfc => clm_bgc_data%frac_h2osfc_col , & ! Input: fraction of ground covered by surface water (0 to 1) - ! - eflx_bot => clm_bgc_data%eflx_bot_col , &! heat flux from beneath column (W/m**2) [+ = upward] -! eflx_gnet => cef_vars%eflx_gnet_patch , &! net ground heat flux into the surface (W/m**2) per patch -! eflx_soil_grnd => cef_vars%eflx_soil_grnd_patch , &! soil heat flux (W/m**2) [+ = into soil] - eflx_gnet => clm_bgc_data%eflx_gnet_col , & - eflx_soil_grnd => clm_bgc_data%eflx_soil_grnd_col , & - t_grnd => clm_bgc_data%t_grnd_col & ! ground surface temperature [K] - ) - - !---------------------------------------------------------------------------------------------------------- - ! (1) pass the clm_gflux/gtemp to the vec - - call VecGetArrayF90(clm_pf_idata%gflux_subsurf_clmp, gflux_subsurf_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%gflux_subbase_clmp, gflux_subbase_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%gtemp_subsurf_clmp, gtemp_subsurf_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%gtemp_subbase_clmp, gtemp_subbase_clmp_loc, ierr) - CHKERRQ(ierr) - - gflux_subsurf_clmp_loc(:) = 0._r8 - gflux_subbase_clmp_loc(:) = 0._r8 - gtemp_subsurf_clmp_loc(:) = 0._r8 - gtemp_subbase_clmp_loc(:) = 0._r8 - - ! CLM appears NO column-level ground-heat-flux variable, instead by 'patch' - do fc = 1, num_soilc - c = filter_soilc(fc) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - g = cgridcell(c) - gcount = g - bounds%begg - - gflux_subsurf_clmp_loc(gcount+1) = gflux_subsurf_clmp_loc(gcount+1) & - + eflx_soil_grnd(c)*1.d-3 * col_pp%wtgcell(c) ! 1.d-3: from W/m2 --> kJ/m2/s -! do pftindex = 1, max_patch_per_col -! if (pftindex <= col_pp%npfts(c)) then -! p = pfti(c) + pftindex - 1 -! if (pwtgcell(p)>0._r8) then -! gflux_subsurf_clmp_loc(gcount+1) = gflux_subsurf_clmp_loc(gcount+1) & -! + eflx_soil_grnd(p)*1.d-3 * pwtcol(p) ! (TODO - checking) from W/m2 --> kJ/m2/s -! end if -! end if -! end do - end do - - ! CLM column-level variables available to PFLOTRAN - do fc = 1,num_soilc - c = filter_soilc(fc) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - - g = cgridcell(c) - gcount = g - bounds%begg - - gflux_subbase_clmp_loc(gcount+1) = gflux_subbase_clmp_loc(gcount+1) & - + eflx_bot(c)*1.d-3 * col_pp%wtgcell(c) - gtemp_subsurf_clmp_loc(gcount+1) = gflux_subbase_clmp_loc(gcount+1) & - + (t_grnd(c) - tfrz) * col_pp%wtgcell(c) - - gtemp_subbase_clmp_loc(gcount+1) = 0._r8 ! not yet get it from CLM (i.e.,dirichlet type not available) - - end do - - call VecRestoreArrayF90(clm_pf_idata%gflux_subsurf_clmp, gflux_subsurf_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%gflux_subbase_clmp, gflux_subbase_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%gtemp_subsurf_clmp, gtemp_subsurf_clmp_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%gtemp_subbase_clmp, gtemp_subbase_clmp_loc, ierr) - CHKERRQ(ierr) - - end associate - end subroutine get_clm_bceflx - - - !----------------------------------------------------------------------------- - !BOP - ! - ! !ROUTINE: get_clm_bgc_conc(bounds) - ! - ! !INTERFACE: - - subroutine get_clm_bgc_conc(clm_bgc_data, & - bounds, num_soilc, filter_soilc) -!! TODO: add phosphorus vars -#ifndef FLEXIBLE_POOLS - use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -#endif - - implicit none - - 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 - -! type(carbonstate_type) , intent(in) :: carbonstate_vars -! type(nitrogenstate_type) , intent(in) :: nitrogenstate_vars -! type(phosphorusstate_type) , intent(in) :: phosphorusstate_vars -! type(ch4_type) , intent(in) :: ch4_vars - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data - - character(len=256) :: subname = "get_clm_bgc_concentration" - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - ! Local variables - integer :: g, fc, c, j, k - integer :: gcount, cellcount - real(r8) :: wtgcell, realc_gcell, realn_gcell - -#ifdef FLEXIBLE_POOLS - integer :: vec_offset - PetscScalar, pointer :: decomp_cpools_vr_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_npools_vr_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools -#else - integer :: isom - PetscScalar, pointer :: decomp_cpools_vr_lit1_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_lit2_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_lit3_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_cwd_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som1_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som2_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som3_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som4_clm_loc(:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_npools_vr_lit1_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - PetscScalar, pointer :: decomp_npools_vr_lit2_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - PetscScalar, pointer :: decomp_npools_vr_lit3_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - PetscScalar, pointer :: decomp_npools_vr_cwd_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - PetscScalar, pointer :: decomp_npools_vr_som1_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) n pools - PetscScalar, pointer :: decomp_npools_vr_som2_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) n pools - PetscScalar, pointer :: decomp_npools_vr_som3_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) n pools - PetscScalar, pointer :: decomp_npools_vr_som4_clm_loc(:) ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) n pools -#endif - - PetscScalar, pointer :: smin_no3_vr_clm_loc(:) ! (gN/m3) vertically-resolved soil mineral NO3 - PetscScalar, pointer :: smin_nh4_vr_clm_loc(:) ! (gN/m3) vertically-resolved soil mineral NH4 - PetscScalar, pointer :: smin_nh4sorb_vr_clm_loc(:) ! (gN/m3) vertically-resolved soil mineral NH4 absorbed - - PetscErrorCode :: ierr - ! - !------------------------------------------------------------------------------------------ - ! - associate ( & - decomp_cpools_vr=> clm_bgc_data%decomp_cpools_vr_col , & ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - decomp_npools_vr=> clm_bgc_data%decomp_npools_vr_col , & ! (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - smin_no3_vr => clm_bgc_data%smin_no3_vr_col , & ! (gN/m3) vertically-resolved soil mineral NO3 - smin_nh4_vr => clm_bgc_data%smin_nh4_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 - smin_nh4sorb_vr => clm_bgc_data%smin_nh4sorb_vr_col , & ! (gN/m3) vertically-resolved soil mineral NH4 absorbed - - decomp_ppools_vr=> clm_bgc_data%decomp_ppools_vr_col , & ! [real(r8) (:,:,:) ! col (gP/m3) vertically-resolved decomposing (litter, cwd, soil) P pools - solutionp_vr => clm_bgc_data%solutionp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil solution P - labilep_vr => clm_bgc_data%labilep_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil labile mineral P - secondp_vr => clm_bgc_data%secondp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil secondary mineralP - occlp_vr => clm_bgc_data%occlp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil occluded mineral P - primp_vr => clm_bgc_data%primp_vr_col , & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil primary mineral P - sminp_vr => clm_bgc_data%sminp_vr_col & ! [real(r8) (:,:) ! col (gP/m3) vertically-resolved soil mineral P = solutionp + labilep + secondp - ) - -#ifdef FLEXIBLE_POOLS - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_clmp, decomp_cpools_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_clmp, decomp_npools_vr_clm_loc, ierr) - CHKERRQ(ierr) -#else - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_lit1_clmp, decomp_cpools_vr_lit1_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_lit2_clmp, decomp_cpools_vr_lit2_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_lit3_clmp, decomp_cpools_vr_lit3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_cwd_clmp, decomp_cpools_vr_cwd_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_som1_clmp, decomp_cpools_vr_som1_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_som2_clmp, decomp_cpools_vr_som2_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_som3_clmp, decomp_cpools_vr_som3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_cpools_vr_som4_clmp, decomp_cpools_vr_som4_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_lit1_clmp, decomp_npools_vr_lit1_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_lit2_clmp, decomp_npools_vr_lit2_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_lit3_clmp, decomp_npools_vr_lit3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_cwd_clmp, decomp_npools_vr_cwd_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_som1_clmp, decomp_npools_vr_som1_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_som2_clmp, decomp_npools_vr_som2_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_som3_clmp, decomp_npools_vr_som3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%decomp_npools_vr_som4_clmp, decomp_npools_vr_som4_clm_loc, ierr) - CHKERRQ(ierr) -#endif - - call VecGetArrayF90(clm_pf_idata%smin_no3_vr_clmp, smin_no3_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%smin_nh4_vr_clmp, smin_nh4_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%smin_nh4sorb_vr_clmp, smin_nh4sorb_vr_clm_loc, ierr) - CHKERRQ(ierr) - -#ifdef FLEXIBLE_POOLS - decomp_cpools_vr_clm_loc(:) = 0._r8 - decomp_npools_vr_clm_loc(:) = 0._r8 -#else - decomp_cpools_vr_lit1_clm_loc(:) = 0._r8 - decomp_cpools_vr_lit2_clm_loc(:) = 0._r8 - decomp_cpools_vr_lit3_clm_loc(:) = 0._r8 - decomp_cpools_vr_cwd_clm_loc(:) = 0._r8 - decomp_cpools_vr_som1_clm_loc(:) = 0._r8 - decomp_cpools_vr_som2_clm_loc(:) = 0._r8 - decomp_cpools_vr_som3_clm_loc(:) = 0._r8 - decomp_cpools_vr_som4_clm_loc(:) = 0._r8 - decomp_npools_vr_lit1_clm_loc(:) = 0._r8 - decomp_npools_vr_lit2_clm_loc(:) = 0._r8 - decomp_npools_vr_lit3_clm_loc(:) = 0._r8 - decomp_npools_vr_cwd_clm_loc(:) = 0._r8 - decomp_npools_vr_som1_clm_loc(:) = 0._r8 - decomp_npools_vr_som2_clm_loc(:) = 0._r8 - decomp_npools_vr_som3_clm_loc(:) = 0._r8 - decomp_npools_vr_som4_clm_loc(:) = 0._r8 -#endif - - smin_no3_vr_clm_loc(:) = 0._r8 - smin_nh4_vr_clm_loc(:) = 0._r8 - smin_nh4sorb_vr_clm_loc(:) = 0._r8 - - do fc = 1, num_soilc ! will need to extend to multiple columns? - c = filter_soilc(fc) - - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data to PF for inactive cell - - g = col_pp%gridcell(c) - wtgcell = col_pp%wtgcell(c) - - gcount = g - bounds%begg - do j = 1, nlevdecomp - - ! note: all clm-pf soil layers are 'nzclm_mapped' for both TH/BGC, - ! but in CLM, TH is within nlevsoi, bgc within 'nlevdecomp' - - cellcount = gcount*clm_pf_idata%nzclm_mapped+j - - if(j <= clm_pf_idata%nzclm_mapped) then - - do k = 1, ndecomp_pools - realc_gcell = decomp_cpools_vr(c,j,k) & - /clm_pf_idata%C_molecular_weight * wtgcell - realn_gcell = decomp_npools_vr(c,j,k) & - /clm_pf_idata%N_molecular_weight * wtgcell - -#ifdef FLEXIBLE_POOLS - vec_offset = (k-1)*clm_pf_idata%ngclm_sub ! decomp_pool vec: 'cell' first, then 'species' - - decomp_cpools_vr_clm_loc(vec_offset+cellcount) = realc_gcell & - + decomp_cpools_vr_clm_loc(vec_offset+cellcount) - decomp_npools_vr_clm_loc(vec_offset+cellcount) = realn_gcell & - + decomp_npools_vr_clm_loc(vec_offset+cellcount) - -#else - if (k==i_met_lit) then - decomp_cpools_vr_lit1_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_lit1_clm_loc(cellcount) - decomp_npools_vr_lit1_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_lit1_clm_loc(cellcount) - - elseif (k==i_cel_lit) then - decomp_cpools_vr_lit2_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_lit2_clm_loc(cellcount) - decomp_npools_vr_lit2_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_lit2_clm_loc(cellcount) - - elseif (k==i_lig_lit) then - decomp_cpools_vr_lit3_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_lit3_clm_loc(cellcount) - decomp_npools_vr_lit3_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_lit3_clm_loc(cellcount) - - elseif (k==i_cwd) then - decomp_cpools_vr_cwd_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_cwd_clm_loc(cellcount) - decomp_npools_vr_cwd_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_cwd_clm_loc(cellcount) - - else - isom = k-i_cwd - if (isom==1 .and. isom<=ndecomp_pools) then - decomp_cpools_vr_som1_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_som1_clm_loc(cellcount) - decomp_npools_vr_som1_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_som1_clm_loc(cellcount) - - elseif (isom==2 .and. isom<=ndecomp_pools) then - decomp_cpools_vr_som2_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_som2_clm_loc(cellcount) - decomp_npools_vr_som2_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_som2_clm_loc(cellcount) - - elseif (isom==3 .and. isom<=ndecomp_pools) then - decomp_cpools_vr_som3_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_som3_clm_loc(cellcount) - decomp_npools_vr_som3_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_som3_clm_loc(cellcount) - - elseif (isom==4 .and. isom<=ndecomp_pools) then ! if using 'century' type, will end here - decomp_cpools_vr_som4_clm_loc(cellcount) = realc_gcell & - + decomp_cpools_vr_som4_clm_loc(cellcount) - decomp_npools_vr_som4_clm_loc(cellcount) = realn_gcell & - + decomp_npools_vr_som4_clm_loc(cellcount) - end if - - end if -#endif - - enddo ! do k=1, ndecomp_pools - - realn_gcell = smin_no3_vr(c,j)/clm_pf_idata%N_molecular_weight * wtgcell - smin_no3_vr_clm_loc(cellcount) = realn_gcell & - + smin_no3_vr_clm_loc(cellcount) - - realn_gcell = smin_nh4_vr(c,j)/clm_pf_idata%N_molecular_weight * wtgcell - smin_nh4_vr_clm_loc(cellcount) = realn_gcell & - + smin_nh4_vr_clm_loc(cellcount) - - realn_gcell = smin_nh4sorb_vr(c,j)/clm_pf_idata%N_molecular_weight * wtgcell - smin_nh4sorb_vr_clm_loc(cellcount) = realn_gcell & - + smin_nh4sorb_vr_clm_loc(cellcount) - - endif - - enddo ! do j = 1, nlevdecomp - - enddo ! do c = begc, endc - -#ifdef FLEXIBLE_POOLS - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_clmp, decomp_cpools_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_clmp, decomp_npools_vr_clm_loc, ierr) - CHKERRQ(ierr) -#else -!----------------------------------------------------------------------------- -!write(*,'(A,50(1h-))')">>>DEBUG | get_clm_bgc_conc,lev=1 for C & N" -!write(*,'(12A14)')"lit1","lit2","lit3","cwd","som1","som2","som3","som4","no3","nh4","nh4sorb" -!write(*,'(12E14.6)')decomp_cpools_vr(1,1,1:8) -!write(*,'(12E14.6)')decomp_npools_vr(1,1,1:8),smin_no3_vr(1,1),smin_nh4_vr(1,1),smin_nh4sorb_vr(1,1) -!----------------------------------------------------------------------------- - - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_lit1_clmp, decomp_cpools_vr_lit1_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_lit2_clmp, decomp_cpools_vr_lit2_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_lit3_clmp, decomp_cpools_vr_lit3_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_cwd_clmp, decomp_cpools_vr_cwd_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_som1_clmp, decomp_cpools_vr_som1_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_som2_clmp, decomp_cpools_vr_som2_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_som3_clmp, decomp_cpools_vr_som3_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_cpools_vr_som4_clmp, decomp_cpools_vr_som4_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_lit1_clmp, decomp_npools_vr_lit1_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_lit2_clmp, decomp_npools_vr_lit2_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_lit3_clmp, decomp_npools_vr_lit3_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_cwd_clmp, decomp_npools_vr_cwd_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_som1_clmp, decomp_npools_vr_som1_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_som2_clmp, decomp_npools_vr_som2_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_som3_clmp, decomp_npools_vr_som3_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%decomp_npools_vr_som4_clmp, decomp_npools_vr_som4_clm_loc, ierr) - CHKERRQ(ierr) -#endif - call VecRestoreArrayF90(clm_pf_idata%smin_no3_vr_clmp, smin_no3_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%smin_nh4_vr_clmp, smin_nh4_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%smin_nh4sorb_vr_clmp, smin_nh4sorb_vr_clm_loc, ierr) - CHKERRQ(ierr) - - end associate - end subroutine get_clm_bgc_conc - - !----------------------------------------------------------------------------- - ! - ! !IROUTINE: get_clm_bgc_rate() - ! - ! !INTERFACE: - subroutine get_clm_bgc_rate(clm_bgc_data, & - bounds, num_soilc, filter_soilc) -!! TODO: add phosphorus vars - ! - ! !DESCRIPTION: - ! - ! - ! !USES: - - use clm_time_manager, only : get_step_size, get_nstep -#ifndef FLEXIBLE_POOLS - use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -#endif - - ! !ARGUMENTS: - implicit none - - 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 - - type(clm_bgc_interface_data_type), intent(in) :: clm_bgc_data - -! type(cnstate_type) , intent(in) :: cnstate_vars -! type(carbonflux_type) , intent(in) :: carbonflux_vars -! type(nitrogenflux_type) , intent(in) :: nitrogenflux_vars - - character(len=256) :: subname = "get_clm_bgc_rate" - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - ! !LOCAL VARIABLES: - integer :: fc, c, g, j, k ! do loop indices - integer :: gcount, cellcount - real(r8) :: wtgcell, realc_gcell, realn_gcell - - real(r8) :: dtime ! land model time step (sec) - - ! ratios of NH4:NO3 in N deposition and fertilization (temporarily set here, will be as inputs) -! real(r8) :: r_nh4_no3_dep(bounds%begc:bounds%endc) -! real(r8) :: r_nh4_no3_fert(bounds%begc:bounds%endc) -! real(r8) :: fnh4_dep, fnh4_fert - - ! C/N source/sink rates as inputs for pflotran: Units - moles/m3/s (note: do unit conversion here for input rates) -#ifdef FLEXIBLE_POOLS - integer :: vec_offset - PetscScalar, pointer :: rate_decomp_c_clm_loc(:) ! - PetscScalar, pointer :: rate_decomp_n_clm_loc(:) ! -#else - integer :: isom - PetscScalar, pointer :: rate_lit1c_clm_loc(:) ! - PetscScalar, pointer :: rate_lit2c_clm_loc(:) ! - PetscScalar, pointer :: rate_lit3c_clm_loc(:) ! - PetscScalar, pointer :: rate_cwdc_clm_loc(:) ! - PetscScalar, pointer :: rate_som1c_clm_loc(:) ! - PetscScalar, pointer :: rate_som2c_clm_loc(:) ! - PetscScalar, pointer :: rate_som3c_clm_loc(:) ! - PetscScalar, pointer :: rate_som4c_clm_loc(:) ! - PetscScalar, pointer :: rate_lit1n_clm_loc(:) ! - PetscScalar, pointer :: rate_lit2n_clm_loc(:) ! - PetscScalar, pointer :: rate_lit3n_clm_loc(:) ! - PetscScalar, pointer :: rate_cwdn_clm_loc(:) ! - PetscScalar, pointer :: rate_som1n_clm_loc(:) ! - PetscScalar, pointer :: rate_som2n_clm_loc(:) ! - PetscScalar, pointer :: rate_som3n_clm_loc(:) ! - PetscScalar, pointer :: rate_som4n_clm_loc(:) ! -#endif - - PetscScalar, pointer :: rate_plantndemand_clm_loc(:) ! - PetscScalar, pointer :: rate_smin_no3_clm_loc(:) ! - PetscScalar, pointer :: rate_smin_nh4_clm_loc(:) ! - - PetscErrorCode :: ierr - - ! - !--------------------------------------------------------------------------- - ! - associate ( & - ! plant litering and removal + SOM/LIT vertical transport - col_net_to_decomp_cpools_vr => clm_bgc_data%externalc_to_decomp_cpools_col , & - col_net_to_decomp_npools_vr => clm_bgc_data%externaln_to_decomp_npools_col , & - ! inorg. nitrogen source -! ndep_to_sminn => nitrogenflux_vars%ndep_to_sminn_col , & -! nfix_to_sminn => nitrogenflux_vars%nfix_to_sminn_col , & -! fert_to_sminn => nitrogenflux_vars%fert_to_sminn_col , & -! soyfixn_to_sminn => nitrogenflux_vars%soyfixn_to_sminn_col , & -! supplement_to_sminn_vr => nitrogenflux_vars%supplement_to_sminn_vr_col , & -! ! -! nfixation_prof => cnstate_vars%nfixation_prof_col , & -! ndep_prof => cnstate_vars%ndep_prof_col , & -! activeroot_prof => cnstate_vars%activeroot_prof_col , & - ! inorg. nitrogen sink (if not going to be done in PF) - no3_net_transport_vr => clm_bgc_data%no3_net_transport_vr_col , & - ! inorg. nitrogen sink potential - col_plant_ndemand_vr => clm_bgc_data%plant_ndemand_vr_col , & - - externaln_to_nh4_vr => clm_bgc_data%externaln_to_nh4_col , & - externaln_to_no3_vr => clm_bgc_data%externaln_to_no3_col , & - - col_net_to_decomp_ppools_vr => clm_bgc_data%externalp_to_decomp_ppools_col , & - externalp_to_primp_vr => clm_bgc_data%externalp_to_primp_col , & - externalp_to_labilep_vr => clm_bgc_data%externalp_to_labilep_col , & - externalp_to_solutionp => clm_bgc_data%externalp_to_solutionp_col , & - sminp_net_transport_vr => clm_bgc_data%sminp_net_transport_vr_col , & - col_plant_pdemand_vr => clm_bgc_data%plant_pdemand_vr_col & - ) - - dtime = get_step_size() - -#ifdef FLEXIBLE_POOLS - call VecGetArrayF90(clm_pf_idata%rate_decomp_c_clmp, rate_decomp_c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_decomp_n_clmp, rate_decomp_n_clm_loc, ierr) - CHKERRQ(ierr) -#else - call VecGetArrayF90(clm_pf_idata%rate_lit1c_clmp, rate_lit1c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_lit2c_clmp, rate_lit2c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_lit3c_clmp, rate_lit3c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_cwdc_clmp, rate_cwdc_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som1c_clmp, rate_som1c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som2c_clmp, rate_som2c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som3c_clmp, rate_som3c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som4c_clmp, rate_som4c_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_lit1n_clmp, rate_lit1n_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_lit2n_clmp, rate_lit2n_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_lit3n_clmp, rate_lit3n_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_cwdn_clmp, rate_cwdn_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som1n_clmp, rate_som1n_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som2n_clmp, rate_som2n_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som3n_clmp, rate_som3n_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_som4n_clmp, rate_som4n_clm_loc, ierr) -#endif - - call VecGetArrayF90(clm_pf_idata%rate_plantndemand_clmp, rate_plantndemand_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_smin_no3_clmp, rate_smin_no3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%rate_smin_nh4_clmp, rate_smin_nh4_clm_loc, ierr) - CHKERRQ(ierr) - - ! Initialize to ZERO -#ifdef FLEXIBLE_POOLS - rate_decomp_c_clm_loc(:) = 0.0_r8 - rate_decomp_n_clm_loc(:) = 0.0_r8 -#else - rate_lit1c_clm_loc(:) = 0.0_r8 - rate_lit2c_clm_loc(:) = 0.0_r8 - rate_lit3c_clm_loc(:) = 0.0_r8 - rate_cwdc_clm_loc (:) = 0.0_r8 - rate_som1c_clm_loc(:) = 0.0_r8 - rate_som2c_clm_loc(:) = 0.0_r8 - rate_som3c_clm_loc(:) = 0.0_r8 - rate_som4c_clm_loc(:) = 0.0_r8 - rate_lit1n_clm_loc(:) = 0.0_r8 - rate_lit2n_clm_loc(:) = 0.0_r8 - rate_lit3n_clm_loc(:) = 0.0_r8 - rate_cwdn_clm_loc (:) = 0.0_r8 - rate_som1n_clm_loc(:) = 0.0_r8 - rate_som2n_clm_loc(:) = 0.0_r8 - rate_som3n_clm_loc(:) = 0.0_r8 - rate_som4n_clm_loc(:) = 0.0_r8 -#endif - rate_smin_no3_clm_loc(:) = 0.0_r8 - rate_smin_nh4_clm_loc(:) = 0.0_r8 - rate_plantndemand_clm_loc(:) = 0.0_r8 - -! r_nh4_no3_dep(:) = 1.0_r8 ! temporarily assuming half of N dep is in NH4 and another half in NO3 -! r_nh4_no3_fert(:) = 1.0_r8 ! temporarily assiming half of N fertilization is in NH4 and another half in NO3 - - do fc = 1,num_soilc - c = filter_soilc(fc) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - - g = col_pp%gridcell(c) - gcount = g - bounds%begg - wtgcell = col_pp%wtgcell(c) - - do j = 1, nlevdecomp - cellcount = gcount*clm_pf_idata%nzclm_mapped+j - - ! note: all clm-pf soil layers are 'clm_pf_idata%nzclm_mapped' for both TH/BGC, - ! but in CLM, TH is within clm_pf_idata%nzclm_mapped, bgc within 'nlevdecomp' - if(j <= clm_pf_idata%nzclm_mapped) then - - do k = 1, ndecomp_pools - ! need more checking here: how to weight column data onto grid (F.-M. Yuan) - realc_gcell = col_net_to_decomp_cpools_vr(c,j,k) & - /clm_pf_idata%C_molecular_weight * wtgcell - realn_gcell = col_net_to_decomp_npools_vr(c,j,k) & - /clm_pf_idata%N_molecular_weight * wtgcell - -#ifdef FLEXIBLE_POOLS - vec_offset = (k-1)*clm_pf_idata%ngclm_sub ! decomp_pool vec: 'cell' first, then 'species' - - rate_decomp_c_clm_loc(vec_offset+cellcount) = realc_gcell & - + rate_decomp_c_clm_loc(vec_offset+cellcount) - rate_decomp_n_clm_loc(vec_offset+cellcount) = realn_gcell & - + rate_decomp_n_clm_loc(vec_offset+cellcount) -#else - if (k==i_met_lit) then - rate_lit1c_clm_loc(cellcount) = realc_gcell & - + rate_lit1c_clm_loc(cellcount) - rate_lit1n_clm_loc(cellcount) = realn_gcell & - + rate_lit1n_clm_loc(cellcount) - else if(k==i_cel_lit) then - rate_lit2c_clm_loc(cellcount) = realc_gcell & - + rate_lit2c_clm_loc(cellcount) - rate_lit2n_clm_loc(cellcount) = realn_gcell & - + rate_lit2n_clm_loc(cellcount) - else if(k==i_lig_lit) then - rate_lit3c_clm_loc(cellcount) = realc_gcell & - + rate_lit3c_clm_loc(cellcount) - rate_lit3n_clm_loc(cellcount) = realn_gcell & - + rate_lit3n_clm_loc(cellcount) - else if(k==i_cwd) then - rate_cwdc_clm_loc(cellcount) = realc_gcell & - + rate_cwdc_clm_loc(cellcount) - rate_cwdn_clm_loc(cellcount) = realn_gcell & - + rate_cwdn_clm_loc(cellcount) - ! - else - isom = k-i_cwd - if(isom==1 .and. isom<=ndecomp_pools) then - rate_som1c_clm_loc(cellcount) = realc_gcell & - + rate_som1c_clm_loc(cellcount) - rate_som1n_clm_loc(cellcount) = realn_gcell & - + rate_som1n_clm_loc(cellcount) - else if(isom==2 .and. isom<=ndecomp_pools) then - rate_som2c_clm_loc(cellcount) = realc_gcell & - + rate_som2c_clm_loc(cellcount) - rate_som2n_clm_loc(cellcount) = realn_gcell & - + rate_som2n_clm_loc(cellcount) - else if(isom==3 .and. isom<=ndecomp_pools) then - rate_som3c_clm_loc(cellcount) = realc_gcell & - + rate_som3c_clm_loc(cellcount) - rate_som3n_clm_loc(cellcount) = realn_gcell & - + rate_som3n_clm_loc(cellcount) - else if(isom==4 .and. isom<=ndecomp_pools) then ! if using 'century' type, will end here - rate_som4c_clm_loc(cellcount) = realc_gcell & - + rate_som4c_clm_loc(cellcount) - rate_som4n_clm_loc(cellcount) = realn_gcell & - + rate_som4n_clm_loc(cellcount) - end if - - endif -#endif - enddo ! do k=1, ndecomp_pools - -! fnh4_dep = max(0._r8, min(1.0_r8, 1._r8/(r_nh4_no3_dep(c)+1._r8))) -! fnh4_fert = max(0._r8, min(1.0_r8, 1._r8/(r_nh4_no3_fert(c)+1._r8))) - -! realn_gcell = & -! ( fnh4_dep*ndep_to_sminn(c) * ndep_prof(c, j) + & -! fnh4_fert*fert_to_sminn(c) * ndep_prof(c, j) + & -! fnh4_fert*supplement_to_sminn_vr(c,j) + & -! nfix_to_sminn(c) * nfixation_prof(c, j) + & -! soyfixn_to_sminn(c) * nfixation_prof(c, j) & -! )/ clm_pf_idata%N_molecular_weight * wtgcell - - realn_gcell = externaln_to_nh4_vr(c,j)/ clm_pf_idata%N_molecular_weight * wtgcell - rate_smin_nh4_clm_loc(cellcount) = realn_gcell + rate_smin_nh4_clm_loc(cellcount) - -! realn_gcell = & -! ( (1._r8-fnh4_dep)*ndep_to_sminn(c) * ndep_prof(c, j) + & -! (1._r8-fnh4_fert)*fert_to_sminn(c) * ndep_prof(c, j) + & -! (1._r8-fnh4_fert)*supplement_to_sminn_vr(c,j) & -! )/ clm_pf_idata%N_molecular_weight * wtgcell - - realn_gcell = externaln_to_no3_vr(c,j)/ clm_pf_idata%N_molecular_weight * wtgcell - ! PF hydrological mode is OFF, then NO3 transport NOT to calculate in PF - ! then it's done in CLM, so need to pass those to PF as source/sink term (RT mass transfer) - if(.not.pf_hmode) then - realn_gcell = realn_gcell - (no3_net_transport_vr(c,j) & - )/ clm_pf_idata%N_molecular_weight * wtgcell - endif - rate_smin_no3_clm_loc(cellcount) = realn_gcell + rate_smin_no3_clm_loc(cellcount) - - ! plant N uptake rate here IS the N demand (potential uptake) - realn_gcell = col_plant_ndemand_vr(c,j) & - /clm_pf_idata%N_molecular_weight * wtgcell - rate_plantndemand_clm_loc(cellcount) = rate_plantndemand_clm_loc(cellcount) + realn_gcell - -#ifdef CLM_PF_DEBUG - write(pflotran_m%option%myrank+200,*) 'checking bgc-mass-rate - clm: ', & - 'rank=',pflotran_m%option%myrank, 'column=',c, 'layer_id=',j, & - 'rate_nh4_clm(layer_id)=',rate_smin_nh4_clm_loc(cellcount) -#endif - - endif ! if (j<=clm_pf_idata%nzclm_mapped) - enddo ! do j=1, nlevdecomp - enddo ! do fc=1,numsoic - -#ifdef FLEXIBLE_POOLS - call VecRestoreArrayF90(clm_pf_idata%rate_decomp_c_clmp, rate_decomp_c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_decomp_n_clmp, rate_decomp_n_clm_loc, ierr) - CHKERRQ(ierr) -#else - -!----------------------------------------------------------------------------- -!write(*,'(A,50(1h-))')">>>DEBUG | get_clm_bgc_rate,lev=1 for C & N" -!write(*,'(12A14)')"lit1","lit2","lit3","cwd","som1","som2","som3","som4","no3","nh4","plantNdemand" -!write(*,'(12E14.6)')col_net_to_decomp_cpools_vr(1,1,1:ndecomp_pools) -!write(*,'(12E14.6)')col_net_to_decomp_npools_vr(1,1,1:ndecomp_pools),& -! (rate_smin_no3_clm_loc(1))*clm_pf_idata%N_molecular_weight, & -! (rate_smin_nh4_clm_loc(1))*clm_pf_idata%N_molecular_weight, & -! (rate_plantndemand_clm_loc(1))*clm_pf_idata%N_molecular_weight -!----------------------------------------------------------------------------- - - call VecRestoreArrayF90(clm_pf_idata%rate_lit1c_clmp, rate_lit1c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_lit2c_clmp, rate_lit2c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_lit3c_clmp, rate_lit3c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_cwdc_clmp, rate_cwdc_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som1c_clmp, rate_som1c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som2c_clmp, rate_som2c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som3c_clmp, rate_som3c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som4c_clmp, rate_som4c_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_lit1n_clmp, rate_lit1n_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_lit2n_clmp, rate_lit2n_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_lit3n_clmp, rate_lit3n_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_cwdn_clmp, rate_cwdn_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som1n_clmp, rate_som1n_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som2n_clmp, rate_som2n_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som3n_clmp, rate_som3n_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_som4n_clmp, rate_som4n_clm_loc, ierr) -#endif - - call VecRestoreArrayF90(clm_pf_idata%rate_plantndemand_clmp, rate_plantndemand_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_smin_no3_clmp, rate_smin_no3_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%rate_smin_nh4_clmp, rate_smin_nh4_clm_loc, ierr) - CHKERRQ(ierr) - - end associate - end subroutine get_clm_bgc_rate - - - ! =============================UPDATE PFLOTRAN evolving variables to CLM ========================================== - - - !----------------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: update_soil_moisture_pf2clm - ! - ! !INTERFACE: - subroutine update_soil_moisture_pf2clm(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - - ! - ! !DESCRIPTION: - ! - ! - ! !USES: - - ! !ARGUMENTS: - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - type(bounds_type), intent(in) :: bounds - integer, intent(in) :: num_soilc ! number of column soil points in column filter - integer, intent(in) :: filter_soilc(:) ! column filter for soil points -! type(soilstate_type) , intent(in) :: soilstate_vars -! type(waterstate_type), intent(inout) :: waterstate_vars - type(clm_bgc_interface_data_type), intent(inout) :: clm_bgc_data - - ! !LOCAL VARIABLES: - integer :: fc, c, j, g, gcount ! indices - - PetscScalar, pointer :: sat_ice_clm_loc(:) - PetscScalar, pointer :: sat_clm_loc(:) - PetscScalar, pointer :: watsat_clm_loc(:) - PetscErrorCode :: ierr - - !EOP - !----------------------------------------------------------------------- - associate ( & - gridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column - wtgcell => col_pp%wtgcell , & ! [real(r8) (:)] weight (relative to gridcell - dz => col_pp%dz , & ! [real(r8) (:,:)] layer thickness depth (m) - ! - h2osoi_liq_col => clm_bgc_data%h2osoi_liq_col , & - h2osoi_ice_col => clm_bgc_data%h2osoi_ice_col , & - h2osoi_vol_col => clm_bgc_data%h2osoi_vol_col , & - watsat_col => clm_bgc_data%watsat_col & - ) - - call VecGetArrayF90(clm_pf_idata%soillsat_clms, sat_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%effporosity_clms, watsat_clm_loc, ierr) - CHKERRQ(ierr) - if (pf_frzmode) & - call VecGetArrayF90(clm_pf_idata%soilisat_clms, sat_ice_clm_loc, ierr) - CHKERRQ(ierr) - - do fc = 1,num_soilc - c = filter_soilc(fc) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - - g = col_pp%gridcell(c) - gcount = g - bounds%begg - do j = 1, nlevsoi - - if (j<=clm_pf_idata%nzclm_mapped) then - h2osoi_liq_col(c,j) = sat_clm_loc(gcount*nlevsoi + j) * & - watsat_clm_loc(gcount*nlevsoi + j) * dz(c,j) * denh2o ! 'watsat_clm_loc' may be effective porosity - if (pf_frzmode) then - h2osoi_ice_col(c,j) = sat_ice_clm_loc(gcount*nlevsoi + j) * & - watsat_clm_loc(gcount*nlevsoi + j) * dz(c,j) * denice - end if - - else - h2osoi_liq_col(c,j) = h2osoi_liq_col(c,clm_pf_idata%nzclm_mapped) - if (pf_frzmode) then - h2osoi_ice_col(c,j) = h2osoi_ice_col(c,clm_pf_idata%nzclm_mapped) - end if - - end if - - h2osoi_vol_col(c,j) = h2osoi_liq_col(c,j) / dz(c,j) / denh2o + & - h2osoi_ice_col(c,j) / dz(c,j) / denice - h2osoi_vol_col(c,j) = min(h2osoi_vol_col(c,j), watsat_col(c,j)) - - enddo - - enddo - - call VecRestoreArrayF90(clm_pf_idata%soillsat_clms, sat_clm_loc, ierr) - CHKERRQ(ierr) - call VecRestoreArrayF90(clm_pf_idata%effporosity_clms, watsat_clm_loc, ierr) - CHKERRQ(ierr) - if (pf_frzmode) & - call VecRestoreArrayF90(clm_pf_idata%soilisat_clms, sat_ice_clm_loc, ierr) - CHKERRQ(ierr) - - end associate - end subroutine update_soil_moisture_pf2clm - - !----------------------------------------------------------------------------- - !BOP - ! - ! !IROUTINE: update_soil_temperature_pf2clm - ! - ! !INTERFACE: - subroutine update_soil_temperature_pf2clm(clm_bgc_data, & - bounds, num_soilc, filter_soilc) - - ! - ! !DESCRIPTION: - ! - ! - ! !USES: - - ! !ARGUMENTS: - implicit none - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - type(bounds_type), intent(in) :: bounds - integer, intent(in) :: num_soilc ! number of column soil points in column filter - integer, intent(in) :: filter_soilc(:) ! column filter for soil points -! type(soilstate_type) , intent(in) :: soilstate_vars -! type(temperature_type), intent(inout):: temperature_vars - type(clm_bgc_interface_data_type), intent(inout) :: clm_bgc_data - - ! !LOCAL VARIABLES: - integer :: fc, c, j, g, gcount ! indices - - PetscScalar, pointer :: soilt_clms_loc(:) - PetscErrorCode :: ierr - - !EOP - !----------------------------------------------------------------------- - associate ( & - gridcell => col_pp%gridcell , & ! [integer (:)] gridcell index of column - wtgcell => col_pp%wtgcell , & ! [real(r8) (:)] weight (relative to gridcell - dz => col_pp%dz , & ! [real(r8) (:,:)] layer thickness depth (m) - ! - t_soisno => clm_bgc_data%t_soisno_col & ! snow-soil temperature (Kelvin) - ) - - call VecGetArrayReadF90(clm_pf_idata%soilt_clms, soilt_clms_loc, ierr) - CHKERRQ(ierr) - - do fc = 1,num_soilc - c = filter_soilc(fc) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - - g = col_pp%gridcell(c) - gcount = g - bounds%begg - do j = 1, nlevsoi - - if (j<=clm_pf_idata%nzclm_mapped) then - t_soisno(c,j) = soilt_clms_loc(gcount*clm_pf_idata%nzclm_mapped+j) + tfrz - - else - t_soisno(c,j) = t_soisno(c, clm_pf_idata%nzclm_mapped) - - end if - - enddo - - enddo - - call VecRestoreArrayReadF90(clm_pf_idata%soilt_clms, soilt_clms_loc, ierr) - CHKERRQ(ierr) - - end associate - end subroutine update_soil_temperature_pf2clm - - !----------------------------------------------------------------------------- - ! - ! !ROUTINE: update_soil_bgc_pf2clm() - ! - ! !INTERFACE: - ! - ! ! calculating BGC state variable changes over one time-step (rates) - ! NOTE: Don't update the organic C/N state variables, which will be updated in those 'update' subroutines - ! and the 'CNSoilLittVertTranspMod.F90' after 'update1'. - ! - subroutine update_soil_bgc_pf2clm(clm_bgc_data, & - bounds, num_soilc, filter_soilc) -!! TODO: add phosphorus vars - use CNDecompCascadeConType, only : decomp_cascade_con - use clm_time_manager, only : get_step_size -#ifndef FLEXIBLE_POOLS - use clm_varpar, only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd -#endif - - implicit none - - 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 - -! type(atm2lnd_type) , intent(in) :: clm_a2l -! type(waterstate_type) , intent(in) :: waterstate_vars -! type(soilstate_type) , intent(in) :: soilstate_vars -! type(cnstate_type) , intent(in) :: cnstate_vars -! type(carbonstate_type) , intent(inout) :: carbonstate_vars -! type(carbonflux_type) , intent(inout) :: carbonflux_vars -! type(nitrogenstate_type) , intent(inout) :: nitrogenstate_vars -! type(nitrogenflux_type) , intent(inout) :: nitrogenflux_vars -! type(ch4_type) , intent(inout) :: ch4_vars - type(clm_bgc_interface_data_type), intent(inout) :: clm_bgc_data - - character(len=256) :: subname = "update_soil_bgc_pf2clm" - -#include "finclude/petscsys.h" -#include "finclude/petscvec.h" -#include "finclude/petscvec.h90" - - integer :: fc,c,g,j,k - integer :: gcount, cellcount - real(r8) :: wtgcell - - real(r8) :: dtime ! land model time step (sec) - -#ifdef FLEXIBLE_POOLS - integer :: vec_offset - PetscScalar, pointer :: decomp_cpools_vr_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_npools_vr_clm_loc(:) ! (moleN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools -#else - integer :: isom - PetscScalar, pointer :: decomp_cpools_vr_lit1_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_lit2_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_lit3_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_cwd_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som1_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som2_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som3_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_cpools_vr_som4_clm_loc(:) ! (moleC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools - PetscScalar, pointer :: decomp_npools_vr_lit1_clm_loc(:) ! (moleN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - PetscScalar, pointer :: decomp_npools_vr_lit2_clm_loc(:) ! (moleN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - PetscScalar, pointer :: decomp_npools_vr_lit3_clm_loc(:) ! (moleN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools - PetscScalar, pointer :: decomp_npools_vr_cwd_clm_loc(:) ! (moleN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools -#endif - - PetscScalar, pointer :: smin_no3_vr_clm_loc(:) ! (moleN/m3) vertically-resolved soil mineral NO3 - PetscScalar, pointer :: smin_nh4_vr_clm_loc(:) ! (moleN/m3) vertically-resolved total soil mineral NH4 - PetscScalar, pointer :: smin_nh4sorb_vr_clm_loc(:) ! (moleN/m3) vertically-resolved absorbed soil mineral NH4 - - ! 'accextrn_vr' - accumulative (root) extracted N, i.e., actual plant N uptake from each soil layer, within a CLM timestep - PetscScalar, pointer :: accextrnh4_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil mineral N root-extraction (accumulated) - PetscScalar, pointer :: accextrno3_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil mineral N root-extraction (accumulated) - - ! 'accnmin_vr' - accumulative gross N mineralization within a CLM timestep - PetscScalar, pointer :: accnmin_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil N mineralization (accumulated) - - ! 'accnimm_vr' - accumulative N immobilization within a CLM timestep - PetscScalar, pointer :: accnimmp_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil N potential immoblilization (accumulated) - PetscScalar, pointer :: accnimm_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil N immoblilization (accumulated) - - PetscErrorCode :: ierr - -!------------------------------------------------------------------------------------ - ! - associate ( & - initial_cn_ratio => clm_bgc_data%initial_cn_ratio , & - decomp_cpools_vr => clm_bgc_data%decomp_cpools_vr_col , & - decomp_npools_vr => clm_bgc_data%decomp_npools_vr_col , & - sminn_vr => clm_bgc_data%sminn_vr_col , & - smin_no3_vr => clm_bgc_data%smin_no3_vr_col , & - smin_nh4_vr => clm_bgc_data%smin_nh4_vr_col , & - smin_nh4sorb_vr => clm_bgc_data%smin_nh4sorb_vr_col , & - decomp_cpools_delta_vr => clm_bgc_data%decomp_cpools_sourcesink_col , & - decomp_npools_delta_vr => clm_bgc_data%decomp_npools_sourcesink_col , & - - sminn_to_plant_vr => clm_bgc_data%sminn_to_plant_vr_col , & - smin_no3_to_plant_vr => clm_bgc_data%smin_no3_to_plant_vr_col , & - smin_nh4_to_plant_vr => clm_bgc_data%smin_nh4_to_plant_vr_col , & - potential_immob_vr => clm_bgc_data%potential_immob_vr_col , & - actual_immob_vr => clm_bgc_data%actual_immob_vr_col , & - gross_nmin_vr => clm_bgc_data%gross_nmin_vr_col & - ) -! ------------------------------------------------------------------------ - dtime = get_step_size() - - ! soil C/N pool increments set to the previous timestep (i.e., not yet updated) - decomp_cpools_delta_vr = 0._r8-decomp_cpools_vr - decomp_npools_delta_vr = 0._r8-decomp_npools_vr - - ! clm-pf interface data updated -#ifdef FLEXIBLE_POOLS - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_clms, decomp_cpools_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_npools_vr_clms, decomp_npools_vr_clm_loc, ierr) - CHKERRQ(ierr) -#else - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_lit1_clms, decomp_cpools_vr_lit1_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_lit2_clms, decomp_cpools_vr_lit2_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_lit3_clms, decomp_cpools_vr_lit3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_cwd_clms, decomp_cpools_vr_cwd_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_som1_clms, decomp_cpools_vr_som1_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_som2_clms, decomp_cpools_vr_som2_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_som3_clms, decomp_cpools_vr_som3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_cpools_vr_som4_clms, decomp_cpools_vr_som4_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_npools_vr_lit1_clms, decomp_npools_vr_lit1_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_npools_vr_lit2_clms, decomp_npools_vr_lit2_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_npools_vr_lit3_clms, decomp_npools_vr_lit3_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%decomp_npools_vr_cwd_clms, decomp_npools_vr_cwd_clm_loc, ierr) - CHKERRQ(ierr) -#endif - - call VecGetArrayReadF90(clm_pf_idata%smin_no3_vr_clms, smin_no3_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%smin_nh4_vr_clms, smin_nh4_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%smin_nh4sorb_vr_clms, smin_nh4sorb_vr_clm_loc, ierr) - CHKERRQ(ierr) - - call VecGetArrayReadF90(clm_pf_idata%accextrnh4_vr_clms, accextrnh4_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%accextrno3_vr_clms, accextrno3_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%accnmin_vr_clms, accnmin_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%accnimmp_vr_clms, accnimmp_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayReadF90(clm_pf_idata%accnimm_vr_clms, accnimm_vr_clm_loc, ierr) - CHKERRQ(ierr) - - ! soil C/N pool increments, and actual plant N uptake, gross N mineralization and immobilization - do fc = 1,num_soilc - ! only operating on soil column, which then back to CLM-CN - ! (TODO) NOT YET do columna-level down-scaling from PF's grid-cell variables - - c = filter_soilc(fc) - g = col_pp%gridcell(c) - wtgcell = col_pp%wtgcell(c) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - - gcount = g - bounds%begg - do j = 1, nlevdecomp - - cellcount = gcount*clm_pf_idata%nzclm_mapped+j - if(j <= clm_pf_idata%nzclm_mapped) then - - ! updates the 'decomp_pools' src/sink terms, - ! which then used in 'CNSoilLittVertTranspMod.F90' to update the pools - do k=1, ndecomp_pools -#ifdef FLEXIBLE_POOLS - vec_offset = (k-1)*clm_pf_idata%nlclm_sub ! decomp_pool vec: 'cell' first, then 'species' - - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_clm_loc(vec_offset+cellcount) & - * clm_pf_idata%C_molecular_weight - - if (clm_pf_idata%floating_cn_ratio(k)) then - decomp_npools_delta_vr(c,j,k) = decomp_npools_delta_vr(c,j,k) & - + decomp_npools_vr_clm_loc(vec_offset+cellcount) & - * clm_pf_idata%N_molecular_weight - - else - decomp_npools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - /initial_cn_ratio(k) - endif - -#else - if (k==i_met_lit) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_lit1_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - decomp_npools_delta_vr(c,j,k) = decomp_npools_delta_vr(c,j,k) & - + decomp_npools_vr_lit1_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight - else if (k==i_cel_lit) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_lit2_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - decomp_npools_delta_vr(c,j,k) = decomp_npools_delta_vr(c,j,k) & - + decomp_npools_vr_lit2_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight - else if (k==i_lig_lit) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_lit3_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - decomp_npools_delta_vr(c,j,k) = decomp_npools_delta_vr(c,j,k) & - + decomp_npools_vr_lit3_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight - else if (k==i_cwd) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_cwd_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - decomp_npools_delta_vr(c,j,k) = decomp_npools_delta_vr(c,j,k) & - + decomp_npools_vr_cwd_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight - ! - else - - isom = k-i_cwd - - if (isom==1 .and. isom<=ndecomp_pools) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_som1_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - elseif (isom==2 .and. isom<=ndecomp_pools) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_som2_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - elseif (isom==3 .and. isom<=ndecomp_pools) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_som3_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - elseif (isom==4 .and. isom<=ndecomp_pools) then - decomp_cpools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - + decomp_cpools_vr_som4_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight - end if - - if (isom>0) then - decomp_npools_delta_vr(c,j,k) = decomp_cpools_delta_vr(c,j,k) & - /initial_cn_ratio(k) - end if - - endif - -#endif - if (abs(decomp_cpools_delta_vr(c,j,k))<=1.d-20) decomp_cpools_delta_vr(c,j,k)=0._r8 - if (abs(decomp_npools_delta_vr(c,j,k))<=1.d-21) decomp_npools_delta_vr(c,j,k)=0._r8 - - enddo - - ! directly update the 'smin' N pools (SO, must bypass the 'CNNStateUpdate1,2,3' relevant to soil N) - smin_no3_vr(c,j) = & - smin_no3_vr_clm_loc(cellcount)*clm_pf_idata%N_molecular_weight - - smin_nh4_vr(c,j) = & - smin_nh4_vr_clm_loc(cellcount)*clm_pf_idata%N_molecular_weight - - smin_nh4sorb_vr(c,j) = & - smin_nh4sorb_vr_clm_loc(cellcount)*clm_pf_idata%N_molecular_weight - - sminn_vr(c,j) = smin_no3_vr(c,j) + smin_nh4_vr(c,j) + smin_nh4sorb_vr(c,j) - - ! flows or changes (unit: g/m3/s) - smin_nh4_to_plant_vr(c,j) = (accextrnh4_vr_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - smin_no3_to_plant_vr(c,j) = (accextrno3_vr_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) - - gross_nmin_vr(c,j) = (accnmin_vr_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - - potential_immob_vr(c,j) = (accnimmp_vr_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - actual_immob_vr(c,j) = (accnimm_vr_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - - else ! just in case 'clm_pf_idata%nzclm_mapped0: soil layer) - - ! gases from PFLOTRAN are timely accumulated, so gas fluxes are calculated here if over atm. partial pressure (no explicit transport available from PF now) - PetscScalar, pointer :: gco2_vr_clms_loc(:) ! (M: molC/m3 bulk soil) vertically-resolved soil gas CO2 from PF's evolution - PetscScalar, pointer :: gn2_vr_clms_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2 from PF's evolution - PetscScalar, pointer :: gn2o_vr_clms_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2O from PF's evolution - PetscScalar, pointer :: gco2_vr_clmp_loc(:) ! (M: molC/m3 bulk soil) vertically-resolved soil gas CO2 to reset PF's CO2g - PetscScalar, pointer :: gn2_vr_clmp_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2 to reset PF's N2g - PetscScalar, pointer :: gn2o_vr_clmp_loc(:) ! (M: molN/m3 bulk soil) vertically-resolved soil gas N2O to reset PF's N2Og - - ! 'acchr_vr' - accumulative CO2 proudction from decompositon (for tracking HR, not involving mass-balance) - PetscScalar, pointer :: acchr_vr_clm_loc(:) ! (moleC/m3/timestep) vertically-resolved soil CO2 production (accumulated) - ! 'accngasmin_vr' - accumulative N gas proudction from mineralization (for tracking, not involving mass-balance) - PetscScalar, pointer :: accngasmin_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil gaseous N production (accumulated) - ! 'accngasnitr_vr' - accumulative N gas proudction from nitrification (for tracking) - PetscScalar, pointer :: accngasnitr_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil gaseous N production (accumulated) - ! 'accngasdeni_vr' - accumulative N gas proudction from denitrification (for tracking) - PetscScalar, pointer :: accngasdeni_vr_clm_loc(:) ! (moleN/m3/timestep) vertically-resolved soil gaseous N production (accumulated) - - ! - PetscScalar, pointer :: soillsat_clm_loc(:) - PetscScalar, pointer :: soilisat_clm_loc(:) - PetscScalar, pointer :: soilpor_clm_loc(:) - PetscScalar, pointer :: soilt_clm_loc(:) - PetscScalar, pointer :: soilpress_clm_loc(:) - PetscErrorCode :: ierr - - real(r8), parameter :: rgas = 8.3144621 ! m3 Pa K-1 mol-1 - -!------------------------------------------------------------------------------------ - associate ( & - forc_pco2 => clm_bgc_data%forc_pco2_grc , & ! partial pressure co2 (Pa) - forc_pch4 => clm_bgc_data%forc_pch4_grc , & ! partial pressure ch4 (Pa) - forc_pbot => clm_bgc_data%forc_pbot_not_downscaled_grc , & ! atmospheric pressure (Pa) - frac_sno => clm_bgc_data%frac_sno_eff_col , & ! fraction of ground covered by snow (0 to 1) - frac_h2osfc => clm_bgc_data%frac_h2osfc_col , & ! fraction of ground covered by surface water (0 to 1) - dz => clm_bgc_data%dz , & ! soil layer thickness depth (m) - hr_vr => clm_bgc_data%hr_vr_col , & - f_co2_soil_vr => clm_bgc_data%f_co2_soil_vr_col , & - f_n2o_soil_vr => clm_bgc_data%f_n2o_soil_vr_col , & - f_n2_soil_vr => clm_bgc_data%f_n2_soil_vr_col , & - f_ngas_decomp_vr => clm_bgc_data%f_ngas_decomp_vr_col , & - f_ngas_nitri_vr => clm_bgc_data%f_ngas_nitri_vr_col , & - f_ngas_denit_vr => clm_bgc_data%f_ngas_denit_vr_col & - ) -! ------------------------------------------------------------------------ - dtime = get_step_size() - nstep = get_nstep() - - ! get the current time-step state variables of aq. phase of interested species - call VecGetArrayF90(clm_pf_idata%gco2_vr_clms, gco2_vr_clms_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%gn2_vr_clms, gn2_vr_clms_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%gn2o_vr_clms, gn2o_vr_clms_loc, ierr) - CHKERRQ(ierr) - - call VecGetArrayF90(clm_pf_idata%gco2_vr_clmp, gco2_vr_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%gn2_vr_clmp, gn2_vr_clmp_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%gn2o_vr_clmp, gn2o_vr_clmp_loc, ierr) - CHKERRQ(ierr) - - call VecGetArrayF90(clm_pf_idata%acchr_vr_clms, acchr_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%accngasmin_vr_clms, accngasmin_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%accngasnitr_vr_clms, accngasnitr_vr_clm_loc, ierr) - CHKERRQ(ierr) - call VecGetArrayF90(clm_pf_idata%accngasdeni_vr_clms, accngasdeni_vr_clm_loc, ierr) - CHKERRQ(ierr) - - ! env. variables to properties of gases - if (pf_tmode) then - call VecGetArrayF90(clm_pf_idata%soilt_clms, soilt_clm_loc, ierr) - CHKERRQ(ierr) ! PF evolved 'soilt' - else - call VecGetArrayF90(clm_pf_idata%soilt_clmp, soilt_clm_loc, ierr) - CHKERRQ(ierr) ! CLM evolved 'soilt' - for CLM, MPI vecs and Seq. vecs should be same - end if - - if (pf_frzmode) then - call VecGetArrayF90(clm_pf_idata%soilisat_clms, soilisat_clm_loc, ierr) - CHKERRQ(ierr) ! PF evolved 'soil ice saturation' - end if - - if (pf_hmode) then - call VecGetArrayF90(clm_pf_idata%soillsat_clms, soillsat_clm_loc, ierr) - CHKERRQ(ierr) ! PF evolved 'soil liq. saturation' - call VecGetArrayF90(clm_pf_idata%press_clms, soilpress_clm_loc, ierr) - CHKERRQ(ierr) ! PF evolved 'soil liq. saturation' - else - call VecGetArrayF90(clm_pf_idata%soillsat_clmp, soillsat_clm_loc, ierr) - CHKERRQ(ierr)! CLM evolved 'soilt liq. saturation' - call VecGetArrayF90(clm_pf_idata%press_clmp, soilpress_clm_loc, ierr) - CHKERRQ(ierr)! CLM evolved 'soilt liq. saturation' - endif - call VecGetArrayF90(clm_pf_idata%effporosity_clms, soilpor_clm_loc, ierr) ! PF evolved 'soil porosity' - CHKERRQ(ierr) - - ! find the toppest air barrier layer - lair_barrier(:) = -1 ! (-1: no barrier, 0: ground snow/ice/water-layer barrier, >=1: barrier in soil column) - do fc = 1,num_soilc - c = filter_soilc(fc) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - - g = col_pp%gridcell(c) - gcount = g - bounds%begg - - if((frac_sno(c)+ frac_h2osfc(c))>=0.90_r8) then - lair_barrier(c) = 0 - endif - - do j = 1, clm_pf_idata%nzclm_mapped - - cellcount = gcount*clm_pf_idata%nzclm_mapped+j - - wfps = 0._r8 - if (lair_barrier(c) >= 0) exit - - if (pf_frzmode) then - wfps =soillsat_clm_loc(cellcount) & - + soilisat_clm_loc(cellcount) - else - wfps =soillsat_clm_loc(cellcount) ! note: 'lsat' from PF has been adjusted by 'isat' reduced porosity - endif - if (wfps > 0.95_r8) then ! 95% total saturation as a critical-point for air-flow into deep soil - lair_barrier(c) = j - endif - enddo - enddo - - ! - do fc = 1,num_soilc ! operating on soil column, which then back to CLM-CN - c = filter_soilc(fc) - if ( col_pp%wtgcell(c) <= 0._r8 .or. (.not.col_pp%active(c)) ) cycle ! don't assign data from PF for inactive cell - - g = col_pp%gridcell(c) - gcount = g - bounds%begg - - total_p = forc_pbot(g) - - do j = 1, nlevdecomp - cellcount = gcount*clm_pf_idata%nzclm_mapped+j - if(j <= clm_pf_idata%nzclm_mapped) then - - tc = soilt_clm_loc(cellcount) ! soil layer tc (oC) - tk = tc+tfrz - - ! total_p is soil air pressure (soil water pressure if not less than atm. pressure) - total_p = max(total_p, soilpress_clm_loc(cellcount)) - - ! the following is for adjusting air space in soil (seems not right ?? -- off) - !air_vol = (1.0_r8 - soillsat_clm_loc(cellcount)) * & - ! soilpor_clm_loc(cellcount) ! m3 air/m3 soil - !air_vol = max(air_vol, 0.01d0) ! min. 0.01 to avoid math. issue - - air_vol = 1.0_r8 ! atm used if not commented out - air_molar = total_p*air_vol/rgas/tk ! moles of air in a cell - - ! gas fluxes from immobile PFLOTRAN evolving CO2imm, N2Oimm and N2imm, which are cumulative - ! CO2 - - cgas = gco2_vr_clms_loc(cellcount) ! mol/m3 soil (evolving in PF, but not yet transport) - co2_p = forc_pco2(g) ! assuming atm. pco2 (pa) as directly equilibrated with soil CO2(g) - cgas_p = co2_p/forc_pbot(g) * air_molar - - f_co2_soil_vr(c,j) = cgas-cgas_p - cgas = cgas - f_co2_soil_vr(c,j) - if (j <= lair_barrier(c) .or. lair_barrier(c) < 0) then ! above barrier OR no-barrier(-1) - gco2_vr_clmp_loc(cellcount) = cgas_p ! this refreshed-air will pass back to PF - else - gco2_vr_clmp_loc(cellcount) = cgas ! currently don't have air transport (TODO) - endif - - f_co2_soil_vr(c,j) = f_co2_soil_vr(c,j)*clm_pf_idata%C_molecular_weight ! moleCO2/m3 --> gC/m3 soil - f_co2_soil_vr(c,j) = f_co2_soil_vr(c,j)/dtime ! gC/m3/s - - ! N2 - cgas = gn2_vr_clms_loc(cellcount) ! mol/m3 soil (evolving in PF, but not yet transport) - n2_p = 0.78084_r8 ! assuming atm. pn2 as directly equilibrated with soil n2(g) - cgas_p = n2_p * air_molar ! moleN2/m3 - - f_n2_soil_vr(c,j) = cgas-cgas_p - cgas = cgas - f_n2_soil_vr(c,j) - if (j <= lair_barrier(c) .or. lair_barrier(c) < 0) then ! above barrier OR no-barrier(-1) - gn2_vr_clmp_loc(cellcount) = cgas_p ! this refreshed-air will pass back to PF - else - gn2_vr_clmp_loc(cellcount) = cgas ! currently don't have air transport (TODO) - endif - - f_n2_soil_vr(c,j) = f_n2_soil_vr(c,j)*clm_pf_idata%N_molecular_weight*2._r8 ! mole-N2/m3 --> g-N/m3 soil - f_n2_soil_vr(c,j) = f_n2_soil_vr(c,j)/dtime ! gN/m3/s - - ! N2O - cgas = gn2o_vr_clms_loc(cellcount) - n2o_p = 310e-9_r8 ! assuming general atm. pN2O (310ppbv in 1990) as directly equilibrated with soil N2(aq) - cgas_p = n2o_p * air_molar ! moleN2O/m3 - - f_n2o_soil_vr(c,j) = cgas-cgas_p - cgas = cgas - f_n2o_soil_vr(c,j) - if (j <= lair_barrier(c) .or. lair_barrier(c) < 0) then ! above barrier OR no-barrier(-1) - gn2o_vr_clmp_loc(cellcount) = cgas_p ! this refreshed-air will pass back to PF - else - gn2o_vr_clmp_loc(cellcount) = cgas ! currently don't have air transport (TODO) - endif - - f_n2o_soil_vr(c,j) = f_n2o_soil_vr(c,j)*clm_pf_idata%N_molecular_weight*2._r8 ! mole-N2O/m3 --> g-N/m3 soil - f_n2o_soil_vr(c,j) = f_n2o_soil_vr(c,j)/dtime ! gN/m3/s - - ! tracking HR from SOM-C reaction network - hr_vr(c,j) = (acchr_vr_clm_loc(cellcount) & - * clm_pf_idata%C_molecular_weight)/dtime - - ! tracking gaseous N production from N reaction network - f_ngas_decomp_vr(c,j)= (accngasmin_vr_clm_loc (cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - - f_ngas_nitri_vr(c,j) = (accngasnitr_vr_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - - f_ngas_denit_vr(c,j) = (accngasdeni_vr_clm_loc(cellcount) & - * clm_pf_idata%N_molecular_weight)/dtime - - else ! just in case 'clm_pf_idata%nzclm_mapped PF) - call pflotranModelUpdateAqGasesfromCLM(pflotran_m) - - end associate - end subroutine update_bgc_gaslosses_pf2clm - - - !----------------------------------------------------------------------------- - !BOP - ! comment out this subroutine currently for bgc-only - ! !IROUTINE: update_bcflow_pf2clm - ! - ! !INTERFACE: -! subroutine update_bcflow_pf2clm( & -! bounds, num_soilc, filter_soilc, & -! clm_a2l, ces_vars, cef_vars, cws_vars, cwf_vars) -! ! -! ! !DESCRIPTION: -! ! update qflx_surf, qflx_infl from PF's -! ! 'mass_balance' retrieving from PFLOTRAN -! ! -! ! !USES: -! use clm_time_manager, only : get_step_size -! -! type(bounds_type), intent(in) :: bounds -! integer, intent(in) :: num_soilc ! number of column soil points in column filter -! integer, intent(in) :: filter_soilc(:) ! column filter for soil points -! -! type(atm2lnd_type) , intent(in) :: clm_a2l -! type(temperature_type) , intent(in) :: ces_vars -! type(energyflux_type) , intent(in) :: cef_vars -! type(waterstate_type) , intent(in) :: cws_vars -! type(waterflux_type) , intent(inout) :: cwf_vars -! -! ! !LOCAL VARIABLES: -!#include "finclude/petscsys.h" -!#include "finclude/petscvec.h" -!#include "finclude/petscvec.h90" -! -! integer :: fc, c, g, gcount ! indices -! real(r8) :: area ! top face area -! real(r8) :: dtime ! land model time step (sec) -! real(r8) :: dew -! real(r8) :: qflx_evap(bounds%begc:bounds%endc) ! soil surface evaporation (mmH2O/s) -! -! PetscScalar, pointer :: area_clm_loc(:) -! PetscScalar, pointer :: qinfl_subsurf_clm_loc(:) ! kgH2O/time-step -! PetscScalar, pointer :: qsurf_subsurf_clm_loc(:) ! kgH2O/time-step -! PetscScalar, pointer :: qflux_subbase_clm_loc(:) ! kgH2O/time-step -! PetscErrorCode :: ierr -! -! character(len=32) :: subname = 'update_bcflow_pf2clm' ! subroutine name -! -! !----------------------------------------------------------------------- -! -! associate(& -! clandunit => col_pp%landunit , & ! column's landunit -! ltype => lun_pp%itype , & ! landunit type -! zi => col_pp%zi , & ! Input: (:,:) soil layer interface depth (m) -! dz => col_pp%dz , & ! Input: (:,:) soil layer thickness (m) -! ! -! forc_pbot => clm_a2l%forc_pbot_not_downscaled_grc , & ! Input: [real(r8) (:)] atmospheric pressure (Pa) -! t_grnd => ces_vars%t_grnd_col , & ! Input: [real(r8) (:)] ground surface temperature [K] -! htvp => cef_vars%htvp_col , & ! Input: [real(r8) (:)] latent heat of vapor of water (or sublimation) [j/kg] -! ! -! frac_sno => cws_vars%frac_sno_eff_col , & ! Input: fraction of ground covered by snow (0 to 1) -! frac_h2osfc => cws_vars%frac_h2osfc_col , & ! Input: fraction of ground covered by surface water (0 to 1) -! ! -! qflx_top_soil => cwf_vars%qflx_top_soil_col , & ! Input: [real(r8) (:)] net water input into soil from top (mm/s) -! qflx_ev_h2osfc => cwf_vars%qflx_ev_h2osfc_col , & ! Input: column-level evaporation flux from h2osfc (W/m2) [+ to atm] : checking unit -! qflx_evap_soil => cwf_vars%qflx_evap_soi_col , & ! Input: column-level soil evaporation (mm H2O/s) (+ = to atm) -! qflx_subl_snow => cwf_vars%qflx_sub_snow_col , & ! Input: column-level evaporation flux from snow (mm H2O/s) [+ to atm] -! qflx_surf => cwf_vars%qflx_surf_col , & ! Output: [real(r8) (:)] surface runoff (mm H2O /s) -! qflx_infl => cwf_vars%qflx_infl_col , & ! Output: [real(r8) (:)] soil infiltration (mm H2O /s) -! qflx_drain => cwf_vars%qflx_drain_col & ! Output: [real(r8) (:)] sub-surface runoff (drainage) (mm H2O /s) -! ) -! -! dtime = get_step_size() -! -! ! the following was actually duplicated from 'get_clm_bcwflx' to calculate total water evap from 'qflx_topsoil' -! ! in order to get potential infiltration from CLM (not yet run-off) -! do fc = 1, num_soilc -! c = filter_soilc(fc) -! if (ltype(clandunit(c)) == istsoil .or. ltype(clandunit(c))==istcrop) then -! ! not sure if using 'qflx_evap_soi_col' as a whole ground-surface better than individual surfaces, i.e. 'qflx_ev_snow/soi/h2osfc' -! ! all of those 4 variables are calculated in 'BareGroundFluxesMod', 'CanopyFluxesMod', and then adjusted in 'Biogeophysics2' after soil temperature call -! ! note that: all 4 variables could be negative (i.e., dew formation on ground) -! qflx_evap(c)=(1.0_r8 - frac_sno(c) - frac_h2osfc(c))*qflx_evap_soil(c) + & -! frac_h2osfc(c)*qflx_ev_h2osfc(c)/htvp(c) -! !frac_sno(c)*qflx_evap_snow(c) ! snow-covered area should be excluded (see SoilHydrologyMod:: infiltration) -! else -! ! for other types of landunits -! qflx_evap(c) = (1.0_r8 - frac_sno(c))*qflx_evap_soil(c) -! end if -! -! if (t_grnd(c) <= tfrz) qflx_evap(c) = max(0._r8, qflx_evap(c)) ! frozen ground, no dew contribution to subsurface infiltration -! end do -! -! -! ! from PF==>CLM -! call VecGetArrayF90(clm_pf_idata%area_top_face_clms, area_clm_loc, ierr) -! CHKERRQ(ierr) -! -! call VecGetArrayF90(clm_pf_idata%qinfl_subsurf_clms,qinfl_subsurf_clm_loc,ierr) -! CHKERRQ(ierr) -! call VecGetArrayF90(clm_pf_idata%qsurf_subsurf_clms,qsurf_subsurf_clm_loc,ierr) -! CHKERRQ(ierr) -! call VecGetArrayF90(clm_pf_idata%qflux_subbase_clms,qflux_subbase_clm_loc,ierr) -! CHKERRQ(ierr) -! -! do fc = 1, num_soilc -! -! c = filter_soilc(fc) -! g = col_pp%gridcell(c) -! gcount = g - bounds%begg -! -! dew = 0._r8 -! if (t_grnd(c) > tfrz) then ! frozen ground, no dew contribution to subsurface infiltration -! if (ltype(clandunit(c)) == istsoil .or. ltype(clandunit(c))==istcrop) then -! dew = -min(0._r8, (1.0_r8 - frac_sno(c) - frac_h2osfc(c))*qflx_evap_soil(c) + & -! frac_h2osfc(c)*qflx_ev_h2osfc(c)/htvp(c) ) -! else -! dew = -min(0._r8, qflx_evap_soil(c)) -! end if -! endif -! -! !'from PF: qinfl_subsurf_clm_loc: positive - in, negative - out -! area = area_clm_loc(gcount*clm_pf_idata%nzclm_mapped+1) -! qflx_infl(c) = qinfl_subsurf_clm_loc(gcount+1) & -! /dtime/(area*denh2o*1.e-3) ! kgH2O/time-step ==> mmH2O/sec -! -! qflx_surf(c) = dew + max(0._r8, qflx_top_soil(c)-qflx_evap(c)) - qflx_infl(c) -! qflx_surf(c) = max(0._r8, qflx_surf(c)) -! -! !'from PF: qflux_subbase_clm_loc: positive - in, negative - out) -! area = area_clm_loc((gcount+1)*clm_pf_idata%nzclm_mapped) ! note: this 'area_clm_loc' is in 3-D for all subsurface domain -! qflx_drain(c) = -qflux_subbase_clm_loc(gcount+1) & -! /dtime/(area*denh2o*1.e-3) ! kgH2O/time-step ==> mmH2O/sec (+ drainage, - upward-in) -! -! end do -! call VecRestoreArrayF90(clm_pf_idata%area_top_face_clms, area_clm_loc, ierr) -! CHKERRQ(ierr) -! call VecRestoreArrayF90(clm_pf_idata%qinfl_subsurf_clms,qinfl_subsurf_clm_loc,ierr) -! CHKERRQ(ierr) -! call VecRestoreArrayF90(clm_pf_idata%qsurf_subsurf_clms,qsurf_subsurf_clm_loc,ierr) -! CHKERRQ(ierr) -! call VecRestoreArrayF90(clm_pf_idata%qflux_subbase_clms,qflux_subbase_clm_loc,ierr) -! CHKERRQ(ierr) -! -! end associate -! end subroutine update_bcflow_pf2clm - -#endif -!---------------------------------------------------------------------------------------------- -! END of CLM-PFLOTRAN bgc coupling interface -!---------------------------------------------------------------------------------------------- - -end module clm_pflotran_interfaceMod - diff --git a/components/clm/src/main/clm_varctl.F90 b/components/clm/src/main/clm_varctl.F90 index 1aa34e2f3521..81d3e76b6250 100644 --- a/components/clm/src/main/clm_varctl.F90 +++ b/components/clm/src/main/clm_varctl.F90 @@ -337,16 +337,17 @@ module clm_varctl !----------------------------------------------------------------------- ! bgc & pflotran interface ! - logical, public :: use_bgc_interface = .false. + logical, public :: use_clm_interface = .false. logical, public :: use_clm_bgc = .false. logical, public :: use_pflotran = .false. logical, public :: pf_surfaceflow = .false. ! the following switches will allow flexibility of coupling CLM with PFLOTRAN (which in fact runs in 3 modes individually or coupled) + logical, public :: pf_cmode = .false. ! switch for 'C' mode coupling (will be updated in interface) logical, public :: pf_hmode = .false. ! switch for 'H' mode coupling (will be updated in interface) logical, public :: pf_tmode = .false. ! switch for 'T' mode coupling (will be updated in interface) logical, public :: pf_frzmode = .false. ! switch for 'freezing' mode availablity in PF-thmode (will be updated in interface) - logical, public :: pf_cmode = .false. ! switch for 'C' mode coupling (will be updated in interface) logical, public :: initth_pf2clm= .false. ! switch for initializing CLM TH states from pflotran + integer, public :: pf_clmnstep0 = 0 ! the CLM timestep of start/restart ! cpl_bypass character(len=fname_len), public :: metdata_type = ' ' ! metdata type for CPL_BYPASS mode diff --git a/components/clm/src/main/controlMod.F90 b/components/clm/src/main/controlMod.F90 index fb002e6555e4..201d55ca2748 100644 --- a/components/clm/src/main/controlMod.F90 +++ b/components/clm/src/main/controlMod.F90 @@ -108,7 +108,7 @@ subroutine control_init( ) use clm_time_manager , only : set_timemgr_init, get_timemgr_defaults use fileutils , only : getavu, relavu use shr_string_mod , only : shr_string_getParentDir - use clm_pflotran_interfaceMod , only : clm_pf_readnl + use clm_interface_pflotranMod , only : clm_pf_readnl use ALMBeTRNLMod , only : betr_readNL ! implicit none @@ -129,7 +129,7 @@ subroutine control_init( ) ! Time step namelist / clm_inparm/ & - dtime + dtime ! CLM namelist settings @@ -238,7 +238,7 @@ subroutine control_init( ) co2_file, aero_file ! bgc & pflotran interface - namelist /clm_inparm/ use_bgc_interface, use_clm_bgc, use_pflotran + namelist /clm_inparm/ use_clm_interface, use_clm_bgc, use_pflotran namelist /clm_inparm/ use_dynroot @@ -402,20 +402,22 @@ subroutine control_init( ) end if ! ---------------------------------------------------------------------- - !! bgc & pflotran interface - if(.not.use_bgc_interface) then - use_clm_bgc = .true. + ! bgc & pflotran interface + if(.not.use_clm_interface) then + use_clm_bgc = .false. use_pflotran = .false. - end if - - if (use_clm_bgc) then - use_pflotran = .false. - end if - - if (use_pflotran) then - use_clm_bgc = .false. - !! enable 'use_nitrif_denitrif' to initilize Nh4 & NO3 pools, NOT to implement 'nitrif_denitrif' - use_nitrif_denitrif = .true. + else + ! use_clm_interface + if (use_clm_bgc) then + use_pflotran = .false. + end if + + if (use_pflotran) then + use_clm_bgc = .false. + ! enable 'use_nitrif_denitrif' to initilize Nh4 & NO3 pools, + ! but NOT to implement 'nitrif_denitrif' + use_nitrif_denitrif = .true. + end if end if endif ! end of if-masterproc if-block @@ -736,7 +738,7 @@ subroutine control_spmd() call mpi_bcast (domain_decomp_type, len(domain_decomp_type), MPI_CHARACTER, 0, mpicom, ier) ! bgc & pflotran interface - call mpi_bcast (use_bgc_interface, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_clm_interface, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_clm_bgc, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_pflotran, 1, MPI_LOGICAL, 0, mpicom, ier) diff --git a/components/clm/src/main/filterMod.F90 b/components/clm/src/main/filterMod.F90 index 859bd884196d..2b73636c3434 100644 --- a/components/clm/src/main/filterMod.F90 +++ b/components/clm/src/main/filterMod.F90 @@ -60,6 +60,9 @@ module filterMod integer, pointer :: hydrologyc(:) ! hydrology filter (columns) integer :: num_hydrologyc ! number of columns in hydrology filter + integer, pointer :: hydrononsoic(:) ! non-soil hydrology filter (columns) + integer :: num_hydrononsoic ! number of columns in non-soil hydrology filter + integer, pointer :: urbanl(:) ! urban filter (landunits) integer :: num_urbanl ! number of landunits in urban filter integer, pointer :: nourbanl(:) ! non-urban filter (landunits) @@ -195,6 +198,7 @@ subroutine allocFiltersOneGroup(this_filter) allocate(this_filter(nc)%natvegp(bounds%endp-bounds%begp+1)) allocate(this_filter(nc)%hydrologyc(bounds%endc-bounds%begc+1)) + allocate(this_filter(nc)%hydrononsoic(bounds%endc-bounds%begc+1)) allocate(this_filter(nc)%urbanp(bounds%endp-bounds%begp+1)) allocate(this_filter(nc)%nourbanp(bounds%endp-bounds%begp+1)) @@ -364,6 +368,7 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, icemask_grc ! Create column-level hydrology filter (soil and Urban pervious road cols) f = 0 + fn= 0 do c = bounds%begc,bounds%endc if (col_pp%active(c) .or. include_inactive) then l =col_pp%landunit(c) @@ -371,10 +376,17 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, icemask_grc lun_pp%itype(l) == istcrop) then f = f + 1 this_filter(nc)%hydrologyc(f) = c + + if (col_pp%itype(c) == icol_road_perv) then + fn = fn + 1 + this_filter(nc)%hydrononsoic(fn) = c + end if + end if end if end do this_filter(nc)%num_hydrologyc = f + this_filter(nc)%num_hydrononsoic = fn ! Create prognostic crop and soil w/o prog. crop filters at pft-level ! according to where the crop model should be used diff --git a/components/clm/src/main/surfrdMod.F90 b/components/clm/src/main/surfrdMod.F90 index 9da0541be9ed..11f8155f8c84 100644 --- a/components/clm/src/main/surfrdMod.F90 +++ b/components/clm/src/main/surfrdMod.F90 @@ -15,7 +15,7 @@ module surfrdMod use clm_varctl , only : create_glacier_mec_landunit, use_cndv use surfrdUtilsMod , only : check_sums_equal_1 use ncdio_pio , only : file_desc_t, var_desc_t, ncd_pio_openfile, ncd_pio_closefile - use ncdio_pio , only : ncd_io, check_var, ncd_inqfdims, check_dim, ncd_inqdid + use ncdio_pio , only : ncd_io, check_var, ncd_inqfdims, check_dim, ncd_inqdid, ncd_inqdlen use pio use spmdMod ! @@ -139,6 +139,7 @@ subroutine surfrd_get_grid(begg, endg, ldomain, filename, glcfilename) use clm_varcon, only : spval, re use domainMod , only : domain_type, domain_init, domain_clean, lon1d, lat1d use fileutils , only : getfil + use clm_varctl, only : use_pflotran ! ! !ARGUMENTS: integer ,intent(in) :: begg, endg @@ -160,10 +161,16 @@ subroutine surfrd_get_grid(begg, endg, ldomain, filename, glcfilename) logical :: isgrid2d ! true => file is 2d lat/lon logical :: istype_domain ! true => input file is of type domain real(r8), allocatable :: rdata2d(:,:) ! temporary + real(r8), allocatable :: rdata3d(:,:,:) ! temporary ! pflotran character(len=16) :: vname ! temporary character(len=256):: locfn ! local file name integer :: n ! indices real(r8):: eps = 1.0e-12_r8 ! lat/lon error tolerance + + ! pflotran:beg----------------------------- + integer :: j, np, nv + + ! pflotran:end----------------------------- character(len=32) :: subname = 'surfrd_get_grid' ! subroutine name !----------------------------------------------------------------------- @@ -179,6 +186,15 @@ subroutine surfrd_get_grid(begg, endg, ldomain, filename, glcfilename) ! Determine dimensions call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) + + ! pflotran:beg----------------------------------------------- + call ncd_inqdlen(ncid, dimid, nv, 'nv') + if (nv>0) then + ldomain%nv = nv + else + ldomain%nv = 0 + endif + ! pflotran:end----------------------------------------------- ! Determine isgrid2d flag for domain call domain_init(ldomain, isgrid2d=isgrid2d, ni=ni, nj=nj, nbeg=begg, nend=endg) @@ -206,6 +222,21 @@ subroutine surfrd_get_grid(begg, endg, ldomain, filename, glcfilename) call ncd_io(ncid=ncid, varname= 'yc', flag='read', data=ldomain%latc, & dim1name=grlnd, readvar=readvar) if (.not. readvar) call endrun( msg=' ERROR: yc NOT on file'//errMsg(__FILE__, __LINE__)) + + ! pflotran:beg----------------------------------------------- + ! user-defined grid-cell vertices (ususally 'nv' is 4, + ! but for future use, we set the following if condition of 'nv>=3' so that possible to use TIN grids + if (ldomain%nv>=3 .and. use_pflotran) then + call ncd_io(ncid=ncid, varname='xv', flag='read', data=ldomain%lonv, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=trim(subname)//' ERROR: xv NOT on file'//errMsg(__FILE__, __LINE__)) + + call ncd_io(ncid=ncid, varname='yv', flag='read', data=ldomain%latv, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=trim(subname)//' ERROR: yv NOT on file'//errMsg(__FILE__, __LINE__)) + + end if + ! pflotran:end----------------------------------------------- else call ncd_io(ncid=ncid, varname= 'AREA', flag='read', data=ldomain%area, & dim1name=grlnd, readvar=readvar) @@ -218,9 +249,27 @@ subroutine surfrd_get_grid(begg, endg, ldomain, filename, glcfilename) call ncd_io(ncid=ncid, varname= 'LATIXY', flag='read', data=ldomain%latc, & dim1name=grlnd, readvar=readvar) if (.not. readvar) call endrun( msg=' ERROR: LATIXY NOT on file'//errMsg(__FILE__, __LINE__)) + + ! pflotran:beg----------------------------------------------- + ! user-defined grid-cell vertices (ususally 'nv' is 4, + ! but for future use, we set the following if condition of 'nv>=3' so that possible to use TIN grids + if (ldomain%nv>=3 .and. use_pflotran) then + + call ncd_io(ncid=ncid, varname='LONGV', flag='read', data=ldomain%lonv, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=trim(subname)//' ERROR: LONGV NOT on file'//errMsg(__FILE__, __LINE__)) + + call ncd_io(ncid=ncid, varname='LATIV', flag='read', data=ldomain%latv, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=trim(subname)//' ERROR: LATIV NOT on file'//errMsg(__FILE__, __LINE__)) + + end if + ! pflotran:end----------------------------------------------- end if - if (isgrid2d) then + + ! let lat1d/lon1d data available for all grid-types, if coupled with PFLOTRAN. + if (isgrid2d .or. use_pflotran) then allocate(rdata2d(ni,nj), lon1d(ni), lat1d(nj)) if (istype_domain) then vname = 'xc' @@ -237,7 +286,81 @@ subroutine surfrd_get_grid(begg, endg, ldomain, filename, glcfilename) call ncd_io(ncid=ncid, varname=trim(vname), data=rdata2d, flag='read', readvar=readvar) lat1d(:) = rdata2d(1,:) deallocate(rdata2d) - end if + + ! pflotran:beg----------------------------------------------- + ! find the origin of ldomain, if vertices of first grid known + if (use_pflotran) then + ldomain%lon0 = -9999._r8 + ldomain%lat0 = -9999._r8 + if (ldomain%nv==4 .and. ldomain%nv /= huge(1)) then + allocate(rdata3d(ni,nj,nv)) + if (istype_domain) then + vname = 'xv' + else + vname = 'LONGV' + end if + + call ncd_io(ncid=ncid, varname=trim(vname), data=rdata3d, flag='read', readvar=readvar) + + if (readvar) then + ldomain%lon0 = 0._r8 + np=0 + do j=1,nv + ! may have issue if mixed longitude values (i.e. 0~360 or -180~180) + if ( ni>1 .and. & + ( (rdata3d(1,1,j) < lon1d(1) .and. rdata3d(1,1,j) < lon1d(2)) .or. & + (rdata3d(1,1,j) > lon1d(1) .and. rdata3d(1,1,j) > lon1d(2)) ) ) then + np = np + 1 + ldomain%lon0 = ldomain%lon0+rdata3d(1,1,j) + + else if (ni==1 .and. rdata3d(1,1,j)0) then + ldomain%lon0 = ldomain%lon0/np + else + ldomain%lon0 = -9999._r8 + end if + end if + + ! + if (istype_domain) then + vname = 'yv' + else + vname = 'LATIV' + end if + call ncd_io(ncid=ncid, varname=trim(vname), data=rdata3d, flag='read', readvar=readvar) + if (readvar) then + ldomain%lat0 = 0._r8 + np=0 + do j=1,nv + if ( nj>1 .and. & + ( (rdata3d(1,1,j) < lat1d(1) .and. rdata3d(1,1,j) < lat1d(2)) .or. & + (rdata3d(1,1,j) > lat1d(1) .and. rdata3d(1,1,j) > lat1d(2)) ) ) then + np = np + 1 + ldomain%lat0 = ldomain%lat0+rdata3d(1,1,j) + + else if (nj==1 .and. rdata3d(1,1,j)0) then + ldomain%lat0 = ldomain%lat0/np + else + ldomain%lat0 = -9999._r8 + end if + end if + ! + deallocate(rdata3d) + end if + end if + ! pflotran:end----------------------------------------------- + end if ! if (isgrid2d .or. use_pflotran) + + ! Check lat limited to -90,90 @@ -495,6 +618,7 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat) end if call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) + surfdata_domain%nv = 0 ! must be initialized to 0 here prior to call 'domain_init' call domain_init(surfdata_domain, isgrid2d, ni, nj, begg, endg, clmlevel=grlnd) call ncd_io(ncid=ncid, varname=lon_var, flag='read', data=surfdata_domain%lonc, & diff --git a/components/clm/src/utils/clm_time_manager.F90 b/components/clm/src/utils/clm_time_manager.F90 index cc5e2aa6a41a..f12102f4d280 100644 --- a/components/clm/src/utils/clm_time_manager.F90 +++ b/components/clm/src/utils/clm_time_manager.F90 @@ -50,7 +50,7 @@ module clm_time_manager is_perpetual, &! return true if perpetual calendar is in use is_restart, &! return true if this is a restart run update_rad_dtime, &! track radiation interval via nstep - !!below used by pflotran + !below used by pflotran nsstep, &! (re-)start timestep nestep ! ending timestep @@ -112,7 +112,8 @@ module clm_time_manager private :: timemgr_spmdbcast private :: init_calendar private :: init_clock - private :: calc_nestep +! private :: calc_nestep + public :: calc_nestep !pflotran private :: timemgr_print private :: TimeGetymd @@ -632,7 +633,7 @@ subroutine timemgr_restart( ) tm_first_restart_step = .true. - !! pflotran: nsstep + ! pflotran: nsstep ! save the first restart 'nstep' nsstep = get_nstep() diff --git a/components/clm/src/utils/domainMod.F90 b/components/clm/src/utils/domainMod.F90 index 2d752adcc1b4..b82f97321e19 100644 --- a/components/clm/src/utils/domainMod.F90 +++ b/components/clm/src/utils/domainMod.F90 @@ -40,6 +40,15 @@ module domainMod ! (glcmask is just a guess at the appropriate mask, known at initialization - in contrast to icemask, which is the true mask obtained from glc) character*16 :: set ! flag to check if domain is set logical :: decomped ! decomposed locally or global copy + + ! pflotran:beg----------------------------------------------------- + integer :: nv ! number of vertices + real(r8),pointer :: latv(:,:) ! latitude of grid cell's vertices (deg) + real(r8),pointer :: lonv(:,:) ! longitude of grid cell's vertices (deg) + real(r8) :: lon0 ! the origin lon/lat (Most western/southern corner, if not globally covered grids; OR -180W(360E)/-90N) + real(r8) :: lat0 ! the origin lon/lat (Most western/southern corner, if not globally covered grids; OR -180W(360E)/-90N) + + ! pflotran:end----------------------------------------------------- end type domain_type type(domain_type) , public :: ldomain @@ -115,6 +124,24 @@ subroutine domain_init(domain,isgrid2d,ni,nj,nbeg,nend,clmlevel) call shr_sys_abort('domain_init ERROR: allocate mask, frac, lat, lon, area ') endif + ! pflotran:beg----------------------------------------------------- + ! 'nv' is user-defined, so it must be initialized or assigned value prior to call this subroutine + if (domain%nv > 0 .and. domain%nv /= huge(1)) then + if(.not.associated(domain%lonv)) then + allocate(domain%lonv(nb:ne, 1:domain%nv), stat=ier) + if (ier /= 0) & + call shr_sys_abort('domain_init ERROR: allocate lonv ') + domain%lonv = nan + endif + if(.not.associated(domain%latv)) then + allocate(domain%latv(nb:ne, 1:domain%nv)) + if (ier /= 0) & + call shr_sys_abort('domain_init ERROR: allocate latv ') + domain%latv = nan + endif + end if + ! pflotran:end----------------------------------------------------- + if (present(clmlevel)) then domain%clmlevel = clmlevel endif @@ -179,6 +206,26 @@ subroutine domain_clean(domain) if (ier /= 0) then call shr_sys_abort('domain_clean ERROR: deallocate mask, frac, lat, lon, area ') endif + + ! pflotran:beg----------------------------------------------------- + ! 'nv' is user-defined, so it must be initialized or assigned value prior to call this subroutine + if (domain%nv > 0 .and. domain%nv /= huge(1)) then + if (associated(domain%lonv)) then + deallocate(domain%lonv, stat=ier) + if (ier /= 0) & + call shr_sys_abort('domain_clean ERROR: deallocate lonv ') + nullify(domain%lonv) + endif + + if (associated(domain%latv)) then + deallocate(domain%latv, stat=ier) + if (ier /= 0) & + call shr_sys_abort('domain_clean ERROR: deallocate latv ') + nullify(domain%latv) + endif + endif + ! pflotran:beg----------------------------------------------------- + else if (masterproc) then write(iulog,*) 'domain_clean WARN: clean domain unecessary '